mirror of
https://github.com/Z3Prover/z3
synced 2025-04-26 18:45:33 +00:00
Merge branch 'master' of https://github.com/Z3Prover/z3 into new-ml-api
This commit is contained in:
commit
b178420797
174 changed files with 9762 additions and 2502 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -84,3 +84,5 @@ 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
|
||||
|
|
|
@ -105,7 +105,7 @@ else()
|
|||
message(STATUS "CMAKE_BUILD_TYPE is not set. Setting default")
|
||||
message(STATUS "The available build types are: ${available_build_types}")
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE String
|
||||
"Options are ${build_types}"
|
||||
"Options are ${available_build_types}"
|
||||
FORCE)
|
||||
# Provide drop down menu options in cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${available_build_types})
|
||||
|
@ -239,6 +239,7 @@ if (OPENMP_FOUND)
|
|||
else()
|
||||
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_NO_OMP_")
|
||||
message(STATUS "Not using OpenMP")
|
||||
set(USE_OPENMP OFF CACHE BOOL "Use OpenMP" FORCE)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
|
@ -288,15 +289,16 @@ endif()
|
|||
################################################################################
|
||||
# Tracing
|
||||
################################################################################
|
||||
option(ENABLE_TRACING OFF "Enable tracing")
|
||||
if (ENABLE_TRACING)
|
||||
option(ENABLE_TRACING_FOR_NON_DEBUG "Enable tracing in non-debug builds." OFF)
|
||||
if (ENABLE_TRACING_FOR_NON_DEBUG)
|
||||
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_TRACE")
|
||||
else()
|
||||
# Tracing is always enabled in debug builds
|
||||
list(APPEND Z3_COMPONENT_CXX_DEFINES $<$<CONFIG:Debug>:_TRACE>)
|
||||
endif()
|
||||
# Should we always enable tracing when doing a debug build?
|
||||
#list(APPEND Z3_COMPONENT_CXX_DEFINES $<$<CONFIG:Debug>:_TRACE>)
|
||||
|
||||
################################################################################
|
||||
# Postion indepdent code
|
||||
# Postion independent code
|
||||
################################################################################
|
||||
# This is required because code built in the components will end up in a shared
|
||||
# library. If not building a shared library ``-fPIC`` isn't needed and would add
|
||||
|
@ -320,9 +322,36 @@ message(STATUS "Z3_DEPENDENT_EXTRA_C_LINK_FLAGS: ${Z3_DEPENDENT_EXTRA_C_LINK_FLA
|
|||
################################################################################
|
||||
# Z3 installation locations
|
||||
################################################################################
|
||||
set (Z3_INSTALL_LIB_DIR "lib")
|
||||
set (Z3_INSTALL_BIN_DIR "bin")
|
||||
set (Z3_INSTALL_INCLUDE_DIR "include")
|
||||
include(GNUInstallDirs)
|
||||
set(CMAKE_INSTALL_PKGCONFIGDIR
|
||||
"${CMAKE_INSTALL_LIBDIR}/pkgconfig"
|
||||
CACHE
|
||||
PATH
|
||||
"Directory to install pkgconfig files"
|
||||
)
|
||||
message(STATUS "CMAKE_INSTALL_LIBDIR: \"${CMAKE_INSTALL_LIBDIR}\"")
|
||||
message(STATUS "CMAKE_INSTALL_BINDIR: \"${CMAKE_INSTALL_BINDIR}\"")
|
||||
message(STATUS "CMAKE_INSTALL_INCLUDEDIR: \"${CMAKE_INSTALL_INCLUDEDIR}\"")
|
||||
message(STATUS "CMAKE_INSTALL_PKGCONFIGDIR: \"${CMAKE_INSTALL_PKGCONFIGDIR}\"")
|
||||
|
||||
################################################################################
|
||||
# Uninstall rule
|
||||
################################################################################
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
# Target needs to be declared before the components so that they can add
|
||||
# dependencies to this target so they can run their own custom uninstall rules.
|
||||
add_custom_target(uninstall
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
COMMENT "Uninstalling..."
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# CMake build file locations
|
||||
|
@ -333,6 +362,17 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
|||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
|
||||
################################################################################
|
||||
# Extra dependencies for build rules that use the Python infrastructure to
|
||||
# generate files used for Z3's build. Changes to these files will trigger
|
||||
# a rebuild of all the generated files.
|
||||
################################################################################
|
||||
# Note: ``update_api.py`` is deliberately not here because it not used
|
||||
# to generate every generated file. The targets that need it list it explicitly.
|
||||
set(Z3_GENERATED_FILE_EXTRA_DEPENDENCIES
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_genfile_common.py"
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Z3 components, library and executables
|
||||
################################################################################
|
||||
|
@ -348,19 +388,3 @@ if (ENABLE_EXAMPLE_TARGETS)
|
|||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
# Uninstall rule
|
||||
################################################################################
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
add_custom_target(uninstall
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
COMMENT "Uninstalling..."
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
VERBATIM
|
||||
)
|
||||
|
|
|
@ -261,14 +261,24 @@ when invoking CMake and instead set the build type within Visual Studio itself.
|
|||
The following useful options can be passed to CMake whilst configuring.
|
||||
|
||||
* ``CMAKE_BUILD_TYPE`` - STRING. The build type to use. Only relevant for single configuration generators (e.g. "Unix Makefile" and "Ninja").
|
||||
* ``CMAKE_INSTALL_PREFIX`` - STRING. The install prefix to use (e.g. ``/usr/local/``)
|
||||
* ``ENABLE_TRACING`` - BOOL. If set to ``TRUE`` enable tracing, if set to ``FALSE`` disable tracing.
|
||||
* ``CMAKE_INSTALL_BINDIR`` - STRING. The path to install z3 binaries (relative to ``CMAKE_INSTALL_PREFIX``), e.g. ``bin``.
|
||||
* ``CMAKE_INSTALL_INCLUDEDIR`` - STRING. The path to install z3 include files (relative to ``CMAKE_INSTALL_PREFIX``), e.g. ``include``.
|
||||
* ``CMAKE_INSTALL_LIBDIR`` - STRING. The path to install z3 libraries (relative to ``CMAKE_INSTALL_PREFIX``), e.g. ``lib``.
|
||||
* ``CMAKE_INSTALL_PREFIX`` - STRING. The install prefix to use (e.g. ``/usr/local/``).
|
||||
* ``CMAKE_INSTALL_PKGCONFIGDIR`` - STRING. The path to install pkgconfig files.
|
||||
* ``CMAKE_INSTALL_PYTHON_PKG_DIR`` - STRING. The path to install the z3 python bindings. This can be relative (to ``CMAKE_INSTALL_PREFIX``) or absolute.
|
||||
* ``ENABLE_TRACING_FOR_NON_DEBUG`` - BOOL. If set to ``TRUE`` enable tracing in non-debug builds, if set to ``FALSE`` disable tracing in non-debug builds. Note in debug builds tracing is always enabled.
|
||||
* ``BUILD_LIBZ3_SHARED`` - BOOL. If set to ``TRUE`` build libz3 as a shared library otherwise build as a static library.
|
||||
* ``ENABLE_EXAMPLE_TARGETS`` - BOOL. If set to ``TRUE`` add the build targets for building the API examples.
|
||||
* ``USE_OPENMP`` - BOOL. If set to ``TRUE`` and OpenMP support is detected build with OpenMP support.
|
||||
* ``USE_LIB_GMP`` - BOOL. If set to ``TRUE`` use the GNU multiple precision library. If set to ``FALSE`` use an internal implementation.
|
||||
* ``PYTHON_EXECUTABLE`` - STRING. The python executable to use during the build.
|
||||
* ``BUILD_PYTHON_BINDINGS`` - BOOL. If set to ``TRUE`` then Z3's python bindings will be built.
|
||||
* ``INSTALL_PYTHON_BINDINGS`` - BOOL. If set to ``TRUE`` and ``BUILD_PYTHON_BINDINGS`` is ``TRUE`` then running the ``install`` target will install Z3's Python bindings.
|
||||
* ``BUILD_DOTNET_BINDINGS`` - BOOL. If set to ``TRUE`` then Z3's .NET bindings will be built.
|
||||
* ``INSTALL_DOTNET_BINDINGS`` - BOOL. If set to ``TRUE`` and ``BUILD_DOTNET_BINDINGS`` is ``TRUE`` then running the ``install`` target will install Z3's .NET bindings.
|
||||
* ``DOTNET_CSC_EXECUTABLE`` - STRING. The path to the C# compiler to use. Only relevant if ``BUILD_DOTNET_BINDINGS`` is set to ``TRUE``.
|
||||
* ``DOTNET_GACUTIL_EXECUTABLE`` - STRING. The path to the gacutil program to use. Only relevant if ``BUILD_DOTNET_BINDINGS`` is set to ``TRUE``.
|
||||
|
||||
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.
|
||||
|
||||
|
@ -322,8 +332,9 @@ 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 set the install
|
||||
prefix.
|
||||
Install and uninstall targets are supported. Use ``CMAKE_INSTALL_PREFIX`` to
|
||||
set the install prefix. If you also need need to control which directories are
|
||||
used for install set the documented ``CMAKE_INSTALL_*`` options.
|
||||
|
||||
To install run
|
||||
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
Z3 is a theorem prover from Microsoft Research. It is licensed
|
||||
under the [MIT license](LICENSE.txt).
|
||||
|
||||
Z3 can be built using [Visual Studio][1] or a [Makefile][2]. It provides
|
||||
[bindings for several programming languages][3].
|
||||
If you are not familiar with Z3, you can start [here](https://github.com/Z3Prover/z3/wiki#background).
|
||||
|
||||
Z3 can be built using [Visual Studio][1], a [Makefile][2] or using [CMake][3]. It provides
|
||||
[bindings for several programming languages][4].
|
||||
|
||||
See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z3.
|
||||
|
||||
[1]: #building-z3-on-windows-using-visual-studio-command-prompt
|
||||
[2]: #building-z3-using-make-and-gccclang
|
||||
[3]: #z3-bindings
|
||||
[3]: #building-z3-using-cmake
|
||||
[4]: #z3-bindings
|
||||
|
||||
## Building Z3 on Windows using Visual Studio Command Prompt
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This file overrides the default compiler flags for CMake's built-in
|
||||
# configurations (CMAKE_BUILD_TYPE). Most compiler flags should not be set here.
|
||||
# The main purpose is to make sure ``-DNDEBUG`` is never set by default.
|
||||
# The main purpose is to have very fine grained control of the compiler flags.
|
||||
if (CMAKE_C_COMPILER_ID)
|
||||
set(_lang C)
|
||||
elseif(CMAKE_CXX_COMPILER_ID)
|
||||
|
@ -9,19 +9,25 @@ else()
|
|||
message(FATAL_ERROR "Unknown language")
|
||||
endif()
|
||||
|
||||
# TODO: The value of doing this is debatable. The flags set here are pretty
|
||||
# much the CMake defaults now (they didn't use to be) and makes extra work for
|
||||
# us when supporting different compilers. Perhaps we should move the remaining
|
||||
# code that sets non-default flags out into the CMakeLists.txt files and remove
|
||||
# any overrides here?
|
||||
if (("${CMAKE_${_lang}_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_${_lang}_COMPILER_ID}" MATCHES "GNU"))
|
||||
# Taken from Modules/Compiler/GNU.cmake but -DNDEBUG is removed
|
||||
# Taken from Modules/Compiler/GNU.cmake
|
||||
set(CMAKE_${_lang}_FLAGS_INIT "")
|
||||
set(CMAKE_${_lang}_FLAGS_DEBUG_INIT "-g -O0")
|
||||
set(CMAKE_${_lang}_FLAGS_MINSIZEREL_INIT "-Os")
|
||||
set(CMAKE_${_lang}_FLAGS_RELEASE_INIT "-O3")
|
||||
set(CMAKE_${_lang}_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")
|
||||
set(CMAKE_${_lang}_FLAGS_MINSIZEREL_INIT "-Os -DNDEBUG")
|
||||
set(CMAKE_${_lang}_FLAGS_RELEASE_INIT "-O3 -DNDEBUG")
|
||||
set(CMAKE_${_lang}_FLAGS_RELWITHDEBINFO_INIT "-O2 -g -DNDEBUG")
|
||||
# FIXME: Remove "x.." when CMP0054 is set to NEW
|
||||
elseif ("x${CMAKE_${_lang}_COMPILER_ID}" STREQUAL "xMSVC")
|
||||
# FIXME: Perhaps we should be using /MD instead?
|
||||
set(CMAKE_${_lang}_FLAGS_DEBUG_INIT "/MTd /Zi /Ob0 /Od /RTC1")
|
||||
set(CMAKE_${_lang}_FLAGS_MINSIZEREL_INIT "/MT /O1 /Ob1")
|
||||
set(CMAKE_${_lang}_FLAGS_RELEASE_INIT "/MT /O2 /Ob2")
|
||||
set(CMAKE_${_lang}_FLAGS_RELWITHDEBINFO_INIT "/MT /Zi /O2 /Ob1")
|
||||
set(CMAKE_${_lang}_FLAGS_MINSIZEREL_INIT "/MT /O1 /Ob1 /D NDEBUG")
|
||||
set(CMAKE_${_lang}_FLAGS_RELEASE_INIT "/MT /O2 /Ob2 /D NDEBUG")
|
||||
set(CMAKE_${_lang}_FLAGS_RELWITHDEBINFO_INIT "/MT /Zi /O2 /Ob1 /D NDEBUG")
|
||||
# Override linker flags (see Windows-MSVC.cmake for CMake's defaults)
|
||||
# The stack size comes from the Python build system.
|
||||
set(_msvc_stack_size "8388608")
|
||||
|
|
53
contrib/cmake/cmake/modules/FindDotNetToolchain.cmake
Normal file
53
contrib/cmake/cmake/modules/FindDotNetToolchain.cmake
Normal file
|
@ -0,0 +1,53 @@
|
|||
# Tries to find a working .NET tool chain
|
||||
#
|
||||
# Once complete this will define
|
||||
# DOTNET_TOOLCHAIN_FOUND : BOOL : System has a .NET toolchain
|
||||
# DOTNET_CSC_EXECUTABLE - STRING : Path to C# compiler
|
||||
# DOTNET_GACUTIL_EXECUTABLE - STRING : Path to gacutil
|
||||
# DOTNET_TOOLCHAIN_IS_MONO : BOOL : True if detected .NET toolchain is Mono
|
||||
# DOTNET_TOOLCHAIN_IS_WINDOWS : BOOL : True if detected .NET toolchain is native Windows
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_program(
|
||||
DOTNET_CSC_EXECUTABLE
|
||||
NAMES "csc.exe" "mcs" "dmcs"
|
||||
)
|
||||
message(STATUS "DOTNET_CSC_EXECUTABLE: \"${DOTNET_CSC_EXECUTABLE}\"")
|
||||
|
||||
find_program(
|
||||
DOTNET_GACUTIL_EXECUTABLE
|
||||
NAMES "gacutil.exe" "gacutil"
|
||||
)
|
||||
message(STATUS "DOTNET_GACUTIL_EXECUTABLE: \"${DOTNET_GACUTIL_EXECUTABLE}\"")
|
||||
|
||||
# Try to determine the tool chain vendor
|
||||
set(DOTNET_DETERMINED_VENDOR FALSE)
|
||||
if (DOTNET_CSC_EXECUTABLE)
|
||||
execute_process(COMMAND "${DOTNET_CSC_EXECUTABLE}" "/help"
|
||||
RESULT_VARIABLE CSC_EXIT_CODE
|
||||
OUTPUT_VARIABLE CSC_STD_OUT
|
||||
)
|
||||
if (${CSC_EXIT_CODE} EQUAL 0)
|
||||
if ("${CSC_STD_OUT}" MATCHES "^Mono[ ]+C#")
|
||||
set(DOTNET_DETERMINED_VENDOR TRUE)
|
||||
set(DOTNET_TOOLCHAIN_IS_MONO TRUE)
|
||||
set(DOTNET_TOOLCHAIN_IS_WINDOWS FALSE)
|
||||
message(STATUS ".NET toolchain is Mono")
|
||||
elseif ("${CSC_STD_OUT}" MATCHES "^Microsoft.+Visual[ ]+C#")
|
||||
set(DOTNET_DETERMINED_VENDOR TRUE)
|
||||
set(DOTNET_TOOLCHAIN_IS_MONO FALSE)
|
||||
set(DOTNET_TOOLCHAIN_IS_WINDOWS TRUE)
|
||||
message(STATUS ".NET toolchain is Windows native")
|
||||
else()
|
||||
message(STATUS ".NET toolchain is unknown")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# TODO: Check C# compiler works
|
||||
|
||||
find_package_handle_standard_args(DotNetToolChain DEFAULT_MSG
|
||||
DOTNET_CSC_EXECUTABLE
|
||||
DOTNET_GACUTIL_EXECUTABLE
|
||||
DOTNET_DETERMINED_VENDOR
|
||||
)
|
|
@ -104,7 +104,8 @@ macro(z3_add_component component_name)
|
|||
add_custom_command(OUTPUT "${_output_file}"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/pyg2hpp.py" "${_full_pyg_file_path}" "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
MAIN_DEPENDENCY "${_full_pyg_file_path}"
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/scripts/pyg2hpp.py" "${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/scripts/pyg2hpp.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
COMMENT "Generating \"${_full_output_file_path}\" from \"${pyg_file}\""
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
|
@ -203,7 +204,7 @@ macro(z3_add_install_tactic_rule)
|
|||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
${_search_paths}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_install_tactic_cpp.py"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
${_expanded_components}
|
||||
COMMENT "Generating \"${CMAKE_CURRENT_BINARY_DIR}/install_tactic.cpp\""
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
|
@ -235,7 +236,7 @@ macro(z3_add_memory_initializer_rule)
|
|||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
${_search_paths}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_mem_initializer_cpp.py"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
${_expanded_components}
|
||||
COMMENT "Generating \"${CMAKE_CURRENT_BINARY_DIR}/mem_initializer.cpp\""
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
|
@ -267,7 +268,7 @@ macro(z3_add_gparams_register_modules_rule)
|
|||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
${_search_paths}
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_gparams_register_modules_cpp.py"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
${_expanded_components}
|
||||
COMMENT "Generating \"${CMAKE_CURRENT_BINARY_DIR}/gparams_register_modules.cpp\""
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
|
|
|
@ -165,9 +165,9 @@ foreach (header ${libz3_public_headers})
|
|||
endforeach()
|
||||
|
||||
install(TARGETS libz3
|
||||
LIBRARY DESTINATION "${Z3_INSTALL_LIB_DIR}"
|
||||
ARCHIVE DESTINATION "${Z3_INSTALL_LIB_DIR}"
|
||||
PUBLIC_HEADER DESTINATION "${Z3_INSTALL_INCLUDE_DIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
|
@ -186,7 +186,7 @@ if (MSVC)
|
|||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
DEPENDS
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_def_file.py"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
COMMENT "Generating \"${dll_module_exports_file}\""
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
|
@ -222,4 +222,16 @@ if (BUILD_PYTHON_BINDINGS)
|
|||
add_subdirectory(api/python)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
# .NET bindings
|
||||
################################################################################
|
||||
option(BUILD_DOTNET_BINDINGS "Build .NET bindings for Z3" OFF)
|
||||
if (BUILD_DOTNET_BINDINGS)
|
||||
if (NOT BUILD_LIBZ3_SHARED)
|
||||
message(FATAL_ERROR "The .NET bindings will not work with a static libz3. "
|
||||
"You either need to disable BUILD_DOTNET_BINDINGS or enable BUILD_LIBZ3_SHARED")
|
||||
endif()
|
||||
add_subdirectory(api/dotnet)
|
||||
endif()
|
||||
|
||||
# TODO: Implement support for other bindigns
|
||||
|
|
|
@ -24,8 +24,10 @@ add_custom_command(OUTPUT ${generated_files}
|
|||
"--api_output_dir"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/scripts/update_api.py"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
# FIXME: When update_api.py no longer uses ``mk_util`` drop this dependency
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
COMMENT "Generating ${generated_files}"
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
VERBATIM
|
||||
|
|
276
contrib/cmake/src/api/dotnet/CMakeLists.txt
Normal file
276
contrib/cmake/src/api/dotnet/CMakeLists.txt
Normal file
|
@ -0,0 +1,276 @@
|
|||
find_package(DotNetToolchain REQUIRED)
|
||||
|
||||
# Configure AssemblyInfo.cs
|
||||
set(VER_MAJOR "${Z3_VERSION_MAJOR}")
|
||||
set(VER_MINOR "${Z3_VERSION_MINOR}")
|
||||
set(VER_BUILD "${Z3_VERSION_PATCH}")
|
||||
set(VER_REVISION "${Z3_VERSION_TWEAK}")
|
||||
set(Z3_DOTNET_ASSEMBLY_INFO_FILE "${CMAKE_CURRENT_BINARY_DIR}/Properties/AssemblyInfo.cs")
|
||||
configure_file("Properties/AssemblyInfo.cs.in" "${Z3_DOTNET_ASSEMBLY_INFO_FILE}" @ONLY)
|
||||
|
||||
# Generate Native.cs
|
||||
set(Z3_DOTNET_NATIVE_FILE "${CMAKE_CURRENT_BINARY_DIR}/Native.cs")
|
||||
add_custom_command(OUTPUT "${Z3_DOTNET_NATIVE_FILE}"
|
||||
COMMAND "${PYTHON_EXECUTABLE}"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/update_api.py"
|
||||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
"--dotnet-output-dir"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
DEPENDS
|
||||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
"${CMAKE_SOURCE_DIR}/scripts/update_api.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
# FIXME: When update_api.py no longer uses ``mk_util`` drop this dependency
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
COMMENT "Generating ${Z3_DOTNET_NATIVE_FILE}"
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
)
|
||||
|
||||
# Generate Enumerations.cs
|
||||
set(Z3_DOTNET_CONST_FILE "${CMAKE_CURRENT_BINARY_DIR}/Enumerations.cs")
|
||||
add_custom_command(OUTPUT "${Z3_DOTNET_CONST_FILE}"
|
||||
COMMAND "${PYTHON_EXECUTABLE}"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_consts_files.py"
|
||||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
"--dotnet-output-dir"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
DEPENDS
|
||||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_consts_files.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
COMMENT "Generating ${Z3_DOTNET_CONST_FILE}"
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
)
|
||||
|
||||
set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE
|
||||
AlgebraicNum.cs
|
||||
ApplyResult.cs
|
||||
ArithExpr.cs
|
||||
ArithSort.cs
|
||||
ArrayExpr.cs
|
||||
ArraySort.cs
|
||||
AST.cs
|
||||
ASTMap.cs
|
||||
ASTVector.cs
|
||||
BitVecExpr.cs
|
||||
BitVecNum.cs
|
||||
BitVecSort.cs
|
||||
BoolExpr.cs
|
||||
BoolSort.cs
|
||||
Constructor.cs
|
||||
ConstructorList.cs
|
||||
Context.cs
|
||||
DatatypeExpr.cs
|
||||
DatatypeSort.cs
|
||||
Deprecated.cs
|
||||
EnumSort.cs
|
||||
Expr.cs
|
||||
FiniteDomainExpr.cs
|
||||
FiniteDomainNum.cs
|
||||
FiniteDomainSort.cs
|
||||
Fixedpoint.cs
|
||||
FPExpr.cs
|
||||
FPNum.cs
|
||||
FPRMExpr.cs
|
||||
FPRMNum.cs
|
||||
FPRMSort.cs
|
||||
FPSort.cs
|
||||
FuncDecl.cs
|
||||
FuncInterp.cs
|
||||
Global.cs
|
||||
Goal.cs
|
||||
IDecRefQueue.cs
|
||||
InterpolationContext.cs
|
||||
IntExpr.cs
|
||||
IntNum.cs
|
||||
IntSort.cs
|
||||
IntSymbol.cs
|
||||
ListSort.cs
|
||||
Log.cs
|
||||
Model.cs
|
||||
Optimize.cs
|
||||
ParamDescrs.cs
|
||||
Params.cs
|
||||
Pattern.cs
|
||||
Probe.cs
|
||||
Quantifier.cs
|
||||
RatNum.cs
|
||||
RealExpr.cs
|
||||
RealSort.cs
|
||||
ReExpr.cs
|
||||
RelationSort.cs
|
||||
ReSort.cs
|
||||
SeqExpr.cs
|
||||
SeqSort.cs
|
||||
SetSort.cs
|
||||
Solver.cs
|
||||
Sort.cs
|
||||
Statistics.cs
|
||||
Status.cs
|
||||
StringSymbol.cs
|
||||
Symbol.cs
|
||||
Tactic.cs
|
||||
TupleSort.cs
|
||||
UninterpretedSort.cs
|
||||
Version.cs
|
||||
Z3Exception.cs
|
||||
Z3Object.cs
|
||||
)
|
||||
|
||||
set(Z3_DOTNET_ASSEMBLY_SOURCES "")
|
||||
# Make paths to source files absolute
|
||||
foreach (csfile ${Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE})
|
||||
list(APPEND Z3_DOTNET_ASSEMBLY_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${csfile}")
|
||||
endforeach()
|
||||
|
||||
# Add generated files
|
||||
list(APPEND Z3_DOTNET_ASSEMBLY_SOURCES
|
||||
"${Z3_DOTNET_CONST_FILE}"
|
||||
"${Z3_DOTNET_NATIVE_FILE}"
|
||||
"${Z3_DOTNET_ASSEMBLY_INFO_FILE}"
|
||||
)
|
||||
|
||||
# ``csc.exe`` doesn't like UNIX style paths so convert them
|
||||
# if necessary first to native paths.
|
||||
set(Z3_DOTNET_ASSEMBLY_SOURCES_NATIVE_PATH "")
|
||||
foreach (csfile_path ${Z3_DOTNET_ASSEMBLY_SOURCES})
|
||||
file(TO_NATIVE_PATH "${csfile_path}" csfile_path_native)
|
||||
list(APPEND Z3_DOTNET_ASSEMBLY_SOURCES_NATIVE_PATH "${csfile_path_native}")
|
||||
endforeach()
|
||||
|
||||
set(CSC_FLAGS "")
|
||||
if (DOTNET_TOOLCHAIN_IS_WINDOWS)
|
||||
# FIXME: Why use these flags?
|
||||
# Note these flags have been copied from the Python build system.
|
||||
list(APPEND CSC_FLAGS
|
||||
"/noconfig"
|
||||
"/nostdlib+"
|
||||
"/reference:mscorlib.dll"
|
||||
)
|
||||
# FIXME: This flag only works when the working directory of csc.exe is
|
||||
# the directory containing the ``libz3`` target. I can't get this to work
|
||||
# correctly with multi-configuration generators (i.e. Visual Studio) so
|
||||
# just don't set the flag for now.
|
||||
#list(APPEND CSC_FLAGS "/linkresource:$<TARGET_FILE_NAME:libz3>")
|
||||
elseif (DOTNET_TOOLCHAIN_IS_MONO)
|
||||
# We need to give the assembly a strong name so that it can be installed
|
||||
# into the GAC.
|
||||
list(APPEND CSC_FLAGS
|
||||
"/keyfile:${CMAKE_CURRENT_SOURCE_DIR}/Microsoft.Z3.mono.snk"
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown .NET toolchain")
|
||||
endif()
|
||||
|
||||
# Common flags
|
||||
list(APPEND CSC_FLAGS
|
||||
"/unsafe+"
|
||||
"/nowarn:1701,1702"
|
||||
"/errorreport:prompt"
|
||||
"/warn:4"
|
||||
"/reference:System.Core.dll"
|
||||
"/reference:System.dll"
|
||||
"/reference:System.Numerics.dll"
|
||||
"/filealign:512" # Why?
|
||||
"/target:library"
|
||||
)
|
||||
|
||||
# Set the build type flags. The build type for the assembly roughly corresponds
|
||||
# with the native code build type.
|
||||
list(APPEND CSC_FLAGS
|
||||
# Debug flags, expands to nothing if we aren't doing a debug build
|
||||
"$<$<CONFIG:Debug>:/debug+>"
|
||||
"$<$<CONFIG:Debug>:/debug:full>"
|
||||
"$<$<CONFIG:Debug>:/optimize->"
|
||||
# This has to be quoted otherwise the ``;`` is interpreted as a command separator
|
||||
"$<$<CONFIG:Debug>:\"/define:DEBUG$<SEMICOLON>TRACE\">"
|
||||
# Release flags, expands to nothing if we are doing a debug build
|
||||
"$<$<NOT:$<CONFIG:Debug>>:/optimize+>"
|
||||
)
|
||||
|
||||
# Mono's gacutil crashes when trying to install an assembly if we set the
|
||||
# platform in some cases, so only set it on Windows. This bug has been
|
||||
# reported at https://bugzilla.xamarin.com/show_bug.cgi?id=39955 . However mono
|
||||
# ignores the platform of an assembly when running it (
|
||||
# http://lists.ximian.com/pipermail/mono-devel-list/2015-November/043370.html )
|
||||
# so this shouldn't matter in practice.
|
||||
if (DOTNET_TOOLCHAIN_IS_WINDOWS)
|
||||
# Set platform for assembly
|
||||
if ("${TARGET_ARCHITECTURE}" STREQUAL "x86_64")
|
||||
list(APPEND CSC_FLAGS "/platform:x64")
|
||||
elseif ("${TARGET_ARCHITECTURE}" STREQUAL "i686")
|
||||
list(APPEND CSC_FLAGS "/platform:x86")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FIXME: The get_property() command only works correctly for single configuration generators
|
||||
# so we can't use it. We also can't use ``$<TARGET_FILE_DIR:libz3>`` because the ``OUTPUT``
|
||||
# argument to ``add_custom_commands()`` won't accept it. For now just output file to the
|
||||
# current binary directory.
|
||||
# get_property(Z3_DOTNET_ASSEMBLY_OUTPUT_DIR TARGET libz3 PROPERTY LIBRARY_OUTPUT_DIRECTORY)
|
||||
set(Z3_DOTNET_ASSEMBLY_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
set(Z3_DOTNET_ASSEMBLY_NAME "Microsoft.Z3.dll")
|
||||
set(Z3_DOTNET_ASSEMBLY_DLL "${Z3_DOTNET_ASSEMBLY_OUTPUT_DIR}/${Z3_DOTNET_ASSEMBLY_NAME}")
|
||||
# csc.exe doesn't work with UNIX style paths so convert to native path
|
||||
file(TO_NATIVE_PATH "${Z3_DOTNET_ASSEMBLY_DLL}" Z3_DOTNET_ASSEMBLY_DLL_NATIVE_PATH)
|
||||
set(Z3_DOTNET_ASSEMBLY_DLL_DOC "${Z3_DOTNET_ASSEMBLY_OUTPUT_DIR}/Microsoft.Z3.xml")
|
||||
file(TO_NATIVE_PATH "${Z3_DOTNET_ASSEMBLY_DLL_DOC}" Z3_DOTNET_ASSEMBLY_DLL_DOC_NATIVE_PATH)
|
||||
add_custom_command(OUTPUT "${Z3_DOTNET_ASSEMBLY_DLL}" "${Z3_DOTNET_ASSEMBLY_DLL_DOC}"
|
||||
COMMAND
|
||||
"${DOTNET_CSC_EXECUTABLE}"
|
||||
${CSC_FLAGS}
|
||||
"/out:${Z3_DOTNET_ASSEMBLY_DLL_NATIVE_PATH}"
|
||||
"/doc:${Z3_DOTNET_ASSEMBLY_DLL_DOC_NATIVE_PATH}"
|
||||
${Z3_DOTNET_ASSEMBLY_SOURCES_NATIVE_PATH}
|
||||
DEPENDS
|
||||
${Z3_DOTNET_ASSEMBLY_SOURCES}
|
||||
libz3
|
||||
WORKING_DIRECTORY "${Z3_DOTNET_ASSEMBLY_OUTPUT_DIR}"
|
||||
COMMENT "Building \"${Z3_DOTNET_ASSEMBLY_DLL}\""
|
||||
)
|
||||
|
||||
# Convenient top-level target
|
||||
add_custom_target(build_z3_dotnet_bindings
|
||||
ALL
|
||||
DEPENDS
|
||||
"${Z3_DOTNET_ASSEMBLY_DLL}"
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# Install
|
||||
###############################################################################
|
||||
option(INSTALL_DOTNET_BINDINGS "Install .NET bindings when invoking install target" ON)
|
||||
set(GAC_PKG_NAME "Microsoft.Z3.Sharp")
|
||||
set(PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||
set(VERSION "${Z3_VERSION}")
|
||||
set(Z3_DOTNET_PKGCONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/Microsoft.Z3.Sharp.pc")
|
||||
configure_file("Microsoft.Z3.Sharp.pc.in" "${Z3_DOTNET_PKGCONFIG_FILE}" @ONLY)
|
||||
|
||||
if (DOTNET_TOOLCHAIN_IS_MONO)
|
||||
message(STATUS "Emitting install rules for .NET bindings")
|
||||
# Install pkgconfig file for the assembly. This is needed by Monodevelop
|
||||
# to find the assembly
|
||||
install(FILES "${Z3_DOTNET_PKGCONFIG_FILE}" DESTINATION "${CMAKE_INSTALL_PKGCONFIGDIR}")
|
||||
|
||||
# Configure the install and uninstall scripts
|
||||
configure_file(cmake_install_gac.cmake.in cmake_install_gac.cmake @ONLY)
|
||||
configure_file(cmake_uninstall_gac.cmake.in cmake_uninstall_gac.cmake @ONLY)
|
||||
|
||||
# Tell CMake to Invoke a script to install assembly to the GAC during install
|
||||
install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/cmake_install_gac.cmake")
|
||||
|
||||
# Add custom target to uninstall the assembly from the GAC
|
||||
add_custom_target(remove_dotnet_dll_from_gac
|
||||
COMMAND "${CMAKE_COMMAND}" "-P" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall_gac.cmake"
|
||||
COMMENT "Uninstalling ${Z3_DOTNET_ASSEMBLY_NAME} from the GAC"
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
)
|
||||
add_dependencies(uninstall remove_dotnet_dll_from_gac)
|
||||
|
||||
elseif(DOTNET_TOOLCHAIN_IS_WINDOWS)
|
||||
# FIXME: This isn't implemented because I'm not sure how/if the assembly should
|
||||
# be installed to the GAC.
|
||||
message(WARNING "Install of .NET bindings is not implemented for Windows")
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown .NET toolchain")
|
||||
endif()
|
18
contrib/cmake/src/api/dotnet/cmake_install_gac.cmake.in
Normal file
18
contrib/cmake/src/api/dotnet/cmake_install_gac.cmake.in
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Install assembly to the GAC
|
||||
set(GAC_ROOT "$ENV{DESTDIR}@CMAKE_INSTALL_FULL_LIBDIR@")
|
||||
execute_process(COMMAND
|
||||
"@DOTNET_GACUTIL_EXECUTABLE@"
|
||||
"-i"
|
||||
"@Z3_DOTNET_ASSEMBLY_DLL@"
|
||||
"-f"
|
||||
"-package" "@GAC_PKG_NAME@"
|
||||
"-root" "${GAC_ROOT}"
|
||||
WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@"
|
||||
RESULT_VARIABLE gacutil_exit_code
|
||||
)
|
||||
|
||||
if ("${gacutil_exit_code}" EQUAL 0)
|
||||
message(STATUS "Installed \"@Z3_DOTNET_ASSEMBLY_DLL@\" to the GAC")
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to install \"@Z3_DOTNET_ASSEMBLY_DLL@\" to the GAC")
|
||||
endif()
|
20
contrib/cmake/src/api/dotnet/cmake_uninstall_gac.cmake.in
Normal file
20
contrib/cmake/src/api/dotnet/cmake_uninstall_gac.cmake.in
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Uninstall assembly from the GAC
|
||||
set(GAC_ROOT "$ENV{DESTDIR}@CMAKE_INSTALL_FULL_LIBDIR@")
|
||||
execute_process(COMMAND
|
||||
"@DOTNET_GACUTIL_EXECUTABLE@"
|
||||
# Note ``-us`` takes assembly file name rather than
|
||||
# ``-u`` which takes an assembly display name
|
||||
"-us"
|
||||
"@Z3_DOTNET_ASSEMBLY_NAME@"
|
||||
"-f"
|
||||
"-package" "@GAC_PKG_NAME@"
|
||||
"-root" "${GAC_ROOT}"
|
||||
WORKING_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@"
|
||||
RESULT_VARIABLE gacutil_exit_code
|
||||
)
|
||||
|
||||
if ("${gacutil_exit_code}" EQUAL 0)
|
||||
message(STATUS "Uninstalled \"@Z3_DOTNET_ASSEMBLY_NAME@\" from the GAC")
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to uninstall \"@Z3_DOTNET_ASSEMBLY_NAME@\" from the GAC")
|
||||
endif()
|
|
@ -38,6 +38,8 @@ add_custom_command(OUTPUT "${z3py_bindings_build_dest}/z3core.py"
|
|||
DEPENDS
|
||||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
"${CMAKE_SOURCE_DIR}/scripts/update_api.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
# FIXME: When update_api.py no longer uses ``mk_util`` drop this dependency
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
COMMENT "Generating z3core.py"
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
|
@ -54,7 +56,7 @@ add_custom_command(OUTPUT "${z3py_bindings_build_dest}/z3consts.py"
|
|||
DEPENDS
|
||||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_consts_files.py"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
COMMENT "Generating z3consts.py"
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
)
|
||||
|
@ -72,35 +74,50 @@ add_custom_target(build_z3_python_bindings
|
|||
###############################################################################
|
||||
option(INSTALL_PYTHON_BINDINGS "Install Python bindings when invoking install target" ON)
|
||||
if (INSTALL_PYTHON_BINDINGS)
|
||||
# Determine the installation path for the bindings
|
||||
message(STATUS "Emitting rules to install Z3 python bindings")
|
||||
execute_process(
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "-c"
|
||||
"import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())"
|
||||
RESULT_VARIABLE exit_code
|
||||
OUTPUT_VARIABLE python_pkg_dir
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
# Try to guess the installation path for the bindings
|
||||
if (NOT DEFINED CMAKE_INSTALL_PYTHON_PKG_DIR)
|
||||
message(STATUS "CMAKE_INSTALL_PYTHON_PKG_DIR not set. Trying to guess")
|
||||
execute_process(
|
||||
COMMAND "${PYTHON_EXECUTABLE}" "-c"
|
||||
"import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())"
|
||||
RESULT_VARIABLE exit_code
|
||||
OUTPUT_VARIABLE CMAKE_INSTALL_PYTHON_PKG_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if (NOT ("${exit_code}" EQUAL 0))
|
||||
message(FATAL_ERROR "Failed to determine your Python package directory")
|
||||
if (NOT ("${exit_code}" EQUAL 0))
|
||||
message(FATAL_ERROR "Failed to determine your Python package directory")
|
||||
endif()
|
||||
message(STATUS "Detected Python package directory: \"${CMAKE_INSTALL_PYTHON_PKG_DIR}\"")
|
||||
# Set a cache variable that the user can modify if needed
|
||||
set(CMAKE_INSTALL_PYTHON_PKG_DIR
|
||||
"${CMAKE_INSTALL_PYTHON_PKG_DIR}"
|
||||
CACHE PATH
|
||||
"Path to install python bindings. This can be relative or absolute.")
|
||||
mark_as_advanced(CMAKE_INSTALL_PYTHON_PKG_DIR)
|
||||
else()
|
||||
message(STATUS "CMAKE_INSTALL_PYTHON_PKG_DIR already set (\"${CMAKE_INSTALL_PYTHON_PKG_DIR}\")"
|
||||
". Not trying to guess.")
|
||||
endif()
|
||||
message(STATUS "Detected Python package directory: \"${python_pkg_dir}\"")
|
||||
|
||||
# Check if path exists under the install prefix
|
||||
set(python_install_dir "")
|
||||
string(FIND "${python_pkg_dir}" "${CMAKE_INSTALL_PREFIX}" position)
|
||||
if (NOT ("${position}" EQUAL 0))
|
||||
message(WARNING "The detected Python package directory \"${python_pkg_dir}\" "
|
||||
"does not exist under the install prefix \"${CMAKE_INSTALL_PREFIX}\"."
|
||||
" Running the install target may lead to a broken installation."
|
||||
)
|
||||
# Check if path exists under the install prefix if it is absolute. If the
|
||||
# path is relative it will be installed under the install prefix so there
|
||||
# if nothing to check
|
||||
if (IS_ABSOLUTE "${CMAKE_INSTALL_PYTHON_PKG_DIR}")
|
||||
string(FIND "${CMAKE_INSTALL_PYTHON_PKG_DIR}" "${CMAKE_INSTALL_PREFIX}" position)
|
||||
if (NOT ("${position}" EQUAL 0))
|
||||
message(WARNING "The directory to install the python bindings \"${CMAKE_INSTALL_PYTHON_PKG_DIR}\" "
|
||||
"is not under the install prefix \"${CMAKE_INSTALL_PREFIX}\"."
|
||||
" Running the install target may lead to a broken installation. "
|
||||
"To change the install directory modify the CMAKE_INSTALL_PYTHON_PKG_DIR cache variable."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
# Using DESTDIR still seems to work even if we use an absolute path
|
||||
set(python_install_dir "${python_pkg_dir}")
|
||||
message(STATUS "Python bindings will be installed to \"${python_install_dir}\"")
|
||||
message(STATUS "Python bindings will be installed to \"${CMAKE_INSTALL_PYTHON_PKG_DIR}\"")
|
||||
install(FILES ${build_z3_python_bindings_target_depends}
|
||||
DESTINATION "${python_install_dir}"
|
||||
DESTINATION "${CMAKE_INSTALL_PYTHON_PKG_DIR}"
|
||||
)
|
||||
else()
|
||||
message(STATUS "Not emitting rules to install Z3 python bindings")
|
||||
|
|
|
@ -13,7 +13,7 @@ add_custom_command(OUTPUT "database.h"
|
|||
"${CMAKE_CURRENT_BINARY_DIR}/database.h"
|
||||
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/database.smt2"
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/scripts/mk_pat_db.py"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/mk_util.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
COMMENT "Generating \"database.h\""
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
VERBATIM
|
||||
|
|
|
@ -12,6 +12,7 @@ z3_add_component(rewriter
|
|||
expr_safe_replace.cpp
|
||||
factor_rewriter.cpp
|
||||
fpa_rewriter.cpp
|
||||
label_rewriter.cpp
|
||||
mk_simplified_app.cpp
|
||||
pb_rewriter.cpp
|
||||
quant_hoist.cpp
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
z3_add_component(qe
|
||||
SOURCES
|
||||
nlarith_util.cpp
|
||||
nlqsat.cpp
|
||||
qe_arith.cpp
|
||||
qe_arith_plugin.cpp
|
||||
qe_array_plugin.cpp
|
||||
qe_arrays.cpp
|
||||
qe_bool_plugin.cpp
|
||||
qe_bv_plugin.cpp
|
||||
qe_cmd.cpp
|
||||
qe.cpp
|
||||
qe_datatype_plugin.cpp
|
||||
qe_datatypes.cpp
|
||||
qe_dl_plugin.cpp
|
||||
qe_lite.cpp
|
||||
qe_mbp.cpp
|
||||
qe_sat_tactic.cpp
|
||||
qe_tactic.cpp
|
||||
qe_util.cpp
|
||||
qsat.cpp
|
||||
vsubst_tactic.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
nlsat_tactic
|
||||
nlsat
|
||||
sat
|
||||
smt
|
||||
smt
|
||||
tactic
|
||||
)
|
||||
|
|
|
@ -43,5 +43,5 @@ target_link_libraries(shell PRIVATE ${Z3_DEPENDENT_LIBS})
|
|||
z3_add_component_dependencies_to_target(shell ${shell_expanded_deps})
|
||||
z3_append_linker_flag_list_to_target(shell ${Z3_DEPENDENT_EXTRA_CXX_LINK_FLAGS})
|
||||
install(TARGETS shell
|
||||
RUNTIME DESTINATION "${Z3_INSTALL_BIN_DIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
)
|
||||
|
|
|
@ -18,6 +18,7 @@ z3_add_component(core_tactics
|
|||
split_clause_tactic.cpp
|
||||
symmetry_reduce_tactic.cpp
|
||||
tseitin_cnf_tactic.cpp
|
||||
collect_occs.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
normal_forms
|
||||
tactic
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
API documentation
|
||||
-----------------
|
||||
|
||||
To generate the API documentation for the C, .NET and Python APIs, we must execute
|
||||
To generate the API documentation for the C, C++, .NET, Java and Python APIs, we must execute
|
||||
|
||||
python mk_api_doc.py
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Small example using the c++ bindings.
|
||||
Small example using the C bindings.
|
||||
To build the example execute
|
||||
make examples
|
||||
in the build directory.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Small example using the c++ bindings.
|
||||
Small example using the C bindings.
|
||||
To build the example execute
|
||||
make examples
|
||||
in the build directory.
|
||||
|
|
|
@ -4,44 +4,48 @@ Reads a list of Z3 API header files and
|
|||
generate the constant declarations need
|
||||
by one or more Z3 language bindings
|
||||
"""
|
||||
import mk_util
|
||||
import mk_genfile_common
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
def check_dir(output_dir):
|
||||
if not os.path.isdir(output_dir):
|
||||
logging.error('"{}" is not an existing directory'.format(output_dir))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def main(args):
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("api_files", nargs="+")
|
||||
parser.add_argument("--z3py-output-dir", dest="z3py_output_dir", default=None)
|
||||
pargs = parser.parse_args(args)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("api_files", nargs="+")
|
||||
parser.add_argument("--z3py-output-dir", dest="z3py_output_dir", default=None)
|
||||
parser.add_argument("--dotnet-output-dir", dest="dotnet_output_dir", default=None)
|
||||
pargs = parser.parse_args(args)
|
||||
|
||||
for api_file in pargs.api_files:
|
||||
if not os.path.exists(api_file):
|
||||
logging.error('"{}" does not exist'.format(api_file))
|
||||
return 1
|
||||
if not mk_genfile_common.check_files_exist(pargs.api_files):
|
||||
logging.error('One or more API files do not exist')
|
||||
return 1
|
||||
|
||||
count = 0
|
||||
count = 0
|
||||
|
||||
if pargs.z3py_output_dir:
|
||||
if check_dir(pargs.z3py_output_dir) != 0:
|
||||
return 1
|
||||
mk_util.mk_z3consts_py_internal(pargs.api_files, pargs.z3py_output_dir)
|
||||
count += 1
|
||||
if pargs.z3py_output_dir:
|
||||
if not mk_genfile_common.check_dir_exists(pargs.z3py_output_dir):
|
||||
return 1
|
||||
output = mk_genfile_common.mk_z3consts_py_internal(pargs.api_files, pargs.z3py_output_dir)
|
||||
logging.info('Generated "{}"'.format(output))
|
||||
count += 1
|
||||
|
||||
if count == 0:
|
||||
logging.info('No files generated. You need to specific an output directory'
|
||||
' for the relevant langauge bindings')
|
||||
# TODO: Add support for other bindings
|
||||
return 0
|
||||
if pargs.dotnet_output_dir:
|
||||
if not mk_genfile_common.check_dir_exists(pargs.dotnet_output_dir):
|
||||
return 1
|
||||
output = mk_genfile_common.mk_z3consts_dotnet_internal(
|
||||
pargs.api_files,
|
||||
pargs.dotnet_output_dir)
|
||||
logging.info('Generated "{}"'.format(output))
|
||||
count += 1
|
||||
|
||||
if count == 0:
|
||||
logging.info('No files generated. You need to specific an output directory'
|
||||
' for the relevant langauge bindings')
|
||||
# TODO: Add support for other bindings
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
|
|
@ -6,31 +6,31 @@ exported symbols of a dll. This file
|
|||
can be passed to the ``/DEF`` to the
|
||||
linker used by MSVC.
|
||||
"""
|
||||
import mk_util
|
||||
import mk_genfile_common
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
def main(args):
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("output_file", help="output def file path")
|
||||
parser.add_argument("dllname", help="dllname to use in def file")
|
||||
parser.add_argument("api_files", nargs="+")
|
||||
pargs = parser.parse_args(args)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("output_file", help="output def file path")
|
||||
parser.add_argument("dllname", help="dllname to use in def file")
|
||||
parser.add_argument("api_files", nargs="+")
|
||||
pargs = parser.parse_args(args)
|
||||
|
||||
for api_file in pargs.api_files:
|
||||
if not os.path.exists(api_file):
|
||||
logging.error('"{}" does not exist'.format(api_file))
|
||||
return 1
|
||||
if not mk_genfile_common.check_files_exist(pargs.api_files):
|
||||
logging.error('One or more api files do not exist')
|
||||
return 1
|
||||
|
||||
mk_util.mk_def_file_internal(
|
||||
pargs.output_file,
|
||||
pargs.dllname,
|
||||
pargs.api_files)
|
||||
return 0
|
||||
mk_genfile_common.mk_def_file_internal(
|
||||
pargs.output_file,
|
||||
pargs.dllname,
|
||||
pargs.api_files)
|
||||
logging.info('Generated "{}"'.format(pargs.output_file))
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
|
|
655
scripts/mk_genfile_common.py
Normal file
655
scripts/mk_genfile_common.py
Normal file
|
@ -0,0 +1,655 @@
|
|||
# This file contains code that is common to
|
||||
# both the Python build system and the CMake
|
||||
# build system.
|
||||
#
|
||||
# The code here generally is involved in
|
||||
# generating files needed by Z3 at build time.
|
||||
#
|
||||
# You should **not** import ``mk_util`` here
|
||||
# to avoid having this code depend on the
|
||||
# of the Python build system.
|
||||
import os
|
||||
import pprint
|
||||
import logging
|
||||
import re
|
||||
import sys
|
||||
|
||||
# Logger for this module
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Utility functions
|
||||
###############################################################################
|
||||
def check_dir_exists(output_dir):
|
||||
"""
|
||||
Returns ``True`` if ``output_dir`` exists, otherwise
|
||||
returns ``False``.
|
||||
"""
|
||||
if not os.path.isdir(output_dir):
|
||||
_logger.error('"{}" is not an existing directory'.format(output_dir))
|
||||
return False
|
||||
return True
|
||||
|
||||
def check_files_exist(files):
|
||||
assert isinstance(files, list)
|
||||
for f in files:
|
||||
if not os.path.exists(f):
|
||||
_logger.error('"{}" does not exist'.format(f))
|
||||
return False
|
||||
return True
|
||||
|
||||
def sorted_headers_by_component(l):
|
||||
"""
|
||||
Take a list of header files and sort them by the
|
||||
path after ``src/``. E.g. for ``src/ast/fpa/fpa2bv_converter.h`` the sorting
|
||||
key is ``ast/fpa/fpa2bv_converter.h``.
|
||||
|
||||
The sort is done this way because for the CMake build
|
||||
there are two directories for every component (e.g.
|
||||
``<src_dir>/src/ast/fpa`` and ``<build_dir>/src/ast/fpa``).
|
||||
We don't want to sort based on different ``<src_dir>``
|
||||
and ``<build_dir>`` prefixes so that we can match the Python build
|
||||
system's behaviour.
|
||||
"""
|
||||
assert isinstance(l, list)
|
||||
def get_key(path):
|
||||
_logger.debug("get_key({})".format(path))
|
||||
path_components = []
|
||||
stripped_path = path
|
||||
assert 'src' in stripped_path.split(os.path.sep) or 'src' in stripped_path.split('/')
|
||||
# Keep stripping off directory components until we hit ``src``
|
||||
while os.path.basename(stripped_path) != 'src':
|
||||
path_components.append(os.path.basename(stripped_path))
|
||||
stripped_path = os.path.dirname(stripped_path)
|
||||
assert len(path_components) > 0
|
||||
path_components.reverse()
|
||||
# For consistency across platforms use ``/`` rather than ``os.sep``.
|
||||
# This is a sorting key so it doesn't need to a platform suitable
|
||||
# path
|
||||
r = '/'.join(path_components)
|
||||
_logger.debug("return key:'{}'".format(r))
|
||||
return r
|
||||
sorted_headers = sorted(l, key=get_key)
|
||||
_logger.debug('sorted headers:{}'.format(pprint.pformat(sorted_headers)))
|
||||
return sorted_headers
|
||||
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Functions for generating constant declarations for language bindings
|
||||
###############################################################################
|
||||
|
||||
def mk_z3consts_py_internal(api_files, output_dir):
|
||||
"""
|
||||
Generate ``z3consts.py`` from the list of API header files
|
||||
in ``api_files`` and write the output file into
|
||||
the ``output_dir`` directory
|
||||
|
||||
Returns the path to the generated file.
|
||||
"""
|
||||
assert os.path.isdir(output_dir)
|
||||
assert isinstance(api_files, list)
|
||||
|
||||
blank_pat = re.compile("^ *\r?$")
|
||||
comment_pat = re.compile("^ *//.*$")
|
||||
typedef_pat = re.compile("typedef enum *")
|
||||
typedef2_pat = re.compile("typedef enum { *")
|
||||
openbrace_pat = re.compile("{ *")
|
||||
closebrace_pat = re.compile("}.*;")
|
||||
|
||||
z3consts = open(os.path.join(output_dir, 'z3consts.py'), 'w')
|
||||
z3consts_output_path = z3consts.name
|
||||
z3consts.write('# Automatically generated file\n\n')
|
||||
for api_file in api_files:
|
||||
api = open(api_file, 'r')
|
||||
|
||||
SEARCHING = 0
|
||||
FOUND_ENUM = 1
|
||||
IN_ENUM = 2
|
||||
|
||||
mode = SEARCHING
|
||||
decls = {}
|
||||
idx = 0
|
||||
|
||||
linenum = 1
|
||||
for line in api:
|
||||
m1 = blank_pat.match(line)
|
||||
m2 = comment_pat.match(line)
|
||||
if m1 or m2:
|
||||
# skip blank lines and comments
|
||||
linenum = linenum + 1
|
||||
elif mode == SEARCHING:
|
||||
m = typedef_pat.match(line)
|
||||
if m:
|
||||
mode = FOUND_ENUM
|
||||
m = typedef2_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
elif mode == FOUND_ENUM:
|
||||
m = openbrace_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
else:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
z3consts.write('# enum %s\n' % name)
|
||||
# Iterate over key-value pairs ordered by value
|
||||
for k, v in sorted(decls.items(), key=lambda pair: pair[1]):
|
||||
z3consts.write('%s = %s\n' % (k, v))
|
||||
z3consts.write('\n')
|
||||
mode = SEARCHING
|
||||
elif len(words) <= 2:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
if words[2] != '':
|
||||
if len(words[2]) > 1 and words[2][1] == 'x':
|
||||
idx = int(words[2], 16)
|
||||
else:
|
||||
idx = int(words[2])
|
||||
decls[words[1]] = idx
|
||||
idx = idx + 1
|
||||
linenum = linenum + 1
|
||||
api.close()
|
||||
z3consts.close()
|
||||
return z3consts_output_path
|
||||
|
||||
def mk_z3consts_dotnet_internal(api_files, output_dir):
|
||||
"""
|
||||
Generate ``Enumerations.cs`` from the list of API header files
|
||||
in ``api_files`` and write the output file into
|
||||
the ``output_dir`` directory
|
||||
|
||||
Returns the path to the generated file.
|
||||
"""
|
||||
assert os.path.isdir(output_dir)
|
||||
assert isinstance(api_files, list)
|
||||
blank_pat = re.compile("^ *\r?$")
|
||||
comment_pat = re.compile("^ *//.*$")
|
||||
typedef_pat = re.compile("typedef enum *")
|
||||
typedef2_pat = re.compile("typedef enum { *")
|
||||
openbrace_pat = re.compile("{ *")
|
||||
closebrace_pat = re.compile("}.*;")
|
||||
|
||||
DeprecatedEnums = [ 'Z3_search_failure' ]
|
||||
z3consts = open(os.path.join(output_dir, 'Enumerations.cs'), 'w')
|
||||
z3consts_output_path = z3consts.name
|
||||
z3consts.write('// Automatically generated file\n\n')
|
||||
z3consts.write('using System;\n\n'
|
||||
'#pragma warning disable 1591\n\n'
|
||||
'namespace Microsoft.Z3\n'
|
||||
'{\n')
|
||||
|
||||
for api_file in api_files:
|
||||
api = open(api_file, 'r')
|
||||
|
||||
SEARCHING = 0
|
||||
FOUND_ENUM = 1
|
||||
IN_ENUM = 2
|
||||
|
||||
mode = SEARCHING
|
||||
decls = {}
|
||||
idx = 0
|
||||
|
||||
linenum = 1
|
||||
for line in api:
|
||||
m1 = blank_pat.match(line)
|
||||
m2 = comment_pat.match(line)
|
||||
if m1 or m2:
|
||||
# skip blank lines and comments
|
||||
linenum = linenum + 1
|
||||
elif mode == SEARCHING:
|
||||
m = typedef_pat.match(line)
|
||||
if m:
|
||||
mode = FOUND_ENUM
|
||||
m = typedef2_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
elif mode == FOUND_ENUM:
|
||||
m = openbrace_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
else:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
if name not in DeprecatedEnums:
|
||||
z3consts.write(' /// <summary>%s</summary>\n' % name)
|
||||
z3consts.write(' public enum %s {\n' % name)
|
||||
z3consts.write
|
||||
# Iterate over key-value pairs ordered by value
|
||||
for k, v in sorted(decls.items(), key=lambda pair: pair[1]):
|
||||
z3consts.write(' %s = %s,\n' % (k, v))
|
||||
z3consts.write(' }\n\n')
|
||||
mode = SEARCHING
|
||||
elif len(words) <= 2:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
if words[2] != '':
|
||||
if len(words[2]) > 1 and words[2][1] == 'x':
|
||||
idx = int(words[2], 16)
|
||||
else:
|
||||
idx = int(words[2])
|
||||
decls[words[1]] = idx
|
||||
idx = idx + 1
|
||||
linenum = linenum + 1
|
||||
api.close()
|
||||
z3consts.write('}\n');
|
||||
z3consts.close()
|
||||
return z3consts_output_path
|
||||
|
||||
###############################################################################
|
||||
# Functions for generating a "module definition file" for MSVC
|
||||
###############################################################################
|
||||
|
||||
def mk_def_file_internal(defname, dll_name, export_header_files):
|
||||
"""
|
||||
Writes to a module definition file to a file named ``defname``.
|
||||
|
||||
``dll_name`` is the name of the dll (without the ``.dll`` suffix).
|
||||
``export_header_file`` is a list of header files to scan for symbols
|
||||
to include in the module definition file.
|
||||
"""
|
||||
assert isinstance(export_header_files, list)
|
||||
pat1 = re.compile(".*Z3_API.*")
|
||||
fout = open(defname, 'w')
|
||||
fout.write('LIBRARY "%s"\nEXPORTS\n' % dll_name)
|
||||
num = 1
|
||||
for export_header_file in export_header_files:
|
||||
api = open(export_header_file, 'r')
|
||||
for line in api:
|
||||
m = pat1.match(line)
|
||||
if m:
|
||||
words = re.split('\W+', line)
|
||||
i = 0
|
||||
for w in words:
|
||||
if w == 'Z3_API':
|
||||
f = words[i+1]
|
||||
fout.write('\t%s @%s\n' % (f, num))
|
||||
i = i + 1
|
||||
num = num + 1
|
||||
api.close()
|
||||
fout.close()
|
||||
|
||||
###############################################################################
|
||||
# Functions for generating ``gparams_register_modules.cpp``
|
||||
###############################################################################
|
||||
def mk_gparams_register_modules_internal(component_src_dirs, path):
|
||||
"""
|
||||
Generate a ``gparams_register_modules.cpp`` file in the directory ``path``.
|
||||
Returns the path to the generated file.
|
||||
|
||||
This file implements the procedure
|
||||
|
||||
```
|
||||
void gparams_register_modules()
|
||||
```
|
||||
|
||||
This procedure is invoked by gparams::init()
|
||||
"""
|
||||
assert isinstance(component_src_dirs, list)
|
||||
assert check_dir_exists(path)
|
||||
cmds = []
|
||||
mod_cmds = []
|
||||
mod_descrs = []
|
||||
fullname = os.path.join(path, 'gparams_register_modules.cpp')
|
||||
fout = open(fullname, 'w')
|
||||
fout.write('// Automatically generated file.\n')
|
||||
fout.write('#include"gparams.h"\n')
|
||||
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:
|
||||
for line in fin:
|
||||
m = reg_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % os.path.basename(h_file))
|
||||
cmds.append((m.group(1)))
|
||||
m = reg_mod_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % os.path.basename(h_file))
|
||||
mod_cmds.append((m.group(1), m.group(2)))
|
||||
m = reg_mod_descr_pat.match(line)
|
||||
if m:
|
||||
mod_descrs.append((m.group(1), m.group(2)))
|
||||
fout.write('void gparams_register_modules() {\n')
|
||||
for code in cmds:
|
||||
fout.write('{ param_descrs d; %s(d); gparams::register_global(d); }\n' % code)
|
||||
for (mod, code) in mod_cmds:
|
||||
fout.write('{ param_descrs * d = alloc(param_descrs); %s(*d); gparams::register_module("%s", d); }\n' % (code, mod))
|
||||
for (mod, descr) in mod_descrs:
|
||||
fout.write('gparams::register_module_descr("%s", "%s");\n' % (mod, descr))
|
||||
fout.write('}\n')
|
||||
fout.close()
|
||||
return fullname
|
||||
|
||||
###############################################################################
|
||||
# Functions/data structures for generating ``install_tactics.cpp``
|
||||
###############################################################################
|
||||
|
||||
def mk_install_tactic_cpp_internal(component_src_dirs, path):
|
||||
"""
|
||||
Generate a ``install_tactics.cpp`` file in the directory ``path``.
|
||||
Returns the path the generated file.
|
||||
|
||||
This file implements the procedure
|
||||
|
||||
```
|
||||
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.
|
||||
"""
|
||||
ADD_TACTIC_DATA = []
|
||||
ADD_PROBE_DATA = []
|
||||
def ADD_TACTIC(name, descr, cmd):
|
||||
ADD_TACTIC_DATA.append((name, descr, cmd))
|
||||
|
||||
def ADD_PROBE(name, descr, cmd):
|
||||
ADD_PROBE_DATA.append((name, descr, cmd))
|
||||
|
||||
eval_globals = {
|
||||
'ADD_TACTIC': ADD_TACTIC,
|
||||
'ADD_PROBE': ADD_PROBE,
|
||||
}
|
||||
|
||||
assert isinstance(component_src_dirs, list)
|
||||
assert check_dir_exists(path)
|
||||
fullname = os.path.join(path, 'install_tactic.cpp')
|
||||
fout = open(fullname, 'w')
|
||||
fout.write('// Automatically generated file.\n')
|
||||
fout.write('#include"tactic.h"\n')
|
||||
fout.write('#include"tactic_cmds.h"\n')
|
||||
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:
|
||||
for line in fin:
|
||||
if tactic_pat.match(line):
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % os.path.basename(h_file))
|
||||
try:
|
||||
eval(line.strip('\n '), eval_globals, None)
|
||||
except Exception as e:
|
||||
_logger.error("Failed processing ADD_TACTIC command at '{}'\n{}".format(
|
||||
fullname, line))
|
||||
raise e
|
||||
if probe_pat.match(line):
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % os.path.basename(h_file))
|
||||
try:
|
||||
eval(line.strip('\n '), eval_globals, None)
|
||||
except Exception as e:
|
||||
_logger.error("Failed processing ADD_PROBE command at '{}'\n{}".format(
|
||||
fullname, line))
|
||||
raise e
|
||||
# First pass will just generate the tactic factories
|
||||
idx = 0
|
||||
for data in ADD_TACTIC_DATA:
|
||||
fout.write('MK_SIMPLE_TACTIC_FACTORY(__Z3_local_factory_%s, %s);\n' % (idx, data[2]))
|
||||
idx = idx + 1
|
||||
fout.write('#define ADD_TACTIC_CMD(NAME, DESCR, FACTORY) ctx.insert(alloc(tactic_cmd, symbol(NAME), DESCR, alloc(FACTORY)))\n')
|
||||
fout.write('#define ADD_PROBE(NAME, DESCR, PROBE) ctx.insert(alloc(probe_info, symbol(NAME), DESCR, PROBE))\n')
|
||||
fout.write('void install_tactics(tactic_manager & ctx) {\n')
|
||||
idx = 0
|
||||
for data in ADD_TACTIC_DATA:
|
||||
fout.write(' ADD_TACTIC_CMD("%s", "%s", __Z3_local_factory_%s);\n' % (data[0], data[1], idx))
|
||||
idx = idx + 1
|
||||
for data in ADD_PROBE_DATA:
|
||||
fout.write(' ADD_PROBE("%s", "%s", %s);\n' % data)
|
||||
fout.write('}\n')
|
||||
fout.close()
|
||||
return fullname
|
||||
|
||||
###############################################################################
|
||||
# Functions for generating ``mem_initializer.cpp``
|
||||
###############################################################################
|
||||
|
||||
def mk_mem_initializer_cpp_internal(component_src_dirs, path):
|
||||
"""
|
||||
Generate a ``mem_initializer.cpp`` file in the directory ``path``.
|
||||
Returns the path to the generated file.
|
||||
|
||||
This file implements the procedures
|
||||
|
||||
```
|
||||
void mem_initialize()
|
||||
void mem_finalize()
|
||||
```
|
||||
|
||||
These procedures are invoked by the Z3 memory_manager
|
||||
"""
|
||||
assert isinstance(component_src_dirs, list)
|
||||
assert check_dir_exists(path)
|
||||
initializer_cmds = []
|
||||
finalizer_cmds = []
|
||||
fullname = os.path.join(path, 'mem_initializer.cpp')
|
||||
fout = open(fullname, 'w')
|
||||
fout.write('// Automatically generated file.\n')
|
||||
initializer_pat = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\'\)')
|
||||
# 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:
|
||||
for line in fin:
|
||||
m = initializer_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % os.path.basename(h_file))
|
||||
initializer_cmds.append((m.group(1), 0))
|
||||
m = initializer_prio_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % os.path.basename(h_file))
|
||||
initializer_cmds.append((m.group(1), int(m.group(2))))
|
||||
m = finalizer_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % os.path.basename(h_file))
|
||||
finalizer_cmds.append(m.group(1))
|
||||
initializer_cmds.sort(key=lambda tup: tup[1])
|
||||
fout.write('void mem_initialize() {\n')
|
||||
for (cmd, prio) in initializer_cmds:
|
||||
fout.write(cmd)
|
||||
fout.write('\n')
|
||||
fout.write('}\n')
|
||||
fout.write('void mem_finalize() {\n')
|
||||
for cmd in finalizer_cmds:
|
||||
fout.write(cmd)
|
||||
fout.write('\n')
|
||||
fout.write('}\n')
|
||||
fout.close()
|
||||
return fullname
|
||||
|
||||
###############################################################################
|
||||
# Functions for generating ``database.h``
|
||||
###############################################################################
|
||||
|
||||
def mk_pat_db_internal(inputFilePath, outputFilePath):
|
||||
"""
|
||||
Generate ``g_pattern_database[]`` declaration header file.
|
||||
"""
|
||||
with open(inputFilePath, 'r') as fin:
|
||||
with open(outputFilePath, 'w') as fout:
|
||||
fout.write('static char const g_pattern_database[] =\n')
|
||||
for line in fin:
|
||||
fout.write('"%s\\n"\n' % line.strip('\n'))
|
||||
fout.write(';\n')
|
||||
|
||||
###############################################################################
|
||||
# Functions and data structures for generating ``*_params.hpp`` files from
|
||||
# ``*.pyg`` files
|
||||
###############################################################################
|
||||
|
||||
UINT = 0
|
||||
BOOL = 1
|
||||
DOUBLE = 2
|
||||
STRING = 3
|
||||
SYMBOL = 4
|
||||
UINT_MAX = 4294967295
|
||||
|
||||
TYPE2CPK = { UINT : 'CPK_UINT', BOOL : 'CPK_BOOL', DOUBLE : 'CPK_DOUBLE', STRING : 'CPK_STRING', SYMBOL : 'CPK_SYMBOL' }
|
||||
TYPE2CTYPE = { UINT : 'unsigned', BOOL : 'bool', DOUBLE : 'double', STRING : 'char const *', SYMBOL : 'symbol' }
|
||||
TYPE2GETTER = { UINT : 'get_uint', BOOL : 'get_bool', DOUBLE : 'get_double', STRING : 'get_str', SYMBOL : 'get_sym' }
|
||||
|
||||
def pyg_default(p):
|
||||
if p[1] == BOOL:
|
||||
if p[2]:
|
||||
return "true"
|
||||
else:
|
||||
return "false"
|
||||
return p[2]
|
||||
|
||||
def pyg_default_as_c_literal(p):
|
||||
if p[1] == BOOL:
|
||||
if p[2]:
|
||||
return "true"
|
||||
else:
|
||||
return "false"
|
||||
elif p[1] == STRING:
|
||||
return '"%s"' % p[2]
|
||||
elif p[1] == SYMBOL:
|
||||
return 'symbol("%s")' % p[2]
|
||||
elif p[1] == UINT:
|
||||
return '%su' % p[2]
|
||||
else:
|
||||
return p[2]
|
||||
|
||||
def to_c_method(s):
|
||||
return s.replace('.', '_')
|
||||
|
||||
|
||||
def max_memory_param():
|
||||
return ('max_memory', UINT, UINT_MAX, 'maximum amount of memory in megabytes')
|
||||
|
||||
def max_steps_param():
|
||||
return ('max_steps', UINT, UINT_MAX, 'maximum number of steps')
|
||||
|
||||
def mk_hpp_from_pyg(pyg_file, output_dir):
|
||||
"""
|
||||
Generates the corresponding header file for the input pyg file
|
||||
at the path ``pyg_file``. The file is emitted into the directory
|
||||
``output_dir``.
|
||||
|
||||
Returns the path to the generated file
|
||||
"""
|
||||
CURRENT_PYG_HPP_DEST_DIR = output_dir
|
||||
# Note OUTPUT_HPP_FILE cannot be a string as we need a mutable variable
|
||||
# for the nested function to modify
|
||||
OUTPUT_HPP_FILE = [ ]
|
||||
# The function below has been nested so that it can use closure to capture
|
||||
# the above variables that aren't global but instead local to this
|
||||
# function. This avoids use of global state which makes this function safer.
|
||||
def def_module_params(module_name, export, params, class_name=None, description=None):
|
||||
dirname = CURRENT_PYG_HPP_DEST_DIR
|
||||
assert(os.path.exists(dirname))
|
||||
if class_name is None:
|
||||
class_name = '%s_params' % module_name
|
||||
hpp = os.path.join(dirname, '%s.hpp' % class_name)
|
||||
out = open(hpp, 'w')
|
||||
out.write('// Automatically generated file\n')
|
||||
out.write('#ifndef __%s_HPP_\n' % class_name.upper())
|
||||
out.write('#define __%s_HPP_\n' % class_name.upper())
|
||||
out.write('#include"params.h"\n')
|
||||
if export:
|
||||
out.write('#include"gparams.h"\n')
|
||||
out.write('struct %s {\n' % class_name)
|
||||
out.write(' params_ref const & p;\n')
|
||||
if export:
|
||||
out.write(' params_ref g;\n')
|
||||
out.write(' %s(params_ref const & _p = params_ref::get_empty()):\n' % class_name)
|
||||
out.write(' p(_p)')
|
||||
if export:
|
||||
out.write(', g(gparams::get_module("%s"))' % module_name)
|
||||
out.write(' {}\n')
|
||||
out.write(' static void collect_param_descrs(param_descrs & d) {\n')
|
||||
for param in params:
|
||||
out.write(' d.insert("%s", %s, "%s", "%s","%s");\n' % (param[0], TYPE2CPK[param[1]], param[3], pyg_default(param), module_name))
|
||||
out.write(' }\n')
|
||||
if export:
|
||||
out.write(' /*\n')
|
||||
out.write(" REG_MODULE_PARAMS('%s', '%s::collect_param_descrs')\n" % (module_name, class_name))
|
||||
if description is not None:
|
||||
out.write(" REG_MODULE_DESCRIPTION('%s', '%s')\n" % (module_name, description))
|
||||
out.write(' */\n')
|
||||
# Generated accessors
|
||||
for param in params:
|
||||
if export:
|
||||
out.write(' %s %s() const { return p.%s("%s", g, %s); }\n' %
|
||||
(TYPE2CTYPE[param[1]], to_c_method(param[0]), TYPE2GETTER[param[1]], param[0], pyg_default_as_c_literal(param)))
|
||||
else:
|
||||
out.write(' %s %s() const { return p.%s("%s", %s); }\n' %
|
||||
(TYPE2CTYPE[param[1]], to_c_method(param[0]), TYPE2GETTER[param[1]], param[0], pyg_default_as_c_literal(param)))
|
||||
out.write('};\n')
|
||||
out.write('#endif\n')
|
||||
out.close()
|
||||
OUTPUT_HPP_FILE.append(hpp)
|
||||
|
||||
# Globals to use when executing the ``.pyg`` file.
|
||||
pyg_globals = {
|
||||
'UINT' : UINT,
|
||||
'BOOL' : BOOL,
|
||||
'DOUBLE' : DOUBLE,
|
||||
'STRING' : STRING,
|
||||
'SYMBOL' : SYMBOL,
|
||||
'UINT_MAX' : UINT_MAX,
|
||||
'max_memory_param' : max_memory_param,
|
||||
'max_steps_param' : max_steps_param,
|
||||
# Note that once this function is enterred that function
|
||||
# executes with respect to the globals of this module and
|
||||
# not the globals defined here
|
||||
'def_module_params' : def_module_params,
|
||||
}
|
||||
with open(pyg_file, 'r') as fh:
|
||||
eval(fh.read() + "\n", pyg_globals, None)
|
||||
assert len(OUTPUT_HPP_FILE) == 1
|
||||
return OUTPUT_HPP_FILE[0]
|
|
@ -6,42 +6,34 @@ and generates a ``gparams_register_modules.cpp`` file in
|
|||
the destination directory that defines a function
|
||||
``void gparams_register_modules()``.
|
||||
"""
|
||||
import mk_util
|
||||
import mk_genfile_common
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
def check_dir(path):
|
||||
if not os.path.exists(path):
|
||||
logging.error('"{}" does not exist'.format(path))
|
||||
return 1
|
||||
|
||||
if not os.path.isdir(path):
|
||||
logging.error('"{}" is not a directory'.format(path))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
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")
|
||||
pargs = parser.parse_args(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")
|
||||
pargs = parser.parse_args(args)
|
||||
|
||||
if check_dir(pargs.destination_dir) != 0:
|
||||
return 1
|
||||
if not mk_genfile_common.check_dir_exists(pargs.destination_dir):
|
||||
return 1
|
||||
|
||||
for source_dir in pargs.source_dirs:
|
||||
if check_dir(source_dir) != 0:
|
||||
return 1
|
||||
for source_dir in pargs.source_dirs:
|
||||
if not mk_genfile_common.check_dir_exists(source_dir):
|
||||
return 1
|
||||
|
||||
mk_util.mk_gparams_register_modules_internal(pargs.source_dirs, pargs.destination_dir)
|
||||
return 0
|
||||
output = mk_genfile_common.mk_gparams_register_modules_internal(
|
||||
pargs.source_dirs,
|
||||
pargs.destination_dir
|
||||
)
|
||||
logging.info('Generated "{}"'.format(output))
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
|
|
|
@ -6,42 +6,33 @@ and generates a ``install_tactic.cpp`` file in
|
|||
the destination directory that defines a function
|
||||
``void install_tactics(tactic_manager& ctx)``.
|
||||
"""
|
||||
import mk_util
|
||||
import mk_genfile_common
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
def check_dir(path):
|
||||
if not os.path.exists(path):
|
||||
logging.error('"{}" does not exist'.format(path))
|
||||
return 1
|
||||
|
||||
if not os.path.isdir(path):
|
||||
logging.error('"{}" is not a directory'.format(path))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
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")
|
||||
pargs = parser.parse_args(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")
|
||||
pargs = parser.parse_args(args)
|
||||
|
||||
if check_dir(pargs.destination_dir) != 0:
|
||||
return 1
|
||||
if not mk_genfile_common.check_dir_exists(pargs.destination_dir):
|
||||
return 1
|
||||
|
||||
for source_dir in pargs.source_dirs:
|
||||
if check_dir(source_dir) != 0:
|
||||
return 1
|
||||
for source_dir in pargs.source_dirs:
|
||||
if not mk_genfile_common.check_dir_exists(source_dir):
|
||||
return 1
|
||||
|
||||
mk_util.mk_install_tactic_cpp_internal(pargs.source_dirs, pargs.destination_dir)
|
||||
return 0
|
||||
output = mk_genfile_common.mk_install_tactic_cpp_internal(
|
||||
pargs.source_dirs,
|
||||
pargs.destination_dir
|
||||
)
|
||||
logging.info('Generated "{}"'.format(output))
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
|
|
@ -7,42 +7,34 @@ emits and implementation of
|
|||
``void mem_finalize()`` into ``mem_initializer.cpp``
|
||||
in the destination directory.
|
||||
"""
|
||||
import mk_util
|
||||
import mk_genfile_common
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
def check_dir(path):
|
||||
if not os.path.exists(path):
|
||||
logging.error('"{}" does not exist'.format(path))
|
||||
return 1
|
||||
|
||||
if not os.path.isdir(path):
|
||||
logging.error('"{}" is not a directory'.format(path))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
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")
|
||||
pargs = parser.parse_args(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")
|
||||
pargs = parser.parse_args(args)
|
||||
|
||||
if check_dir(pargs.destination_dir) != 0:
|
||||
return 1
|
||||
if not mk_genfile_common.check_dir_exists(pargs.destination_dir):
|
||||
return 1
|
||||
|
||||
for source_dir in pargs.source_dirs:
|
||||
if check_dir(source_dir) != 0:
|
||||
return 1
|
||||
for source_dir in pargs.source_dirs:
|
||||
if not mk_genfile_common.check_dir_exists(source_dir):
|
||||
return 1
|
||||
|
||||
mk_util.mk_mem_initializer_cpp_internal(pargs.source_dirs, pargs.destination_dir)
|
||||
return 0
|
||||
output = mk_genfile_common.mk_mem_initializer_cpp_internal(
|
||||
pargs.source_dirs,
|
||||
pargs.destination_dir
|
||||
)
|
||||
logging.info('Generated "{}"'.format(output))
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
|
|
|
@ -3,32 +3,27 @@
|
|||
Reads a pattern database and generates the corresponding
|
||||
header file.
|
||||
"""
|
||||
import mk_util
|
||||
import mk_genfile_common
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
def main(args):
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("db_file", help="pattern database file")
|
||||
parser.add_argument("output_file", help="output header file path")
|
||||
pargs = parser.parse_args(args)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("db_file", help="pattern database file")
|
||||
parser.add_argument("output_file", help="output header file path")
|
||||
pargs = parser.parse_args(args)
|
||||
|
||||
if not os.path.exists(pargs.db_file):
|
||||
logging.error('"{}" does not exist'.format(pargs.db_file))
|
||||
return 1
|
||||
if not os.path.exists(pargs.db_file):
|
||||
logging.error('"{}" does not exist'.format(pargs.db_file))
|
||||
return 1
|
||||
|
||||
if (os.path.exists(pargs.output_file) and
|
||||
not os.path.isfile(pargs.output_file)):
|
||||
logging.error('Refusing to overwrite "{}"'.format(
|
||||
pargs.output_file))
|
||||
return 1
|
||||
|
||||
mk_util.mk_pat_db_internal(pargs.db_file, pargs.output_file)
|
||||
return 0
|
||||
mk_genfile_common.mk_pat_db_internal(pargs.db_file, pargs.output_file)
|
||||
logging.info('Generated "{}"'.format(pargs.output_file))
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ def init_project_def():
|
|||
add_lib('fuzzing', ['ast'], 'test/fuzzing')
|
||||
add_lib('smt_tactic', ['smt'], 'smt/tactic')
|
||||
add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls')
|
||||
add_lib('qe', ['smt','sat'], 'qe')
|
||||
add_lib('qe', ['smt','sat','nlsat','tactic','nlsat_tactic'], 'qe')
|
||||
add_lib('duality', ['smt', 'interp', 'qe'])
|
||||
add_lib('muz', ['smt', 'sat', 'smt2parser', 'aig_tactic', 'qe'], 'muz/base')
|
||||
add_lib('dataflow', ['muz'], 'muz/dataflow')
|
||||
|
|
|
@ -12,6 +12,7 @@ import re
|
|||
import getopt
|
||||
import shutil
|
||||
from mk_exception import *
|
||||
import mk_genfile_common
|
||||
from fnmatch import fnmatch
|
||||
import distutils.sysconfig
|
||||
import compileall
|
||||
|
@ -27,6 +28,7 @@ CXX=getenv("CXX", None)
|
|||
CC=getenv("CC", None)
|
||||
CPPFLAGS=getenv("CPPFLAGS", "")
|
||||
CXXFLAGS=getenv("CXXFLAGS", "")
|
||||
AR=getenv("AR", "ar")
|
||||
EXAMP_DEBUG_FLAG=''
|
||||
LDFLAGS=getenv("LDFLAGS", "")
|
||||
JNI_HOME=getenv("JNI_HOME", None)
|
||||
|
@ -499,8 +501,8 @@ def is64():
|
|||
def check_ar():
|
||||
if is_verbose():
|
||||
print("Testing ar...")
|
||||
if which('ar') is None:
|
||||
raise MKException('ar (archive tool) was not found')
|
||||
if which(AR) is None:
|
||||
raise MKException('%s (archive tool) was not found' % AR)
|
||||
|
||||
def find_cxx_compiler():
|
||||
global CXX, CXX_COMPILERS
|
||||
|
@ -1934,6 +1936,7 @@ class MLComponent(Component):
|
|||
else:
|
||||
out.write(' ' + os.path.join(self.sub_dir, m) + '.mli')
|
||||
out.write(' ' + os.path.join(self.sub_dir, m) + '.cmi')
|
||||
out.write(' ' + os.path.join(self.sub_dir, m) + '.cmx')
|
||||
out.write(' %s' % ((os.path.join(self.sub_dir, 'libz3ml$(LIB_EXT)'))))
|
||||
out.write(' %s' % ((os.path.join(self.sub_dir, 'z3ml$(LIB_EXT)'))))
|
||||
out.write(' %s' % ((os.path.join(self.sub_dir, 'z3ml.cma'))))
|
||||
|
@ -2034,7 +2037,7 @@ class DotNetExampleComponent(ExampleComponent):
|
|||
if VS_X64:
|
||||
out.write(' /platform:x64')
|
||||
elif VS_ARM:
|
||||
out.write(' /platform:arm')
|
||||
out.write(' /platform:arm')
|
||||
else:
|
||||
out.write(' /platform:x86')
|
||||
for csfile in get_cs_files(self.ex_dir):
|
||||
|
@ -2227,7 +2230,7 @@ def mk_config():
|
|||
static_opt = static_opt + 'd'
|
||||
config.write(
|
||||
'AR_FLAGS=/nologo\n'
|
||||
'LINK_FLAGS=/nologo %s\n'
|
||||
'LINK_FLAGS=/nologo %s\n'
|
||||
'SLINK_FLAGS=/nologo /LDd\n' % static_opt)
|
||||
if VS_X64:
|
||||
config.write(
|
||||
|
@ -2270,7 +2273,7 @@ def mk_config():
|
|||
'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))
|
||||
|
||||
|
||||
|
||||
|
||||
# End of Windows VS config.mk
|
||||
if is_verbose():
|
||||
|
@ -2387,7 +2390,7 @@ def mk_config():
|
|||
config.write('CXX_OUT_FLAG=-o \n')
|
||||
config.write('OBJ_EXT=.o\n')
|
||||
config.write('LIB_EXT=.a\n')
|
||||
config.write('AR=ar\n')
|
||||
config.write('AR=%s\n' % AR)
|
||||
config.write('AR_FLAGS=rcs\n')
|
||||
config.write('AR_OUTFLAG=\n')
|
||||
config.write('EXE_EXT=\n')
|
||||
|
@ -2408,6 +2411,7 @@ def mk_config():
|
|||
print('Host platform: %s' % sysname)
|
||||
print('C++ Compiler: %s' % CXX)
|
||||
print('C Compiler : %s' % CC)
|
||||
print('Archive Tool: %s' % AR)
|
||||
print('Arithmetic: %s' % ARITH)
|
||||
print('OpenMP: %s' % HAS_OMP)
|
||||
print('Prefix: %s' % PREFIX)
|
||||
|
@ -2503,7 +2507,7 @@ def mk_makefile():
|
|||
print("To build Z3, open a [Visual Studio x64 Command Prompt], then")
|
||||
elif VS_ARM:
|
||||
print(" platform: ARM\n")
|
||||
print("To build Z3, open a [Visual Studio ARM Command Prompt], then")
|
||||
print("To build Z3, open a [Visual Studio ARM Command Prompt], then")
|
||||
else:
|
||||
print(" platform: x86")
|
||||
print("To build Z3, open a [Visual Studio Command Prompt], then")
|
||||
|
@ -2521,104 +2525,6 @@ def mk_auto_src():
|
|||
mk_all_mem_initializer_cpps()
|
||||
mk_all_gparams_register_modules()
|
||||
|
||||
UINT = 0
|
||||
BOOL = 1
|
||||
DOUBLE = 2
|
||||
STRING = 3
|
||||
SYMBOL = 4
|
||||
UINT_MAX = 4294967295
|
||||
CURRENT_PYG_HPP_DEST_DIR = None
|
||||
|
||||
def get_current_pyg_hpp_dest_dir():
|
||||
return CURRENT_PYG_HPP_DEST_DIR
|
||||
|
||||
TYPE2CPK = { UINT : 'CPK_UINT', BOOL : 'CPK_BOOL', DOUBLE : 'CPK_DOUBLE', STRING : 'CPK_STRING', SYMBOL : 'CPK_SYMBOL' }
|
||||
TYPE2CTYPE = { UINT : 'unsigned', BOOL : 'bool', DOUBLE : 'double', STRING : 'char const *', SYMBOL : 'symbol' }
|
||||
TYPE2GETTER = { UINT : 'get_uint', BOOL : 'get_bool', DOUBLE : 'get_double', STRING : 'get_str', SYMBOL : 'get_sym' }
|
||||
|
||||
def pyg_default(p):
|
||||
if p[1] == BOOL:
|
||||
if p[2]:
|
||||
return "true"
|
||||
else:
|
||||
return "false"
|
||||
return p[2]
|
||||
|
||||
def pyg_default_as_c_literal(p):
|
||||
if p[1] == BOOL:
|
||||
if p[2]:
|
||||
return "true"
|
||||
else:
|
||||
return "false"
|
||||
elif p[1] == STRING:
|
||||
return '"%s"' % p[2]
|
||||
elif p[1] == SYMBOL:
|
||||
return 'symbol("%s")' % p[2]
|
||||
elif p[1] == UINT:
|
||||
return '%su' % p[2]
|
||||
else:
|
||||
return p[2]
|
||||
|
||||
def to_c_method(s):
|
||||
return s.replace('.', '_')
|
||||
|
||||
def def_module_params(module_name, export, params, class_name=None, description=None):
|
||||
dirname = get_current_pyg_hpp_dest_dir()
|
||||
assert(os.path.exists(dirname))
|
||||
if class_name is None:
|
||||
class_name = '%s_params' % module_name
|
||||
hpp = os.path.join(dirname, '%s.hpp' % class_name)
|
||||
out = open(hpp, 'w')
|
||||
out.write('// Automatically generated file\n')
|
||||
out.write('#ifndef __%s_HPP_\n' % class_name.upper())
|
||||
out.write('#define __%s_HPP_\n' % class_name.upper())
|
||||
out.write('#include"params.h"\n')
|
||||
if export:
|
||||
out.write('#include"gparams.h"\n')
|
||||
out.write('struct %s {\n' % class_name)
|
||||
out.write(' params_ref const & p;\n')
|
||||
if export:
|
||||
out.write(' params_ref g;\n')
|
||||
out.write(' %s(params_ref const & _p = params_ref::get_empty()):\n' % class_name)
|
||||
out.write(' p(_p)')
|
||||
if export:
|
||||
out.write(', g(gparams::get_module("%s"))' % module_name)
|
||||
out.write(' {}\n')
|
||||
out.write(' static void collect_param_descrs(param_descrs & d) {\n')
|
||||
for param in params:
|
||||
out.write(' d.insert("%s", %s, "%s", "%s","%s");\n' % (param[0], TYPE2CPK[param[1]], param[3], pyg_default(param), module_name))
|
||||
out.write(' }\n')
|
||||
if export:
|
||||
out.write(' /*\n')
|
||||
out.write(" REG_MODULE_PARAMS('%s', '%s::collect_param_descrs')\n" % (module_name, class_name))
|
||||
if description is not None:
|
||||
out.write(" REG_MODULE_DESCRIPTION('%s', '%s')\n" % (module_name, description))
|
||||
out.write(' */\n')
|
||||
# Generated accessors
|
||||
for param in params:
|
||||
if export:
|
||||
out.write(' %s %s() const { return p.%s("%s", g, %s); }\n' %
|
||||
(TYPE2CTYPE[param[1]], to_c_method(param[0]), TYPE2GETTER[param[1]], param[0], pyg_default_as_c_literal(param)))
|
||||
else:
|
||||
out.write(' %s %s() const { return p.%s("%s", %s); }\n' %
|
||||
(TYPE2CTYPE[param[1]], to_c_method(param[0]), TYPE2GETTER[param[1]], param[0], pyg_default_as_c_literal(param)))
|
||||
out.write('};\n')
|
||||
out.write('#endif\n')
|
||||
out.close()
|
||||
if is_verbose():
|
||||
print("Generated '%s'" % hpp)
|
||||
|
||||
def max_memory_param():
|
||||
return ('max_memory', UINT, UINT_MAX, 'maximum amount of memory in megabytes')
|
||||
|
||||
def max_steps_param():
|
||||
return ('max_steps', UINT, UINT_MAX, 'maximum number of steps')
|
||||
|
||||
PYG_GLOBALS = { 'UINT' : UINT, 'BOOL' : BOOL, 'DOUBLE' : DOUBLE, 'STRING' : STRING, 'SYMBOL' : SYMBOL,
|
||||
'UINT_MAX' : UINT_MAX,
|
||||
'max_memory_param' : max_memory_param,
|
||||
'max_steps_param' : max_steps_param,
|
||||
'def_module_params' : def_module_params }
|
||||
|
||||
def _execfile(file, globals=globals(), locals=locals()):
|
||||
if sys.version < "2.7":
|
||||
|
@ -2629,13 +2535,13 @@ def _execfile(file, globals=globals(), locals=locals()):
|
|||
|
||||
# Execute python auxiliary scripts that generate extra code for Z3.
|
||||
def exec_pyg_scripts():
|
||||
global CURRENT_PYG_HPP_DEST_DIR
|
||||
for root, dirs, files in os.walk('src'):
|
||||
for f in files:
|
||||
if f.endswith('.pyg'):
|
||||
script = os.path.join(root, f)
|
||||
CURRENT_PYG_HPP_DEST_DIR = root
|
||||
_execfile(script, PYG_GLOBALS)
|
||||
generated_file = mk_genfile_common.mk_hpp_from_pyg(script, root)
|
||||
if is_verbose():
|
||||
print("Generated '{}'".format(generated_file))
|
||||
|
||||
# TODO: delete after src/ast/pattern/expr_pattern_match
|
||||
# database.smt ==> database.h
|
||||
|
@ -2643,17 +2549,9 @@ def mk_pat_db():
|
|||
c = get_component(PATTERN_COMPONENT)
|
||||
fin = os.path.join(c.src_dir, 'database.smt2')
|
||||
fout = os.path.join(c.src_dir, 'database.h')
|
||||
mk_pat_db_internal(fin, fout)
|
||||
|
||||
def mk_pat_db_internal(inputFilePath, outputFilePath):
|
||||
with open(inputFilePath, 'r') as fin:
|
||||
with open(outputFilePath, 'w') as fout:
|
||||
fout.write('static char const g_pattern_database[] =\n')
|
||||
for line in fin:
|
||||
fout.write('"%s\\n"\n' % line.strip('\n'))
|
||||
fout.write(';\n')
|
||||
mk_genfile_common.mk_pat_db_internal(fin, fout)
|
||||
if VERBOSE:
|
||||
print("Generated '%s'" % outputFilePath)
|
||||
print("Generated '{}'".format(fout))
|
||||
|
||||
# Update version numbers
|
||||
def update_version():
|
||||
|
@ -2704,82 +2602,14 @@ def mk_all_assembly_infos(major, minor, build, revision):
|
|||
else:
|
||||
raise MKException("Failed to find assembly template info file '%s'" % assembly_info_template)
|
||||
|
||||
ADD_TACTIC_DATA=[]
|
||||
ADD_PROBE_DATA=[]
|
||||
|
||||
def ADD_TACTIC(name, descr, cmd):
|
||||
global ADD_TACTIC_DATA
|
||||
ADD_TACTIC_DATA.append((name, descr, cmd))
|
||||
|
||||
def ADD_PROBE(name, descr, cmd):
|
||||
global ADD_PROBE_DATA
|
||||
ADD_PROBE_DATA.append((name, descr, cmd))
|
||||
|
||||
# Generate an install_tactics.cpp at path.
|
||||
# This file implements the procedure
|
||||
# void install_tactics(tactic_manager & ctx)
|
||||
# It installs all tactics in the given component (name) list cnames
|
||||
# The procedure looks for ADD_TACTIC commands in the .h files of these components.
|
||||
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)
|
||||
mk_install_tactic_cpp_internal(component_src_dirs, path)
|
||||
|
||||
def mk_install_tactic_cpp_internal(component_src_dirs, path):
|
||||
global ADD_TACTIC_DATA, ADD_PROBE_DATA
|
||||
ADD_TACTIC_DATA = []
|
||||
ADD_PROBE_DATA = []
|
||||
fullname = os.path.join(path, 'install_tactic.cpp')
|
||||
fout = open(fullname, 'w')
|
||||
fout.write('// Automatically generated file.\n')
|
||||
fout.write('#include"tactic.h"\n')
|
||||
fout.write('#include"tactic_cmds.h"\n')
|
||||
fout.write('#include"cmd_context.h"\n')
|
||||
tactic_pat = re.compile('[ \t]*ADD_TACTIC\(.*\)')
|
||||
probe_pat = re.compile('[ \t]*ADD_PROBE\(.*\)')
|
||||
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))
|
||||
for h_file in h_files:
|
||||
added_include = False
|
||||
fin = open(os.path.join(component_src_dir, h_file), 'r')
|
||||
for line in fin:
|
||||
if tactic_pat.match(line):
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % h_file)
|
||||
try:
|
||||
exec(line.strip('\n '), globals())
|
||||
except:
|
||||
raise MKException("Failed processing ADD_TACTIC command at '%s'\n%s" % (fullname, line))
|
||||
if probe_pat.match(line):
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % h_file)
|
||||
try:
|
||||
exec(line.strip('\n '), globals())
|
||||
except:
|
||||
raise MKException("Failed processing ADD_PROBE command at '%s'\n%s" % (fullname, line))
|
||||
fin.close()
|
||||
# First pass will just generate the tactic factories
|
||||
idx = 0
|
||||
for data in ADD_TACTIC_DATA:
|
||||
fout.write('MK_SIMPLE_TACTIC_FACTORY(__Z3_local_factory_%s, %s);\n' % (idx, data[2]))
|
||||
idx = idx + 1
|
||||
fout.write('#define ADD_TACTIC_CMD(NAME, DESCR, FACTORY) ctx.insert(alloc(tactic_cmd, symbol(NAME), DESCR, alloc(FACTORY)))\n')
|
||||
fout.write('#define ADD_PROBE(NAME, DESCR, PROBE) ctx.insert(alloc(probe_info, symbol(NAME), DESCR, PROBE))\n')
|
||||
fout.write('void install_tactics(tactic_manager & ctx) {\n')
|
||||
idx = 0
|
||||
for data in ADD_TACTIC_DATA:
|
||||
fout.write(' ADD_TACTIC_CMD("%s", "%s", __Z3_local_factory_%s);\n' % (data[0], data[1], idx))
|
||||
idx = idx + 1
|
||||
for data in ADD_PROBE_DATA:
|
||||
fout.write(' ADD_PROBE("%s", "%s", %s);\n' % data)
|
||||
fout.write('}\n')
|
||||
fout.close()
|
||||
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)
|
||||
if VERBOSE:
|
||||
print("Generated '%s'" % fullname)
|
||||
print("Generated '{}'".format(generated_file))
|
||||
|
||||
def mk_all_install_tactic_cpps():
|
||||
if not ONLY_MAKEFILES:
|
||||
|
@ -2790,67 +2620,14 @@ def mk_all_install_tactic_cpps():
|
|||
cnames.append(c.name)
|
||||
mk_install_tactic_cpp(cnames, c.src_dir)
|
||||
|
||||
# Generate an mem_initializer.cpp at path.
|
||||
# This file implements the procedures
|
||||
# void mem_initialize()
|
||||
# void mem_finalize()
|
||||
# These procedures are invoked by the Z3 memory_manager
|
||||
def mk_mem_initializer_cpp(cnames, path):
|
||||
component_src_dirs = []
|
||||
for cname in cnames:
|
||||
c = get_component(cname)
|
||||
component_src_dirs.append(c.src_dir)
|
||||
mk_mem_initializer_cpp_internal(component_src_dirs, path)
|
||||
|
||||
def mk_mem_initializer_cpp_internal(component_src_dirs, path):
|
||||
initializer_cmds = []
|
||||
finalizer_cmds = []
|
||||
fullname = os.path.join(path, 'mem_initializer.cpp')
|
||||
fout = open(fullname, 'w')
|
||||
fout.write('// Automatically generated file.\n')
|
||||
initializer_pat = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\'\)')
|
||||
# ADD_INITIALIZER with priority
|
||||
initializer_prio_pat = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\',[ \t]*(-?[0-9]*)\)')
|
||||
finalizer_pat = re.compile('[ \t]*ADD_FINALIZER\(\'([^\']*)\'\)')
|
||||
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))
|
||||
for h_file in h_files:
|
||||
added_include = False
|
||||
fin = open(os.path.join(component_src_dir, h_file), 'r')
|
||||
for line in fin:
|
||||
m = initializer_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % h_file)
|
||||
initializer_cmds.append((m.group(1), 0))
|
||||
m = initializer_prio_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % h_file)
|
||||
initializer_cmds.append((m.group(1), int(m.group(2))))
|
||||
m = finalizer_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % h_file)
|
||||
finalizer_cmds.append(m.group(1))
|
||||
fin.close()
|
||||
initializer_cmds.sort(key=lambda tup: tup[1])
|
||||
fout.write('void mem_initialize() {\n')
|
||||
for (cmd, prio) in initializer_cmds:
|
||||
fout.write(cmd)
|
||||
fout.write('\n')
|
||||
fout.write('}\n')
|
||||
fout.write('void mem_finalize() {\n')
|
||||
for cmd in finalizer_cmds:
|
||||
fout.write(cmd)
|
||||
fout.write('\n')
|
||||
fout.write('}\n')
|
||||
fout.close()
|
||||
component_src_dirs = []
|
||||
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)
|
||||
if VERBOSE:
|
||||
print("Generated '%s'" % fullname)
|
||||
print("Generated '{}'".format(generated_file))
|
||||
|
||||
def mk_all_mem_initializer_cpps():
|
||||
if not ONLY_MAKEFILES:
|
||||
|
@ -2861,61 +2638,14 @@ def mk_all_mem_initializer_cpps():
|
|||
cnames.append(c.name)
|
||||
mk_mem_initializer_cpp(cnames, c.src_dir)
|
||||
|
||||
# Generate an ``gparams_register_modules.cpp`` at path.
|
||||
# This file implements the procedure
|
||||
# void gparams_register_modules()
|
||||
# This procedure is invoked by gparams::init()
|
||||
def mk_gparams_register_modules(cnames, path):
|
||||
component_src_dirs = []
|
||||
for cname in cnames:
|
||||
c = get_component(cname)
|
||||
component_src_dirs.append(c.src_dir)
|
||||
mk_gparams_register_modules_internal(component_src_dirs, path)
|
||||
|
||||
def mk_gparams_register_modules_internal(component_src_dirs, path):
|
||||
cmds = []
|
||||
mod_cmds = []
|
||||
mod_descrs = []
|
||||
fullname = os.path.join(path, 'gparams_register_modules.cpp')
|
||||
fout = open(fullname, 'w')
|
||||
fout.write('// Automatically generated file.\n')
|
||||
fout.write('#include"gparams.h"\n')
|
||||
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\(\'([^\']*)\', *\'([^\']*)\'\)')
|
||||
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))
|
||||
for h_file in h_files:
|
||||
added_include = False
|
||||
fin = open(os.path.join(component_src_dir, h_file), 'r')
|
||||
for line in fin:
|
||||
m = reg_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % h_file)
|
||||
cmds.append((m.group(1)))
|
||||
m = reg_mod_pat.match(line)
|
||||
if m:
|
||||
if not added_include:
|
||||
added_include = True
|
||||
fout.write('#include"%s"\n' % h_file)
|
||||
mod_cmds.append((m.group(1), m.group(2)))
|
||||
m = reg_mod_descr_pat.match(line)
|
||||
if m:
|
||||
mod_descrs.append((m.group(1), m.group(2)))
|
||||
fin.close()
|
||||
fout.write('void gparams_register_modules() {\n')
|
||||
for code in cmds:
|
||||
fout.write('{ param_descrs d; %s(d); gparams::register_global(d); }\n' % code)
|
||||
for (mod, code) in mod_cmds:
|
||||
fout.write('{ param_descrs * d = alloc(param_descrs); %s(*d); gparams::register_module("%s", d); }\n' % (code, mod))
|
||||
for (mod, descr) in mod_descrs:
|
||||
fout.write('gparams::register_module_descr("%s", "%s");\n' % (mod, descr))
|
||||
fout.write('}\n')
|
||||
fout.close()
|
||||
component_src_dirs = []
|
||||
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)
|
||||
if VERBOSE:
|
||||
print("Generated '%s'" % fullname)
|
||||
print("Generated '{}'".format(generated_file))
|
||||
|
||||
def mk_all_gparams_register_modules():
|
||||
if not ONLY_MAKEFILES:
|
||||
|
@ -2935,28 +2665,7 @@ def mk_def_file(c):
|
|||
dot_h_c = c.find_file(dot_h, c.name)
|
||||
api = os.path.join(dot_h_c.src_dir, dot_h)
|
||||
export_header_files.append(api)
|
||||
mk_def_file_internal(defname, dll_name, export_header_files)
|
||||
|
||||
def mk_def_file_internal(defname, dll_name, export_header_files):
|
||||
pat1 = re.compile(".*Z3_API.*")
|
||||
fout = open(defname, 'w')
|
||||
fout.write('LIBRARY "%s"\nEXPORTS\n' % dll_name)
|
||||
num = 1
|
||||
for export_header_file in export_header_files:
|
||||
api = open(export_header_file, 'r')
|
||||
for line in api:
|
||||
m = pat1.match(line)
|
||||
if m:
|
||||
words = re.split('\W+', line)
|
||||
i = 0
|
||||
for w in words:
|
||||
if w == 'Z3_API':
|
||||
f = words[i+1]
|
||||
fout.write('\t%s @%s\n' % (f, num))
|
||||
i = i + 1
|
||||
num = num + 1
|
||||
api.close()
|
||||
fout.close()
|
||||
mk_genfile_common.mk_def_file_internal(defname, dll_name, export_header_files)
|
||||
if VERBOSE:
|
||||
print("Generated '%s'" % defname)
|
||||
|
||||
|
@ -3049,174 +2758,21 @@ def mk_z3consts_py(api_files):
|
|||
api_file_c = api_dll.find_file(api_file, api_dll.name)
|
||||
api_file = os.path.join(api_file_c.src_dir, api_file)
|
||||
full_path_api_files.append(api_file)
|
||||
mk_z3consts_py_internal(full_path_api_files, Z3PY_SRC_DIR)
|
||||
|
||||
def mk_z3consts_py_internal(api_files, output_dir):
|
||||
assert os.path.isdir(output_dir)
|
||||
assert isinstance(api_files, list)
|
||||
|
||||
blank_pat = re.compile("^ *\r?$")
|
||||
comment_pat = re.compile("^ *//.*$")
|
||||
typedef_pat = re.compile("typedef enum *")
|
||||
typedef2_pat = re.compile("typedef enum { *")
|
||||
openbrace_pat = re.compile("{ *")
|
||||
closebrace_pat = re.compile("}.*;")
|
||||
|
||||
z3consts = open(os.path.join(output_dir, 'z3consts.py'), 'w')
|
||||
z3consts.write('# Automatically generated file\n\n')
|
||||
for api_file in api_files:
|
||||
api = open(api_file, 'r')
|
||||
|
||||
SEARCHING = 0
|
||||
FOUND_ENUM = 1
|
||||
IN_ENUM = 2
|
||||
|
||||
mode = SEARCHING
|
||||
decls = {}
|
||||
idx = 0
|
||||
|
||||
linenum = 1
|
||||
for line in api:
|
||||
m1 = blank_pat.match(line)
|
||||
m2 = comment_pat.match(line)
|
||||
if m1 or m2:
|
||||
# skip blank lines and comments
|
||||
linenum = linenum + 1
|
||||
elif mode == SEARCHING:
|
||||
m = typedef_pat.match(line)
|
||||
if m:
|
||||
mode = FOUND_ENUM
|
||||
m = typedef2_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
elif mode == FOUND_ENUM:
|
||||
m = openbrace_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
else:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
z3consts.write('# enum %s\n' % name)
|
||||
for k in decls:
|
||||
i = decls[k]
|
||||
z3consts.write('%s = %s\n' % (k, i))
|
||||
z3consts.write('\n')
|
||||
mode = SEARCHING
|
||||
elif len(words) <= 2:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
if words[2] != '':
|
||||
if len(words[2]) > 1 and words[2][1] == 'x':
|
||||
idx = int(words[2], 16)
|
||||
else:
|
||||
idx = int(words[2])
|
||||
decls[words[1]] = idx
|
||||
idx = idx + 1
|
||||
linenum = linenum + 1
|
||||
api.close()
|
||||
z3consts.close()
|
||||
generated_file = mk_genfile_common.mk_z3consts_py_internal(full_path_api_files, Z3PY_SRC_DIR)
|
||||
if VERBOSE:
|
||||
print("Generated '%s'" % os.path.join(output_dir, 'z3consts.py'))
|
||||
|
||||
print("Generated '{}".format(generated_file))
|
||||
|
||||
# Extract enumeration types from z3_api.h, and add .Net definitions
|
||||
def mk_z3consts_dotnet(api_files):
|
||||
blank_pat = re.compile("^ *\r?$")
|
||||
comment_pat = re.compile("^ *//.*$")
|
||||
typedef_pat = re.compile("typedef enum *")
|
||||
typedef2_pat = re.compile("typedef enum { *")
|
||||
openbrace_pat = re.compile("{ *")
|
||||
closebrace_pat = re.compile("}.*;")
|
||||
|
||||
dotnet = get_component(DOTNET_COMPONENT)
|
||||
|
||||
DeprecatedEnums = [ 'Z3_search_failure' ]
|
||||
z3consts = open(os.path.join(dotnet.src_dir, 'Enumerations.cs'), 'w')
|
||||
z3consts.write('// Automatically generated file\n\n')
|
||||
z3consts.write('using System;\n\n'
|
||||
'#pragma warning disable 1591\n\n'
|
||||
'namespace Microsoft.Z3\n'
|
||||
'{\n')
|
||||
|
||||
full_path_api_files = []
|
||||
for api_file in api_files:
|
||||
api_file_c = dotnet.find_file(api_file, dotnet.name)
|
||||
api_file = os.path.join(api_file_c.src_dir, api_file)
|
||||
|
||||
api = open(api_file, 'r')
|
||||
|
||||
SEARCHING = 0
|
||||
FOUND_ENUM = 1
|
||||
IN_ENUM = 2
|
||||
|
||||
mode = SEARCHING
|
||||
decls = {}
|
||||
idx = 0
|
||||
|
||||
linenum = 1
|
||||
for line in api:
|
||||
m1 = blank_pat.match(line)
|
||||
m2 = comment_pat.match(line)
|
||||
if m1 or m2:
|
||||
# skip blank lines and comments
|
||||
linenum = linenum + 1
|
||||
elif mode == SEARCHING:
|
||||
m = typedef_pat.match(line)
|
||||
if m:
|
||||
mode = FOUND_ENUM
|
||||
m = typedef2_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
elif mode == FOUND_ENUM:
|
||||
m = openbrace_pat.match(line)
|
||||
if m:
|
||||
mode = IN_ENUM
|
||||
decls = {}
|
||||
idx = 0
|
||||
else:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
assert mode == IN_ENUM
|
||||
words = re.split('[^\-a-zA-Z0-9_]+', line)
|
||||
m = closebrace_pat.match(line)
|
||||
if m:
|
||||
name = words[1]
|
||||
if name not in DeprecatedEnums:
|
||||
z3consts.write(' /// <summary>%s</summary>\n' % name)
|
||||
z3consts.write(' public enum %s {\n' % name)
|
||||
z3consts.write
|
||||
for k in decls:
|
||||
i = decls[k]
|
||||
z3consts.write(' %s = %s,\n' % (k, i))
|
||||
z3consts.write(' }\n\n')
|
||||
mode = SEARCHING
|
||||
elif len(words) <= 2:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
if words[2] != '':
|
||||
if len(words[2]) > 1 and words[2][1] == 'x':
|
||||
idx = int(words[2], 16)
|
||||
else:
|
||||
idx = int(words[2])
|
||||
decls[words[1]] = idx
|
||||
idx = idx + 1
|
||||
linenum = linenum + 1
|
||||
api.close()
|
||||
z3consts.write('}\n');
|
||||
z3consts.close()
|
||||
full_path_api_files.append(api_file)
|
||||
generated_file = mk_genfile_common.mk_z3consts_dotnet_internal(full_path_api_files, dotnet.src_dir)
|
||||
if VERBOSE:
|
||||
print("Generated '%s'" % os.path.join(dotnet.src_dir, 'Enumerations.cs'))
|
||||
|
||||
print("Generated '{}".format(generated_file))
|
||||
|
||||
# Extract enumeration types from z3_api.h, and add Java definitions
|
||||
def mk_z3consts_java(api_files):
|
||||
|
@ -3777,7 +3333,7 @@ class MakeRuleCmd(object):
|
|||
cls.write_cmd(out, "mkdir -p {install_root}{dir}".format(
|
||||
install_root=install_root,
|
||||
dir=dir))
|
||||
|
||||
|
||||
@classmethod
|
||||
def _is_path_prefix_of(cls, temp_path, target_as_abs):
|
||||
"""
|
||||
|
@ -3906,4 +3462,3 @@ def configure_file(template_file_path, output_file_path, substitutions):
|
|||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
|
|
@ -4,39 +4,33 @@ Reads a pyg file and emits the corresponding
|
|||
C++ header file into the specified destination
|
||||
directory.
|
||||
"""
|
||||
import mk_util
|
||||
import mk_genfile_common
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
def main(args):
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("pyg_file", help="pyg file")
|
||||
parser.add_argument("destination_dir", help="destination directory")
|
||||
pargs = parser.parse_args(args)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("pyg_file", help="pyg file")
|
||||
parser.add_argument("destination_dir", help="destination directory")
|
||||
pargs = parser.parse_args(args)
|
||||
|
||||
if not os.path.exists(pargs.pyg_file):
|
||||
logging.error('"{}" does not exist'.format(pargs.pyg_file))
|
||||
return 1
|
||||
if not os.path.exists(pargs.pyg_file):
|
||||
logging.error('"{}" does not exist'.format(pargs.pyg_file))
|
||||
return 1
|
||||
|
||||
if not os.path.exists(pargs.destination_dir):
|
||||
logging.error('"{}" does not exist'.format(pargs.destination_dir))
|
||||
return 1
|
||||
if not mk_genfile_common.check_dir_exists(pargs.destination_dir):
|
||||
return 1
|
||||
|
||||
if not os.path.isdir(pargs.destination_dir):
|
||||
logging.error('"{}" is not a directory'.format(pargs.destination_dir))
|
||||
return 1
|
||||
|
||||
pyg_full_path = os.path.abspath(pargs.pyg_file)
|
||||
destination_dir_full_path = os.path.abspath(pargs.destination_dir)
|
||||
logging.info('Using {}'.format(pyg_full_path))
|
||||
# Use the existing infrastructure to do this
|
||||
mk_util.CURRENT_PYG_HPP_DEST_DIR = destination_dir_full_path
|
||||
mk_util._execfile(pyg_full_path, mk_util.PYG_GLOBALS)
|
||||
return 0
|
||||
pyg_full_path = os.path.abspath(pargs.pyg_file)
|
||||
destination_dir_full_path = os.path.abspath(pargs.destination_dir)
|
||||
logging.info('Using {}'.format(pyg_full_path))
|
||||
output = mk_genfile_common.mk_hpp_from_pyg(pyg_full_path, destination_dir_full_path)
|
||||
logging.info('Generated "{}"'.format(output))
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
tactic_report report("ackermannize", *g);
|
||||
fail_if_unsat_core_generation("ackermannize", g);
|
||||
fail_if_proof_generation("ackermannize", g);
|
||||
TRACE("ackermannize", g->display(tout << "in\n"););
|
||||
|
||||
expr_ref_vector flas(m);
|
||||
const unsigned sz = g->size();
|
||||
|
@ -48,6 +49,7 @@ public:
|
|||
goal_ref resg(alloc(goal, *g, true));
|
||||
const bool success = lackr.mk_ackermann(resg, m_lemma_limit);
|
||||
if (!success) { // Just pass on the input unchanged
|
||||
TRACE("ackermannize", tout << "ackermannize not run due to limit" << std::endl;);
|
||||
result.reset();
|
||||
result.push_back(g.get());
|
||||
mc = 0;
|
||||
|
@ -62,7 +64,7 @@ public:
|
|||
}
|
||||
|
||||
resg->inc_depth();
|
||||
TRACE("ackermannize", resg->display(tout););
|
||||
TRACE("ackermannize", resg->display(tout << "out\n"););
|
||||
SASSERT(resg->is_well_sorted());
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ lackr::~lackr() {
|
|||
|
||||
lbool lackr::operator() () {
|
||||
SASSERT(m_sat);
|
||||
init();
|
||||
if (!init()) return l_undef;
|
||||
const lbool rv = m_eager ? eager() : lazy();
|
||||
if (rv == l_true) m_sat->get_model(m_model);
|
||||
CTRACE("lackr", rv == l_true,
|
||||
|
@ -63,7 +63,7 @@ lbool lackr::operator() () {
|
|||
|
||||
bool lackr::mk_ackermann(/*out*/goal_ref& g, double lemmas_upper_bound) {
|
||||
if (lemmas_upper_bound <= 0) return false;
|
||||
init();
|
||||
if (!init()) return false;
|
||||
if (lemmas_upper_bound != std::numeric_limits<double>::infinity()) {
|
||||
const double lemmas_bound = ackr_helper::calculate_lemma_bound(m_fun2terms);
|
||||
if (lemmas_bound > lemmas_upper_bound) return false;
|
||||
|
@ -74,14 +74,15 @@ bool lackr::mk_ackermann(/*out*/goal_ref& g, double lemmas_upper_bound) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void lackr::init() {
|
||||
SASSERT(!m_is_init);
|
||||
m_is_init = true;
|
||||
bool lackr::init() {
|
||||
SASSERT(!m_is_init);
|
||||
params_ref simp_p(m_p);
|
||||
m_simp.updt_params(simp_p);
|
||||
m_info = alloc(ackr_info, m_m);
|
||||
collect_terms();
|
||||
if (!collect_terms()) return false;
|
||||
abstract();
|
||||
m_is_init = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -96,10 +97,8 @@ bool lackr::ackr(app * const t1, app * const t2) {
|
|||
for (unsigned i = 0; i < sz; ++i) {
|
||||
expr * const arg1 = t1->get_arg(i);
|
||||
expr * const arg2 = t2->get_arg(i);
|
||||
if (arg1 == arg2) continue; // quickly skip syntactically equal
|
||||
if (m_ackr_helper.bvutil().is_numeral(arg1) && m_ackr_helper.bvutil().is_numeral(arg2)) {
|
||||
// quickly abort if there are two distinct numerals
|
||||
SASSERT(arg1 != arg2);
|
||||
if (m_m.are_equal(arg1, arg2)) continue; // quickly skip syntactically equal
|
||||
if (m_m.are_distinct(arg1, arg2)){ // quickly abort if there are two distinct (e.g. numerals)
|
||||
TRACE("lackr", tout << "never eq\n";);
|
||||
return false;
|
||||
}
|
||||
|
@ -110,7 +109,8 @@ bool lackr::ackr(app * const t1, app * const t2) {
|
|||
SASSERT(a1 && a2);
|
||||
TRACE("lackr", tout << "abstr1 " << mk_ismt2_pp(a1, m_m, 2) << "\n";);
|
||||
TRACE("lackr", tout << "abstr2 " << mk_ismt2_pp(a2, m_m, 2) << "\n";);
|
||||
expr_ref lhs(m_m.mk_and(eqs.size(), eqs.c_ptr()), m_m);
|
||||
expr_ref lhs(m_m);
|
||||
lhs = (eqs.size() == 1) ? eqs.get(0) : m_m.mk_and(eqs.size(), eqs.c_ptr());
|
||||
TRACE("lackr", tout << "ackr constr lhs" << mk_ismt2_pp(lhs, m_m, 2) << "\n";);
|
||||
expr_ref rhs(m_m.mk_eq(a1, a2),m_m);
|
||||
TRACE("lackr", tout << "ackr constr rhs" << mk_ismt2_pp(rhs, m_m, 2) << "\n";);
|
||||
|
@ -203,6 +203,7 @@ void lackr::push_abstraction() {
|
|||
}
|
||||
|
||||
lbool lackr::eager() {
|
||||
SASSERT(m_is_init);
|
||||
push_abstraction();
|
||||
TRACE("lackr", tout << "run sat 0\n"; );
|
||||
const lbool rv0 = m_sat->check_sat(0, 0);
|
||||
|
@ -217,6 +218,7 @@ lbool lackr::eager() {
|
|||
}
|
||||
|
||||
lbool lackr::lazy() {
|
||||
SASSERT(m_is_init);
|
||||
lackr_model_constructor mc(m_m, m_info);
|
||||
push_abstraction();
|
||||
unsigned ackr_head = 0;
|
||||
|
@ -247,7 +249,7 @@ lbool lackr::lazy() {
|
|||
//
|
||||
// Collect all uninterpreted terms, skipping 0-arity.
|
||||
//
|
||||
void lackr::collect_terms() {
|
||||
bool lackr::collect_terms() {
|
||||
ptr_vector<expr> stack;
|
||||
expr * curr;
|
||||
expr_mark visited;
|
||||
|
@ -279,12 +281,11 @@ void lackr::collect_terms() {
|
|||
}
|
||||
break;
|
||||
case AST_QUANTIFIER:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
return false; // quantifiers not supported
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
visited.reset();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ class lackr {
|
|||
lackr_stats& m_st;
|
||||
bool m_is_init;
|
||||
|
||||
void init();
|
||||
bool init();
|
||||
lbool eager();
|
||||
lbool lazy();
|
||||
|
||||
|
@ -118,6 +118,6 @@ class lackr {
|
|||
//
|
||||
// Collect all uninterpreted terms, skipping 0-arity.
|
||||
//
|
||||
void collect_terms();
|
||||
bool collect_terms();
|
||||
};
|
||||
#endif /* LACKR_H_ */
|
||||
|
|
|
@ -34,11 +34,13 @@ struct lackr_model_constructor::imp {
|
|||
, m_conflicts(conflicts)
|
||||
, m_b_rw(m)
|
||||
, m_bv_rw(m)
|
||||
, m_evaluator(NULL)
|
||||
, m_empty_model(m)
|
||||
, m_ackr_helper(m)
|
||||
{}
|
||||
|
||||
~imp() {
|
||||
if (m_evaluator) dealloc(m_evaluator);
|
||||
{
|
||||
values2val_t::iterator i = m_values2val.begin();
|
||||
const values2val_t::iterator e = m_values2val.end();
|
||||
|
@ -60,15 +62,17 @@ struct lackr_model_constructor::imp {
|
|||
|
||||
//
|
||||
// Returns true iff model was successfully constructed.
|
||||
// Conflicts are saved as a side effect.
|
||||
//
|
||||
bool check() {
|
||||
bool retv = true;
|
||||
for (unsigned i = 0; i < m_abstr_model->get_num_constants(); i++) {
|
||||
func_decl * const c = m_abstr_model->get_constant(i);
|
||||
app * const term = m_info->find_term(c);
|
||||
if (term) m_stack.push_back(term);
|
||||
else m_stack.push_back(m_m.mk_const(c));
|
||||
app * const _term = m_info->find_term(c);
|
||||
expr * const term = _term ? _term : m_m.mk_const(c);
|
||||
if (!check_term(term)) retv = false;
|
||||
}
|
||||
return run();
|
||||
return retv;
|
||||
}
|
||||
|
||||
|
||||
|
@ -134,7 +138,7 @@ struct lackr_model_constructor::imp {
|
|||
conflict_list& m_conflicts;
|
||||
bool_rewriter m_b_rw;
|
||||
bv_rewriter m_bv_rw;
|
||||
scoped_ptr<model_evaluator> m_evaluator;
|
||||
model_evaluator * m_evaluator;
|
||||
model m_empty_model;
|
||||
private:
|
||||
struct val_info { expr * value; app * source_term; };
|
||||
|
@ -144,6 +148,7 @@ struct lackr_model_constructor::imp {
|
|||
app2val_t m_app2val;
|
||||
ptr_vector<expr> m_stack;
|
||||
ackr_helper m_ackr_helper;
|
||||
expr_mark m_visited;
|
||||
|
||||
static inline val_info mk_val_info(expr* value, app* source_term) {
|
||||
val_info rv;
|
||||
|
@ -152,17 +157,23 @@ struct lackr_model_constructor::imp {
|
|||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// Performs congruence check on a given term.
|
||||
bool check_term(expr * term) {
|
||||
m_stack.push_back(term);
|
||||
const bool rv = _check_stack();
|
||||
m_stack.reset();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Performs congruence check on terms on the stack.
|
||||
// (Currently stops upon the first failure).
|
||||
// Returns true if and only if congruence check succeeded.
|
||||
bool run() {
|
||||
m_evaluator = alloc(model_evaluator, m_empty_model);
|
||||
expr_mark visited;
|
||||
// Stops upon the first failure.
|
||||
// Returns true if and only if all congruence checks succeeded.
|
||||
bool _check_stack() {
|
||||
if (m_evaluator == NULL) m_evaluator = alloc(model_evaluator, m_empty_model);
|
||||
expr * curr;
|
||||
while (!m_stack.empty()) {
|
||||
curr = m_stack.back();
|
||||
if (visited.is_marked(curr)) {
|
||||
if (m_visited.is_marked(curr)) {
|
||||
m_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
@ -173,8 +184,8 @@ struct lackr_model_constructor::imp {
|
|||
return false;
|
||||
case AST_APP: {
|
||||
app * a = to_app(curr);
|
||||
if (for_each_expr_args(m_stack, visited, a->get_num_args(), a->get_args())) {
|
||||
visited.mark(a, true);
|
||||
if (for_each_expr_args(m_stack, m_visited, a->get_num_args(), a->get_args())) {
|
||||
m_visited.mark(a, true);
|
||||
m_stack.pop_back();
|
||||
if (!mk_value(a)) return false;
|
||||
}
|
||||
|
@ -212,7 +223,11 @@ struct lackr_model_constructor::imp {
|
|||
for (unsigned i = 0; i < num; ++i) {
|
||||
expr * val;
|
||||
const bool b = eval_cached(to_app(args[i]), val); // TODO: OK conversion to_app?
|
||||
CTRACE("model_constructor", !b, tout << "fail arg val(\n" << mk_ismt2_pp(args[i], m_m, 2); );
|
||||
CTRACE("model_constructor", m_conflicts.empty() && !b, tout << "fail arg val(\n" << mk_ismt2_pp(args[i], m_m, 2) << '\n'; );
|
||||
if (!b) {
|
||||
// bailing out because args eval failed previously
|
||||
return false;
|
||||
}
|
||||
TRACE("model_constructor", tout <<
|
||||
"arg val " << i << "(\n" << mk_ismt2_pp(args[i], m_m, 2)
|
||||
<< " : " << mk_ismt2_pp(val, m_m, 2) << '\n'; );
|
||||
|
|
|
@ -1129,7 +1129,7 @@ extern "C" {
|
|||
case Z3_OP_SEQ_INDEX: return Z3_OP_SEQ_INDEX;
|
||||
case Z3_OP_SEQ_TO_RE: return Z3_OP_SEQ_TO_RE;
|
||||
case Z3_OP_SEQ_IN_RE: return Z3_OP_SEQ_IN_RE;
|
||||
|
||||
|
||||
case Z3_OP_RE_PLUS: return Z3_OP_RE_PLUS;
|
||||
case Z3_OP_RE_STAR: return Z3_OP_RE_STAR;
|
||||
case Z3_OP_RE_OPTION: return Z3_OP_RE_OPTION;
|
||||
|
@ -1186,9 +1186,14 @@ extern "C" {
|
|||
case OP_FPA_TO_IEEE_BV: return Z3_OP_FPA_TO_IEEE_BV;
|
||||
case OP_FPA_INTERNAL_BVWRAP:
|
||||
case OP_FPA_INTERNAL_BVUNWRAP:
|
||||
case OP_FPA_INTERNAL_MIN_I:
|
||||
case OP_FPA_INTERNAL_MAX_I:
|
||||
case OP_FPA_INTERNAL_MIN_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_MAX_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
||||
return Z3_OP_UNINTERPRETED;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -604,8 +604,16 @@ namespace z3 {
|
|||
|
||||
/**
|
||||
\brief Return true if this expression is a numeral.
|
||||
Specialized functions also return representations for the numerals as
|
||||
small integers, 64 bit integers or rational or decimal strings.
|
||||
*/
|
||||
bool is_numeral() const { return kind() == Z3_NUMERAL_AST; }
|
||||
bool is_numeral_i64(__int64& i) const { bool r = 0 != Z3_get_numeral_int64(ctx(), m_ast, &i); check_error(); return r;}
|
||||
bool is_numeral_u64(__uint64& i) const { bool r = 0 != Z3_get_numeral_uint64(ctx(), m_ast, &i); check_error(); return r;}
|
||||
bool is_numeral_i(int& i) const { bool r = 0 != Z3_get_numeral_int(ctx(), m_ast, &i); check_error(); return r;}
|
||||
bool is_numeral_u(unsigned& i) const { bool r = 0 != Z3_get_numeral_uint(ctx(), m_ast, &i); check_error(); return r;}
|
||||
bool is_numeral(std::string& s) const { if (!is_numeral()) return false; s = Z3_get_numeral_string(ctx(), m_ast); check_error(); return true; }
|
||||
bool is_numeral(std::string& s, unsigned precision) const { if (!is_numeral()) return false; s = Z3_get_numeral_decimal_string(ctx(), m_ast, precision); check_error(); return true; }
|
||||
/**
|
||||
\brief Return true if this expression is an application.
|
||||
*/
|
||||
|
@ -622,11 +630,86 @@ namespace z3 {
|
|||
\brief Return true if this expression is a variable.
|
||||
*/
|
||||
bool is_var() const { return kind() == Z3_VAR_AST; }
|
||||
/**
|
||||
\brief Return true if expression is an algebraic number.
|
||||
*/
|
||||
bool is_algebraic() const { return 0 != Z3_is_algebraic_number(ctx(), m_ast); }
|
||||
|
||||
/**
|
||||
\brief Return true if this expression is well sorted (aka type correct).
|
||||
*/
|
||||
bool is_well_sorted() const { bool r = Z3_is_well_sorted(ctx(), m_ast) != 0; check_error(); return r; }
|
||||
|
||||
/**
|
||||
\brief Return string representation of numeral or algebraic number
|
||||
This method assumes the expression is numeral or algebraic
|
||||
|
||||
\pre is_numeral() || is_algebraic()
|
||||
*/
|
||||
std::string get_decimal_string(int precision) const {
|
||||
assert(is_numeral() || is_algebraic());
|
||||
return std::string(Z3_get_numeral_decimal_string(ctx(), m_ast, precision));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return int value of numeral, throw if result cannot fit in
|
||||
machine int
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
int get_numeral_int() const {
|
||||
int result;
|
||||
if (!is_numeral_i(result)) {
|
||||
throw exception("numeral does not fit in machine int");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return uint value of numeral, throw if result cannot fit in
|
||||
machine uint
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
unsigned get_numeral_uint() const {
|
||||
assert(is_numeral());
|
||||
unsigned result;
|
||||
if (!is_numeral_u(result)) {
|
||||
throw exception("numeral does not fit in machine uint");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return __int64 value of numeral, throw if result cannot fit in
|
||||
__int64
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
__int64 get_numeral_int64() const {
|
||||
assert(is_numeral());
|
||||
__int64 result;
|
||||
if (!is_numeral_i64(result)) {
|
||||
throw exception("numeral does not fit in machine __int64");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return __uint64 value of numeral, throw if result cannot fit in
|
||||
__uint64
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
__uint64 get_numeral_uint64() const {
|
||||
assert(is_numeral());
|
||||
__uint64 result;
|
||||
if (!is_numeral_u64(result)) {
|
||||
throw exception("numeral does not fit in machine __uint64");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
operator Z3_app() const { assert(is_app()); return reinterpret_cast<Z3_app>(m_ast); }
|
||||
|
||||
|
|
|
@ -3940,7 +3940,7 @@ class ArraySortRef(SortRef):
|
|||
>>> A.range()
|
||||
Bool
|
||||
"""
|
||||
return _to_sort_ref(Z3_get_array_sort_range(self.ctx_ref(), self.ast), self.ctx)
|
||||
return _to_sort_ref(Z3_get_array_sort_range(self.ctx_ref(), self.ast), self.ctx)
|
||||
|
||||
class ArrayRef(ExprRef):
|
||||
"""Array expressions. """
|
||||
|
@ -4162,6 +4162,7 @@ def Select(a, i):
|
|||
_z3_assert(is_array(a), "First argument must be a Z3 array expression")
|
||||
return a[i]
|
||||
|
||||
|
||||
def Map(f, *args):
|
||||
"""Return a Z3 map array expression.
|
||||
|
||||
|
@ -8178,8 +8179,13 @@ class FPRef(ExprRef):
|
|||
return self
|
||||
|
||||
def __neg__(self):
|
||||
"""Create the Z3 expression `-self`."""
|
||||
return FPRef(fpNeg(self))
|
||||
"""Create the Z3 expression `-self`.
|
||||
|
||||
>>> x = FP('x', Float32())
|
||||
>>> -x
|
||||
-x
|
||||
"""
|
||||
return fpNeg(self)
|
||||
|
||||
def __div__(self, other):
|
||||
"""Create the Z3 expression `self / other`.
|
||||
|
|
|
@ -664,3 +664,45 @@ algebraic_numbers::anum const & arith_util::to_irrational_algebraic_numeral(expr
|
|||
SASSERT(is_irrational_algebraic_numeral(n));
|
||||
return plugin().aw().to_anum(to_app(n)->get_decl());
|
||||
}
|
||||
|
||||
expr_ref arith_util::mk_mul_simplify(expr_ref_vector const& args) {
|
||||
return mk_mul_simplify(args.size(), args.c_ptr());
|
||||
|
||||
}
|
||||
expr_ref arith_util::mk_mul_simplify(unsigned sz, expr* const* args) {
|
||||
expr_ref result(m_manager);
|
||||
|
||||
switch (sz) {
|
||||
case 0:
|
||||
result = mk_numeral(rational(1), true);
|
||||
break;
|
||||
case 1:
|
||||
result = args[0];
|
||||
break;
|
||||
default:
|
||||
result = mk_mul(sz, args);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref arith_util::mk_add_simplify(expr_ref_vector const& args) {
|
||||
return mk_add_simplify(args.size(), args.c_ptr());
|
||||
|
||||
}
|
||||
expr_ref arith_util::mk_add_simplify(unsigned sz, expr* const* args) {
|
||||
expr_ref result(m_manager);
|
||||
|
||||
switch (sz) {
|
||||
case 0:
|
||||
result = mk_numeral(rational(0), true);
|
||||
break;
|
||||
case 1:
|
||||
result = args[0];
|
||||
break;
|
||||
default:
|
||||
result = mk_add(sz, args);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,6 @@ protected:
|
|||
func_decl * m_mod_0_decl;
|
||||
func_decl * m_u_asin_decl;
|
||||
func_decl * m_u_acos_decl;
|
||||
|
||||
ptr_vector<app> m_small_ints;
|
||||
ptr_vector<app> m_small_reals;
|
||||
|
||||
|
@ -416,6 +415,11 @@ public:
|
|||
return m_manager.mk_eq(lhs, rhs);
|
||||
}
|
||||
|
||||
expr_ref mk_mul_simplify(expr_ref_vector const& args);
|
||||
expr_ref mk_mul_simplify(unsigned sz, expr* const* args);
|
||||
|
||||
expr_ref mk_add_simplify(expr_ref_vector const& args);
|
||||
expr_ref mk_add_simplify(unsigned sz, expr* const* args);
|
||||
};
|
||||
|
||||
#endif /* ARITH_DECL_PLUGIN_H_ */
|
||||
|
|
|
@ -1560,6 +1560,9 @@ bool ast_manager::is_unique_value(expr* e) const {
|
|||
}
|
||||
|
||||
bool ast_manager::are_equal(expr * a, expr * b) const {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
if (is_app(a) && is_app(b)) {
|
||||
app* ap = to_app(a), *bp = to_app(b);
|
||||
decl_plugin const * p = get_plugin(ap->get_family_id());
|
||||
|
|
|
@ -87,10 +87,10 @@ bool smt2_pp_environment::is_indexed_fdecl(func_decl * f) const {
|
|||
}
|
||||
|
||||
bool smt2_pp_environment::is_sort_param(func_decl * f) const {
|
||||
return
|
||||
return
|
||||
f->get_family_id() != null_family_id &&
|
||||
f->get_num_parameters() == 1 &&
|
||||
f->get_parameter(0).is_ast() &&
|
||||
f->get_num_parameters() == 1 &&
|
||||
f->get_parameter(0).is_ast() &&
|
||||
is_sort(f->get_parameter(0).get_ast()) &&
|
||||
f->get_range() == to_sort(f->get_parameter(0).get_ast());
|
||||
}
|
||||
|
@ -107,8 +107,8 @@ format * smt2_pp_environment::pp_fdecl_params(format * fname, func_decl * f) {
|
|||
ptr_buffer<format> fs;
|
||||
fs.push_back(fname);
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
SASSERT(f->get_parameter(i).is_int() ||
|
||||
f->get_parameter(i).is_rational() ||
|
||||
SASSERT(f->get_parameter(i).is_int() ||
|
||||
f->get_parameter(i).is_rational() ||
|
||||
(f->get_parameter(i).is_ast() && is_func_decl(f->get_parameter(i).get_ast())));
|
||||
if (f->get_parameter(i).is_int())
|
||||
fs.push_back(mk_int(get_manager(), f->get_parameter(i).get_int()));
|
||||
|
@ -122,7 +122,7 @@ format * smt2_pp_environment::pp_fdecl_params(format * fname, func_decl * f) {
|
|||
|
||||
format * smt2_pp_environment::pp_fdecl(func_decl * f, unsigned & len) {
|
||||
format * fname = pp_fdecl_name(f, len);
|
||||
if (f->get_family_id() == null_family_id)
|
||||
if (f->get_family_id() == null_family_id)
|
||||
return fname;
|
||||
if (is_sort_param(f)) {
|
||||
len = UINT_MAX;
|
||||
|
@ -247,7 +247,7 @@ format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits, bool u
|
|||
buf << "(_ -oo " << v.get().get_ebits() << " " << v.get().get_sbits() << ")";
|
||||
return mk_string(m, buf.c_str());
|
||||
}
|
||||
else if (fm.is_pzero(v)) {
|
||||
else if (fm.is_pzero(v)) {
|
||||
buf << "(_ +zero " << v.get().get_ebits() << " " << v.get().get_sbits() << ")";
|
||||
return mk_string(m, buf.c_str());
|
||||
}
|
||||
|
@ -257,9 +257,9 @@ format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits, bool u
|
|||
}
|
||||
else if (use_float_real_lits)
|
||||
{
|
||||
buf << "((_ to_fp " << v.get().get_ebits() << " " <<
|
||||
v.get().get_sbits() << ") RTZ " <<
|
||||
fm.to_string(v).c_str() << ")";
|
||||
buf << "((_ to_fp " << v.get().get_ebits() << " " <<
|
||||
v.get().get_sbits() << ") RTZ " <<
|
||||
fm.to_string(v).c_str() << ")";
|
||||
return mk_string(m, buf.c_str());
|
||||
}
|
||||
else {
|
||||
|
@ -283,7 +283,7 @@ format * smt2_pp_environment::pp_float_literal(app * t, bool use_bv_lits, bool u
|
|||
app_ref e_sig(m);
|
||||
e_sig = get_bvutil().mk_numeral(rational(sig), v.get().get_sbits() - 1);
|
||||
body = mk_compose(m, body, pp_bv_literal(e_sig, use_bv_lits, false));
|
||||
|
||||
|
||||
body = mk_compose(m, body, mk_string(m, ")"));
|
||||
return body;
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ format * smt2_pp_environment::pp_arith_literal(app * t, bool decimal, unsigned d
|
|||
am.display_decimal(buffer, abs_val, decimal_prec);
|
||||
}
|
||||
else {
|
||||
am.display_root_smt2(buffer, val2);
|
||||
am.display_root_smt2(buffer, val2);
|
||||
}
|
||||
vf = mk_string(get_manager(), buffer.str().c_str());
|
||||
return is_neg ? mk_neg(vf) : vf;
|
||||
|
@ -378,7 +378,7 @@ format * smt2_pp_environment::pp_string_literal(app * t) {
|
|||
buffer << encs[i];
|
||||
}
|
||||
}
|
||||
buffer << "\"";
|
||||
buffer << "\"";
|
||||
return mk_string(get_manager(), buffer.str().c_str());
|
||||
}
|
||||
|
||||
|
@ -395,7 +395,7 @@ format_ns::format * smt2_pp_environment::pp_sort(sort * s) {
|
|||
// This method is redefined in cmd_context::pp_env: support for parametric sorts.
|
||||
// Here, we just pretty print builtin sorts: Bool, Int, Real, BitVec and Array.
|
||||
ast_manager & m = get_manager();
|
||||
if (m.is_bool(s))
|
||||
if (m.is_bool(s))
|
||||
return mk_string(m, "Bool");
|
||||
if (get_autil().is_int(s))
|
||||
return mk_string(m, "Int");
|
||||
|
@ -431,7 +431,7 @@ format_ns::format * smt2_pp_environment::pp_sort(sort * s) {
|
|||
fs.push_back(pp_sort(to_sort(s->get_parameter(0).get_ast())));
|
||||
return mk_seq1(m, fs.begin(), fs.end(), f2f(), get_sutil().is_seq(s)?"Seq":"Re");
|
||||
}
|
||||
return format_ns::mk_string(get_manager(), s->get_name().str().c_str());
|
||||
return format_ns::mk_string(get_manager(), s->get_name().str().c_str());
|
||||
}
|
||||
|
||||
typedef app_ref_vector format_ref_vector;
|
||||
|
@ -449,8 +449,8 @@ class smt2_printer {
|
|||
expr2alias * m_expr2alias; // expr -> position @ m_aliased_exprs, m_aliased_pps, m_aliased_lvls_names.
|
||||
ptr_vector<expr> m_aliased_exprs;
|
||||
format_ref_vector m_aliased_pps;
|
||||
svector<std::pair<unsigned, symbol> > m_aliased_lvls_names;
|
||||
unsigned m_next_alias_idx;
|
||||
svector<std::pair<unsigned, symbol> > m_aliased_lvls_names;
|
||||
unsigned m_next_alias_idx;
|
||||
struct scope {
|
||||
unsigned m_aliased_exprs_lim;
|
||||
unsigned m_old_next_alias_idx;
|
||||
|
@ -461,7 +461,7 @@ class smt2_printer {
|
|||
svector<symbol> m_var_names;
|
||||
typedef hashtable<symbol, symbol_hash_proc, symbol_eq_proc> symbol_set;
|
||||
symbol_set m_var_names_set;
|
||||
|
||||
|
||||
struct frame {
|
||||
expr * m_curr;
|
||||
unsigned m_idx;
|
||||
|
@ -469,7 +469,7 @@ class smt2_printer {
|
|||
bool m_use_alias; // if new aliases can be created
|
||||
frame(expr * c, unsigned i, unsigned s, bool use_alias):m_curr(c), m_idx(i), m_spos(s), m_use_alias(use_alias) {}
|
||||
};
|
||||
|
||||
|
||||
svector<frame> m_frame_stack;
|
||||
format_ref_vector m_format_stack;
|
||||
struct info {
|
||||
|
@ -517,7 +517,7 @@ class smt2_printer {
|
|||
SASSERT(m_aliased_exprs.size() == m_aliased_pps.size());
|
||||
SASSERT(m_aliased_exprs.size() == m_aliased_lvls_names.size());
|
||||
unsigned idx = m_aliased_exprs.size();
|
||||
m_expr2alias->insert(n, idx);
|
||||
m_expr2alias->insert(n, idx);
|
||||
m_aliased_exprs.push_back(n);
|
||||
m_aliased_pps.push_back(nf);
|
||||
m_aliased_lvls_names.push_back(std::make_pair(lvl, name));
|
||||
|
@ -567,12 +567,12 @@ class smt2_printer {
|
|||
buf.append(")");
|
||||
f = mk_string(m(), buf.c_str());
|
||||
}
|
||||
m_format_stack.push_back(f);
|
||||
m_format_stack.push_back(f);
|
||||
m_info_stack.push_back(info(0, 1, 1));
|
||||
}
|
||||
|
||||
format * pp_attribute(char const * attr, format * f) {
|
||||
return mk_compose(m(),
|
||||
return mk_compose(m(),
|
||||
mk_string(m(), attr),
|
||||
mk_indent(m(), static_cast<unsigned>(strlen(attr)), f));
|
||||
}
|
||||
|
@ -639,7 +639,7 @@ class smt2_printer {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void process_var(var * v) {
|
||||
pp_var(v);
|
||||
pop_frame();
|
||||
|
@ -651,7 +651,7 @@ class smt2_printer {
|
|||
expr * arg = t->get_arg(fr.m_idx);
|
||||
fr.m_idx++;
|
||||
if (pp_aliased(arg))
|
||||
continue;
|
||||
continue;
|
||||
switch (arg->get_kind()) {
|
||||
case AST_VAR:
|
||||
pp_var(to_var(arg));
|
||||
|
@ -679,11 +679,11 @@ class smt2_printer {
|
|||
m_format_stack.shrink(fr.m_spos);
|
||||
m_info_stack.shrink(fr.m_spos);
|
||||
if (fr.m_use_alias && m_root != t &&
|
||||
((f_info.m_depth >= m_pp_max_depth) ||
|
||||
((f_info.m_depth >= m_pp_max_depth) ||
|
||||
((f_info.m_weight >= m_pp_min_alias_size || is_quantifier(t)) && m_soccs.is_shared(t)))) {
|
||||
symbol a = next_alias();
|
||||
TRACE("smt2_pp", tout << "a: " << a << " depth: " << f_info.m_depth << ", weight: " << f_info.m_weight
|
||||
<< ", lvl: " << f_info.m_lvl << " t: #" << t->get_id() << "\n" << mk_ll_pp(t, m())
|
||||
TRACE("smt2_pp", tout << "a: " << a << " depth: " << f_info.m_depth << ", weight: " << f_info.m_weight
|
||||
<< ", lvl: " << f_info.m_lvl << " t: #" << t->get_id() << "\n" << mk_ll_pp(t, m())
|
||||
<< ", is-shared: " << m_soccs.is_shared(t) << "\n";);
|
||||
register_alias(t, f, f_info.m_lvl, a);
|
||||
m_format_stack.push_back(mk_string(m(), a.str().c_str()));
|
||||
|
@ -745,7 +745,7 @@ class smt2_printer {
|
|||
f = mk_group(m(), mk_compose(m(),
|
||||
mk_indent(m(), 1, mk_compose(m(), mk_string(m(), "("), fname)),
|
||||
mk_indent(m(), SMALL_INDENT, mk_compose(m(),
|
||||
mk_seq<format**, f2f>(m(), it, end, f2f()),
|
||||
mk_seq<format**, f2f>(m(), it, end, f2f()),
|
||||
mk_string(m(), ")")))));
|
||||
}
|
||||
else {
|
||||
|
@ -756,7 +756,7 @@ class smt2_printer {
|
|||
mk_indent(m(), len + 2, mk_compose(m(),
|
||||
mk_string(m(), " "),
|
||||
first,
|
||||
mk_seq<format**, f2f>(m(), it, end, f2f()),
|
||||
mk_seq<format**, f2f>(m(), it, end, f2f()),
|
||||
mk_string(m(), ")")))));
|
||||
}
|
||||
}
|
||||
|
@ -832,7 +832,7 @@ class smt2_printer {
|
|||
m_expr2alias = m_expr2alias_stack[lvl];
|
||||
m_next_alias_idx = 1;
|
||||
}
|
||||
|
||||
|
||||
void end_scope() {
|
||||
TRACE("pp_scope", tout << "[end-scope] before sz: " << m_aliased_exprs.size() << ", m_root: " << m_root << "\n";);
|
||||
m_expr2alias->reset();
|
||||
|
@ -853,7 +853,7 @@ class smt2_printer {
|
|||
void register_var_names(quantifier * q) {
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
symbol name = ensure_quote_sym(q->get_decl_name(i));
|
||||
symbol name = ensure_quote_sym(q->get_decl_name(i));
|
||||
if (name.is_numerical()) {
|
||||
unsigned idx = 1;
|
||||
name = next_name("x", idx);
|
||||
|
@ -914,7 +914,7 @@ class smt2_printer {
|
|||
format * f_body = pp_let(m_format_stack.back(), num_lets);
|
||||
// The current SMT2 frontend uses weight 1 as default.
|
||||
#define MIN_WEIGHT 1
|
||||
if (q->has_patterns() || q->get_weight() > MIN_WEIGHT ||
|
||||
if (q->has_patterns() || q->get_weight() > MIN_WEIGHT ||
|
||||
q->get_skid() != symbol::null || (q->get_qid() != symbol::null && !q->get_qid().is_numerical())) {
|
||||
ptr_buffer<format> buf;
|
||||
buf.push_back(f_body);
|
||||
|
@ -952,12 +952,12 @@ class smt2_printer {
|
|||
format * fs[2] = { f_decls, f_body };
|
||||
char const * header = q->is_forall() ? "forall" : "exists";
|
||||
format * f = mk_seq3<format**, f2f>(m(), fs, fs+2, f2f(), header, 1, SMALL_INDENT);
|
||||
|
||||
|
||||
info f_info = m_info_stack.back();
|
||||
f_info.m_lvl = 0; // quantifiers don't depend on any let-decls, pp_let added all dependencies for the body.
|
||||
f_info.m_depth++;
|
||||
f_info.m_weight += q->get_num_decls()*2 + num_lets*8;
|
||||
|
||||
|
||||
unregister_var_names(q);
|
||||
end_scope();
|
||||
|
||||
|
@ -1002,7 +1002,7 @@ class smt2_printer {
|
|||
reset_stacks();
|
||||
SASSERT(&(r.get_manager()) == &(fm()));
|
||||
m_soccs(n);
|
||||
TRACE("smt2_pp_shared",
|
||||
TRACE("smt2_pp_shared",
|
||||
tout << "shared terms for:\n" << mk_pp(n, m()) << "\n";
|
||||
tout << "------>\n";
|
||||
shared_occs::iterator it = m_soccs.begin_shared();
|
||||
|
@ -1043,7 +1043,7 @@ public:
|
|||
m_env(env),
|
||||
m_soccs(m_manager),
|
||||
m_root(0),
|
||||
m_aliased_pps(fm()),
|
||||
m_aliased_pps(fm()),
|
||||
m_next_alias_idx(1),
|
||||
m_format_stack(fm()) {
|
||||
init_expr2alias_stack();
|
||||
|
@ -1108,7 +1108,7 @@ public:
|
|||
|
||||
};
|
||||
|
||||
void mk_smt2_format(expr * n, smt2_pp_environment & env, params_ref const & p,
|
||||
void mk_smt2_format(expr * n, smt2_pp_environment & env, params_ref const & p,
|
||||
unsigned num_vars, char const * var_prefix,
|
||||
format_ref & r, sbuffer<symbol> & var_names) {
|
||||
smt2_printer pr(env, p);
|
||||
|
@ -1125,13 +1125,13 @@ void mk_smt2_format(func_decl * f, smt2_pp_environment & env, params_ref const &
|
|||
pr(f, r);
|
||||
}
|
||||
|
||||
std::ostream & ast_smt2_pp(std::ostream & out, expr * n, smt2_pp_environment & env, params_ref const & p, unsigned indent,
|
||||
std::ostream & ast_smt2_pp(std::ostream & out, expr * n, smt2_pp_environment & env, params_ref const & p, unsigned indent,
|
||||
unsigned num_vars, char const * var_prefix) {
|
||||
ast_manager & m = env.get_manager();
|
||||
format_ref r(fm(m));
|
||||
sbuffer<symbol> var_names;
|
||||
mk_smt2_format(n, env, p, num_vars, var_prefix, r, var_names);
|
||||
if (indent > 0)
|
||||
if (indent > 0)
|
||||
r = mk_indent(m, indent, r.get());
|
||||
pp(out, r.get(), m, p);
|
||||
return out;
|
||||
|
@ -1142,7 +1142,7 @@ std::ostream & ast_smt2_pp(std::ostream & out, sort * s, smt2_pp_environment & e
|
|||
format_ref r(fm(m));
|
||||
sbuffer<symbol> var_names;
|
||||
mk_smt2_format(s, env, p, r);
|
||||
if (indent > 0)
|
||||
if (indent > 0)
|
||||
r = mk_indent(m, indent, r.get());
|
||||
pp(out, r.get(), m, p);
|
||||
return out;
|
||||
|
@ -1153,7 +1153,7 @@ std::ostream & ast_smt2_pp(std::ostream & out, func_decl * f, smt2_pp_environmen
|
|||
format_ref r(fm(m));
|
||||
sbuffer<symbol> var_names;
|
||||
mk_smt2_format(f, env, p, r);
|
||||
if (indent > 0)
|
||||
if (indent > 0)
|
||||
r = mk_indent(m, indent, r.get());
|
||||
pp(out, r.get(), m, p);
|
||||
return out;
|
||||
|
@ -1200,6 +1200,14 @@ std::ostream& operator<<(std::ostream& out, app_ref const& e) {
|
|||
return out << mk_ismt2_pp(e.get(), e.get_manager());
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, func_decl_ref const& e) {
|
||||
return out << mk_ismt2_pp(e.get(), e.get_manager());
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, sort_ref const& e) {
|
||||
return out << mk_ismt2_pp(e.get(), e.get_manager());
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, expr_ref_vector const& e) {
|
||||
for (unsigned i = 0; i < e.size(); ++i) {
|
||||
out << mk_ismt2_pp(e[i], e.get_manager());
|
||||
|
@ -1216,6 +1224,18 @@ std::ostream& operator<<(std::ostream& out, app_ref_vector const& e) {
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, func_decl_ref_vector const& e) {
|
||||
for (unsigned i = 0; i < e.size(); ++i)
|
||||
out << mk_ismt2_pp(e[i], e.get_manager()) << "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, sort_ref_vector const& e) {
|
||||
for (unsigned i = 0; i < e.size(); ++i)
|
||||
out << mk_ismt2_pp(e[i], e.get_manager()) << "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
void pp(expr const * n, ast_manager & m) {
|
||||
std::cout << mk_ismt2_pp(const_cast<expr*>(n), m) << std::endl;
|
||||
|
|
|
@ -117,8 +117,13 @@ std::ostream& operator<<(std::ostream& out, mk_ismt2_pp const & p);
|
|||
|
||||
std::ostream& operator<<(std::ostream& out, expr_ref const& e);
|
||||
std::ostream& operator<<(std::ostream& out, app_ref const& e);
|
||||
std::ostream& operator<<(std::ostream& out, func_decl_ref const& e);
|
||||
std::ostream& operator<<(std::ostream& out, sort_ref const& e);
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, expr_ref_vector const& e);
|
||||
std::ostream& operator<<(std::ostream& out, app_ref_vector const& e);
|
||||
std::ostream& operator<<(std::ostream& out, func_decl_ref_vector const& e);
|
||||
std::ostream& operator<<(std::ostream& out, sort_ref_vector const& e);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,7 @@ Revision History:
|
|||
#include"bv_decl_plugin.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include"fpa_decl_plugin.h"
|
||||
#include"vector.h"
|
||||
#include"for_each_ast.h"
|
||||
#include"decl_collector.h"
|
||||
|
@ -43,7 +44,7 @@ static const char m_predef_names[][8] = {
|
|||
symbol smt_renaming::fix_symbol(symbol s, int k) {
|
||||
std::ostringstream buffer;
|
||||
char const * data = s.is_numerical() ? "" : s.bare_str();
|
||||
|
||||
|
||||
if (data[0] && !data[1]) {
|
||||
switch (data[0]) {
|
||||
case '/': data = "op_div"; break;
|
||||
|
@ -51,7 +52,7 @@ symbol smt_renaming::fix_symbol(symbol s, int k) {
|
|||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (k == 0 && *data) {
|
||||
if (s.is_numerical()) {
|
||||
return s;
|
||||
|
@ -63,10 +64,10 @@ symbol smt_renaming::fix_symbol(symbol s, int k) {
|
|||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (s.is_numerical()) {
|
||||
buffer << s << k;
|
||||
return symbol(buffer.str().c_str());
|
||||
return symbol(buffer.str().c_str());
|
||||
}
|
||||
|
||||
if (is_smt2_quoted_symbol(s)) {
|
||||
|
@ -78,12 +79,12 @@ symbol smt_renaming::fix_symbol(symbol s, int k) {
|
|||
if (k > 0) {
|
||||
buffer << k;
|
||||
}
|
||||
|
||||
|
||||
return symbol(buffer.str().c_str());
|
||||
}
|
||||
|
||||
bool smt_renaming::is_legal(char c) {
|
||||
return c == '.' || c == '_' || c == '\''
|
||||
return c == '.' || c == '_' || c == '\''
|
||||
|| c == '?' || c == '!' || isalnum(c);
|
||||
}
|
||||
|
||||
|
@ -134,11 +135,11 @@ symbol smt_renaming::get_symbol(symbol s0) {
|
|||
if (m_translate.find(s0, s)) {
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
int k = 0;
|
||||
do {
|
||||
s = fix_symbol(s0, k++);
|
||||
}
|
||||
}
|
||||
while (m_rev_translate.contains(s));
|
||||
m_translate.insert(s0, s);
|
||||
m_rev_translate.insert(s, s0);
|
||||
|
@ -162,11 +163,13 @@ class smt_printer {
|
|||
arith_util m_autil;
|
||||
bv_util m_bvutil;
|
||||
seq_util m_sutil;
|
||||
fpa_util m_futil;
|
||||
family_id m_basic_fid;
|
||||
family_id m_bv_fid;
|
||||
family_id m_arith_fid;
|
||||
family_id m_array_fid;
|
||||
family_id m_dt_fid;
|
||||
family_id m_fpa_fid;
|
||||
family_id m_label_fid;
|
||||
symbol m_logic;
|
||||
symbol m_AUFLIRA;
|
||||
|
@ -176,7 +179,7 @@ class smt_printer {
|
|||
expr* m_top;
|
||||
|
||||
bool is_bool(sort* s) {
|
||||
return
|
||||
return
|
||||
m_basic_fid == s->get_family_id() &&
|
||||
s->get_decl_kind() == BOOL_SORT;
|
||||
}
|
||||
|
@ -186,13 +189,13 @@ class smt_printer {
|
|||
}
|
||||
|
||||
bool is_proof(sort* s) {
|
||||
return
|
||||
return
|
||||
m_basic_fid == s->get_family_id() &&
|
||||
s->get_decl_kind() == PROOF_SORT;
|
||||
s->get_decl_kind() == PROOF_SORT;
|
||||
}
|
||||
|
||||
bool is_proof(expr* e) {
|
||||
return is_proof(m_manager.get_sort(e));
|
||||
bool is_proof(expr* e) {
|
||||
return is_proof(m_manager.get_sort(e));
|
||||
}
|
||||
|
||||
void pp_id(expr* n) {
|
||||
|
@ -236,8 +239,8 @@ class smt_printer {
|
|||
}
|
||||
|
||||
bool is_sort_param(unsigned num_params, parameter const* params) {
|
||||
return
|
||||
num_params == 1 &&
|
||||
return
|
||||
num_params == 1 &&
|
||||
params[0].is_ast() &&
|
||||
is_sort(params[0].get_ast());
|
||||
}
|
||||
|
@ -253,14 +256,17 @@ class smt_printer {
|
|||
m_out << "String";
|
||||
return;
|
||||
}
|
||||
if (is_sort_symbol && sym != symbol("BitVec")) {
|
||||
m_out << "(" << sym << " ";
|
||||
if (is_sort_symbol &&
|
||||
sym != symbol("BitVec") &&
|
||||
sym != symbol("FloatingPoint") &&
|
||||
sym != symbol("RoundingMode")) {
|
||||
m_out << "(" << sym << " ";
|
||||
}
|
||||
else if (!is_sort_symbol && is_sort_param(num_params, params)) {
|
||||
m_out << "(as " << sym << " ";
|
||||
}
|
||||
else {
|
||||
m_out << "(_ " << sym << " ";
|
||||
m_out << "(_ " << sym << " ";
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -302,13 +308,13 @@ class smt_printer {
|
|||
m_out << "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool is_auflira() const {
|
||||
return m_logic == m_AUFLIRA;
|
||||
}
|
||||
|
||||
void visit_sort(sort* s, bool bool2int = false) {
|
||||
symbol sym;
|
||||
symbol sym;
|
||||
if (bool2int && is_bool(s) && !m_is_smt2) {
|
||||
sym = symbol("Int");
|
||||
} else if (s->is_sort_of(m_bv_fid, BV_SORT)) {
|
||||
|
@ -326,7 +332,7 @@ class smt_printer {
|
|||
else if (s->is_sort_of(m_array_fid, ARRAY_SORT) && m_is_smt2) {
|
||||
sym = "Array";
|
||||
}
|
||||
else if (s->is_sort_of(m_array_fid, ARRAY_SORT) && !m_is_smt2) {
|
||||
else if (s->is_sort_of(m_array_fid, ARRAY_SORT) && !m_is_smt2) {
|
||||
unsigned num_params = s->get_num_parameters();
|
||||
SASSERT(num_params >= 2);
|
||||
if (is_auflira()) {
|
||||
|
@ -341,12 +347,12 @@ class smt_printer {
|
|||
}
|
||||
sort* s1 = to_sort(s->get_parameter(0).get_ast());
|
||||
sort* s2 = to_sort(s->get_parameter(1).get_ast());
|
||||
if (num_params == 2 &&
|
||||
if (num_params == 2 &&
|
||||
s1->is_sort_of(m_bv_fid, BV_SORT) &&
|
||||
s2->is_sort_of(m_bv_fid, BV_SORT)) {
|
||||
m_out << "Array";
|
||||
m_out << "[" << s1->get_parameter(0).get_int();
|
||||
m_out << ":" << s2->get_parameter(0).get_int() << "]";
|
||||
m_out << ":" << s2->get_parameter(0).get_int() << "]";
|
||||
return;
|
||||
}
|
||||
m_out << "(Array ";
|
||||
|
@ -379,7 +385,7 @@ class smt_printer {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pp_arg(expr *arg, app *parent)
|
||||
{
|
||||
if (!m_is_smt2 && is_bool(arg) && is_var(arg) && parent->get_family_id() == m_basic_fid) {
|
||||
|
@ -387,7 +393,7 @@ class smt_printer {
|
|||
pp_marked_expr(arg);
|
||||
m_out << " 0))";
|
||||
} else if (!m_is_smt2 && is_bool(arg) && !is_var(arg) &&
|
||||
parent->get_family_id() != m_basic_fid &&
|
||||
parent->get_family_id() != m_basic_fid &&
|
||||
parent->get_family_id() != m_dt_fid) {
|
||||
|
||||
m_out << "(ite ";
|
||||
|
@ -403,9 +409,10 @@ class smt_printer {
|
|||
bool is_int, pos;
|
||||
buffer<symbol> names;
|
||||
unsigned bv_size;
|
||||
zstring s;
|
||||
zstring s;
|
||||
unsigned num_args = n->get_num_args();
|
||||
func_decl* decl = n->get_decl();
|
||||
scoped_mpf float_val(m_futil.fm());
|
||||
if (m_autil.is_numeral(n, val, is_int)) {
|
||||
if (val.is_neg()) {
|
||||
val.neg();
|
||||
|
@ -433,7 +440,7 @@ class smt_printer {
|
|||
m_out << encs[i];
|
||||
}
|
||||
}
|
||||
m_out << "\"";
|
||||
m_out << "\"";
|
||||
}
|
||||
else if (m_bvutil.is_numeral(n, val, bv_size)) {
|
||||
if (m_is_smt2) {
|
||||
|
@ -443,7 +450,13 @@ class smt_printer {
|
|||
m_out << "bv" << val << "[" << bv_size << "]";
|
||||
}
|
||||
}
|
||||
else if (m_bvutil.is_bit2bool(n)) {
|
||||
else if (m_futil.is_numeral(n, float_val)) {
|
||||
m_out << "((_ to_fp " <<
|
||||
float_val.get().get_ebits() << " " <<
|
||||
float_val.get().get_sbits() << ") RTZ " <<
|
||||
m_futil.fm().to_string(float_val).c_str() << ")";
|
||||
}
|
||||
else if (m_bvutil.is_bit2bool(n)) {
|
||||
unsigned bit = n->get_decl()->get_parameter(0).get_int();
|
||||
if (m_is_smt2) {
|
||||
m_out << "(= ((_ extract " << bit << " " << bit << ") ";
|
||||
|
@ -458,14 +471,14 @@ class smt_printer {
|
|||
}
|
||||
else if (m_manager.is_label(n, pos, names) && names.size() >= 1) {
|
||||
if (m_is_smt2) {
|
||||
m_out << "(! ";
|
||||
m_out << "(! ";
|
||||
pp_marked_expr(n->get_arg(0));
|
||||
m_out << (pos?":lblpos":":lblneg") << " " << m_renaming.get_symbol(names[0]) << ")";
|
||||
}
|
||||
else {
|
||||
m_out << "(" << (pos?"lblpos":"lblneg") << " " << m_renaming.get_symbol(names[0]) << " ";
|
||||
expr* ch = n->get_arg(0);
|
||||
pp_marked_expr(ch);
|
||||
pp_marked_expr(ch);
|
||||
m_out << ")";
|
||||
}
|
||||
}
|
||||
|
@ -547,13 +560,13 @@ class smt_printer {
|
|||
m_out << " ";
|
||||
}
|
||||
}
|
||||
m_out << ")";
|
||||
m_out << ")";
|
||||
}
|
||||
}
|
||||
|
||||
void print_no_lets(expr *e)
|
||||
{
|
||||
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, true, m_simplify_implies, m_is_smt2, m_indent, m_num_var_names, m_var_names);
|
||||
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, true, m_simplify_implies, m_is_smt2, m_indent, m_num_var_names, m_var_names);
|
||||
p(e);
|
||||
}
|
||||
|
||||
|
@ -565,7 +578,7 @@ class smt_printer {
|
|||
}
|
||||
|
||||
void visit_quantifier(quantifier* q) {
|
||||
m_qlists.push_back(q);
|
||||
m_qlists.push_back(q);
|
||||
|
||||
m_out << "(";
|
||||
if (q->is_forall()) {
|
||||
|
@ -588,12 +601,12 @@ class smt_printer {
|
|||
if (m_is_smt2) {
|
||||
m_out << ")";
|
||||
}
|
||||
|
||||
|
||||
if (m_is_smt2 && (q->get_num_patterns() > 0 || q->get_qid() != symbol::null)) {
|
||||
m_out << "(! ";
|
||||
}
|
||||
{
|
||||
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, false, m_is_smt2, m_simplify_implies, m_indent, m_num_var_names, m_var_names);
|
||||
smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, false, m_is_smt2, m_simplify_implies, m_indent, m_num_var_names, m_var_names);
|
||||
p(q->get_expr());
|
||||
}
|
||||
|
||||
|
@ -644,7 +657,7 @@ class smt_printer {
|
|||
void newline() {
|
||||
unsigned i = m_indent;
|
||||
m_out << "\n";
|
||||
while (i > 0) { m_out << " "; --i; }
|
||||
while (i > 0) { m_out << " "; --i; }
|
||||
}
|
||||
|
||||
void visit_var(var* v) {
|
||||
|
@ -685,15 +698,15 @@ class smt_printer {
|
|||
case AST_QUANTIFIER:
|
||||
visit_quantifier(to_quantifier(n));
|
||||
break;
|
||||
case AST_APP:
|
||||
case AST_APP:
|
||||
visit_app(to_app(n));
|
||||
break;
|
||||
case AST_VAR:
|
||||
case AST_VAR:
|
||||
visit_var(to_var(n));
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visit_expr(expr* n) {
|
||||
|
@ -714,7 +727,7 @@ class smt_printer {
|
|||
}
|
||||
m_out << ")";
|
||||
newline();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_unit(expr* n) {
|
||||
if (n->get_ref_count() <= 2 && is_small(n)) {
|
||||
|
@ -724,9 +737,9 @@ class smt_printer {
|
|||
return true;
|
||||
}
|
||||
switch(n->get_kind()) {
|
||||
case AST_VAR:
|
||||
case AST_VAR:
|
||||
return true;
|
||||
case AST_APP:
|
||||
case AST_APP:
|
||||
return to_app(n)->get_num_args() == 0;
|
||||
default:
|
||||
return false;
|
||||
|
@ -749,9 +762,9 @@ class smt_printer {
|
|||
return sz <= m_line_length;
|
||||
}
|
||||
switch(n->get_kind()) {
|
||||
case AST_QUANTIFIER:
|
||||
case AST_QUANTIFIER:
|
||||
return false;
|
||||
case AST_VAR:
|
||||
case AST_VAR:
|
||||
sz += 5;
|
||||
return sz <= m_line_length;
|
||||
case AST_APP: {
|
||||
|
@ -777,14 +790,14 @@ class smt_printer {
|
|||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool visit_children(expr* n) {
|
||||
unsigned todo_size = m_todo.size();
|
||||
switch(n->get_kind()) {
|
||||
case AST_QUANTIFIER:
|
||||
case AST_VAR:
|
||||
case AST_QUANTIFIER:
|
||||
case AST_VAR:
|
||||
break;
|
||||
case AST_APP: {
|
||||
app* a = to_app(n);
|
||||
|
@ -805,9 +818,9 @@ class smt_printer {
|
|||
}
|
||||
|
||||
public:
|
||||
smt_printer(std::ostream& out, ast_manager& m, ptr_vector<quantifier>& ql, smt_renaming& rn,
|
||||
smt_printer(std::ostream& out, ast_manager& m, ptr_vector<quantifier>& ql, smt_renaming& rn,
|
||||
symbol logic, bool no_lets, bool is_smt2, bool simplify_implies, unsigned indent, unsigned num_var_names = 0, char const* const* var_names = 0) :
|
||||
m_out(out),
|
||||
m_out(out),
|
||||
m_manager(m),
|
||||
m_qlists(ql),
|
||||
m_renaming(rn),
|
||||
|
@ -818,6 +831,7 @@ public:
|
|||
m_autil(m),
|
||||
m_bvutil(m),
|
||||
m_sutil(m),
|
||||
m_futil(m),
|
||||
m_logic(logic),
|
||||
m_AUFLIRA("AUFLIRA"),
|
||||
// It's much easier to read those testcases with that.
|
||||
|
@ -831,8 +845,9 @@ public:
|
|||
m_arith_fid = m.mk_family_id("arith");
|
||||
m_array_fid = m.mk_family_id("array");
|
||||
m_dt_fid = m.mk_family_id("datatype");
|
||||
m_fpa_fid = m.mk_family_id("fpa");
|
||||
}
|
||||
|
||||
|
||||
void operator()(expr* n) {
|
||||
m_top = n;
|
||||
if (!m_no_lets) {
|
||||
|
@ -842,7 +857,7 @@ public:
|
|||
m_todo.push_back(to_app(n)->get_arg(i));
|
||||
}
|
||||
break;
|
||||
// Don't do this for quantifiers -- they need to have the body be
|
||||
// Don't do this for quantifiers -- they need to have the body be
|
||||
// visited when the m_qlist contains the relevant quantifier.
|
||||
default:
|
||||
break;
|
||||
|
@ -867,7 +882,7 @@ public:
|
|||
|
||||
pp_marked_expr(n);
|
||||
for (unsigned i = 0; i < m_num_lets; ++i) {
|
||||
m_out << ")";
|
||||
m_out << ")";
|
||||
}
|
||||
m_mark.reset();
|
||||
m_num_lets = 0;
|
||||
|
@ -880,7 +895,7 @@ public:
|
|||
ptr_vector<func_decl> const* decls;
|
||||
ptr_vector<sort> rec_sorts;
|
||||
|
||||
rec_sorts.push_back(s);
|
||||
rec_sorts.push_back(s);
|
||||
mark.mark(s, true);
|
||||
|
||||
// collect siblings and sorts that have not already been printed.
|
||||
|
@ -905,20 +920,20 @@ public:
|
|||
}
|
||||
else {
|
||||
pp_sort_decl(mark, s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_is_smt2) {
|
||||
// TBD: datatypes may be declared parametrically.
|
||||
// TBD: datatypes may be declared parametrically.
|
||||
// get access to parametric generalization, or print
|
||||
// monomorphic specialization with a tag that gets reused at use-point.
|
||||
m_out << "(declare-datatypes () (";
|
||||
}
|
||||
else {
|
||||
m_out << ":datatypes (";
|
||||
m_out << ":datatypes (";
|
||||
}
|
||||
for (unsigned si = 0; si < rec_sorts.size(); ++si) {
|
||||
s = rec_sorts[si];
|
||||
|
@ -928,7 +943,7 @@ public:
|
|||
decls = util.get_datatype_constructors(s);
|
||||
|
||||
for (unsigned i = 0; i < decls->size(); ++i) {
|
||||
func_decl* f = (*decls)[i];
|
||||
func_decl* f = (*decls)[i];
|
||||
ptr_vector<func_decl> const& accs = *util.get_constructor_accessors(f);
|
||||
if (m_is_smt2 || accs.size() > 0) {
|
||||
m_out << "(";
|
||||
|
@ -937,7 +952,7 @@ public:
|
|||
if (!accs.empty() || !m_is_smt2) {
|
||||
m_out << " ";
|
||||
}
|
||||
for (unsigned j = 0; j < accs.size(); ++j) {
|
||||
for (unsigned j = 0; j < accs.size(); ++j) {
|
||||
func_decl* a = accs[j];
|
||||
m_out << "(" << m_renaming.get_symbol(a->get_name()) << " ";
|
||||
visit_sort(a->get_range());
|
||||
|
@ -1081,7 +1096,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
|
|||
ptr_vector<quantifier> ql;
|
||||
ast_manager& m = m_manager;
|
||||
decl_collector decls(m);
|
||||
smt_renaming rn;
|
||||
smt_renaming rn;
|
||||
|
||||
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
|
||||
decls.visit(m_assumptions[i].get());
|
||||
|
@ -1089,7 +1104,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
|
|||
for (unsigned i = 0; i < m_assumptions_star.size(); ++i) {
|
||||
decls.visit(m_assumptions_star[i].get());
|
||||
}
|
||||
decls.visit(n);
|
||||
decls.visit(n);
|
||||
|
||||
if (m.is_proof(n)) {
|
||||
strm << "(";
|
||||
|
@ -1099,7 +1114,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
|
|||
}
|
||||
if (m_source_info != symbol::null && m_source_info != symbol("")) {
|
||||
strm << "; :source { " << m_source_info << " }\n";
|
||||
}
|
||||
}
|
||||
if (m.is_bool(n)) {
|
||||
strm << "(set-info :status " << m_status << ")\n";
|
||||
}
|
||||
|
@ -1119,7 +1134,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
|
|||
if (!(*m_is_declared)(s)) {
|
||||
smt_printer p(strm, m, ql, rn, m_logic, true, true, m_simplify_implies, 0);
|
||||
p.pp_sort_decl(sort_mark, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < decls.get_num_decls(); ++i) {
|
||||
|
@ -1147,7 +1162,7 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
|
|||
strm << ")\n";
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < m_assumptions_star.size(); ++i) {
|
||||
for (unsigned i = 0; i < m_assumptions_star.size(); ++i) {
|
||||
smt_printer p(strm, m, ql, rn, m_logic, false, true, m_simplify_implies, 1);
|
||||
strm << "(assert\n ";
|
||||
p(m_assumptions_star[i].get());
|
||||
|
@ -1170,13 +1185,13 @@ void ast_smt_pp::display_smt2(std::ostream& strm, expr* n) {
|
|||
}
|
||||
else {
|
||||
p(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ast_smt_pp::display(std::ostream& strm, expr* n) {
|
||||
ptr_vector<quantifier> ql;
|
||||
decl_collector decls(m_manager);
|
||||
smt_renaming rn;
|
||||
smt_renaming rn;
|
||||
|
||||
for (unsigned i = 0; i < m_assumptions.size(); ++i) {
|
||||
decls.visit(m_assumptions[i].get());
|
||||
|
@ -1185,7 +1200,7 @@ void ast_smt_pp::display(std::ostream& strm, expr* n) {
|
|||
decls.visit(m_assumptions_star[i].get());
|
||||
}
|
||||
decls.visit(n);
|
||||
|
||||
|
||||
strm << "(benchmark ";
|
||||
|
||||
if (m_benchmark_name != symbol::null) {
|
||||
|
@ -1214,8 +1229,8 @@ void ast_smt_pp::display(std::ostream& strm, expr* n) {
|
|||
sort* s = decls.get_sorts()[i];
|
||||
if (!(*m_is_declared)(s)) {
|
||||
smt_printer p(strm, m_manager, ql, rn, m_logic, true, false, m_simplify_implies, 0);
|
||||
p.pp_sort_decl(sort_mark, s);
|
||||
}
|
||||
p.pp_sort_decl(sort_mark, s);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < decls.get_num_decls(); ++i) {
|
||||
|
@ -1242,14 +1257,14 @@ void ast_smt_pp::display(std::ostream& strm, expr* n) {
|
|||
expr * e = m_assumptions[i].get();
|
||||
strm << ":assumption\n";
|
||||
smt_printer p(strm, m_manager, ql, rn, m_logic, false, false, m_simplify_implies, 0);
|
||||
p(e);
|
||||
strm << "\n";
|
||||
p(e);
|
||||
strm << "\n";
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < m_assumptions_star.size(); ++i) {
|
||||
strm << ":assumption-core\n";
|
||||
smt_printer p(strm, m_manager, ql, rn, m_logic, false, false, m_simplify_implies, 0);
|
||||
p(m_assumptions_star[i].get());
|
||||
p(m_assumptions_star[i].get());
|
||||
strm << "\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -170,7 +170,6 @@ app* mk_and(ast_manager & m, unsigned num_args, app * const * args) {
|
|||
return to_app(mk_and(m, num_args, (expr* const*) args));
|
||||
}
|
||||
|
||||
|
||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
if (num_args == 0)
|
||||
return m.mk_false();
|
||||
|
@ -188,10 +187,43 @@ expr * mk_not(ast_manager & m, expr * arg) {
|
|||
expr * atom;
|
||||
if (m.is_not(arg, atom))
|
||||
return atom;
|
||||
else if (m.is_true(arg))
|
||||
return m.mk_false();
|
||||
else if (m.is_false(arg))
|
||||
return m.mk_true();
|
||||
else
|
||||
return m.mk_not(arg);
|
||||
}
|
||||
|
||||
expr_ref push_not(const expr_ref& e) {
|
||||
ast_manager& m = e.get_manager();
|
||||
if (!is_app(e)) {
|
||||
return expr_ref(m.mk_not(e), m);
|
||||
}
|
||||
app* a = to_app(e);
|
||||
if (m.is_and(a)) {
|
||||
if (a->get_num_args() == 0) {
|
||||
return expr_ref(m.mk_false(), m);
|
||||
}
|
||||
expr_ref_vector args(m);
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
args.push_back(push_not(expr_ref(a->get_arg(i), m)));
|
||||
}
|
||||
return mk_or(args);
|
||||
}
|
||||
if (m.is_or(a)) {
|
||||
if (a->get_num_args() == 0) {
|
||||
return expr_ref(m.mk_true(), m);
|
||||
}
|
||||
expr_ref_vector args(m);
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
args.push_back(push_not(expr_ref(a->get_arg(i), m)));
|
||||
}
|
||||
return mk_and(args);
|
||||
}
|
||||
return expr_ref(mk_not(m, e), m);
|
||||
}
|
||||
|
||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
expr_ref_buffer new_diseqs(m);
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
|
@ -201,6 +233,24 @@ expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args)
|
|||
return mk_and(m, new_diseqs.size(), new_diseqs.c_ptr());
|
||||
}
|
||||
|
||||
expr* mk_distinct(ast_manager& m, unsigned num_args, expr * const * args) {
|
||||
switch (num_args) {
|
||||
case 0:
|
||||
case 1:
|
||||
return m.mk_true();
|
||||
case 2:
|
||||
return m.mk_not(m.mk_eq(args[0], args[1]));
|
||||
default:
|
||||
return m.mk_distinct(num_args, args);
|
||||
}
|
||||
}
|
||||
|
||||
expr_ref mk_distinct(expr_ref_vector const& args) {
|
||||
ast_manager& m = args.get_manager();
|
||||
return expr_ref(mk_distinct(m, args.size(), args.c_ptr()), m);
|
||||
}
|
||||
|
||||
|
||||
void flatten_and(expr_ref_vector& result) {
|
||||
ast_manager& m = result.get_manager();
|
||||
expr* e1, *e2, *e3;
|
||||
|
|
|
@ -121,18 +121,29 @@ app * mk_or(ast_manager & m, unsigned num_args, app * const * args);
|
|||
inline app_ref mk_or(app_ref_vector const& args) { return app_ref(mk_or(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
|
||||
inline expr_ref mk_or(expr_ref_vector const& args) { return expr_ref(mk_or(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
|
||||
|
||||
|
||||
/**
|
||||
Return a if arg = (not a)
|
||||
Retur (not arg) otherwise
|
||||
*/
|
||||
expr * mk_not(ast_manager & m, expr * arg);
|
||||
|
||||
/**
|
||||
Negate and push over conjunction or disjunction.
|
||||
*/
|
||||
expr_ref push_not(const expr_ref& arg);
|
||||
|
||||
/**
|
||||
Return the expression (and (not (= args[0] args[1])) (not (= args[0] args[2])) ... (not (= args[num_args-2] args[num_args-1])))
|
||||
*/
|
||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
|
||||
/**
|
||||
Create simplified distinct term. Binary distinct becomes a single disequality.
|
||||
*/
|
||||
expr * mk_distinct(ast_manager& m, unsigned num_args, expr * const * args);
|
||||
|
||||
expr_ref mk_distinct(expr_ref_vector const& args);
|
||||
|
||||
/**
|
||||
\brief Collect top-level conjunctions and disjunctions.
|
||||
*/
|
||||
|
|
|
@ -865,6 +865,12 @@ sort * bv_util::mk_sort(unsigned bv_size) {
|
|||
return m_manager.mk_sort(get_fid(), BV_SORT, 1, p);
|
||||
}
|
||||
|
||||
unsigned bv_util::get_int2bv_size(parameter const& p) {
|
||||
int sz;
|
||||
VERIFY(m_plugin->get_int2bv_size(1, &p, sz));
|
||||
return static_cast<unsigned>(sz);
|
||||
}
|
||||
|
||||
app * bv_util::mk_bv2int(expr* e) {
|
||||
sort* s = m_manager.mk_sort(m_manager.mk_family_id("arith"), INT_SORT);
|
||||
parameter p(s);
|
||||
|
|
|
@ -234,7 +234,6 @@ protected:
|
|||
|
||||
func_decl * mk_mkbv(unsigned arity, sort * const * domain);
|
||||
|
||||
bool get_int2bv_size(unsigned num_parameters, parameter const * parameters, int & result);
|
||||
|
||||
func_decl * mk_num_decl(unsigned num_parameters, parameter const * parameters, unsigned arity);
|
||||
|
||||
|
@ -267,6 +266,8 @@ public:
|
|||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
bool get_int2bv_size(unsigned num_parameters, parameter const * parameters, int & result);
|
||||
|
||||
virtual bool is_considered_uninterpreted(func_decl * f) {
|
||||
if (f->get_family_id() != get_family_id())
|
||||
return false;
|
||||
|
@ -390,6 +391,8 @@ public:
|
|||
return static_cast<unsigned>(s->get_parameter(0).get_int());
|
||||
}
|
||||
unsigned get_bv_size(expr const * n) const { return get_bv_size(m_manager.get_sort(n)); }
|
||||
unsigned get_int2bv_size(parameter const& p);
|
||||
|
||||
|
||||
app * mk_ule(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_ULEQ, arg1, arg2); }
|
||||
app * mk_sle(expr * arg1, expr * arg2) { return m_manager.mk_app(get_fid(), OP_SLEQ, arg1, arg2); }
|
||||
|
@ -427,6 +430,7 @@ public:
|
|||
app * mk_bvumul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUMUL_NO_OVFL, n, m); }
|
||||
|
||||
app * mk_bv(unsigned n, expr* const* es) { return m_manager.mk_app(get_fid(), OP_MKBV, n, es); }
|
||||
|
||||
};
|
||||
|
||||
#endif /* BV_DECL_PLUGIN_H_ */
|
||||
|
|
|
@ -1000,3 +1000,25 @@ void datatype_util::display_datatype(sort *s0, std::ostream& strm) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
bool datatype_util::is_func_decl(datatype_op_kind k, unsigned num_params, parameter const* params, func_decl* f) {
|
||||
bool eq =
|
||||
f->get_decl_kind() == k &&
|
||||
f->get_family_id() == m_family_id &&
|
||||
f->get_num_parameters() == num_params;
|
||||
for (unsigned i = 0; eq && i < num_params; ++i) {
|
||||
eq = params[i] == f->get_parameter(i);
|
||||
}
|
||||
return eq;
|
||||
}
|
||||
|
||||
bool datatype_util::is_constructor_of(unsigned num_params, parameter const* params, func_decl* f) {
|
||||
return
|
||||
num_params == 2 &&
|
||||
m_family_id == f->get_family_id() &&
|
||||
OP_DT_CONSTRUCTOR == f->get_decl_kind() &&
|
||||
2 == f->get_num_parameters() &&
|
||||
params[0] == f->get_parameter(0) &&
|
||||
params[1] == f->get_parameter(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -209,6 +209,8 @@ public:
|
|||
func_decl * get_recognizer_constructor(func_decl * recognizer);
|
||||
family_id get_family_id() const { return m_family_id; }
|
||||
bool are_siblings(sort * s1, sort * s2);
|
||||
bool is_func_decl(datatype_op_kind k, unsigned num_params, parameter const* params, func_decl* f);
|
||||
bool is_constructor_of(unsigned num_params, parameter const* params, func_decl* f);
|
||||
void reset();
|
||||
void display_datatype(sort *s, std::ostream& strm);
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@ Notes:
|
|||
|
||||
void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
|
||||
if (num_bound == 0) {
|
||||
result = n;
|
||||
return;
|
||||
}
|
||||
expr * curr = 0, *b = 0;
|
||||
SASSERT(n->get_ref_count() > 0);
|
||||
|
||||
|
@ -106,3 +110,27 @@ void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* cons
|
|||
expr_abstractor abs(m);
|
||||
abs(base, num_bound, bound, n, result);
|
||||
}
|
||||
|
||||
expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
expr_ref result(m);
|
||||
expr_abstract(m, 0, num_bound, (expr* const*)bound, n, result);
|
||||
if (num_bound > 0) {
|
||||
ptr_vector<sort> sorts;
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < num_bound; ++i) {
|
||||
sorts.push_back(m.get_sort(bound[i]));
|
||||
names.push_back(bound[i]->get_decl()->get_name());
|
||||
}
|
||||
result = m.mk_quantifier(is_forall, num_bound, sorts.c_ptr(), names.c_ptr(), result);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
expr_ref mk_forall(ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
return mk_quantifier(true, m, num_bound, bound, n);
|
||||
}
|
||||
|
||||
expr_ref mk_exists(ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
return mk_quantifier(false, m, num_bound, bound, n);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ public:
|
|||
};
|
||||
|
||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result);
|
||||
expr_ref mk_forall(ast_manager& m, unsigned num_bound, app* const* bound, expr* n);
|
||||
expr_ref mk_exists(ast_manager& m, unsigned num_bound, app* const* bound, expr* n);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -980,6 +980,9 @@ void fpa2bv_converter::mk_rem(func_decl * f, unsigned num, expr * const * args,
|
|||
x = args[0];
|
||||
y = args[1];
|
||||
|
||||
TRACE("fpa2bv_rem", tout << "X = " << mk_ismt2_pp(x, m) << std::endl;
|
||||
tout << "Y = " << mk_ismt2_pp(y, m) << std::endl;);
|
||||
|
||||
expr_ref nan(m), nzero(m), pzero(m), ninf(m), pinf(m);
|
||||
mk_nan(f, nan);
|
||||
mk_nzero(f, nzero);
|
||||
|
@ -1039,6 +1042,15 @@ void fpa2bv_converter::mk_rem(func_decl * f, unsigned num, expr * const * args,
|
|||
unpack(x, a_sgn, a_sig, a_exp, a_lz, true);
|
||||
unpack(y, b_sgn, b_sig, b_exp, b_lz, true);
|
||||
|
||||
dbg_decouple("fpa2bv_rem_a_sgn", a_sgn);
|
||||
dbg_decouple("fpa2bv_rem_a_sig", a_sig);
|
||||
dbg_decouple("fpa2bv_rem_a_exp", a_exp);
|
||||
dbg_decouple("fpa2bv_rem_a_lz", a_lz);
|
||||
dbg_decouple("fpa2bv_rem_b_sgn", b_sgn);
|
||||
dbg_decouple("fpa2bv_rem_b_sig", b_sig);
|
||||
dbg_decouple("fpa2bv_rem_b_exp", b_exp);
|
||||
dbg_decouple("fpa2bv_rem_b_lz", b_lz);
|
||||
|
||||
BVSLT(a_exp, b_exp, c6);
|
||||
v6 = x;
|
||||
|
||||
|
@ -1052,15 +1064,25 @@ void fpa2bv_converter::mk_rem(func_decl * f, unsigned num, expr * const * args,
|
|||
unsigned int max_exp_diff_ui = (unsigned int)m_mpz_manager.get_uint64(max_exp_diff);
|
||||
m_mpz_manager.del(max_exp_diff);
|
||||
|
||||
expr_ref a_exp_ext(m), b_exp_ext(m);
|
||||
a_exp_ext = m_bv_util.mk_sign_extend(2, a_exp);
|
||||
b_exp_ext = m_bv_util.mk_sign_extend(2, b_exp);
|
||||
|
||||
expr_ref a_lz_ext(m), b_lz_ext(m);
|
||||
a_lz_ext = m_bv_util.mk_zero_extend(2, a_lz);
|
||||
b_lz_ext = m_bv_util.mk_zero_extend(2, b_lz);
|
||||
|
||||
expr_ref exp_diff(m);
|
||||
exp_diff = m_bv_util.mk_bv_sub(a_exp, b_exp);
|
||||
exp_diff = m_bv_util.mk_bv_sub(
|
||||
m_bv_util.mk_bv_sub(a_exp_ext, a_lz_ext),
|
||||
m_bv_util.mk_bv_sub(b_exp_ext, b_lz_ext));
|
||||
dbg_decouple("fpa2bv_rem_exp_diff", exp_diff);
|
||||
|
||||
// CMW: This creates _huge_ bit-vectors, which is potentially sub-optimal,
|
||||
// but calculating this via rem = x - y * nearest(x/y) creates huge circuits.
|
||||
expr_ref huge_sig(m), shifted_sig(m), huge_rem(m);
|
||||
huge_sig = m_bv_util.mk_zero_extend(max_exp_diff_ui, a_sig);
|
||||
shifted_sig = m_bv_util.mk_bv_shl(huge_sig, m_bv_util.mk_zero_extend(max_exp_diff_ui + sbits - ebits, exp_diff));
|
||||
shifted_sig = m_bv_util.mk_bv_shl(huge_sig, m_bv_util.mk_zero_extend(max_exp_diff_ui + sbits - ebits - 2, exp_diff));
|
||||
huge_rem = m_bv_util.mk_bv_urem(shifted_sig, m_bv_util.mk_zero_extend(max_exp_diff_ui, b_sig));
|
||||
dbg_decouple("fpa2bv_rem_huge_rem", huge_rem);
|
||||
|
||||
|
@ -1068,7 +1090,8 @@ void fpa2bv_converter::mk_rem(func_decl * f, unsigned num, expr * const * args,
|
|||
res_sgn = a_sgn;
|
||||
res_sig = m_bv_util.mk_concat(m_bv_util.mk_extract(sbits, 0, huge_rem),
|
||||
m_bv_util.mk_numeral(0, 3));
|
||||
res_exp = m_bv_util.mk_sign_extend(2, b_exp);
|
||||
|
||||
res_exp = m_bv_util.mk_bv_sub(b_exp_ext, b_lz_ext);
|
||||
|
||||
// CMW: Actual rounding is not necessary here, this is
|
||||
// just convenience to get rid of the extra bits.
|
||||
|
@ -1155,38 +1178,34 @@ expr_ref fpa2bv_converter::mk_min_unspecified(func_decl * f, expr * x, expr * y)
|
|||
expr_ref res(m);
|
||||
|
||||
// The only cases in which min is unspecified for is when the arguments are +0.0 and -0.0.
|
||||
// There is no "hardware interpretation" for fp.min.
|
||||
|
||||
if (m_hi_fp_unspecified)
|
||||
// The hardware interpretation is -0.0.
|
||||
mk_nzero(f, res);
|
||||
else {
|
||||
std::pair<app*, app*> decls(0, 0);
|
||||
if (!m_specials.find(f, decls)) {
|
||||
decls.first = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
decls.second = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
m_specials.insert(f, decls);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(decls.first);
|
||||
m.inc_ref(decls.second);
|
||||
}
|
||||
|
||||
expr_ref pn(m), np(m);
|
||||
mk_fp(decls.first,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
pn);
|
||||
mk_fp(decls.second,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
np);
|
||||
|
||||
expr_ref x_is_pzero(m), x_is_nzero(m), xyzero(m);
|
||||
mk_is_pzero(x, x_is_pzero);
|
||||
mk_is_nzero(y, x_is_nzero);
|
||||
m_simp.mk_and(x_is_pzero, x_is_nzero, xyzero);
|
||||
mk_ite(xyzero, pn, np, res);
|
||||
std::pair<app*, app*> decls(0, 0);
|
||||
if (!m_specials.find(f, decls)) {
|
||||
decls.first = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
decls.second = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
m_specials.insert(f, decls);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(decls.first);
|
||||
m.inc_ref(decls.second);
|
||||
}
|
||||
|
||||
expr_ref pn(m), np(m);
|
||||
mk_fp(decls.first,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
pn);
|
||||
mk_fp(decls.second,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
np);
|
||||
|
||||
expr_ref x_is_pzero(m), x_is_nzero(m), xyzero(m);
|
||||
mk_is_pzero(x, x_is_pzero);
|
||||
mk_is_nzero(y, x_is_nzero);
|
||||
m_simp.mk_and(x_is_pzero, x_is_nzero, xyzero);
|
||||
mk_ite(xyzero, pn, np, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1244,38 +1263,34 @@ expr_ref fpa2bv_converter::mk_max_unspecified(func_decl * f, expr * x, expr * y)
|
|||
expr_ref res(m);
|
||||
|
||||
// The only cases in which max is unspecified for is when the arguments are +0.0 and -0.0.
|
||||
// There is no "hardware interpretation" for fp.max.
|
||||
|
||||
if (m_hi_fp_unspecified)
|
||||
// The hardware interpretation is +0.0.
|
||||
mk_pzero(f, res);
|
||||
else {
|
||||
std::pair<app*, app*> decls(0, 0);
|
||||
if (!m_specials.find(f, decls)) {
|
||||
decls.first = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
decls.second = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
m_specials.insert(f, decls);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(decls.first);
|
||||
m.inc_ref(decls.second);
|
||||
}
|
||||
|
||||
expr_ref pn(m), np(m);
|
||||
mk_fp(decls.first,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
pn);
|
||||
mk_fp(decls.second,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
np);
|
||||
|
||||
expr_ref x_is_pzero(m), x_is_nzero(m), xyzero(m);
|
||||
mk_is_pzero(x, x_is_pzero);
|
||||
mk_is_nzero(y, x_is_nzero);
|
||||
m_simp.mk_and(x_is_pzero, x_is_nzero, xyzero);
|
||||
mk_ite(xyzero, pn, np, res);
|
||||
std::pair<app*, app*> decls(0, 0);
|
||||
if (!m_specials.find(f, decls)) {
|
||||
decls.first = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
decls.second = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
m_specials.insert(f, decls);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(decls.first);
|
||||
m.inc_ref(decls.second);
|
||||
}
|
||||
|
||||
expr_ref pn(m), np(m);
|
||||
mk_fp(decls.first,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
pn);
|
||||
mk_fp(decls.second,
|
||||
m_bv_util.mk_numeral(0, ebits),
|
||||
m_bv_util.mk_numeral(0, sbits - 1),
|
||||
np);
|
||||
|
||||
expr_ref x_is_pzero(m), x_is_nzero(m), xyzero(m);
|
||||
mk_is_pzero(x, x_is_pzero);
|
||||
mk_is_nzero(y, x_is_nzero);
|
||||
m_simp.mk_and(x_is_pzero, x_is_nzero, xyzero);
|
||||
mk_ite(xyzero, pn, np, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -2366,7 +2381,7 @@ void fpa2bv_converter::mk_to_fp_float(func_decl * f, sort * s, expr * rm, expr *
|
|||
|
||||
void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * x, expr_ref & result) {
|
||||
TRACE("fpa2bv_to_fp_real", tout << "rm: " << mk_ismt2_pp(rm, m) << std::endl <<
|
||||
"x: " << mk_ismt2_pp(x, m) << std::endl;);
|
||||
"x: " << mk_ismt2_pp(x, m) << std::endl;);
|
||||
SASSERT(m_util.is_float(s));
|
||||
SASSERT(au().is_real(x) || au().is_int(x));
|
||||
SASSERT(is_app_of(rm, m_util.get_family_id(), OP_FPA_INTERNAL_RM));
|
||||
|
@ -2632,8 +2647,8 @@ void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * ar
|
|||
tout << "exp2 = " << mk_ismt2_pp(exp2, m) << std::endl;);
|
||||
|
||||
result = m.mk_ite(x_is_zero, zero, res);
|
||||
result = m.mk_ite(x_is_inf, mk_to_real_unspecified(), result);
|
||||
result = m.mk_ite(x_is_nan, mk_to_real_unspecified(), result);
|
||||
result = m.mk_ite(x_is_inf, mk_to_real_unspecified(ebits, sbits), result);
|
||||
result = m.mk_ite(x_is_nan, mk_to_real_unspecified(ebits, sbits), result);
|
||||
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
@ -2912,9 +2927,29 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con
|
|||
|
||||
void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 1);
|
||||
expr_ref x(m), x_is_nan(m);
|
||||
expr * sgn, * s, * e;
|
||||
split_fp(args[0], sgn, e, s);
|
||||
result = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s);
|
||||
x = args[0];
|
||||
split_fp(x, sgn, e, s);
|
||||
mk_is_nan(x, x_is_nan);
|
||||
|
||||
sort * fp_srt = m.get_sort(x);
|
||||
unsigned ebits = m_util.get_ebits(fp_srt);
|
||||
unsigned sbits = m_util.get_sbits(fp_srt);
|
||||
|
||||
expr_ref nanv(m);
|
||||
if (m_hi_fp_unspecified)
|
||||
// The "hardware interpretation" is 01...10...01.
|
||||
nanv = m_bv_util.mk_concat(m_bv_util.mk_numeral(0, 1),
|
||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(-1, ebits),
|
||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(0, sbits - 2),
|
||||
m_bv_util.mk_numeral(1, 1))));
|
||||
else
|
||||
nanv = mk_to_ieee_bv_unspecified(ebits, sbits);
|
||||
|
||||
result = m.mk_ite(x_is_nan, nanv, m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s));
|
||||
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args, bool is_signed, expr_ref & result) {
|
||||
|
@ -2950,7 +2985,7 @@ void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args
|
|||
c1 = m.mk_or(x_is_nan, x_is_inf, m.mk_and(x_is_neg, m.mk_not(x_is_nzero)));
|
||||
else
|
||||
c1 = m.mk_or(x_is_nan, x_is_inf);
|
||||
v1 = mk_to_ubv_unspecified(bv_sz);
|
||||
v1 = mk_to_ubv_unspecified(ebits, sbits, bv_sz);
|
||||
dbg_decouple("fpa2bv_to_bv_c1", c1);
|
||||
|
||||
// +-Zero -> 0
|
||||
|
@ -3049,8 +3084,8 @@ void fpa2bv_converter::mk_to_bv(func_decl * f, unsigned num, expr * const * args
|
|||
|
||||
dbg_decouple("fpa2bv_to_bv_rnd", rnd);
|
||||
|
||||
result = m.mk_ite(rnd_has_overflown, mk_to_ubv_unspecified(bv_sz), rnd);
|
||||
result = m.mk_ite(c_in_limits, result, mk_to_ubv_unspecified(bv_sz));
|
||||
result = m.mk_ite(rnd_has_overflown, mk_to_ubv_unspecified(ebits, sbits, bv_sz), rnd);
|
||||
result = m.mk_ite(c_in_limits, result, mk_to_ubv_unspecified(ebits, sbits, bv_sz));
|
||||
result = m.mk_ite(c2, v2, result);
|
||||
result = m.mk_ite(c1, v1, result);
|
||||
|
||||
|
@ -3069,25 +3104,100 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg
|
|||
mk_to_bv(f, num, args, true, result);
|
||||
}
|
||||
|
||||
expr_ref fpa2bv_converter::mk_to_ubv_unspecified(unsigned width) {
|
||||
expr_ref fpa2bv_converter::mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||
expr_ref result(m);
|
||||
if (m_hi_fp_unspecified)
|
||||
return expr_ref(m_bv_util.mk_numeral(0, width), m);
|
||||
else
|
||||
return expr_ref(m_util.mk_internal_to_ubv_unspecified(width), m);
|
||||
result = m_bv_util.mk_numeral(0, width);
|
||||
else {
|
||||
app_ref unspec(m);
|
||||
unspec = m_util.mk_internal_to_ubv_unspecified(ebits, sbits, width);
|
||||
func_decl * unspec_fd = unspec->get_decl();
|
||||
func_decl * fd;
|
||||
if (!m_uf2bvuf.find(unspec_fd, fd)) {
|
||||
app_ref bvc(m);
|
||||
bvc = m.mk_fresh_const(0, unspec_fd->get_range());
|
||||
fd = bvc->get_decl();
|
||||
m_uf2bvuf.insert(unspec_fd, fd);
|
||||
m.inc_ref(unspec_fd);
|
||||
m.inc_ref(fd);
|
||||
}
|
||||
result = m.mk_const(fd);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref fpa2bv_converter::mk_to_sbv_unspecified(unsigned width) {
|
||||
expr_ref fpa2bv_converter::mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||
expr_ref result(m);
|
||||
if (m_hi_fp_unspecified)
|
||||
return expr_ref(m_bv_util.mk_numeral(0, width), m);
|
||||
else
|
||||
return expr_ref(m_util.mk_internal_to_sbv_unspecified(width), m);
|
||||
result = m_bv_util.mk_numeral(0, width);
|
||||
else {
|
||||
app_ref unspec(m);
|
||||
unspec = m_util.mk_internal_to_sbv_unspecified(ebits, sbits, width);
|
||||
func_decl * unspec_fd = unspec->get_decl();
|
||||
func_decl * fd;
|
||||
if (!m_uf2bvuf.find(unspec_fd, fd)) {
|
||||
app_ref bvc(m);
|
||||
bvc = m.mk_fresh_const(0, unspec_fd->get_range());
|
||||
fd = bvc->get_decl();
|
||||
m_uf2bvuf.insert(unspec_fd, fd);
|
||||
m.inc_ref(unspec_fd);
|
||||
m.inc_ref(fd);
|
||||
}
|
||||
result = m.mk_const(fd);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref fpa2bv_converter::mk_to_real_unspecified() {
|
||||
expr_ref fpa2bv_converter::mk_to_real_unspecified(unsigned ebits, unsigned sbits) {
|
||||
expr_ref result(m);
|
||||
if (m_hi_fp_unspecified)
|
||||
return expr_ref(m_arith_util.mk_numeral(rational(0), false), m);
|
||||
else
|
||||
return expr_ref(m_util.mk_internal_to_real_unspecified(), m);
|
||||
result = m_arith_util.mk_numeral(rational(0), false);
|
||||
else {
|
||||
app_ref unspec(m);
|
||||
unspec = m_util.mk_internal_to_real_unspecified(ebits, sbits);
|
||||
func_decl * unspec_fd = unspec->get_decl();
|
||||
func_decl * fd;
|
||||
if (!m_uf2bvuf.find(unspec_fd, fd)) {
|
||||
app_ref bvc(m);
|
||||
bvc = m.mk_fresh_const(0, unspec_fd->get_range());
|
||||
fd = bvc->get_decl();
|
||||
m_uf2bvuf.insert(unspec_fd, fd);
|
||||
m.inc_ref(unspec_fd);
|
||||
m.inc_ref(fd);
|
||||
}
|
||||
result = m.mk_const(fd);
|
||||
result = unspec;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref fpa2bv_converter::mk_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits) {
|
||||
expr_ref result(m);
|
||||
|
||||
app_ref unspec(m);
|
||||
unspec = m_util.mk_internal_to_ieee_bv_unspecified(ebits, sbits);
|
||||
func_decl * unspec_fd = unspec->get_decl();
|
||||
func_decl * fd;
|
||||
if (!m_uf2bvuf.find(unspec_fd, fd)) {
|
||||
app_ref bvc(m);
|
||||
bvc = m.mk_fresh_const(0, unspec_fd->get_range());
|
||||
fd = bvc->get_decl();
|
||||
m_uf2bvuf.insert(unspec_fd, fd);
|
||||
m.inc_ref(unspec_fd);
|
||||
m.inc_ref(fd);
|
||||
}
|
||||
result = m.mk_const(fd);
|
||||
|
||||
app_ref mask(m), extra(m);
|
||||
mask = m_bv_util.mk_concat(m_bv_util.mk_numeral(0, 1),
|
||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(-1, ebits),
|
||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(0, sbits - 2),
|
||||
m_bv_util.mk_numeral(1, 1))));
|
||||
expr * args[2] = { result, mask };
|
||||
extra = m.mk_eq(m.mk_app(m_bv_util.get_fid(), OP_BAND, 2, args), mask);
|
||||
m_extra_assertions.push_back(extra);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_rm(expr * bv3, expr_ref & result) {
|
||||
|
|
|
@ -134,9 +134,10 @@ public:
|
|||
void mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
virtual expr_ref mk_max_unspecified(func_decl * f, expr * x, expr * y);
|
||||
|
||||
expr_ref mk_to_ubv_unspecified(unsigned width);
|
||||
expr_ref mk_to_sbv_unspecified(unsigned width);
|
||||
expr_ref mk_to_real_unspecified();
|
||||
expr_ref mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||
expr_ref mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||
expr_ref mk_to_real_unspecified(unsigned ebits, unsigned sbits);
|
||||
expr_ref mk_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits);
|
||||
|
||||
void reset(void);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ fpa2bv_rewriter_cfg::fpa2bv_rewriter_cfg(ast_manager & m, fpa2bv_converter & c,
|
|||
m_manager(m),
|
||||
m_out(m),
|
||||
m_conv(c),
|
||||
m_bindings(m)
|
||||
m_bindings(m)
|
||||
{
|
||||
updt_params(p);
|
||||
// We need to make sure that the mananger has the BV plugin loaded.
|
||||
|
@ -49,7 +49,7 @@ void fpa2bv_rewriter_cfg::updt_params(params_ref const & p) {
|
|||
updt_local_params(p);
|
||||
}
|
||||
|
||||
bool fpa2bv_rewriter_cfg::max_steps_exceeded(unsigned num_steps) const {
|
||||
bool fpa2bv_rewriter_cfg::max_steps_exceeded(unsigned num_steps) const {
|
||||
cooperate("fpa2bv");
|
||||
return num_steps > m_max_steps;
|
||||
}
|
||||
|
@ -57,22 +57,22 @@ bool fpa2bv_rewriter_cfg::max_steps_exceeded(unsigned num_steps) const {
|
|||
|
||||
br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
TRACE("fpa2bv_rw", tout << "APP: " << f->get_name() << std::endl; );
|
||||
|
||||
|
||||
if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_float(f->get_range())) {
|
||||
m_conv.mk_const(f, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
||||
if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_rm(f->get_range())) {
|
||||
m_conv.mk_rm_const(f, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
||||
if (m().is_eq(f)) {
|
||||
SASSERT(num == 2);
|
||||
TRACE("fpa2bv_rw", tout << "(= " << mk_ismt2_pp(args[0], m()) << " " <<
|
||||
TRACE("fpa2bv_rw", tout << "(= " << mk_ismt2_pp(args[0], m()) << " " <<
|
||||
mk_ismt2_pp(args[1], m()) << ")" << std::endl;);
|
||||
SASSERT(m().get_sort(args[0]) == m().get_sort(args[1]));
|
||||
SASSERT(m().get_sort(args[0]) == m().get_sort(args[1]));
|
||||
sort * ds = f->get_domain()[0];
|
||||
if (m_conv.is_float(ds)) {
|
||||
m_conv.mk_eq(args[0], args[1], result);
|
||||
|
@ -100,7 +100,7 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
||||
if (m_conv.is_float_family(f)) {
|
||||
switch (f->get_decl_kind()) {
|
||||
case OP_FPA_RM_NEAREST_TIES_TO_AWAY:
|
||||
|
@ -108,7 +108,7 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
case OP_FPA_RM_TOWARD_NEGATIVE:
|
||||
case OP_FPA_RM_TOWARD_POSITIVE:
|
||||
case OP_FPA_RM_TOWARD_ZERO: m_conv.mk_rounding_mode(f, result); return BR_DONE;
|
||||
case OP_FPA_NUM: m_conv.mk_numeral(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_NUM: m_conv.mk_numeral(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_PLUS_INF: m_conv.mk_pinf(f, result); return BR_DONE;
|
||||
case OP_FPA_MINUS_INF: m_conv.mk_ninf(f, result); return BR_DONE;
|
||||
case OP_FPA_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE;
|
||||
|
@ -120,7 +120,7 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
case OP_FPA_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
|
||||
|
@ -129,7 +129,7 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
case OP_FPA_GT: m_conv.mk_float_gt(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_LE: m_conv.mk_float_le(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_GE: m_conv.mk_float_ge(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_IS_ZERO: m_conv.mk_is_zero(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_IS_NAN: m_conv.mk_is_nan(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE;
|
||||
|
@ -143,21 +143,23 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
case OP_FPA_TO_SBV: m_conv.mk_to_sbv(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_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
|
||||
|
||||
|
||||
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_REWRITE_FULL;
|
||||
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_REWRITE_FULL;
|
||||
|
||||
|
||||
case OP_FPA_INTERNAL_MIN_UNSPECIFIED: result = m_conv.mk_min_unspecified(f, args[0], args[1]); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_MAX_UNSPECIFIED: result = m_conv.mk_max_unspecified(f, args[0], args[1]); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_MIN_I: m_conv.mk_min_i(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_INTERNAL_MAX_I: m_conv.mk_max_i(f, num, args, result); return BR_DONE;
|
||||
|
||||
|
||||
case OP_FPA_INTERNAL_RM:
|
||||
case OP_FPA_INTERNAL_BVWRAP:
|
||||
case OP_FPA_INTERNAL_BVUNWRAP:
|
||||
case OP_FPA_INTERNAL_BVWRAP:
|
||||
case OP_FPA_INTERNAL_BVUNWRAP:
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED: return BR_FAILED;
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
||||
return BR_FAILED;
|
||||
default:
|
||||
TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n";
|
||||
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;);
|
||||
|
@ -167,27 +169,27 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
else {
|
||||
SASSERT(!m_conv.is_float_family(f));
|
||||
bool is_float_uf = m_conv.is_float(f->get_range()) || m_conv.is_rm(f->get_range());
|
||||
|
||||
|
||||
for (unsigned i = 0; i < f->get_arity(); i++) {
|
||||
sort * di = f->get_domain()[i];
|
||||
is_float_uf |= m_conv.is_float(di) || m_conv.is_rm(di);
|
||||
}
|
||||
|
||||
|
||||
if (is_float_uf) {
|
||||
m_conv.mk_uninterpreted_function(f, num, args, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
bool fpa2bv_rewriter_cfg::pre_visit(expr * t)
|
||||
{
|
||||
TRACE("fpa2bv", tout << "pre_visit: " << mk_ismt2_pp(t, m()) << std::endl;);
|
||||
|
||||
if (is_quantifier(t)) {
|
||||
quantifier * q = to_quantifier(t);
|
||||
|
||||
if (is_quantifier(t)) {
|
||||
quantifier * q = to_quantifier(t);
|
||||
TRACE("fpa2bv", tout << "pre_visit quantifier [" << q->get_id() << "]: " << mk_ismt2_pp(q->get_expr(), m()) << std::endl;);
|
||||
sort_ref_vector new_bindings(m_manager);
|
||||
for (unsigned i = 0 ; i < q->get_num_decls(); i++)
|
||||
|
@ -199,9 +201,9 @@ bool fpa2bv_rewriter_cfg::pre_visit(expr * t)
|
|||
}
|
||||
|
||||
|
||||
bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
|
@ -221,7 +223,7 @@ bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
|||
name_buffer.reset();
|
||||
name_buffer << n << ".bv";
|
||||
new_decl_names.push_back(symbol(name_buffer.c_str()));
|
||||
new_decl_sorts.push_back(m_conv.bu().mk_sort(sbits+ebits));
|
||||
new_decl_sorts.push_back(m_conv.bu().mk_sort(sbits+ebits));
|
||||
}
|
||||
else {
|
||||
new_decl_sorts.push_back(s);
|
||||
|
@ -232,19 +234,19 @@ bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
|||
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
|
||||
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
|
||||
result_pr = 0;
|
||||
m_bindings.shrink(old_sz);
|
||||
TRACE("fpa2bv", tout << "reduce_quantifier[" << old_q->get_depth() << "]: " <<
|
||||
m_bindings.shrink(old_sz);
|
||||
TRACE("fpa2bv", tout << "reduce_quantifier[" << old_q->get_depth() << "]: " <<
|
||||
mk_ismt2_pp(old_q->get_expr(), m()) << std::endl <<
|
||||
" new body: " << mk_ismt2_pp(new_body, m()) << std::endl;
|
||||
tout << "result = " << mk_ismt2_pp(result, m()) << std::endl;);
|
||||
tout << "result = " << mk_ismt2_pp(result, m()) << std::endl;);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fpa2bv_rewriter_cfg::reduce_var(var * t, expr_ref & result, proof_ref & result_pr) {
|
||||
bool fpa2bv_rewriter_cfg::reduce_var(var * t, expr_ref & result, proof_ref & result_pr) {
|
||||
if (t->get_idx() >= m_bindings.size())
|
||||
return false;
|
||||
// unsigned inx = m_bindings.size() - t->get_idx() - 1;
|
||||
|
||||
// unsigned inx = m_bindings.size() - t->get_idx() - 1;
|
||||
|
||||
expr_ref new_exp(m());
|
||||
sort * s = t->get_sort();
|
||||
if (m_conv.is_float(s))
|
||||
|
@ -255,14 +257,14 @@ bool fpa2bv_rewriter_cfg::reduce_var(var * t, expr_ref & result, proof_ref & res
|
|||
new_var = m().mk_var(t->get_idx(), m_conv.bu().mk_sort(sbits+ebits));
|
||||
m_conv.mk_fp(m_conv.bu().mk_extract(sbits+ebits-1, sbits+ebits-1, new_var),
|
||||
m_conv.bu().mk_extract(ebits - 1, 0, new_var),
|
||||
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var),
|
||||
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var),
|
||||
new_exp);
|
||||
}
|
||||
else
|
||||
new_exp = m().mk_var(t->get_idx(), s);
|
||||
|
||||
|
||||
result = new_exp;
|
||||
result_pr = 0;
|
||||
result_pr = 0;
|
||||
TRACE("fpa2bv", tout << "reduce_var: " << mk_ismt2_pp(t, m()) << " -> " << mk_ismt2_pp(result, m()) << std::endl;);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -593,7 +593,7 @@ func_decl * fpa_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_paramet
|
|||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_fp(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 3)
|
||||
m_manager->raise_exception("invalid number of arguments to fp");
|
||||
if (!is_sort_of(domain[0], m_bv_fid, BV_SORT) ||
|
||||
|
@ -610,7 +610,7 @@ func_decl * fpa_decl_plugin::mk_fp(decl_kind k, unsigned num_parameters, paramet
|
|||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
SASSERT(m_bv_plugin);
|
||||
if (arity != 2)
|
||||
m_manager->raise_exception("invalid number of arguments to fp.to_ubv");
|
||||
|
@ -631,7 +631,7 @@ func_decl * fpa_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, par
|
|||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
SASSERT(m_bv_plugin);
|
||||
if (arity != 2)
|
||||
m_manager->raise_exception("invalid number of arguments to fp.to_sbv");
|
||||
|
@ -671,9 +671,9 @@ func_decl * fpa_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameters,
|
|||
|
||||
unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int();
|
||||
parameter ps[] = { parameter(float_sz) };
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps);
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(BV_SORT, 1, ps);
|
||||
symbol name("to_ieee_bv");
|
||||
return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
return m_manager->mk_func_decl(name, 1, domain, bv_srt, func_decl_info(m_family_id, k));
|
||||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_internal_rm(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
|
@ -693,7 +693,7 @@ func_decl * fpa_decl_plugin::mk_internal_rm(decl_kind k, unsigned num_parameters
|
|||
func_decl * fpa_decl_plugin::mk_internal_bv_wrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 1)
|
||||
m_manager->raise_exception("invalid number of arguments to internal_bv_wrap");
|
||||
m_manager->raise_exception("invalid number of arguments to bv_wrap");
|
||||
if (!is_float_sort(domain[0]) && !is_rm_sort(domain[0]))
|
||||
m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint or RoundingMode sort");
|
||||
|
||||
|
@ -714,7 +714,7 @@ func_decl * fpa_decl_plugin::mk_internal_bv_wrap(decl_kind k, unsigned num_param
|
|||
func_decl * fpa_decl_plugin::mk_internal_bv_unwrap(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 1)
|
||||
m_manager->raise_exception("invalid number of arguments to internal_bv_unwrap");
|
||||
m_manager->raise_exception("invalid number of arguments to bv_unwrap");
|
||||
if (!is_sort_of(domain[0], m_bv_fid, BV_SORT))
|
||||
m_manager->raise_exception("sort mismatch, expected argument of bitvector sort");
|
||||
if (!is_float_sort(range) && !is_rm_sort(range))
|
||||
|
@ -728,12 +728,12 @@ func_decl * fpa_decl_plugin::mk_internal_to_ubv_unspecified(
|
|||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 0)
|
||||
m_manager->raise_exception("invalid number of arguments to fp.to_ubv_unspecified");
|
||||
if (num_parameters != 1)
|
||||
m_manager->raise_exception("invalid number of parameters to fp.to_ubv_unspecified; expecting 1");
|
||||
if (!parameters[0].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to fp.to_ubv_unspecified; expecting an integer");
|
||||
if (num_parameters != 3)
|
||||
m_manager->raise_exception("invalid number of parameters to fp.to_ubv_unspecified; expecting 3");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int() || !parameters[2].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to fp.to_ubv_unspecified; expecting 3 integers");
|
||||
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, parameters);
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ¶meters[2]);
|
||||
return m_manager->mk_func_decl(symbol("fp.to_ubv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
|
@ -741,12 +741,13 @@ func_decl * fpa_decl_plugin::mk_internal_to_sbv_unspecified(
|
|||
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 0)
|
||||
m_manager->raise_exception("invalid number of arguments to internal_to_sbv_unspecified");
|
||||
if (num_parameters != 1)
|
||||
m_manager->raise_exception("invalid number of parameters to fp.to_sbv_unspecified; expecting 1");
|
||||
if (!parameters[0].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to fp.to_sbv_unspecified; expecting an integer");
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, parameters);
|
||||
m_manager->raise_exception("invalid number of arguments to fp.to_sbv_unspecified");
|
||||
if (num_parameters != 3)
|
||||
m_manager->raise_exception("invalid number of parameters to fp.to_sbv_unspecified; expecting 3");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int() || !parameters[2].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to fp.to_sbv_unspecified; expecting 3 integers");
|
||||
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ¶meters[2]);
|
||||
return m_manager->mk_func_decl(symbol("fp.to_sbv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
|
@ -754,13 +755,32 @@ func_decl * fpa_decl_plugin::mk_internal_to_real_unspecified(
|
|||
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 0)
|
||||
m_manager->raise_exception("invalid number of arguments to internal_to_real_unspecified");
|
||||
m_manager->raise_exception("invalid number of arguments to fp.to_real_unspecified");
|
||||
if (num_parameters != 2)
|
||||
m_manager->raise_exception("invalid number of parameters to fp.to_real_unspecified; expecting 2");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to fp.to_real_unspecified; expecting 2 integers");
|
||||
if (!is_sort_of(range, m_arith_fid, REAL_SORT))
|
||||
m_manager->raise_exception("sort mismatch, expected range of FloatingPoint sort");
|
||||
m_manager->raise_exception("sort mismatch, expected range of Real sort");
|
||||
|
||||
return m_manager->mk_func_decl(symbol("fp.to_real_unspecified"), 0, domain, m_real_sort, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_internal_to_ieee_bv_unspecified(
|
||||
decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (arity != 0)
|
||||
m_manager->raise_exception("invalid number of arguments to to_ieee_bv_unspecified; expecting none");
|
||||
if (num_parameters != 2)
|
||||
m_manager->raise_exception("invalid number of parameters to to_ieee_bv_unspecified; expecting 2");
|
||||
if (!parameters[0].is_int() || !parameters[1].is_int())
|
||||
m_manager->raise_exception("invalid parameters type provided to to_ieee_bv_unspecified; expecting 2 integers");
|
||||
|
||||
parameter width_p[1] = { parameter(parameters[0].get_int() + parameters[1].get_int()) };
|
||||
sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, width_p);
|
||||
return m_manager->mk_func_decl(symbol("to_ieee_bv_unspecified"), 0, domain, bv_srt, func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||
}
|
||||
|
||||
|
||||
func_decl * fpa_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
|
@ -846,6 +866,8 @@ func_decl * fpa_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
|
|||
return mk_internal_to_sbv_unspecified(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
return mk_internal_to_real_unspecified(k, num_parameters, parameters, arity, domain, range);
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
||||
return mk_internal_to_ieee_bv_unspecified(k, num_parameters, parameters, arity, domain, range);
|
||||
default:
|
||||
m_manager->raise_exception("unsupported floating point operator");
|
||||
return 0;
|
||||
|
@ -1045,25 +1067,26 @@ app * fpa_util::mk_nzero(unsigned ebits, unsigned sbits) {
|
|||
return mk_value(v);
|
||||
}
|
||||
|
||||
app * fpa_util::mk_internal_to_ubv_unspecified(unsigned width) {
|
||||
parameter ps[] = { parameter(width) };
|
||||
app * fpa_util::mk_internal_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||
parameter ps[] = { parameter(ebits), parameter(sbits), parameter(width) };
|
||||
sort * range = m_bv_util.mk_sort(width);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED, 1, ps, 0, 0, range);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED, 3, ps, 0, 0, range);
|
||||
}
|
||||
|
||||
app * fpa_util::mk_internal_to_sbv_unspecified(unsigned width) {
|
||||
parameter ps[] = { parameter(width) };
|
||||
app * fpa_util::mk_internal_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width) {
|
||||
parameter ps[] = { parameter(ebits), parameter(sbits), parameter(width) };
|
||||
sort * range = m_bv_util.mk_sort(width);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED, 1, ps, 0, 0, range);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED, 3, ps, 0, 0, range);
|
||||
}
|
||||
|
||||
app * fpa_util::mk_internal_to_ieee_bv_unspecified(unsigned width) {
|
||||
parameter ps[] = { parameter(width) };
|
||||
sort * range = m_bv_util.mk_sort(width);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED, 1, ps, 0, 0, range);
|
||||
app * fpa_util::mk_internal_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits) {
|
||||
parameter ps[] = { parameter(ebits), parameter(sbits) };
|
||||
sort * range = m_bv_util.mk_sort(ebits+sbits);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED, 2, ps, 0, 0, range);
|
||||
}
|
||||
|
||||
app * fpa_util::mk_internal_to_real_unspecified() {
|
||||
app * fpa_util::mk_internal_to_real_unspecified(unsigned ebits, unsigned sbits) {
|
||||
parameter ps[] = { parameter(ebits), parameter(sbits) };
|
||||
sort * range = m_a_util.mk_real();
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED, 0, 0, 0, 0, range);
|
||||
return m().mk_app(get_family_id(), OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED, 2, ps, 0, 0, range);
|
||||
}
|
||||
|
|
|
@ -177,11 +177,29 @@ class fpa_decl_plugin : public decl_plugin {
|
|||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_internal_to_real_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
func_decl * mk_internal_to_ieee_bv_unspecified(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
virtual void set_manager(ast_manager * m, family_id id);
|
||||
unsigned mk_id(mpf const & v);
|
||||
void recycled_id(unsigned id);
|
||||
|
||||
virtual bool is_considered_uninterpreted(func_decl * f) {
|
||||
if (f->get_family_id() != get_family_id())
|
||||
return false;
|
||||
switch (f->get_decl_kind())
|
||||
{
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
fpa_decl_plugin();
|
||||
|
||||
|
@ -344,10 +362,10 @@ public:
|
|||
|
||||
app * mk_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FPA_TO_IEEE_BV, arg1); }
|
||||
|
||||
app * mk_internal_to_ubv_unspecified(unsigned width);
|
||||
app * mk_internal_to_sbv_unspecified(unsigned width);
|
||||
app * mk_internal_to_ieee_bv_unspecified(unsigned width);
|
||||
app * mk_internal_to_real_unspecified();
|
||||
app * mk_internal_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||
app * mk_internal_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width);
|
||||
app * mk_internal_to_ieee_bv_unspecified(unsigned ebits, unsigned sbits);
|
||||
app * mk_internal_to_real_unspecified(unsigned ebits, unsigned sbits);
|
||||
|
||||
bool is_wrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BVWRAP); }
|
||||
bool is_unwrap(expr * e) const { return is_app_of(e, get_family_id(), OP_FPA_INTERNAL_BVUNWRAP); }
|
||||
|
|
|
@ -638,9 +638,13 @@ br_status arith_rewriter::mk_div_core(expr * arg1, expr * arg2, expr_ref & resul
|
|||
set_curr_sort(m().get_sort(arg1));
|
||||
numeral v1, v2;
|
||||
bool is_int;
|
||||
if (m_util.is_numeral(arg2, v2, is_int) && !v2.is_zero()) {
|
||||
if (m_util.is_numeral(arg2, v2, is_int)) {
|
||||
SASSERT(!is_int);
|
||||
if (m_util.is_numeral(arg1, v1, is_int)) {
|
||||
if (v2.is_zero()) {
|
||||
result = m_util.mk_div0(arg1);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
else if (m_util.is_numeral(arg1, v1, is_int)) {
|
||||
result = m_util.mk_numeral(v1/v2, false);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -691,6 +695,10 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
|
|||
result = m_util.mk_numeral(div(v1, v2), is_int);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m_util.is_numeral(arg2, v2, is_int) && v2.is_zero()) {
|
||||
result = m_util.mk_idiv0(arg1);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
|
|
@ -892,7 +892,7 @@ br_status bv_rewriter::mk_bv_urem_core(expr * arg1, expr * arg2, bool hi_div0, e
|
|||
if (r2.is_zero()) {
|
||||
if (!hi_div0) {
|
||||
result = m().mk_app(get_fid(), OP_BUREM0, arg1);
|
||||
return BR_DONE;
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
else {
|
||||
// The "hardware interpretation" for (bvurem x 0) is x
|
||||
|
|
|
@ -30,6 +30,14 @@ void expr_safe_replace::insert(expr* src, expr* dst) {
|
|||
m_subst.insert(src, dst);
|
||||
}
|
||||
|
||||
void expr_safe_replace::operator()(expr_ref_vector& es) {
|
||||
expr_ref val(m);
|
||||
for (unsigned i = 0; i < es.size(); ++i) {
|
||||
(*this)(es[i].get(), val);
|
||||
es[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
void expr_safe_replace::operator()(expr* e, expr_ref& res) {
|
||||
m_todo.push_back(e);
|
||||
expr* a, *b;
|
||||
|
|
|
@ -42,6 +42,8 @@ public:
|
|||
|
||||
void operator()(expr* src, expr_ref& e);
|
||||
|
||||
void operator()(expr_ref_vector& es);
|
||||
|
||||
void apply_substitution(expr* s, expr* def, expr_ref& t);
|
||||
|
||||
void reset();
|
||||
|
|
|
@ -102,11 +102,10 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
case OP_FPA_INTERNAL_RM:
|
||||
SASSERT(num_args == 1); st = mk_rm(args[0], result); break;
|
||||
case OP_FPA_INTERNAL_TO_UBV_UNSPECIFIED:
|
||||
SASSERT(num_args == 0); st = mk_to_ubv_unspecified(f, result); break;
|
||||
case OP_FPA_INTERNAL_TO_SBV_UNSPECIFIED:
|
||||
SASSERT(num_args == 0); st = mk_to_sbv_unspecified(f, result); break;
|
||||
case OP_FPA_INTERNAL_TO_REAL_UNSPECIFIED:
|
||||
SASSERT(num_args == 0); st = mk_to_real_unspecified(result); break;
|
||||
case OP_FPA_INTERNAL_TO_IEEE_BV_UNSPECIFIED:
|
||||
st = BR_FAILED;
|
||||
|
||||
case OP_FPA_INTERNAL_BVWRAP:
|
||||
case OP_FPA_INTERNAL_BVUNWRAP:
|
||||
|
@ -119,57 +118,34 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
return st;
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_ubv_unspecified(func_decl * f, expr_ref & result) {
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_int());
|
||||
unsigned bv_sz = f->get_parameter(0).get_int();
|
||||
|
||||
br_status fpa_rewriter::mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned width, expr_ref & result) {
|
||||
bv_util bu(m());
|
||||
if (m_hi_fp_unspecified)
|
||||
// The "hardware interpretation" is 0.
|
||||
result = bu.mk_numeral(0, bv_sz);
|
||||
result = bu.mk_numeral(0, width);
|
||||
else
|
||||
result = m_util.mk_internal_to_ubv_unspecified(bv_sz);
|
||||
result = m_util.mk_internal_to_ubv_unspecified(ebits, sbits, width);
|
||||
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_sbv_unspecified(func_decl * f, expr_ref & result) {
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_int());
|
||||
unsigned bv_sz = f->get_parameter(0).get_int();
|
||||
|
||||
br_status fpa_rewriter::mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned width, expr_ref & result) {
|
||||
bv_util bu(m());
|
||||
if (m_hi_fp_unspecified)
|
||||
// The "hardware interpretation" is 0.
|
||||
result = bu.mk_numeral(0, bv_sz);
|
||||
result = bu.mk_numeral(0, width);
|
||||
else
|
||||
result = m_util.mk_internal_to_sbv_unspecified(bv_sz);
|
||||
result = m_util.mk_internal_to_sbv_unspecified(ebits, sbits, width);
|
||||
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_ieee_bv_unspecified(func_decl * f, expr_ref & result) {
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_int());
|
||||
unsigned bv_sz = f->get_parameter(0).get_int();
|
||||
|
||||
bv_util bu(m());
|
||||
if (m_hi_fp_unspecified)
|
||||
// The "hardware interpretation" is 0.
|
||||
result = bu.mk_numeral(0, bv_sz);
|
||||
else
|
||||
result = m_util.mk_internal_to_ieee_bv_unspecified(bv_sz);
|
||||
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_to_real_unspecified(expr_ref & result) {
|
||||
br_status fpa_rewriter::mk_to_real_unspecified(unsigned ebits, unsigned sbits, expr_ref & result) {
|
||||
if (m_hi_fp_unspecified)
|
||||
// The "hardware interpretation" is 0.
|
||||
result = m_util.au().mk_numeral(rational(0), false);
|
||||
else
|
||||
result = m_util.mk_internal_to_real_unspecified();
|
||||
result = m_util.mk_internal_to_real_unspecified(ebits, sbits);
|
||||
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -801,9 +777,10 @@ br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_
|
|||
|
||||
if (m_util.is_rm_numeral(arg1, rmv) &&
|
||||
m_util.is_numeral(arg2, v)) {
|
||||
const mpf & x = v.get();
|
||||
|
||||
if (m_fm.is_nan(v) || m_fm.is_inf(v) || m_fm.is_neg(v)) {
|
||||
mk_to_ubv_unspecified(f, result);
|
||||
mk_to_ubv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
||||
|
@ -818,7 +795,7 @@ br_status fpa_rewriter::mk_to_ubv(func_decl * f, expr * arg1, expr * arg2, expr_
|
|||
if (r >= ll && r <= ul)
|
||||
result = bu.mk_numeral(r, bv_sz);
|
||||
else
|
||||
mk_to_ubv_unspecified(f, result);
|
||||
mk_to_ubv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
@ -834,9 +811,10 @@ br_status fpa_rewriter::mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_
|
|||
|
||||
if (m_util.is_rm_numeral(arg1, rmv) &&
|
||||
m_util.is_numeral(arg2, v)) {
|
||||
const mpf & x = v.get();
|
||||
|
||||
if (m_fm.is_nan(v) || m_fm.is_inf(v)) {
|
||||
mk_to_sbv_unspecified(f, result);
|
||||
mk_to_sbv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
|
||||
|
@ -851,7 +829,7 @@ br_status fpa_rewriter::mk_to_sbv(func_decl * f, expr * arg1, expr * arg2, expr_
|
|||
if (r >= ll && r <= ul)
|
||||
result = bu.mk_numeral(r, bv_sz);
|
||||
else
|
||||
mk_to_sbv_unspecified(f, result);
|
||||
mk_to_sbv_unspecified(x.get_ebits(), x.get_sbits(), bv_sz, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
@ -862,17 +840,35 @@ br_status fpa_rewriter::mk_to_ieee_bv(func_decl * f, expr * arg, expr_ref & resu
|
|||
scoped_mpf v(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg, v)) {
|
||||
bv_util bu(m());
|
||||
const mpf & x = v.get();
|
||||
|
||||
if (m_fm.is_nan(v) || m_fm.is_inf(v)) {
|
||||
mk_to_ieee_bv_unspecified(f, result);
|
||||
if (m_fm.is_nan(v)) {
|
||||
if (m_hi_fp_unspecified) {
|
||||
result = bu.mk_concat(bu.mk_numeral(0, 1),
|
||||
bu.mk_concat(bu.mk_numeral(-1, x.get_ebits()),
|
||||
bu.mk_concat(bu.mk_numeral(0, x.get_sbits() - 2),
|
||||
bu.mk_numeral(1, 1))));
|
||||
}
|
||||
else {
|
||||
app_ref unspec(m()), mask(m()), extra(m());
|
||||
unspec = m_util.mk_internal_to_ieee_bv_unspecified(x.get_ebits(), x.get_sbits());
|
||||
mask = bu.mk_concat(bu.mk_numeral(0, 1),
|
||||
bu.mk_concat(bu.mk_numeral(-1, x.get_ebits()),
|
||||
bu.mk_concat(bu.mk_numeral(0, x.get_sbits() - 2),
|
||||
bu.mk_numeral(1, 1))));
|
||||
expr * args[2] = { unspec, mask };
|
||||
result = m().mk_app(bu.get_fid(), OP_BOR, 2, args);
|
||||
}
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
else {
|
||||
scoped_mpz rz(m_fm.mpq_manager());
|
||||
m_fm.to_ieee_bv_mpz(v, rz);
|
||||
|
||||
bv_util bu(m());
|
||||
scoped_mpz rz(m_fm.mpq_manager());
|
||||
m_fm.to_ieee_bv_mpz(v, rz);
|
||||
result = bu.mk_numeral(rational(rz), v.get().get_ebits() + v.get().get_sbits());
|
||||
return BR_DONE;
|
||||
result = bu.mk_numeral(rational(rz), x.get_ebits() + x.get_sbits());
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
|
@ -883,7 +879,8 @@ br_status fpa_rewriter::mk_to_real(expr * arg, expr_ref & result) {
|
|||
|
||||
if (m_util.is_numeral(arg, v)) {
|
||||
if (m_fm.is_nan(v) || m_fm.is_inf(v)) {
|
||||
result = m_util.mk_internal_to_real_unspecified();
|
||||
const mpf & x = v.get();
|
||||
result = m_util.mk_internal_to_real_unspecified(x.get_ebits(), x.get_sbits());
|
||||
}
|
||||
else {
|
||||
scoped_mpq r(m_fm.mpq_manager());
|
||||
|
|
|
@ -86,10 +86,9 @@ public:
|
|||
br_status mk_to_ieee_bv(func_decl * f, expr * arg, expr_ref & result);
|
||||
br_status mk_to_real(expr * arg, expr_ref & result);
|
||||
|
||||
br_status mk_to_ubv_unspecified(func_decl * f, expr_ref & result);
|
||||
br_status mk_to_sbv_unspecified(func_decl * f, expr_ref & result);
|
||||
br_status mk_to_ieee_bv_unspecified(func_decl * f, expr_ref & result);
|
||||
br_status mk_to_real_unspecified(expr_ref & result);
|
||||
br_status mk_to_ubv_unspecified(unsigned ebits, unsigned sbits, unsigned with, expr_ref & result);
|
||||
br_status mk_to_sbv_unspecified(unsigned ebits, unsigned sbits, unsigned with, expr_ref & result);
|
||||
br_status mk_to_real_unspecified(unsigned ebits, unsigned sbits, expr_ref & result);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
53
src/ast/rewriter/label_rewriter.cpp
Normal file
53
src/ast/rewriter/label_rewriter.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
label_rewriter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Basic rewriting rules for removing labels.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2015-19-10
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
#include"rewriter.h"
|
||||
#include"rewriter_def.h"
|
||||
#include"label_rewriter.h"
|
||||
|
||||
|
||||
label_rewriter::label_rewriter(ast_manager & m) :
|
||||
m_label_fid(m.get_label_family_id()),
|
||||
m_rwr(m, false, *this) {}
|
||||
|
||||
label_rewriter::~label_rewriter() {}
|
||||
|
||||
br_status label_rewriter::reduce_app(
|
||||
func_decl * f, unsigned num, expr * const * args, expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
if (is_decl_of(f, m_label_fid, OP_LABEL)) {
|
||||
SASSERT(num == 1);
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
void label_rewriter::remove_labels(expr_ref& fml, proof_ref& pr) {
|
||||
ast_manager& m = fml.get_manager();
|
||||
expr_ref tmp(m);
|
||||
m_rwr(fml, tmp);
|
||||
if (pr && fml != tmp) {
|
||||
pr = m.mk_modus_ponens(pr, m.mk_rewrite(fml, tmp));
|
||||
}
|
||||
fml = tmp;
|
||||
}
|
||||
|
||||
|
||||
//template class rewriter_tpl<label_rewriter>;
|
41
src/ast/rewriter/label_rewriter.h
Normal file
41
src/ast/rewriter/label_rewriter.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
label_rewriter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Basic rewriting rules for labels.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2015-19-10
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef LABEL_REWRITER_H_
|
||||
#define LABEL_REWRITER_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"rewriter_types.h"
|
||||
|
||||
|
||||
class label_rewriter : public default_rewriter_cfg {
|
||||
family_id m_label_fid;
|
||||
rewriter_tpl<label_rewriter> m_rwr;
|
||||
public:
|
||||
label_rewriter(ast_manager & m);
|
||||
~label_rewriter();
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result,
|
||||
proof_ref & result_pr);
|
||||
|
||||
|
||||
void remove_labels(expr_ref& fml, proof_ref& pr);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -73,7 +73,7 @@ public:
|
|||
unsigned nd = q->get_num_decls();
|
||||
for (unsigned i = 0; i < nd; ++i) {
|
||||
sort* s = q->get_decl_sort(i);
|
||||
app* a = m.mk_fresh_const("x", s);
|
||||
app* a = m.mk_fresh_const(q->get_decl_name(i).str().c_str(), s);
|
||||
vars.push_back(a);
|
||||
}
|
||||
expr * const * exprs = (expr* const*) (vars.c_ptr() + vars.size()- nd);
|
||||
|
@ -154,9 +154,7 @@ private:
|
|||
}
|
||||
|
||||
quantifier_type& negate(quantifier_type& qt) {
|
||||
TRACE("qe", display(qt, tout); tout << "\n";);
|
||||
qt = static_cast<quantifier_type>(qt ^0x1);
|
||||
TRACE("qe", display(qt, tout); tout << "\n";);
|
||||
return qt;
|
||||
}
|
||||
|
||||
|
@ -205,6 +203,7 @@ private:
|
|||
case AST_APP: {
|
||||
expr_ref_vector args(m);
|
||||
expr_ref tmp(m);
|
||||
expr* t1, *t2, *t3;
|
||||
unsigned num_args = 0;
|
||||
app* a = to_app(fml);
|
||||
if (m.is_and(fml)) {
|
||||
|
@ -228,16 +227,35 @@ private:
|
|||
negate(qt);
|
||||
result = m.mk_not(tmp);
|
||||
}
|
||||
else if (m.is_implies(fml)) {
|
||||
pull_quantifier(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
|
||||
else if (m.is_implies(fml, t1, t2)) {
|
||||
pull_quantifier(t1, negate(qt), vars, tmp);
|
||||
negate(qt);
|
||||
pull_quantifier(to_app(fml)->get_arg(1), qt, vars, result);
|
||||
pull_quantifier(t2, qt, vars, result);
|
||||
result = m.mk_implies(tmp, result);
|
||||
}
|
||||
else if (m.is_ite(fml)) {
|
||||
pull_quantifier(to_app(fml)->get_arg(1), qt, vars, tmp);
|
||||
pull_quantifier(to_app(fml)->get_arg(2), qt, vars, result);
|
||||
result = m.mk_ite(to_app(fml)->get_arg(0), tmp, result);
|
||||
else if (m.is_ite(fml, t1, t2, t3)) {
|
||||
expr_ref tt1(m), tt2(m), tt3(m), ntt1(m), nt1(m);
|
||||
pull_quantifier(t2, qt, vars, tt2);
|
||||
pull_quantifier(t3, qt, vars, tt3);
|
||||
if (has_quantifiers(t1)) {
|
||||
pull_quantifier(t1, qt, vars, tt1);
|
||||
nt1 = m.mk_not(t1);
|
||||
pull_quantifier(nt1, qt, vars, ntt1);
|
||||
result = m.mk_and(m.mk_or(ntt1, tt2), m.mk_or(tt1, tt3));
|
||||
}
|
||||
else {
|
||||
result = m.mk_ite(t1, tt2, tt3);
|
||||
}
|
||||
}
|
||||
else if ((m.is_eq(fml, t1, t2) && m.is_bool(t1)) || m.is_iff(fml, t1, t2)) {
|
||||
expr_ref tt1(m), tt2(m), ntt1(m), ntt2(m), nt1(m), nt2(m);
|
||||
pull_quantifier(t1, qt, vars, tt1);
|
||||
pull_quantifier(t2, qt, vars, tt2);
|
||||
nt1 = m.mk_not(t1);
|
||||
nt2 = m.mk_not(t2);
|
||||
pull_quantifier(nt1, qt, vars, ntt1);
|
||||
pull_quantifier(nt2, qt, vars, ntt2);
|
||||
result = m.mk_and(m.mk_or(ntt1, tt2), m.mk_or(ntt2, tt1));
|
||||
}
|
||||
else {
|
||||
// the formula contains a quantifier, but it is "inaccessible"
|
||||
|
|
|
@ -595,6 +595,9 @@ void rewriter_tpl<Config>::set_inv_bindings(unsigned num_bindings, expr * const
|
|||
template<typename Config>
|
||||
template<bool ProofGen>
|
||||
void rewriter_tpl<Config>::main_loop(expr * t, expr_ref & result, proof_ref & result_pr) {
|
||||
if (m().canceled()) {
|
||||
throw rewriter_exception(m().limit().get_cancel_msg());
|
||||
}
|
||||
SASSERT(!ProofGen || result_stack().size() == result_pr_stack().size());
|
||||
SASSERT(not_rewriting());
|
||||
m_root = t;
|
||||
|
|
|
@ -246,6 +246,8 @@ eautomaton* re2automaton::re2aut(expr* e) {
|
|||
expr_ref _stop(bv.mk_numeral(stop, nb), m);
|
||||
expr_ref _pred(m.mk_not(m.mk_and(bv.mk_ule(_start, v), bv.mk_ule(v, _stop))), m);
|
||||
a = alloc(eautomaton, sm, sym_expr::mk_pred(_pred, s));
|
||||
display_expr1 disp(m);
|
||||
TRACE("seq", tout << mk_pp(e, m) << "\n"; a->display(tout, disp););
|
||||
return a.detach();
|
||||
}
|
||||
else if (u.re.is_to_re(e0, e1) && u.str.is_string(e1, s1) && s1.length() == 1) {
|
||||
|
@ -255,6 +257,8 @@ eautomaton* re2automaton::re2aut(expr* e) {
|
|||
expr_ref _ch(bv.mk_numeral(s1[0], nb), m);
|
||||
expr_ref _pred(m.mk_not(m.mk_eq(v, _ch)), m);
|
||||
a = alloc(eautomaton, sm, sym_expr::mk_pred(_pred, s));
|
||||
display_expr1 disp(m);
|
||||
TRACE("seq", tout << mk_pp(e, m) << "\n"; a->display(tout, disp););
|
||||
return a.detach();
|
||||
}
|
||||
else if (u.re.is_to_re(e0, e1) && u.str.is_unit(e1, e2)) {
|
||||
|
@ -262,6 +266,8 @@ eautomaton* re2automaton::re2aut(expr* e) {
|
|||
expr_ref v(m.mk_var(0, s), m);
|
||||
expr_ref _pred(m.mk_not(m.mk_eq(v, e2)), m);
|
||||
a = alloc(eautomaton, sm, sym_expr::mk_pred(_pred, s));
|
||||
display_expr1 disp(m);
|
||||
TRACE("seq", tout << mk_pp(e, m) << "\n"; a->display(tout, disp););
|
||||
return a.detach();
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -578,6 +578,16 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
return st;
|
||||
}
|
||||
|
||||
expr_ref mk_app(func_decl* f, unsigned num_args, expr* const* args) {
|
||||
expr_ref result(m());
|
||||
proof_ref pr(m());
|
||||
if (BR_FAILED == reduce_app(f, num_args, args, result, pr)) {
|
||||
result = m().mk_app(f, num_args, args);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
|
@ -695,6 +705,9 @@ struct th_rewriter::imp : public rewriter_tpl<th_rewriter_cfg> {
|
|||
rewriter_tpl<th_rewriter_cfg>(m, m.proofs_enabled(), m_cfg),
|
||||
m_cfg(m, p) {
|
||||
}
|
||||
expr_ref mk_app(func_decl* f, unsigned sz, expr* const* args) {
|
||||
return m_cfg.mk_app(f, sz, args);
|
||||
}
|
||||
};
|
||||
|
||||
th_rewriter::th_rewriter(ast_manager & m, params_ref const & p):
|
||||
|
@ -776,3 +789,7 @@ void th_rewriter::reset_used_dependencies() {
|
|||
m_imp->cfg().m_used_dependencies = 0;
|
||||
}
|
||||
}
|
||||
|
||||
expr_ref th_rewriter::mk_app(func_decl* f, unsigned num_args, expr* const* args) {
|
||||
return m_imp->mk_app(f, num_args, args);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@ public:
|
|||
void operator()(expr * t, expr_ref & result, proof_ref & result_pr);
|
||||
void operator()(expr * n, unsigned num_bindings, expr * const * bindings, expr_ref & result);
|
||||
|
||||
expr_ref mk_app(func_decl* f, unsigned num_args, expr* const* args);
|
||||
|
||||
void cleanup();
|
||||
void reset();
|
||||
|
||||
|
|
|
@ -112,6 +112,11 @@ zstring::zstring(zstring const& other) {
|
|||
m_encoding = other.m_encoding;
|
||||
}
|
||||
|
||||
zstring::zstring(unsigned sz, unsigned const* s, encoding enc) {
|
||||
m_buffer.append(sz, s);
|
||||
m_encoding = enc;
|
||||
}
|
||||
|
||||
zstring::zstring(unsigned num_bits, bool const* ch) {
|
||||
SASSERT(num_bits == 8 || num_bits == 16);
|
||||
m_encoding = (num_bits == 8)?ascii:unicode;
|
||||
|
@ -578,6 +583,7 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
|
|||
case OP_RE_OF_PRED:
|
||||
case OP_STRING_ITOS:
|
||||
case OP_STRING_STOI:
|
||||
case OP_RE_COMPLEMENT:
|
||||
match(*m_sigs[k], arity, domain, range, rng);
|
||||
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, k));
|
||||
|
||||
|
@ -632,7 +638,7 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
|
|||
default:
|
||||
m.raise_exception("Incorrect number of arguments passed to loop. Expected 1 regular expression and two integer parameters");
|
||||
}
|
||||
|
||||
|
||||
|
||||
case OP_STRING_CONST:
|
||||
if (!(num_parameters == 1 && arity == 0 && parameters[0].is_symbol())) {
|
||||
|
@ -641,7 +647,6 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
|
|||
return m.mk_const_decl(m_stringc_sym, m_string,
|
||||
func_decl_info(m_family_id, OP_STRING_CONST, num_parameters, parameters));
|
||||
|
||||
case OP_RE_COMPLEMENT:
|
||||
case OP_RE_UNION:
|
||||
case OP_RE_CONCAT:
|
||||
case OP_RE_INTERSECT:
|
||||
|
@ -761,10 +766,27 @@ app* seq_decl_plugin::mk_string(zstring const& s) {
|
|||
|
||||
|
||||
bool seq_decl_plugin::is_value(app* e) const {
|
||||
return
|
||||
is_app_of(e, m_family_id, OP_SEQ_EMPTY) ||
|
||||
(is_app_of(e, m_family_id, OP_SEQ_UNIT) &&
|
||||
m_manager->is_value(e->get_arg(0)));
|
||||
while (true) {
|
||||
if (is_app_of(e, m_family_id, OP_SEQ_EMPTY)) {
|
||||
return true;
|
||||
}
|
||||
if (is_app_of(e, m_family_id, OP_STRING_CONST)) {
|
||||
return true;
|
||||
}
|
||||
if (is_app_of(e, m_family_id, OP_SEQ_UNIT) &&
|
||||
m_manager->is_value(e->get_arg(0))) {
|
||||
return true;
|
||||
}
|
||||
if (is_app_of(e, m_family_id, OP_SEQ_CONCAT) &&
|
||||
e->get_num_args() == 2 &&
|
||||
is_app(e->get_arg(0)) &&
|
||||
is_app(e->get_arg(1)) &&
|
||||
is_value(to_app(e->get_arg(0)))) {
|
||||
e = to_app(e->get_arg(1));
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
expr* seq_decl_plugin::get_some_value(sort* s) {
|
||||
|
|
|
@ -95,6 +95,7 @@ private:
|
|||
public:
|
||||
zstring(encoding enc = ascii);
|
||||
zstring(char const* s, encoding enc = ascii);
|
||||
zstring(unsigned sz, unsigned const* s, encoding enc = ascii);
|
||||
zstring(zstring const& other);
|
||||
zstring(unsigned num_bits, bool const* ch);
|
||||
zstring(unsigned ch, encoding enc = ascii);
|
||||
|
|
|
@ -406,8 +406,9 @@ bool arith_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * co
|
|||
case OP_POWER: return false;
|
||||
case OP_ABS: SASSERT(num_args == 1); mk_abs(args[0], result); break;
|
||||
case OP_IRRATIONAL_ALGEBRAIC_NUM: return false;
|
||||
case OP_DIV_0: return false;
|
||||
case OP_IDIV_0: return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
TRACE("arith_simplifier_plugin", tout << mk_pp(result.get(), m_manager) << "\n";);
|
||||
|
|
|
@ -473,6 +473,7 @@ void simplifier::mk_app(func_decl * decl, unsigned num_args, expr * const * args
|
|||
//dump_rewrite_lemma(decl, num_args, args, result.get());
|
||||
return;
|
||||
}
|
||||
|
||||
result = m.mk_app(decl, num_args, args);
|
||||
}
|
||||
|
||||
|
|
|
@ -303,8 +303,8 @@ public:
|
|||
goal_ref g = alloc(goal, m, ctx.produce_proofs(), ctx.produce_models(), ctx.produce_unsat_cores());
|
||||
assert_exprs_from(ctx, *g);
|
||||
|
||||
unsigned timeout = p.get_uint("timeout", UINT_MAX);
|
||||
unsigned rlimit = p.get_uint("rlimit", 0);
|
||||
unsigned timeout = p.get_uint("timeout", ctx.params().m_timeout);
|
||||
unsigned rlimit = p.get_uint("rlimit", ctx.params().m_rlimit);
|
||||
|
||||
goal_ref_buffer result_goals;
|
||||
model_converter_ref mc;
|
||||
|
|
|
@ -539,7 +539,6 @@ namespace algebraic_numbers {
|
|||
}
|
||||
|
||||
bool factor(scoped_upoly const & up, factors & r) {
|
||||
// std::cout << "factor: "; upm().display(std::cout, up); std::cout << std::endl;
|
||||
if (m_factor) {
|
||||
return upm().factor(up, r, m_factor_params);
|
||||
}
|
||||
|
@ -547,7 +546,7 @@ namespace algebraic_numbers {
|
|||
scoped_upoly & up_sqf = m_isolate_tmp3;
|
||||
up_sqf.reset();
|
||||
upm().square_free(up.size(), up.c_ptr(), up_sqf);
|
||||
TRACE("anum_bug", upm().display(tout, up_sqf.size(), up_sqf.c_ptr()); tout << "\n";);
|
||||
TRACE("algebraic", upm().display(tout, up_sqf.size(), up_sqf.c_ptr()); tout << "\n";);
|
||||
r.push_back(up_sqf, 1);
|
||||
return false;
|
||||
}
|
||||
|
@ -566,6 +565,7 @@ namespace algebraic_numbers {
|
|||
}
|
||||
|
||||
void isolate_roots(scoped_upoly const & up, numeral_vector & roots) {
|
||||
TRACE("algebraic", upm().display(tout, up); tout << "\n";);
|
||||
if (up.empty())
|
||||
return; // ignore the zero polynomial
|
||||
factors & fs = m_isolate_factors;
|
||||
|
@ -586,6 +586,7 @@ namespace algebraic_numbers {
|
|||
upolynomial::numeral_vector const & f = fs[i];
|
||||
// polynomial f contains the non zero roots
|
||||
unsigned d = upm().degree(f);
|
||||
TRACE("algebraic", tout << "factor " << i << " degree: " << d << "\n";);
|
||||
if (d == 0)
|
||||
continue; // found all roots of f
|
||||
scoped_mpq r(qm());
|
||||
|
@ -601,8 +602,9 @@ namespace algebraic_numbers {
|
|||
}
|
||||
SASSERT(m_isolate_roots.empty() && m_isolate_lowers.empty() && m_isolate_uppers.empty());
|
||||
upm().sqf_isolate_roots(f.size(), f.c_ptr(), bqm(), m_isolate_roots, m_isolate_lowers, m_isolate_uppers);
|
||||
// collect rational/basic roots
|
||||
// collect rational/basic roots
|
||||
unsigned sz = m_isolate_roots.size();
|
||||
TRACE("algebraic", tout << "isolated roots: " << sz << "\n";);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
to_mpq(qm(), m_isolate_roots[i], r);
|
||||
roots.push_back(numeral(mk_basic_cell(r)));
|
||||
|
|
|
@ -111,7 +111,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
result_pr = 0;
|
||||
family_id fid = f->get_family_id();
|
||||
if (fid == null_family_id && num == 0) {
|
||||
if (num == 0 && (fid == null_family_id || m().get_plugin(f->get_family_id())->is_considered_uninterpreted(f))) {
|
||||
expr * val = m_model.get_const_interp(f);
|
||||
if (val != 0) {
|
||||
result = val;
|
||||
|
@ -178,7 +178,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
|
|||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
TRACE("model_evaluator", tout << f->get_name() << "\n";);
|
||||
CTRACE("model_evaluator", st != BR_FAILED, tout << result << "\n";);
|
||||
return st;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,5 @@ def_module_params('model',
|
|||
('v1', BOOL, False, 'use Z3 version 1.x pretty printer'),
|
||||
('v2', BOOL, False, 'use Z3 version 2.x (x <= 16) pretty printer'),
|
||||
('compact', BOOL, False, 'try to compact function graph (i.e., function interpretations that are lookup tables)'),
|
||||
('new_eval', BOOL, True, 'use new evaluator (temporary parameter for testing)'),
|
||||
))
|
||||
|
||||
|
|
|
@ -55,8 +55,7 @@ namespace datalog {
|
|||
m_args(m),
|
||||
m_hnf(m),
|
||||
m_qe(m),
|
||||
m_cfg(m),
|
||||
m_rwr(m, false, m_cfg),
|
||||
m_rwr(m),
|
||||
m_ufproc(m) {}
|
||||
|
||||
void rule_manager::inc_ref(rule * r) {
|
||||
|
@ -76,28 +75,8 @@ namespace datalog {
|
|||
}
|
||||
}
|
||||
|
||||
rule_manager::remove_label_cfg::~remove_label_cfg() {}
|
||||
|
||||
br_status rule_manager::remove_label_cfg::reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result,
|
||||
proof_ref & result_pr)
|
||||
{
|
||||
if (is_decl_of(f, m_label_fid, OP_LABEL)) {
|
||||
SASSERT(num == 1);
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
||||
void rule_manager::remove_labels(expr_ref& fml, proof_ref& pr) {
|
||||
expr_ref tmp(m);
|
||||
m_rwr(fml, tmp);
|
||||
if (pr && fml != tmp) {
|
||||
|
||||
pr = m.mk_modus_ponens(pr, m.mk_rewrite(fml, tmp));
|
||||
}
|
||||
fml = tmp;
|
||||
m_rwr.remove_labels(fml, pr);
|
||||
}
|
||||
|
||||
var_idx_set& rule_manager::collect_vars(expr* e) {
|
||||
|
@ -1092,5 +1071,4 @@ namespace datalog {
|
|||
|
||||
};
|
||||
|
||||
template class rewriter_tpl<datalog::rule_manager::remove_label_cfg>;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ Revision History:
|
|||
#include"qe_lite.h"
|
||||
#include"var_subst.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include"label_rewriter.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
@ -102,16 +103,6 @@ namespace datalog {
|
|||
*/
|
||||
class rule_manager
|
||||
{
|
||||
class remove_label_cfg : public default_rewriter_cfg {
|
||||
family_id m_label_fid;
|
||||
public:
|
||||
remove_label_cfg(ast_manager& m): m_label_fid(m.get_label_family_id()) {}
|
||||
virtual ~remove_label_cfg();
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result,
|
||||
proof_ref & result_pr);
|
||||
};
|
||||
|
||||
ast_manager& m;
|
||||
context& m_ctx;
|
||||
rule_counter m_counter;
|
||||
|
@ -124,8 +115,7 @@ namespace datalog {
|
|||
svector<bool> m_neg;
|
||||
hnf m_hnf;
|
||||
qe_lite m_qe;
|
||||
remove_label_cfg m_cfg;
|
||||
rewriter_tpl<remove_label_cfg> m_rwr;
|
||||
label_rewriter m_rwr;
|
||||
mutable uninterpreted_function_finder_proc m_ufproc;
|
||||
mutable quantifier_finder_proc m_qproc;
|
||||
mutable expr_sparse_mark m_visited;
|
||||
|
|
|
@ -29,7 +29,6 @@ Revision History:
|
|||
#include"ast_counter.h"
|
||||
#include"statistics.h"
|
||||
#include"lbool.h"
|
||||
#include"qe_util.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ Revision History:
|
|||
#include "pdr_closure.h"
|
||||
#include "pdr_context.h"
|
||||
#include "expr_safe_replace.h"
|
||||
#include "ast_util.h"
|
||||
|
||||
namespace pdr {
|
||||
|
||||
|
@ -147,7 +148,7 @@ namespace pdr {
|
|||
for (unsigned i = 0; i < fmls.size(); ++i) {
|
||||
fmls[i] = close_fml(fmls[i].get());
|
||||
}
|
||||
return qe::mk_and(fmls);
|
||||
return expr_ref(mk_and(fmls), m);
|
||||
}
|
||||
|
||||
expr_ref closure::relax(unsigned i, expr* fml) {
|
||||
|
@ -169,7 +170,7 @@ namespace pdr {
|
|||
for (unsigned i = 0; i < As.size(); ++i) {
|
||||
fmls.push_back(relax(i, As[i]));
|
||||
}
|
||||
B = qe::mk_and(fmls);
|
||||
B = mk_and(fmls);
|
||||
return B;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ Notes:
|
|||
#include "smt_value_sort.h"
|
||||
#include "proof_utils.h"
|
||||
#include "dl_boogie_proof.h"
|
||||
#include "qe_util.h"
|
||||
#include "scoped_proof.h"
|
||||
#include "blast_term_ite_tactic.h"
|
||||
#include "model_implicant.h"
|
||||
|
|
|
@ -201,7 +201,7 @@ namespace pdr {
|
|||
lits.push_back(extract_consequence(lo, hi));
|
||||
lo = hi;
|
||||
}
|
||||
res = qe::mk_or(lits);
|
||||
res = mk_or(lits);
|
||||
IF_VERBOSE(2, { if (lits.size() > 1) { verbose_stream() << "combined lemma: " << mk_pp(res, m) << "\n"; } });
|
||||
#endif
|
||||
}
|
||||
|
@ -415,6 +415,7 @@ namespace pdr {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class collect_pure_proc {
|
||||
|
|
|
@ -117,7 +117,7 @@ namespace pdr {
|
|||
void core_farkas_generalizer::operator()(model_node& n, expr_ref_vector& core, bool& uses_level) {
|
||||
ast_manager& m = n.pt().get_manager();
|
||||
if (core.empty()) return;
|
||||
expr_ref A(m), B(qe::mk_and(core)), C(m);
|
||||
expr_ref A(m), B(mk_and(core)), C(m);
|
||||
expr_ref_vector Bs(m);
|
||||
flatten_or(B, Bs);
|
||||
A = n.pt().get_propagation_formula(m_ctx.get_pred_transformers(), n.level());
|
||||
|
@ -129,13 +129,13 @@ namespace pdr {
|
|||
if (m_farkas_learner.get_lemma_guesses(A, B, lemmas)) {
|
||||
TRACE("pdr",
|
||||
tout << "Old core:\n" << mk_pp(B, m) << "\n";
|
||||
tout << "New core:\n" << mk_pp(qe::mk_and(lemmas), m) << "\n";);
|
||||
Bs[i] = qe::mk_and(lemmas);
|
||||
tout << "New core:\n" << mk_and(lemmas) << "\n";);
|
||||
Bs[i] = mk_and(lemmas);
|
||||
change = true;
|
||||
}
|
||||
}
|
||||
if (change) {
|
||||
C = qe::mk_or(Bs);
|
||||
C = mk_or(Bs);
|
||||
TRACE("pdr", tout << "prop:\n" << mk_pp(A,m) << "\ngen:" << mk_pp(B, m) << "\nto: " << mk_pp(C, m) << "\n";);
|
||||
core.reset();
|
||||
flatten_and(C, core);
|
||||
|
@ -186,7 +186,7 @@ namespace pdr {
|
|||
}
|
||||
closure cl(n.pt(), m_is_closure);
|
||||
|
||||
expr_ref fml1 = qe::mk_and(core);
|
||||
expr_ref fml1 = mk_and(core);
|
||||
expr_ref fml2 = n.pt().get_formulas(n.level(), false);
|
||||
fml1_2.push_back(fml1);
|
||||
fml1_2.push_back(0);
|
||||
|
@ -205,7 +205,7 @@ namespace pdr {
|
|||
if (l_false == n.pt().is_reachable(nd, &conv2, uses_level1)) {
|
||||
new_cores.push_back(std::make_pair(conv2, uses_level1));
|
||||
change = true;
|
||||
expr_ref state1 = qe::mk_and(conv2);
|
||||
expr_ref state1 = mk_and(conv2);
|
||||
TRACE("pdr",
|
||||
tout << mk_pp(state, m) << "\n";
|
||||
tout << "Generalized to:\n" << mk_pp(state1, m) << "\n";);
|
||||
|
@ -593,7 +593,7 @@ namespace pdr {
|
|||
for (unsigned i = ut_size; i < t_size; i++) {
|
||||
conj.push_back(rule.get_tail(i));
|
||||
}
|
||||
result = qe::mk_and(conj);
|
||||
result = mk_and(conj);
|
||||
if (!sub.empty()) {
|
||||
expr_ref tmp = result;
|
||||
var_subst(m, false)(tmp, sub.size(), sub.c_ptr(), result);
|
||||
|
@ -685,7 +685,7 @@ namespace pdr {
|
|||
for (unsigned i = 0; i < rules.size(); ++i) {
|
||||
fmls.push_back(m.mk_not(mk_transition_rule(reps, level, *rules[i])));
|
||||
}
|
||||
fml = qe::mk_and(fmls);
|
||||
fml = mk_and(fmls);
|
||||
TRACE("pdr", tout << mk_pp(fml, m) << "\n";);
|
||||
return fml;
|
||||
}
|
||||
|
@ -741,7 +741,7 @@ namespace pdr {
|
|||
}
|
||||
}
|
||||
|
||||
expr_ref result = qe::mk_and(conjs);
|
||||
expr_ref result = mk_and(conjs);
|
||||
TRACE("pdr", tout << mk_pp(result, m) << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ sym_mux::sym_mux(ast_manager & m)
|
|||
: m(m), m_ref_holder(m),
|
||||
m_next_sym_suffix_idx(0) {
|
||||
m_suffixes.push_back("_n");
|
||||
unsigned suf_sz = m_suffixes.size();
|
||||
size_t suf_sz = m_suffixes.size();
|
||||
for(unsigned i = 0; i < suf_sz; ++i) {
|
||||
symbol suff_sym = symbol(m_suffixes[i].c_str());
|
||||
m_used_suffixes.insert(suff_sym);
|
||||
|
|
|
@ -93,7 +93,6 @@ private:
|
|||
std::string get_suffix(unsigned i);
|
||||
void ensure_tuple_size(func_decl * prim, unsigned sz);
|
||||
|
||||
expr_ref isolate_o_idx(expr* e, unsigned idx) const;
|
||||
public:
|
||||
sym_mux(ast_manager & m);
|
||||
|
||||
|
@ -241,8 +240,6 @@ public:
|
|||
func_decl * const * begin_prim_preds() const { return m_prim_preds.begin(); }
|
||||
func_decl * const * end_prim_preds() const { return m_prim_preds.end(); }
|
||||
|
||||
void get_muxed_cube_from_model(const model_core & model, expr_ref_vector & res) const;
|
||||
|
||||
std::string pp_model(const model_core & mdl) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ Copyright (c) 2015 Microsoft Corporation
|
|||
|
||||
#include "check_relation.h"
|
||||
#include "dl_relation_manager.h"
|
||||
#include "qe_util.h"
|
||||
#include "ast_util.h"
|
||||
#include "smt_kernel.h"
|
||||
#include <typeinfo>
|
||||
|
|
|
@ -23,7 +23,6 @@ Notes:
|
|||
--*/
|
||||
#include "udoc_relation.h"
|
||||
#include "dl_relation_manager.h"
|
||||
#include "qe_util.h"
|
||||
#include "ast_util.h"
|
||||
#include "smt_kernel.h"
|
||||
|
||||
|
|
|
@ -39,6 +39,17 @@ namespace nlsat {
|
|||
m_values.swap(other.m_values);
|
||||
m_assigned.swap(other.m_assigned);
|
||||
}
|
||||
void copy(assignment const& other) {
|
||||
m_assigned.reset();
|
||||
m_assigned.append(other.m_assigned);
|
||||
m_values.reserve(m_assigned.size(), anum());
|
||||
for (unsigned i = 0; i < m_assigned.size(); ++i) {
|
||||
if (is_assigned(i)) {
|
||||
am().set(m_values[i], other.value(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_core(var x, anum & v) {
|
||||
m_values.reserve(x+1, anum());
|
||||
m_assigned.reserve(x+1, false);
|
||||
|
@ -52,11 +63,26 @@ namespace nlsat {
|
|||
am().set(m_values[x], v);
|
||||
}
|
||||
void reset(var x) { if (x < m_assigned.size()) m_assigned[x] = false; }
|
||||
void reset() { m_assigned.reset(); }
|
||||
bool is_assigned(var x) const { return m_assigned.get(x, false); }
|
||||
anum const & value(var x) const { return m_values[x]; }
|
||||
virtual anum_manager & m() const { return am(); }
|
||||
virtual bool contains(var x) const { return is_assigned(x); }
|
||||
virtual anum const & operator()(var x) const { SASSERT(is_assigned(x)); return value(x); }
|
||||
void swap(var x, var y) {
|
||||
SASSERT(x < m_values.size() && y < m_values.size());
|
||||
std::swap(m_assigned[x], m_assigned[y]);
|
||||
std::swap(m_values[x], m_values[y]);
|
||||
}
|
||||
void display(std::ostream& out) const {
|
||||
for (unsigned i = 0; i < m_assigned.size(); ++i) {
|
||||
if (m_assigned[i]) {
|
||||
out << "x" << i << " := ";
|
||||
m_values.m().display(out, m_values[i]);
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,10 +18,12 @@ Revision History:
|
|||
|
||||
--*/
|
||||
#include"nlsat_evaluator.h"
|
||||
#include"nlsat_solver.h"
|
||||
|
||||
namespace nlsat {
|
||||
|
||||
struct evaluator::imp {
|
||||
solver& m_solver;
|
||||
assignment const & m_assignment;
|
||||
pmanager & m_pm;
|
||||
small_object_allocator & m_allocator;
|
||||
|
@ -357,7 +359,8 @@ namespace nlsat {
|
|||
|
||||
sign_table m_sign_table_tmp;
|
||||
|
||||
imp(assignment const & x2v, pmanager & pm, small_object_allocator & allocator):
|
||||
imp(solver& s, assignment const & x2v, pmanager & pm, small_object_allocator & allocator):
|
||||
m_solver(s),
|
||||
m_assignment(x2v),
|
||||
m_pm(pm),
|
||||
m_allocator(allocator),
|
||||
|
@ -420,10 +423,25 @@ namespace nlsat {
|
|||
scoped_anum_vector & roots = m_tmp_values;
|
||||
roots.reset();
|
||||
m_am.isolate_roots(polynomial_ref(a->p(), m_pm), undef_var_assignment(m_assignment, a->x()), roots);
|
||||
TRACE("nlsat",
|
||||
m_solver.display(tout << (neg?"!":""), *a); tout << "\n";
|
||||
if (roots.empty()) {
|
||||
tout << "No roots\n";
|
||||
}
|
||||
else {
|
||||
tout << "Roots for ";
|
||||
for (unsigned i = 0; i < roots.size(); ++i) {
|
||||
m_am.display_interval(tout, roots[i]); tout << " ";
|
||||
}
|
||||
tout << "\n";
|
||||
}
|
||||
m_assignment.display(tout);
|
||||
);
|
||||
SASSERT(a->i() > 0);
|
||||
if (a->i() > roots.size())
|
||||
return false; // p does have sufficient roots
|
||||
int sign = m_am.compare(m_assignment.value(a->x()), roots[a->i() - 1]);
|
||||
if (a->i() > roots.size()) {
|
||||
return neg;
|
||||
}
|
||||
int sign = m_am.compare(m_assignment.value(a->x()), roots[a->i() - 1]);
|
||||
return satisfied(sign, k, neg);
|
||||
}
|
||||
|
||||
|
@ -649,8 +667,8 @@ namespace nlsat {
|
|||
}
|
||||
};
|
||||
|
||||
evaluator::evaluator(assignment const & x2v, pmanager & pm, small_object_allocator & allocator) {
|
||||
m_imp = alloc(imp, x2v, pm, allocator);
|
||||
evaluator::evaluator(solver& s, assignment const & x2v, pmanager & pm, small_object_allocator & allocator) {
|
||||
m_imp = alloc(imp, s, x2v, pm, allocator);
|
||||
}
|
||||
|
||||
evaluator::~evaluator() {
|
||||
|
|
|
@ -26,11 +26,13 @@ Revision History:
|
|||
|
||||
namespace nlsat {
|
||||
|
||||
class solver;
|
||||
|
||||
class evaluator {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
public:
|
||||
evaluator(assignment const & x2v, pmanager & pm, small_object_allocator & allocator);
|
||||
evaluator(solver& s, assignment const & x2v, pmanager & pm, small_object_allocator & allocator);
|
||||
~evaluator();
|
||||
|
||||
interval_set_manager & ism() const;
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace nlsat {
|
|||
polynomial::cache & m_cache;
|
||||
pmanager & m_pm;
|
||||
polynomial_ref_vector m_ps;
|
||||
polynomial_ref_vector m_ps2;
|
||||
polynomial_ref_vector m_psc_tmp;
|
||||
polynomial_ref_vector m_factors;
|
||||
scoped_anum_vector m_roots_tmp;
|
||||
|
@ -43,6 +44,7 @@ namespace nlsat {
|
|||
bool m_full_dimensional;
|
||||
bool m_minimize_cores;
|
||||
bool m_factor;
|
||||
bool m_signed_project;
|
||||
|
||||
struct todo_set {
|
||||
polynomial::cache & m_cache;
|
||||
|
@ -137,6 +139,7 @@ namespace nlsat {
|
|||
m_cache(u),
|
||||
m_pm(u.pm()),
|
||||
m_ps(m_pm),
|
||||
m_ps2(m_pm),
|
||||
m_psc_tmp(m_pm),
|
||||
m_factors(m_pm),
|
||||
m_roots_tmp(m_am),
|
||||
|
@ -148,6 +151,7 @@ namespace nlsat {
|
|||
m_simplify_cores = false;
|
||||
m_full_dimensional = false;
|
||||
m_minimize_cores = false;
|
||||
m_signed_project = false;
|
||||
}
|
||||
|
||||
~imp() {
|
||||
|
@ -202,7 +206,7 @@ namespace nlsat {
|
|||
void reset_already_added() {
|
||||
SASSERT(m_result != 0);
|
||||
unsigned sz = m_result->size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
m_already_added_literal[(*m_result)[i].index()] = false;
|
||||
}
|
||||
|
||||
|
@ -212,7 +216,7 @@ namespace nlsat {
|
|||
max_var(p) must be assigned in the current interpretation.
|
||||
*/
|
||||
int sign(polynomial_ref const & p) {
|
||||
TRACE("nlsat_explain", tout << "p: " << p << "\n";);
|
||||
TRACE("nlsat_explain", tout << "p: " << p << " var: " << max_var(p) << "\n";);
|
||||
SASSERT(max_var(p) == null_var || m_assignment.is_assigned(max_var(p)));
|
||||
return m_am.eval_sign_at(p, m_assignment);
|
||||
}
|
||||
|
@ -697,39 +701,163 @@ namespace nlsat {
|
|||
}
|
||||
}
|
||||
|
||||
void test_root_literal(atom::kind k, var y, unsigned i, poly * p, scoped_literal_vector& result) {
|
||||
m_result = &result;
|
||||
add_root_literal(k, y, i, p);
|
||||
reset_already_added();
|
||||
m_result = 0;
|
||||
}
|
||||
|
||||
void add_root_literal(atom::kind k, var y, unsigned i, poly * p) {
|
||||
polynomial_ref pr(p, m_pm);
|
||||
TRACE("nlsat_explain",
|
||||
display(tout << "x" << y << " " << k << "[" << i << "](", pr); tout << ")\n";);
|
||||
|
||||
if (!mk_linear_root(k, y, i, p) &&
|
||||
//!mk_plinear_root(k, y, i, p) &&
|
||||
!mk_quadratic_root(k, y, i, p)&&
|
||||
true) {
|
||||
bool_var b = m_solver.mk_root_atom(k, y, i, p);
|
||||
literal l(b, true);
|
||||
TRACE("nlsat_explain", tout << "adding literal\n"; display(tout, l); tout << "\n";);
|
||||
add_literal(l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* literal can be expressed using a linear ineq_atom
|
||||
*/
|
||||
bool mk_linear_root(atom::kind k, var y, unsigned i, poly * p) {
|
||||
scoped_mpz c(m_pm.m());
|
||||
bool_var b;
|
||||
bool lsign = false;
|
||||
if (m_pm.degree(p, y) == 1 && m_pm.const_coeff(p, y, 1, c)) {
|
||||
SASSERT(!m_pm.m().is_zero(c));
|
||||
// literal can be expressed using a linear ineq_atom
|
||||
polynomial_ref p_prime(m_pm);
|
||||
p_prime = p;
|
||||
if (m_pm.m().is_neg(c))
|
||||
p_prime = neg(p_prime);
|
||||
p = p_prime.get();
|
||||
switch (k) {
|
||||
case atom::ROOT_EQ: k = atom::EQ; lsign = false; break;
|
||||
case atom::ROOT_LT: k = atom::LT; lsign = false; break;
|
||||
case atom::ROOT_GT: k = atom::GT; lsign = false; break;
|
||||
case atom::ROOT_LE: k = atom::GT; lsign = true; break;
|
||||
case atom::ROOT_GE: k = atom::LT; lsign = true; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
bool is_even = false;
|
||||
b = m_solver.mk_ineq_atom(k, 1, &p, &is_even);
|
||||
mk_linear_root(k, y, i, p, m_pm.m().is_neg(c));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
b = m_solver.mk_root_atom(k, y, i, p);
|
||||
lsign = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create pseudo-linear root depending on the sign of the coefficient to y.
|
||||
*/
|
||||
bool mk_plinear_root(atom::kind k, var y, unsigned i, poly * p) {
|
||||
if (m_pm.degree(p, y) != 1) {
|
||||
return false;
|
||||
}
|
||||
lsign = !lsign; // adding as an assumption
|
||||
literal l(b, lsign);
|
||||
TRACE("nlsat_explain", tout << "adding literal\n"; display(tout, l); tout << "\n";);
|
||||
add_literal(l);
|
||||
polynomial_ref c(m_pm);
|
||||
c = m_pm.coeff(p, y, 1);
|
||||
int s = sign(c);
|
||||
if (s == 0) {
|
||||
return false;
|
||||
}
|
||||
ensure_sign(c);
|
||||
mk_linear_root(k, y, i, p, s < 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Encode root conditions for quadratic polynomials.
|
||||
|
||||
Basically implements Thom's theorem. The roots are characterized by the sign of polynomials and their derivatives.
|
||||
|
||||
b^2 - 4ac = 0:
|
||||
- there is only one root, which is -b/2a.
|
||||
- relation to root is a function of the sign of
|
||||
- 2ax + b
|
||||
b^2 - 4ac > 0:
|
||||
- assert i == 1 or i == 2
|
||||
- relation to root is a function of the signs of:
|
||||
- 2ax + b
|
||||
- ax^2 + bx + c
|
||||
*/
|
||||
|
||||
bool mk_quadratic_root(atom::kind k, var y, unsigned i, poly * p) {
|
||||
if (m_pm.degree(p, y) != 2) {
|
||||
return false;
|
||||
}
|
||||
if (i != 1 && i != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SASSERT(m_assignment.is_assigned(y));
|
||||
polynomial_ref A(m_pm), B(m_pm), C(m_pm), q(m_pm), p_diff(m_pm), yy(m_pm);
|
||||
A = m_pm.coeff(p, y, 2);
|
||||
B = m_pm.coeff(p, y, 1);
|
||||
C = m_pm.coeff(p, y, 0);
|
||||
// TBD throttle based on degree of q?
|
||||
q = (B*B) - (4*A*C);
|
||||
yy = m_pm.mk_polynomial(y);
|
||||
p_diff = 2*A*yy + B;
|
||||
p_diff = m_pm.normalize(p_diff);
|
||||
int sq = ensure_sign(q);
|
||||
if (sq < 0) {
|
||||
return false;
|
||||
}
|
||||
int sa = ensure_sign(A);
|
||||
if (sa == 0) {
|
||||
q = B*yy + C;
|
||||
return mk_plinear_root(k, y, i, q);
|
||||
}
|
||||
ensure_sign(p_diff);
|
||||
if (sq > 0) {
|
||||
polynomial_ref pr(p, m_pm);
|
||||
ensure_sign(pr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int ensure_sign(polynomial_ref & p) {
|
||||
#if 0
|
||||
polynomial_ref f(m_pm);
|
||||
factor(p, m_factors);
|
||||
m_is_even.reset();
|
||||
unsigned num_factors = m_factors.size();
|
||||
int s = 1;
|
||||
for (unsigned i = 0; i < num_factors; i++) {
|
||||
f = m_factors.get(i);
|
||||
s *= sign(f);
|
||||
m_is_even.push_back(false);
|
||||
}
|
||||
if (num_factors > 0) {
|
||||
atom::kind k = atom::EQ;
|
||||
if (s == 0) k = atom::EQ;
|
||||
if (s < 0) k = atom::LT;
|
||||
if (s > 0) k = atom::GT;
|
||||
bool_var b = m_solver.mk_ineq_atom(k, num_factors, m_factors.c_ptr(), m_is_even.c_ptr());
|
||||
add_literal(literal(b, true));
|
||||
}
|
||||
return s;
|
||||
#else
|
||||
int s = sign(p);
|
||||
if (!is_const(p)) {
|
||||
add_simple_assumption(s == 0 ? atom::EQ : (s < 0 ? atom::LT : atom::GT), p);
|
||||
}
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Auxiliary function to linear roots.
|
||||
*/
|
||||
void mk_linear_root(atom::kind k, var y, unsigned i, poly * p, bool mk_neg) {
|
||||
polynomial_ref p_prime(m_pm);
|
||||
p_prime = p;
|
||||
bool lsign = false;
|
||||
if (mk_neg)
|
||||
p_prime = neg(p_prime);
|
||||
p = p_prime.get();
|
||||
switch (k) {
|
||||
case atom::ROOT_EQ: k = atom::EQ; lsign = false; break;
|
||||
case atom::ROOT_LT: k = atom::LT; lsign = false; break;
|
||||
case atom::ROOT_GT: k = atom::GT; lsign = false; break;
|
||||
case atom::ROOT_LE: k = atom::GT; lsign = true; break;
|
||||
case atom::ROOT_GE: k = atom::LT; lsign = true; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
add_simple_assumption(k, p, lsign);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1332,10 +1460,333 @@ namespace nlsat {
|
|||
TRACE("nlsat_explain", tout << "[explain] result\n"; display(tout, result););
|
||||
CASSERT("nlsat", check_already_added());
|
||||
}
|
||||
|
||||
|
||||
void project(var x, unsigned num, literal const * ls, scoped_literal_vector & result) {
|
||||
m_result = &result;
|
||||
svector<literal> lits;
|
||||
TRACE("nlsat", tout << "project x" << x << "\n"; m_solver.display(tout););
|
||||
|
||||
DEBUG_CODE(
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
SASSERT(m_solver.value(ls[i]) == l_true);
|
||||
atom* a = m_atoms[ls[i].var()];
|
||||
SASSERT(!a || m_evaluator.eval(a, ls[i].sign()));
|
||||
});
|
||||
split_literals(x, num, ls, lits);
|
||||
collect_polys(lits.size(), lits.c_ptr(), m_ps);
|
||||
var mx_var = max_var(m_ps);
|
||||
if (!m_ps.empty()) {
|
||||
svector<var> renaming;
|
||||
if (x != mx_var) {
|
||||
for (var i = 0; i < m_solver.num_vars(); ++i) {
|
||||
renaming.push_back(i);
|
||||
}
|
||||
std::swap(renaming[x], renaming[mx_var]);
|
||||
m_solver.reorder(renaming.size(), renaming.c_ptr());
|
||||
TRACE("qe", tout << "x: " << x << " max: " << mx_var << " num_vars: " << m_solver.num_vars() << "\n";
|
||||
m_solver.display(tout););
|
||||
}
|
||||
elim_vanishing(m_ps);
|
||||
if (m_signed_project) {
|
||||
signed_project(m_ps, mx_var);
|
||||
}
|
||||
else {
|
||||
project(m_ps, mx_var);
|
||||
}
|
||||
reset_already_added();
|
||||
m_result = 0;
|
||||
if (x != mx_var) {
|
||||
m_solver.restore_order();
|
||||
}
|
||||
}
|
||||
else {
|
||||
reset_already_added();
|
||||
m_result = 0;
|
||||
}
|
||||
for (unsigned i = 0; i < result.size(); ++i) {
|
||||
result.set(i, ~result[i]);
|
||||
}
|
||||
DEBUG_CODE(
|
||||
for (unsigned i = 0; i < result.size(); ++i) {
|
||||
SASSERT(l_true == m_solver.value(result[i]));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void split_literals(var x, unsigned n, literal const* ls, svector<literal>& lits) {
|
||||
var_vector vs;
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
vs.reset();
|
||||
m_solver.vars(ls[i], vs);
|
||||
if (vs.contains(x)) {
|
||||
lits.push_back(ls[i]);
|
||||
}
|
||||
else {
|
||||
add_literal(~ls[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Signed projection.
|
||||
|
||||
Assumptions:
|
||||
- any variable in ps is at most x.
|
||||
- root expressions are satisfied (positive literals)
|
||||
|
||||
Effect:
|
||||
- if x not in p, then
|
||||
- if sign(p) < 0: p < 0
|
||||
- if sign(p) = 0: p = 0
|
||||
- if sign(p) > 0: p > 0
|
||||
else:
|
||||
- let roots_j be the roots of p_j or roots_j[i]
|
||||
- let L = { roots_j[i] | M(roots_j[i]) < M(x) }
|
||||
- let U = { roots_j[i] | M(roots_j[i]) > M(x) }
|
||||
- let E = { roots_j[i] | M(roots_j[i]) = M(x) }
|
||||
- let glb in L, s.t. forall l in L . M(glb) >= M(l)
|
||||
- let lub in U, s.t. forall u in U . M(lub) <= M(u)
|
||||
- if root in E, then
|
||||
- add E x . x = root & x > lb for lb in L
|
||||
- add E x . x = root & x < ub for ub in U
|
||||
- add E x . x = root & x = root2 for root2 in E \ { root }
|
||||
- else
|
||||
- assume |L| <= |U| (other case is symmetric)
|
||||
- add E x . lb <= x & x <= glb for lb in L
|
||||
- add E x . x = glb & x < ub for ub in U
|
||||
*/
|
||||
|
||||
|
||||
void signed_project(polynomial_ref_vector& ps, var x) {
|
||||
|
||||
TRACE("nlsat_explain", tout << "Signed projection\n";);
|
||||
polynomial_ref p(m_pm);
|
||||
unsigned eq_index = 0;
|
||||
bool eq_valid = false;
|
||||
unsigned eq_degree = 0;
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
p = ps.get(i);
|
||||
int s = sign(p);
|
||||
if (max_var(p) != x) {
|
||||
atom::kind k = (s == 0)?(atom::EQ):((s < 0)?(atom::LT):(atom::GT));
|
||||
add_simple_assumption(k, p, false);
|
||||
ps[i] = ps.back();
|
||||
ps.pop_back();
|
||||
--i;
|
||||
}
|
||||
else if (s == 0) {
|
||||
if (!eq_valid || degree(p, x) < eq_degree) {
|
||||
eq_index = i;
|
||||
eq_valid = true;
|
||||
eq_degree = degree(p, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ps.size() == 1) {
|
||||
project_single(x, ps.get(0));
|
||||
return;
|
||||
}
|
||||
|
||||
// ax + b = 0, p(x) > 0 ->
|
||||
|
||||
if (eq_valid) {
|
||||
p = ps.get(eq_index);
|
||||
if (degree(p, x) == 1) {
|
||||
// ax + b = 0
|
||||
// let d be maximal degree of x in p.
|
||||
// p(x) -> a^d*p(-b/a), a
|
||||
// perform virtual substitution with equality.
|
||||
solve_eq(x, eq_index, ps);
|
||||
}
|
||||
else {
|
||||
project_pairs(x, eq_index, ps);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned num_lub = 0, num_glb = 0;
|
||||
unsigned glb_index = 0, lub_index = 0;
|
||||
scoped_anum lub(m_am), glb(m_am), x_val(m_am);
|
||||
x_val = m_assignment.value(x);
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
p = ps.get(i);
|
||||
scoped_anum_vector & roots = m_roots_tmp;
|
||||
roots.reset();
|
||||
m_am.isolate_roots(p, undef_var_assignment(m_assignment, x), roots);
|
||||
bool glb_valid = false, lub_valid = false;
|
||||
for (unsigned j = 0; j < roots.size(); ++j) {
|
||||
int s = m_am.compare(x_val, roots[j]);
|
||||
SASSERT(s != 0);
|
||||
lub_valid |= s < 0;
|
||||
glb_valid |= s > 0;
|
||||
|
||||
if (s < 0 && m_am.lt(roots[j], lub)) {
|
||||
lub_index = i;
|
||||
m_am.set(lub, roots[j]);
|
||||
}
|
||||
|
||||
if (s > 0 && m_am.lt(glb, roots[j])) {
|
||||
glb_index = i;
|
||||
m_am.set(glb, roots[j]);
|
||||
}
|
||||
}
|
||||
if (glb_valid) {
|
||||
++num_glb;
|
||||
}
|
||||
if (lub_valid) {
|
||||
++num_lub;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_lub == 0) {
|
||||
project_plus_infinity(x, ps);
|
||||
return;
|
||||
}
|
||||
|
||||
if (num_glb == 0) {
|
||||
project_minus_infinity(x, ps);
|
||||
return;
|
||||
}
|
||||
|
||||
if (num_lub <= num_glb) {
|
||||
glb_index = lub_index;
|
||||
}
|
||||
|
||||
project_pairs(x, glb_index, ps);
|
||||
}
|
||||
|
||||
void project_plus_infinity(var x, polynomial_ref_vector const& ps) {
|
||||
polynomial_ref p(m_pm), lc(m_pm);
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
p = ps.get(i);
|
||||
unsigned d = degree(p, x);
|
||||
lc = m_pm.coeff(p, x, d);
|
||||
if (!is_const(lc)) {
|
||||
unsigned s = sign(p);
|
||||
SASSERT(s != 0);
|
||||
atom::kind k = (s > 0)?(atom::GT):(atom::LT);
|
||||
add_simple_assumption(k, lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void project_minus_infinity(var x, polynomial_ref_vector const& ps) {
|
||||
polynomial_ref p(m_pm), lc(m_pm);
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
p = ps.get(i);
|
||||
unsigned d = degree(p, x);
|
||||
lc = m_pm.coeff(p, x, d);
|
||||
if (!is_const(lc)) {
|
||||
unsigned s = sign(p);
|
||||
SASSERT(s != 0);
|
||||
atom::kind k;
|
||||
if (s > 0) {
|
||||
k = (d % 2 == 0)?(atom::GT):(atom::LT);
|
||||
}
|
||||
else {
|
||||
k = (d % 2 == 0)?(atom::LT):(atom::GT);
|
||||
}
|
||||
add_simple_assumption(k, lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void project_pairs(var x, unsigned idx, polynomial_ref_vector const& ps) {
|
||||
polynomial_ref p(m_pm);
|
||||
p = ps.get(idx);
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
if (i != idx) {
|
||||
project_pair(x, ps.get(i), p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void project_pair(var x, polynomial::polynomial* p1, polynomial::polynomial* p2) {
|
||||
m_ps2.reset();
|
||||
m_ps2.push_back(p1);
|
||||
m_ps2.push_back(p2);
|
||||
project(m_ps2, x);
|
||||
}
|
||||
|
||||
void project_single(var x, polynomial::polynomial* p) {
|
||||
m_ps2.reset();
|
||||
m_ps2.push_back(p);
|
||||
project(m_ps2, x);
|
||||
}
|
||||
|
||||
void solve_eq(var x, unsigned idx, polynomial_ref_vector const& ps) {
|
||||
polynomial_ref p(m_pm), A(m_pm), B(m_pm), C(m_pm), D(m_pm), E(m_pm), q(m_pm), r(m_pm);
|
||||
polynomial_ref_vector qs(m_pm);
|
||||
p = ps.get(idx);
|
||||
SASSERT(degree(p, x) == 1);
|
||||
A = m_pm.coeff(p, x, 1);
|
||||
B = m_pm.coeff(p, x, 0);
|
||||
B = neg(B);
|
||||
TRACE("nlsat_explain", tout << "p: " << p << " A: " << A << " B: " << B << "\n";);
|
||||
// x = B/A
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
if (i != idx) {
|
||||
q = ps.get(i);
|
||||
unsigned d = degree(q, x);
|
||||
D = m_pm.mk_const(rational(1));
|
||||
E = D;
|
||||
r = m_pm.mk_zero();
|
||||
for (unsigned j = 0; j <= d; ++j) {
|
||||
qs.push_back(D);
|
||||
D = D*A;
|
||||
}
|
||||
for (unsigned j = 0; j <= d; ++j) {
|
||||
// A^d*p0 + A^{d-1}*B*p1 + ... + B^j*A^{d-j}*pj + ... + B^d*p_d
|
||||
C = m_pm.coeff(q, x, j);
|
||||
if (!is_zero(C)) {
|
||||
D = qs.get(d-j);
|
||||
r = r + D*E*C;
|
||||
}
|
||||
E = E*B;
|
||||
}
|
||||
TRACE("nlsat_explain", tout << "q: " << q << " r: " << r << "\n";);
|
||||
ensure_sign(r);
|
||||
}
|
||||
else {
|
||||
ensure_sign(A);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void maximize(var x, unsigned num, literal const * ls, scoped_anum& val, bool& unbounded) {
|
||||
svector<literal> lits;
|
||||
polynomial_ref p(m_pm);
|
||||
split_literals(x, num, ls, lits);
|
||||
collect_polys(lits.size(), lits.c_ptr(), m_ps);
|
||||
unbounded = true;
|
||||
scoped_anum x_val(m_am);
|
||||
x_val = m_assignment.value(x);
|
||||
for (unsigned i = 0; i < m_ps.size(); ++i) {
|
||||
p = m_ps.get(i);
|
||||
scoped_anum_vector & roots = m_roots_tmp;
|
||||
roots.reset();
|
||||
m_am.isolate_roots(p, undef_var_assignment(m_assignment, x), roots);
|
||||
for (unsigned j = 0; j < roots.size(); ++j) {
|
||||
int s = m_am.compare(x_val, roots[j]);
|
||||
if (s <= 0 && (unbounded || m_am.compare(roots[j], val) <= 0)) {
|
||||
unbounded = false;
|
||||
val = roots[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
explain::explain(solver & s, assignment const & x2v, polynomial::cache & u, atom_vector const & atoms, atom_vector const & x2eq,
|
||||
evaluator & ev) {
|
||||
explain::explain(solver & s, assignment const & x2v, polynomial::cache & u,
|
||||
atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev) {
|
||||
m_imp = alloc(imp, s, x2v, u, atoms, x2eq, ev);
|
||||
}
|
||||
|
||||
|
@ -1364,10 +1815,26 @@ namespace nlsat {
|
|||
m_imp->m_factor = f;
|
||||
}
|
||||
|
||||
void explain::set_signed_project(bool f) {
|
||||
m_imp->m_signed_project = f;
|
||||
}
|
||||
|
||||
void explain::operator()(unsigned n, literal const * ls, scoped_literal_vector & result) {
|
||||
(*m_imp)(n, ls, result);
|
||||
}
|
||||
|
||||
void explain::project(var x, unsigned n, literal const * ls, scoped_literal_vector & result) {
|
||||
m_imp->project(x, n, ls, result);
|
||||
}
|
||||
|
||||
void explain::maximize(var x, unsigned n, literal const * ls, scoped_anum& val, bool& unbounded) {
|
||||
m_imp->maximize(x, n, ls, val, unbounded);
|
||||
}
|
||||
|
||||
void explain::test_root_literal(atom::kind k, var y, unsigned i, poly* p, scoped_literal_vector & result) {
|
||||
m_imp->test_root_literal(k, y, i, p, result);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
|
@ -1398,3 +1865,4 @@ void pp_lit(nlsat::explain::imp & ex, nlsat::literal l) {
|
|||
std::cout << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -22,9 +22,11 @@ Revision History:
|
|||
#include"nlsat_solver.h"
|
||||
#include"nlsat_scoped_literal_vector.h"
|
||||
#include"polynomial_cache.h"
|
||||
#include"algebraic_numbers.h"
|
||||
|
||||
namespace nlsat {
|
||||
class evaluator;
|
||||
|
||||
|
||||
class explain {
|
||||
public:
|
||||
|
@ -32,8 +34,8 @@ namespace nlsat {
|
|||
private:
|
||||
imp * m_imp;
|
||||
public:
|
||||
explain(solver & s, assignment const & x2v, polynomial::cache & u, atom_vector const & atoms, atom_vector const & x2eq,
|
||||
evaluator & ev);
|
||||
explain(solver & s, assignment const & x2v, polynomial::cache & u,
|
||||
atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev);
|
||||
~explain();
|
||||
|
||||
void reset();
|
||||
|
@ -41,6 +43,7 @@ namespace nlsat {
|
|||
void set_full_dimensional(bool f);
|
||||
void set_minimize_cores(bool f);
|
||||
void set_factor(bool f);
|
||||
void set_signed_project(bool f);
|
||||
|
||||
/**
|
||||
\brief Given a set of literals ls[0], ... ls[n-1] s.t.
|
||||
|
@ -60,6 +63,48 @@ namespace nlsat {
|
|||
- s_1, ..., s_m are false in the current interpretation
|
||||
*/
|
||||
void operator()(unsigned n, literal const * ls, scoped_literal_vector & result);
|
||||
|
||||
|
||||
/**
|
||||
\brief projection for a given variable.
|
||||
|
||||
Given: M |= l1[x] /\ ... /\ ln[x]
|
||||
|
||||
Find: M |= s1, ..., sm
|
||||
|
||||
Such that: |= ~s1 \/ ... \/ ~sm \/ E x. l1[x] /\ ... /\ ln[x]
|
||||
|
||||
Contrast this with with the core-based projection above:
|
||||
|
||||
Given: M |= A x . l1[x] \/ ... \/ ln[x]
|
||||
|
||||
Find: M |= ~s1, ..., ~sm.
|
||||
|
||||
Such that: |= s1 \/ ... \/ sm \/ A x . l1[x] \/ ... \/ ln[x]
|
||||
|
||||
Claim: the two compute the same solutions if the projection operators are independent of the value of x.
|
||||
Claim: A complete, convergent projection operator can be obtained from M in a way that is independent of x.
|
||||
|
||||
|
||||
*/
|
||||
void project(var x, unsigned n, literal const * ls, scoped_literal_vector & result);
|
||||
|
||||
/**
|
||||
Maximize the value of x (locally) under the current assignment to other variables and
|
||||
while maintaining the assignment to the literals ls.
|
||||
Set unbounded to 'true' if the value of x is unbounded.
|
||||
|
||||
Precondition: the set of literals are true in the current model.
|
||||
|
||||
By local optimization we understand that x is increased to the largest value within
|
||||
the signs delineated by the roots of the polynomials in ls.
|
||||
*/
|
||||
void maximize(var x, unsigned n, literal const * ls, scoped_anum& val, bool& unbounded);
|
||||
|
||||
/**
|
||||
Unit test routine.
|
||||
*/
|
||||
void test_root_literal(atom::kind k, var y, unsigned i, poly* p, scoped_literal_vector & result);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -64,6 +64,13 @@ namespace nlsat {
|
|||
for (unsigned i = 0; i < sz; i++)
|
||||
push_back(ls[i]);
|
||||
}
|
||||
void append(scoped_literal_vector const& ls) {
|
||||
append(ls.size(), ls.c_ptr());
|
||||
}
|
||||
void swap(scoped_literal_vector& other) {
|
||||
SASSERT(&m_solver == &other.m_solver);
|
||||
m_lits.swap(other.m_lits);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ namespace nlsat {
|
|||
typedef polynomial::cache cache;
|
||||
typedef ptr_vector<interval_set> interval_set_vector;
|
||||
|
||||
solver & m_solver;
|
||||
reslimit& m_rlimit;
|
||||
small_object_allocator m_allocator;
|
||||
unsynch_mpq_manager m_qm;
|
||||
|
@ -159,8 +158,7 @@ namespace nlsat {
|
|||
unsigned m_stages;
|
||||
unsigned m_irrational_assignments; // number of irrational witnesses
|
||||
|
||||
imp(solver & s, reslimit& rlim, params_ref const & p):
|
||||
m_solver(s),
|
||||
imp(solver& s, reslimit& rlim, params_ref const & p):
|
||||
m_rlimit(rlim),
|
||||
m_allocator("nlsat"),
|
||||
m_pm(rlim, m_qm, &m_allocator),
|
||||
|
@ -168,7 +166,7 @@ namespace nlsat {
|
|||
m_am(rlim, m_qm, p, &m_allocator),
|
||||
m_asm(*this, m_allocator),
|
||||
m_assignment(m_am),
|
||||
m_evaluator(m_assignment, m_pm, m_allocator),
|
||||
m_evaluator(s, m_assignment, m_pm, m_allocator),
|
||||
m_ism(m_evaluator.ism()),
|
||||
m_num_bool_vars(0),
|
||||
m_display_var(m_perm),
|
||||
|
@ -183,12 +181,7 @@ namespace nlsat {
|
|||
}
|
||||
|
||||
~imp() {
|
||||
m_explain.reset();
|
||||
m_lemma.reset();
|
||||
m_lazy_clause.reset();
|
||||
undo_until_size(0);
|
||||
del_clauses();
|
||||
del_unref_atoms();
|
||||
reset();
|
||||
}
|
||||
|
||||
void mk_true_bvar() {
|
||||
|
@ -216,6 +209,18 @@ namespace nlsat {
|
|||
m_am.updt_params(p.p);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_explain.reset();
|
||||
m_lemma.reset();
|
||||
m_lazy_clause.reset();
|
||||
undo_until_size(0);
|
||||
del_clauses();
|
||||
del_unref_atoms();
|
||||
m_cache.reset();
|
||||
m_assignment.reset();
|
||||
}
|
||||
|
||||
|
||||
void checkpoint() {
|
||||
if (!m_rlimit.inc()) throw solver_exception(m_rlimit.get_cancel_msg());
|
||||
if (memory::get_allocation_size() > m_max_memory) throw solver_exception(Z3_MAX_MEMORY_MSG);
|
||||
|
@ -252,6 +257,7 @@ namespace nlsat {
|
|||
}
|
||||
|
||||
void inc_ref(bool_var b) {
|
||||
TRACE("ref", tout << "inc: " << b << "\n";);
|
||||
if (b == null_bool_var)
|
||||
return;
|
||||
if (m_atoms[b] == 0)
|
||||
|
@ -264,6 +270,7 @@ namespace nlsat {
|
|||
}
|
||||
|
||||
void dec_ref(bool_var b) {
|
||||
TRACE("ref", tout << "dec: " << b << "\n";);
|
||||
if (b == null_bool_var)
|
||||
return;
|
||||
atom * a = m_atoms[b];
|
||||
|
@ -412,6 +419,34 @@ namespace nlsat {
|
|||
return x;
|
||||
}
|
||||
|
||||
svector<bool> m_found_vars;
|
||||
void vars(literal l, var_vector& vs) {
|
||||
vs.reset();
|
||||
atom * a = m_atoms[l.var()];
|
||||
if (a == 0) {
|
||||
|
||||
}
|
||||
else if (a->is_ineq_atom()) {
|
||||
unsigned sz = to_ineq_atom(a)->size();
|
||||
var_vector new_vs;
|
||||
for (unsigned j = 0; j < sz; j++) {
|
||||
m_found_vars.reset();
|
||||
m_pm.vars(to_ineq_atom(a)->p(j), new_vs);
|
||||
for (unsigned i = 0; i < new_vs.size(); ++i) {
|
||||
if (!m_found_vars.get(new_vs[i], false)) {
|
||||
m_found_vars.setx(new_vs[i], true, false);
|
||||
vs.push_back(new_vs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_pm.vars(to_root_atom(a)->p(), vs);
|
||||
//vs.erase(max_var(to_root_atom(a)->p()));
|
||||
vs.push_back(to_root_atom(a)->x());
|
||||
}
|
||||
}
|
||||
|
||||
void deallocate(ineq_atom * a) {
|
||||
unsigned obj_sz = ineq_atom::get_obj_size(a->size());
|
||||
a->~ineq_atom();
|
||||
|
@ -425,7 +460,7 @@ namespace nlsat {
|
|||
|
||||
void del(bool_var b) {
|
||||
SASSERT(m_bwatches[b].empty());
|
||||
SASSERT(m_bvalues[b] == l_undef);
|
||||
//SASSERT(m_bvalues[b] == l_undef);
|
||||
m_num_bool_vars--;
|
||||
m_dead[b] = true;
|
||||
m_atoms[b] = 0;
|
||||
|
@ -491,6 +526,7 @@ namespace nlsat {
|
|||
TRACE("nlsat_table_bug", ineq_atom::hash_proc h;
|
||||
tout << "mk_ineq_atom hash: " << h(new_atom) << "\n"; display(tout, *new_atom, m_display_var); tout << "\n";);
|
||||
ineq_atom * old_atom = m_ineq_atoms.insert_if_not_there(new_atom);
|
||||
CTRACE("nlsat_table_bug", old_atom->max_var() != max, display(tout, *old_atom, m_display_var); tout << "\n";);
|
||||
SASSERT(old_atom->max_var() == max);
|
||||
if (old_atom != new_atom) {
|
||||
deallocate(new_atom);
|
||||
|
@ -726,7 +762,7 @@ namespace nlsat {
|
|||
|
||||
template<typename Predicate>
|
||||
void undo_until(Predicate const & pred) {
|
||||
while (pred()) {
|
||||
while (pred() && !m_trail.empty()) {
|
||||
trail & t = m_trail.back();
|
||||
switch (t.m_kind) {
|
||||
case trail::BVAR_ASSIGNMENT:
|
||||
|
@ -803,6 +839,14 @@ namespace nlsat {
|
|||
SASSERT(m_bvalues[b] == l_undef);
|
||||
}
|
||||
|
||||
struct true_pred {
|
||||
bool operator()() const { return true; }
|
||||
};
|
||||
|
||||
void undo_until_empty() {
|
||||
undo_until(true_pred());
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create a new scope level
|
||||
*/
|
||||
|
@ -868,10 +912,11 @@ namespace nlsat {
|
|||
var max = a->max_var();
|
||||
if (!m_assignment.is_assigned(max))
|
||||
return l_undef;
|
||||
TRACE("value_bug", tout << "value of: "; display(tout, l); tout << "\n"; tout << "xk: " << m_xk << ", a->max_var(): " << a->max_var() << "\n";
|
||||
display_assignment(tout);
|
||||
display_bool_assignment(tout););
|
||||
return to_lbool(m_evaluator.eval(a, l.sign()));
|
||||
val = to_lbool(m_evaluator.eval(a, l.sign()));
|
||||
TRACE("value_bug", tout << "value of: "; display(tout, l); tout << " := " << val << "\n";
|
||||
tout << "xk: " << m_xk << ", a->max_var(): " << a->max_var() << "\n";
|
||||
display_assignment(tout););
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -880,8 +925,10 @@ namespace nlsat {
|
|||
bool is_satisfied(clause const & cls) const {
|
||||
unsigned sz = cls.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
if (const_cast<imp*>(this)->value(cls[i]) == l_true)
|
||||
if (const_cast<imp*>(this)->value(cls[i]) == l_true) {
|
||||
TRACE("value_bug:", tout << cls[i] << " := true\n";);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -984,8 +1031,10 @@ namespace nlsat {
|
|||
If satisfy_learned is true, then learned clauses are satisfied even if m_lazy > 0
|
||||
*/
|
||||
bool process_arith_clause(clause const & cls, bool satisfy_learned) {
|
||||
if (!satisfy_learned && m_lazy >= 2 && cls.is_learned())
|
||||
if (!satisfy_learned && m_lazy >= 2 && cls.is_learned()) {
|
||||
TRACE("nlsat", tout << "skip learned\n";);
|
||||
return true; // ignore lemmas in super lazy mode
|
||||
}
|
||||
SASSERT(m_xk == max_var(cls));
|
||||
unsigned num_undef = 0; // number of undefined literals
|
||||
unsigned first_undef = UINT_MAX; // position of the first undefined literal
|
||||
|
@ -1064,7 +1113,7 @@ namespace nlsat {
|
|||
If satisfy_learned is true, then (arithmetic) learned clauses are satisfied even if m_lazy > 0
|
||||
*/
|
||||
bool process_clause(clause const & cls, bool satisfy_learned) {
|
||||
TRACE("nlsat", tout << "processing clause:\n"; display(tout, cls); tout << "\n";);
|
||||
TRACE("nlsat", tout << "processing clause: "; display(tout, cls); tout << "\n";);
|
||||
if (is_satisfied(cls))
|
||||
return true;
|
||||
if (m_xk == null_var)
|
||||
|
@ -1151,7 +1200,7 @@ namespace nlsat {
|
|||
}
|
||||
TRACE("nlsat_bug", tout << "xk: x" << m_xk << " bk: b" << m_bk << "\n";);
|
||||
if (m_bk == null_bool_var && m_xk >= num_vars()) {
|
||||
TRACE("nlsat", tout << "found model\n"; display_assignment(tout); display_bool_assignment(tout););
|
||||
TRACE("nlsat", tout << "found model\n"; display_assignment(tout););
|
||||
return l_true; // all variables were assigned, and all clauses were satisfied.
|
||||
}
|
||||
TRACE("nlsat", tout << "processing variable ";
|
||||
|
@ -1186,23 +1235,102 @@ namespace nlsat {
|
|||
lbool check() {
|
||||
TRACE("nlsat_smt2", display_smt2(tout););
|
||||
TRACE("nlsat_fd", tout << "is_full_dimensional: " << is_full_dimensional() << "\n";);
|
||||
m_xk = null_var;
|
||||
init_search();
|
||||
m_explain.set_full_dimensional(is_full_dimensional());
|
||||
if (m_random_order) {
|
||||
bool reordered = false;
|
||||
if (!can_reorder()) {
|
||||
|
||||
}
|
||||
else if (m_random_order) {
|
||||
shuffle_vars();
|
||||
reordered = true;
|
||||
}
|
||||
else if (m_reorder) {
|
||||
heuristic_reorder();
|
||||
reordered = true;
|
||||
}
|
||||
sort_watched_clauses();
|
||||
lbool r = search();
|
||||
CTRACE("nlsat_model", r == l_true, tout << "model before restore order\n"; display_assignment(tout); display_bool_assignment(tout););
|
||||
if (m_reorder)
|
||||
CTRACE("nlsat_model", r == l_true, tout << "model before restore order\n"; display_assignment(tout););
|
||||
if (reordered)
|
||||
restore_order();
|
||||
CTRACE("nlsat_model", r == l_true, tout << "model\n"; display_assignment(tout); display_bool_assignment(tout););
|
||||
CTRACE("nlsat_model", r == l_true, tout << "model\n"; display_assignment(tout););
|
||||
CTRACE("nlsat", r == l_false, display(tout););
|
||||
return r;
|
||||
}
|
||||
|
||||
void init_search() {
|
||||
undo_until_empty();
|
||||
while (m_scope_lvl > 0) {
|
||||
undo_new_level();
|
||||
}
|
||||
m_xk = null_var;
|
||||
for (unsigned i = 0; i < m_bvalues.size(); ++i) {
|
||||
m_bvalues[i] = l_undef;
|
||||
}
|
||||
m_assignment.reset();
|
||||
}
|
||||
|
||||
lbool check(literal_vector& assumptions) {
|
||||
literal_vector result;
|
||||
unsigned sz = assumptions.size();
|
||||
literal const* ptr = assumptions.c_ptr();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
mk_clause(1, ptr+i, (assumption)(ptr+i));
|
||||
}
|
||||
lbool r = check();
|
||||
|
||||
if (r == l_false) {
|
||||
// collect used literals from m_lemma_assumptions
|
||||
vector<assumption, false> deps;
|
||||
m_asm.linearize(m_lemma_assumptions.get(), deps);
|
||||
for (unsigned i = 0; i < deps.size(); ++i) {
|
||||
literal const* lp = (literal const*)(deps[i]);
|
||||
if (ptr <= lp && lp < ptr + sz) {
|
||||
result.push_back(*lp);
|
||||
}
|
||||
}
|
||||
}
|
||||
collect(assumptions, m_clauses);
|
||||
collect(assumptions, m_learned);
|
||||
|
||||
assumptions.reset();
|
||||
assumptions.append(result);
|
||||
return r;
|
||||
}
|
||||
|
||||
void collect(literal_vector const& assumptions, clause_vector& clauses) {
|
||||
unsigned n = clauses.size();
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
clause * c = clauses[i];
|
||||
if (collect(assumptions, *c)) {
|
||||
del_clause(c);
|
||||
}
|
||||
else {
|
||||
clauses[j] = c;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
clauses.shrink(j);
|
||||
}
|
||||
|
||||
bool collect(literal_vector const& assumptions, clause const& c) {
|
||||
unsigned sz = assumptions.size();
|
||||
literal const* ptr = assumptions.c_ptr();
|
||||
_assumption_set asms = static_cast<_assumption_set>(c.assumptions());
|
||||
if (asms == 0) {
|
||||
return false;
|
||||
}
|
||||
vector<assumption, false> deps;
|
||||
m_asm.linearize(asms, deps);
|
||||
bool found = false;
|
||||
for (unsigned i = 0; !found && i < deps.size(); ++i) {
|
||||
found = ptr <= deps[i] && deps[i] < ptr + sz;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
//
|
||||
// Conflict Resolution
|
||||
|
@ -1447,7 +1575,7 @@ namespace nlsat {
|
|||
TRACE("nlsat", tout << "resolve, conflicting clause:\n"; display(tout, *conflict_clause); tout << "\n";
|
||||
tout << "xk: "; if (m_xk != null_var) m_display_var(tout, m_xk); else tout << "<null>"; tout << "\n";
|
||||
tout << "scope_lvl: " << scope_lvl() << "\n";
|
||||
tout << "current assignment\n"; display_assignment(tout); display_bool_assignment(tout););
|
||||
tout << "current assignment\n"; display_assignment(tout););
|
||||
|
||||
// static unsigned counter = 0;
|
||||
// counter++;
|
||||
|
@ -1588,7 +1716,7 @@ namespace nlsat {
|
|||
conflict_clause = new_cls;
|
||||
goto start;
|
||||
}
|
||||
TRACE("nlsat_resolve_done", display_assignment(tout); display_bool_assignment(tout););
|
||||
TRACE("nlsat_resolve_done", display_assignment(tout););
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1801,6 +1929,15 @@ namespace nlsat {
|
|||
reorder(p.size(), p.c_ptr());
|
||||
}
|
||||
|
||||
bool can_reorder() const {
|
||||
for (unsigned i = 0; i < m_atoms.size(); ++i) {
|
||||
if (m_atoms[i]) {
|
||||
if (m_atoms[i]->is_root_atom()) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Reorder variables using the giving permutation.
|
||||
p maps internal variables to their new positions
|
||||
|
@ -1921,6 +2058,9 @@ namespace nlsat {
|
|||
void reinit_cache() {
|
||||
reinit_cache(m_clauses);
|
||||
reinit_cache(m_learned);
|
||||
for (unsigned i = 0; i < m_atoms.size(); ++i) {
|
||||
reinit_cache(m_atoms[i]);
|
||||
}
|
||||
}
|
||||
void reinit_cache(clause_vector const & cs) {
|
||||
unsigned sz = cs.size();
|
||||
|
@ -1934,10 +2074,13 @@ namespace nlsat {
|
|||
}
|
||||
void reinit_cache(literal l) {
|
||||
bool_var b = l.var();
|
||||
atom * a = m_atoms[b];
|
||||
if (a == 0)
|
||||
return;
|
||||
if (a->is_ineq_atom()) {
|
||||
reinit_cache(m_atoms[b]);
|
||||
}
|
||||
void reinit_cache(atom* a) {
|
||||
if (a == 0) {
|
||||
|
||||
}
|
||||
else if (a->is_ineq_atom()) {
|
||||
var max = 0;
|
||||
unsigned sz = to_ineq_atom(a)->size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
|
@ -2073,7 +2216,7 @@ namespace nlsat {
|
|||
//
|
||||
// -----------------------
|
||||
|
||||
void display_assignment(std::ostream & out, display_var_proc const & proc) const {
|
||||
void display_num_assignment(std::ostream & out, display_var_proc const & proc) const {
|
||||
for (var x = 0; x < num_vars(); x++) {
|
||||
if (m_assignment.is_assigned(x)) {
|
||||
proc(out, x);
|
||||
|
@ -2084,7 +2227,7 @@ namespace nlsat {
|
|||
}
|
||||
}
|
||||
|
||||
void display_bool_assignment(std::ostream & out, display_var_proc const & proc) const {
|
||||
void display_bool_assignment(std::ostream & out) const {
|
||||
unsigned sz = m_atoms.size();
|
||||
for (bool_var b = 0; b < sz; b++) {
|
||||
if (m_atoms[b] == 0 && m_bvalues[b] != l_undef) {
|
||||
|
@ -2112,12 +2255,13 @@ namespace nlsat {
|
|||
return !first;
|
||||
}
|
||||
|
||||
void display_assignment(std::ostream & out) const {
|
||||
display_assignment(out, m_display_var);
|
||||
void display_num_assignment(std::ostream & out) const {
|
||||
display_num_assignment(out, m_display_var);
|
||||
}
|
||||
|
||||
void display_bool_assignment(std::ostream & out) const {
|
||||
display_bool_assignment(out, m_display_var);
|
||||
void display_assignment(std::ostream& out) const {
|
||||
display_bool_assignment(out);
|
||||
display_num_assignment(out);
|
||||
}
|
||||
|
||||
void display(std::ostream & out, ineq_atom const & a, display_var_proc const & proc, bool use_star = false) const {
|
||||
|
@ -2511,6 +2655,7 @@ namespace nlsat {
|
|||
|
||||
void display(std::ostream & out) const {
|
||||
display(out, m_display_var);
|
||||
display_assignment(out);
|
||||
}
|
||||
|
||||
void display_vars(std::ostream & out) const {
|
||||
|
@ -2562,6 +2707,20 @@ namespace nlsat {
|
|||
return m_imp->check();
|
||||
}
|
||||
|
||||
lbool solver::check(literal_vector& assumptions) {
|
||||
return m_imp->check(assumptions);
|
||||
}
|
||||
|
||||
void solver::reset() {
|
||||
m_imp->reset();
|
||||
}
|
||||
|
||||
|
||||
void solver::updt_params(params_ref const & p) {
|
||||
m_imp->updt_params(p);
|
||||
}
|
||||
|
||||
|
||||
void solver::collect_param_descrs(param_descrs & d) {
|
||||
algebraic_numbers::manager::collect_param_descrs(d);
|
||||
nlsat_params::collect_param_descrs(d);
|
||||
|
@ -2583,6 +2742,10 @@ namespace nlsat {
|
|||
m_imp->m_display_var.m_proc = &proc;
|
||||
}
|
||||
|
||||
unsigned solver::num_vars() const {
|
||||
return m_imp->num_vars();
|
||||
}
|
||||
|
||||
bool solver::is_int(var x) const {
|
||||
return m_imp->is_int(x);
|
||||
}
|
||||
|
@ -2590,10 +2753,61 @@ namespace nlsat {
|
|||
bool_var solver::mk_bool_var() {
|
||||
return m_imp->mk_bool_var();
|
||||
}
|
||||
|
||||
literal solver::mk_true() {
|
||||
return literal(0, false);
|
||||
}
|
||||
|
||||
atom * solver::bool_var2atom(bool_var b) {
|
||||
return m_imp->m_atoms[b];
|
||||
}
|
||||
|
||||
void solver::vars(literal l, var_vector& vs) {
|
||||
m_imp->vars(l, vs);
|
||||
}
|
||||
|
||||
atom_vector const& solver::get_atoms() {
|
||||
return m_imp->m_atoms;
|
||||
}
|
||||
|
||||
atom_vector const& solver::get_var2eq() {
|
||||
return m_imp->m_var2eq;
|
||||
}
|
||||
|
||||
evaluator& solver::get_evaluator() {
|
||||
return m_imp->m_evaluator;
|
||||
}
|
||||
|
||||
explain& solver::get_explain() {
|
||||
return m_imp->m_explain;
|
||||
}
|
||||
|
||||
void solver::reorder(unsigned sz, var const* p) {
|
||||
m_imp->reorder(sz, p);
|
||||
}
|
||||
|
||||
void solver::restore_order() {
|
||||
m_imp->restore_order();
|
||||
}
|
||||
|
||||
void solver::set_rvalues(assignment const& as) {
|
||||
m_imp->m_assignment.copy(as);
|
||||
}
|
||||
|
||||
void solver::get_rvalues(assignment& as) {
|
||||
as.copy(m_imp->m_assignment);
|
||||
}
|
||||
|
||||
void solver::get_bvalues(svector<lbool>& vs) {
|
||||
vs.reset();
|
||||
vs.append(m_imp->m_bvalues);
|
||||
}
|
||||
|
||||
void solver::set_bvalues(svector<lbool> const& vs) {
|
||||
m_imp->m_bvalues.reset();
|
||||
m_imp->m_bvalues.append(vs);
|
||||
m_imp->m_bvalues.resize(m_imp->m_atoms.size(), l_undef);
|
||||
}
|
||||
|
||||
var solver::mk_var(bool is_int) {
|
||||
return m_imp->mk_var(is_int);
|
||||
|
@ -2631,10 +2845,21 @@ namespace nlsat {
|
|||
m_imp->display(out, l);
|
||||
}
|
||||
|
||||
void solver::display(std::ostream & out, unsigned n, literal const* ls) const {
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
display(out, ls[i]);
|
||||
out << "; ";
|
||||
}
|
||||
}
|
||||
|
||||
void solver::display(std::ostream & out, var x) const {
|
||||
m_imp->m_display_var(out, x);
|
||||
}
|
||||
|
||||
void solver::display(std::ostream & out, atom const& a) const {
|
||||
m_imp->display(out, a, m_imp->m_display_var);
|
||||
}
|
||||
|
||||
display_var_proc const & solver::display_proc() const {
|
||||
return m_imp->m_display_var;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,9 @@ Revision History:
|
|||
|
||||
namespace nlsat {
|
||||
|
||||
class evaluator;
|
||||
class explain;
|
||||
|
||||
class solver {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
|
@ -63,7 +66,9 @@ namespace nlsat {
|
|||
nonlinear arithmetic atom.
|
||||
*/
|
||||
bool_var mk_bool_var();
|
||||
|
||||
|
||||
literal mk_true();
|
||||
|
||||
/**
|
||||
\brief Create a real/integer variable.
|
||||
*/
|
||||
|
@ -121,6 +126,48 @@ namespace nlsat {
|
|||
*/
|
||||
atom * bool_var2atom(bool_var b);
|
||||
|
||||
/**
|
||||
\brief extract free variables from literal.
|
||||
*/
|
||||
void vars(literal l, var_vector& vs);
|
||||
|
||||
/**
|
||||
\brief provide access to atoms. Used by explain.
|
||||
*/
|
||||
atom_vector const& get_atoms();
|
||||
|
||||
/**
|
||||
\brief Access var -> asserted equality.
|
||||
*/
|
||||
|
||||
atom_vector const& get_var2eq();
|
||||
|
||||
/**
|
||||
\brief expose evaluator.
|
||||
*/
|
||||
|
||||
evaluator& get_evaluator();
|
||||
|
||||
/**
|
||||
\brief Access explanation module.
|
||||
*/
|
||||
explain& get_explain();
|
||||
|
||||
/**
|
||||
\brief Access assignments to variables.
|
||||
*/
|
||||
void get_rvalues(assignment& as);
|
||||
void set_rvalues(assignment const& as);
|
||||
|
||||
void get_bvalues(svector<lbool>& vs);
|
||||
void set_bvalues(svector<lbool> const& vs);
|
||||
|
||||
/**
|
||||
\brief reorder variables.
|
||||
*/
|
||||
void reorder(unsigned sz, var const* permutation);
|
||||
void restore_order();
|
||||
|
||||
/**
|
||||
\brief Return number of integer/real variables
|
||||
*/
|
||||
|
@ -135,6 +182,8 @@ namespace nlsat {
|
|||
// -----------------------
|
||||
lbool check();
|
||||
|
||||
lbool check(literal_vector& assumptions);
|
||||
|
||||
// -----------------------
|
||||
//
|
||||
// Model
|
||||
|
@ -154,6 +203,7 @@ namespace nlsat {
|
|||
void updt_params(params_ref const & p);
|
||||
static void collect_param_descrs(param_descrs & d);
|
||||
|
||||
void reset();
|
||||
void collect_statistics(statistics & st);
|
||||
void reset_statistics();
|
||||
void display_status(std::ostream & out) const;
|
||||
|
@ -174,6 +224,10 @@ namespace nlsat {
|
|||
*/
|
||||
void display(std::ostream & out, literal l) const;
|
||||
|
||||
void display(std::ostream & out, unsigned n, literal const* ls) const;
|
||||
|
||||
void display(std::ostream & out, atom const& a) const;
|
||||
|
||||
/**
|
||||
\brief Display variable
|
||||
*/
|
||||
|
|
|
@ -111,6 +111,21 @@ namespace nlsat {
|
|||
struct eq_proc { bool operator()(ineq_atom const * a1, ineq_atom const * a2) const; };
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, atom::kind k) {
|
||||
switch (k) {
|
||||
case atom::EQ: return out << "=";
|
||||
case atom::LT: return out << "<";
|
||||
case atom::GT: return out << ">";
|
||||
case atom::ROOT_EQ: return out << "= root";
|
||||
case atom::ROOT_LT: return out << "< root";
|
||||
case atom::ROOT_LE: return out << "<= root";
|
||||
case atom::ROOT_GT: return out << "> root";
|
||||
case atom::ROOT_GE: return out << ">= root";
|
||||
default: return out << (int)k;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
class root_atom : public atom {
|
||||
friend class solver;
|
||||
var m_x;
|
||||
|
|
|
@ -29,7 +29,9 @@ Notes:
|
|||
#include"expr2var.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"tactic.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"ast_pp.h"
|
||||
#include"polynomial.h"
|
||||
#include"algebraic_numbers.h"
|
||||
|
||||
struct goal2nlsat::imp {
|
||||
struct nlsat_expr2polynomial : public expr2polynomial {
|
||||
|
@ -124,7 +126,7 @@ struct goal2nlsat::imp {
|
|||
m_qm.neg(d2);
|
||||
polynomial_ref p(m_pm);
|
||||
p = m_pm.addmul(d1, m_pm.mk_unit(), p1, d2, m_pm.mk_unit(), p2);
|
||||
TRACE("goal2nlsat_bug", tout << "p: " << p << "\nk: " << k << "\n";);
|
||||
TRACE("goal2nlsat_bug", tout << mk_pp(f, m) << " p: " << p << "\nk: " << k << "\n";);
|
||||
if (is_const(p)) {
|
||||
int sign;
|
||||
if (is_zero(p))
|
||||
|
@ -192,7 +194,7 @@ struct goal2nlsat::imp {
|
|||
switch (to_app(f)->get_decl_kind()) {
|
||||
case OP_TRUE:
|
||||
case OP_FALSE:
|
||||
TRACE("goal2nlsat", tout << "f: " << mk_ismt2_pp(f, m) << "\n";);
|
||||
TRACE("goal2nlsat", tout << "f: " << mk_pp(f, m) << "\n";);
|
||||
throw tactic_exception("apply simplify before applying nlsat");
|
||||
case OP_AND:
|
||||
case OP_OR:
|
||||
|
@ -257,6 +259,7 @@ struct goal2nlsat::imp {
|
|||
process(g.form(i), g.dep(i));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct goal2nlsat::scoped_set_imp {
|
||||
|
@ -289,4 +292,154 @@ void goal2nlsat::operator()(goal const & g, params_ref const & p, nlsat::solver
|
|||
scoped_set_imp setter(*this, local_imp);
|
||||
local_imp(g);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct nlsat2goal::imp {
|
||||
ast_manager& m;
|
||||
arith_util a;
|
||||
u_map<expr*> const* m_x2t;
|
||||
public:
|
||||
imp(ast_manager& m):m(m),a(m) {}
|
||||
|
||||
expr_ref operator()(nlsat::solver& s, u_map<expr*> const& b2a, u_map<expr*> const& x2t, nlsat::literal l) {
|
||||
m_x2t = &x2t;
|
||||
expr_ref result(m);
|
||||
expr* t;
|
||||
if (b2a.find(l.var(), t)) {
|
||||
result = t;
|
||||
}
|
||||
else {
|
||||
nlsat::atom const* at = s.bool_var2atom(l.var());
|
||||
SASSERT(at != 0);
|
||||
if (at->is_ineq_atom()) {
|
||||
nlsat::ineq_atom const* ia = to_ineq_atom(at);
|
||||
unsigned sz = ia->size();
|
||||
expr_ref_vector ps(m);
|
||||
bool is_int = true;
|
||||
for (unsigned i = 0; is_int && i < sz; ++i) {
|
||||
is_int = poly_is_int(ia->p(i));
|
||||
}
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
polynomial::polynomial* p = ia->p(i);
|
||||
expr_ref t = poly2expr(s, p, is_int);
|
||||
if (ia->is_even(i)) {
|
||||
t = a.mk_power(t, a.mk_numeral(rational(2), a.is_int(t)));
|
||||
}
|
||||
ps.push_back(t);
|
||||
}
|
||||
result = a.mk_mul_simplify(ps);
|
||||
expr_ref zero(m);
|
||||
zero = a.mk_numeral(rational(0), a.is_int(result));
|
||||
switch (ia->get_kind()) {
|
||||
case nlsat::atom::EQ:
|
||||
result = m.mk_eq(result, zero);
|
||||
break;
|
||||
case nlsat::atom::LT:
|
||||
if (l.sign()) {
|
||||
l.neg();
|
||||
result = a.mk_ge(result, zero);
|
||||
}
|
||||
else {
|
||||
result = a.mk_lt(result, zero);
|
||||
}
|
||||
break;
|
||||
case nlsat::atom::GT:
|
||||
if (l.sign()) {
|
||||
l.neg();
|
||||
result = a.mk_le(result, zero);
|
||||
}
|
||||
else {
|
||||
result = a.mk_gt(result, zero);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
else {
|
||||
//nlsat::root_atom const* ra = nlsat::to_root_atom(at);
|
||||
//ra->i();
|
||||
//expr_ref p = poly2expr(s, ra->p());
|
||||
//expr* x = m_x2t->find(ra->x());
|
||||
std::ostringstream strm;
|
||||
s.display(strm, l.sign()?~l:l);
|
||||
result = m.mk_const(symbol(strm.str().c_str()), m.mk_bool_sort());
|
||||
}
|
||||
}
|
||||
|
||||
if (l.sign()) {
|
||||
result = m.mk_not(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref poly2expr(nlsat::solver& s, polynomial::polynomial* p, bool is_int) {
|
||||
expr_ref result(m);
|
||||
unsigned sz = polynomial::manager::size(p);
|
||||
expr_ref_vector args(m);
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
args.push_back(mono2expr(s,
|
||||
polynomial::manager::coeff(p, i),
|
||||
polynomial::manager::get_monomial(p, i), is_int));
|
||||
}
|
||||
result = a.mk_add_simplify(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
expr_ref mono2expr(nlsat::solver& s, polynomial::numeral const& c, polynomial::monomial* mon, bool is_int) {
|
||||
expr_ref result(m);
|
||||
expr_ref_vector args(m);
|
||||
unsigned sz = polynomial::manager::size(mon);
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
unsigned d = polynomial::manager::degree(mon, i);
|
||||
expr* t = m_x2t->find(polynomial::manager::get_var(mon, i));
|
||||
SASSERT(d >= 1);
|
||||
if (d == 1) {
|
||||
args.push_back(t);
|
||||
}
|
||||
else {
|
||||
args.push_back(a.mk_power(t, a.mk_numeral(rational(d), a.is_int(t))));
|
||||
}
|
||||
}
|
||||
if (!s.pm().m().is_one(c)) {
|
||||
args.push_back(a.mk_numeral(c, is_int));
|
||||
}
|
||||
result = a.mk_mul_simplify(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool poly_is_int(polynomial::polynomial* p) {
|
||||
bool is_int = true;
|
||||
unsigned sz = polynomial::manager::size(p);
|
||||
for (unsigned i = 0; is_int && i < sz; ++i) {
|
||||
is_int = mono_is_int(polynomial::manager::get_monomial(p, i));
|
||||
}
|
||||
return is_int;
|
||||
}
|
||||
|
||||
bool mono_is_int(polynomial::monomial* mon) {
|
||||
bool is_int = true;
|
||||
unsigned sz = polynomial::manager::size(mon);
|
||||
for (unsigned i = 0; is_int && i < sz; ++i) {
|
||||
is_int = a.is_int(m_x2t->find(polynomial::manager::get_var(mon, i)));
|
||||
}
|
||||
return is_int;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
nlsat2goal::nlsat2goal(ast_manager& m) {
|
||||
m_imp = alloc(imp, m);
|
||||
}
|
||||
|
||||
|
||||
nlsat2goal::~nlsat2goal() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
expr_ref nlsat2goal::operator()(nlsat::solver& s, u_map<expr*> const& b2a, u_map<expr*> const& x2t, nlsat::literal l) {
|
||||
return (*m_imp)(s, b2a, x2t, l);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -57,17 +57,16 @@ class nlsat2goal {
|
|||
struct imp;
|
||||
imp * m_imp;
|
||||
public:
|
||||
nlsat2goal();
|
||||
nlsat2goal(ast_manager& m);
|
||||
~nlsat2goal();
|
||||
|
||||
static void collect_param_descrs(param_descrs & r);
|
||||
|
||||
/**
|
||||
\brief Translate the state of the nlsat engine back into a goal.
|
||||
*/
|
||||
void operator()(nlsat::solver const & s, expr2var const & a2b, expr2var const & t2x,
|
||||
params_ref const & p, goal & g, model_converter_ref & mc);
|
||||
|
||||
\brief Translate a literal into a formula.
|
||||
*/
|
||||
expr_ref operator()(nlsat::solver& s, u_map<expr*> const& b2a, u_map<expr*> const& x2t, nlsat::literal l);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue