mirror of
https://github.com/Z3Prover/z3
synced 2025-04-05 17:14:07 +00:00
added facility to persist model transformations
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
fd49a0c89c
|
@ -17,6 +17,15 @@ env:
|
|||
###############################################################################
|
||||
# Ubuntu 16.04 LTS
|
||||
###############################################################################
|
||||
# 64-bit UBSan Debug build
|
||||
- LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug UBSAN_BUILD=1 RUN_UNIT_TESTS=SKIP
|
||||
# 64-bit ASan Debug build
|
||||
- LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=Debug ASAN_BUILD=1 RUN_UNIT_TESTS=SKIP ASAN_DSO=/usr/lib/clang/3.9/lib/linux/libclang_rt.asan-x86_64.so
|
||||
# Build for running unit tests under ASan/UBSan
|
||||
# FIXME: We should really be doing a debug build but the unit tests run too
|
||||
# slowly when we do that.
|
||||
- LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/clang-3.9 CXX_COMPILER=/usr/bin/clang++-3.9 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo ASAN_BUILD=1 RUN_UNIT_TESTS=BUILD_AND_RUN ASAN_DSO=/usr/lib/clang/3.9/lib/linux/libclang_rt.asan-x86_64.so UBSAN_BUILD=1 RUN_API_EXAMPLES=0 RUN_SYSTEM_TESTS=0 DOTNET_BINDINGS=0 JAVA_BINDINGS=0 PYTHON_BINDINGS=0
|
||||
|
||||
# 64-bit GCC 5.4 RelWithDebInfo
|
||||
- LINUX_BASE=ubuntu_16.04 C_COMPILER=/usr/bin/gcc-5 CXX_COMPILER=/usr/bin/g++-5 TARGET_ARCH=x86_64 Z3_BUILD_TYPE=RelWithDebInfo
|
||||
# 64-bit Clang 3.9 RelWithDebInfo
|
||||
|
|
|
@ -270,6 +270,7 @@ The following useful options can be passed to CMake whilst configuring.
|
|||
* ``API_LOG_SYNC`` - BOOL. If set to ``TRUE`` will enable experimental API log sync feature.
|
||||
* ``WARNINGS_AS_ERRORS`` - STRING. If set to ``TRUE`` compiler warnings will be treated as errors. If set to ``False`` compiler warnings will not be treated as errors.
|
||||
If set to ``SERIOUS_ONLY`` a subset of compiler warnings will be treated as errors.
|
||||
* ``Z3_C_EXAMPLES_FORCE_CXX_LINKER`` - BOOL. If set to ``TRUE`` the C API examples will request that the C++ linker is used rather than the C linker.
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ utility is used to install ``Microsoft.Z3.dll`` into the
|
|||
[pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/) file
|
||||
(``Microsoft.Z3.Sharp.pc``) is also installed which allows the
|
||||
[MonoDevelop](http://www.monodevelop.com/) IDE to find the bindings. Running
|
||||
``make uninstall`` will remove the dll from the GAC and the pkg-config file.
|
||||
``make uninstall`` will remove the dll from the GAC and the ``pkg-config`` file.
|
||||
|
||||
See [``examples/dotnet``](examples/dotnet) for examples.
|
||||
|
||||
|
@ -170,8 +170,8 @@ If you do need to install to a non standard prefix a better approach is to use
|
|||
a [Python virtual environment](https://virtualenv.readthedocs.org/en/latest/)
|
||||
and install Z3 there. Python packages also work for Python3.
|
||||
Under Windows, recall to build inside the Visual C++ native command build environment.
|
||||
Note that the buit/python/z3 directory should be accessible from where python is used with Z3
|
||||
and it depends on libz3.dll to be in the path.
|
||||
Note that the ``build/python/z3`` directory should be accessible from where python is used with Z3
|
||||
and it depends on ``libz3.dll`` to be in the path.
|
||||
|
||||
```bash
|
||||
virtualenv venv
|
||||
|
|
|
@ -30,6 +30,7 @@ RUN apt-get update && \
|
|||
libgomp1 \
|
||||
libomp5 \
|
||||
libomp-dev \
|
||||
llvm-3.9 \
|
||||
make \
|
||||
mono-devel \
|
||||
ninja-build \
|
||||
|
@ -47,4 +48,4 @@ RUN useradd -m user && \
|
|||
echo 'user ALL=(root) NOPASSWD: ALL' >> /etc/sudoers
|
||||
USER user
|
||||
WORKDIR /home/user
|
||||
|
||||
ENV ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.9/bin/llvm-symbolizer
|
||||
|
|
|
@ -16,6 +16,7 @@ RUN apt-get update && \
|
|||
libgmp-dev \
|
||||
libgomp1 \
|
||||
lib32gomp1 \
|
||||
llvm-3.9 \
|
||||
make \
|
||||
mono-devel \
|
||||
ninja-build \
|
||||
|
@ -32,4 +33,4 @@ RUN useradd -m user && \
|
|||
echo 'user ALL=(root) NOPASSWD: ALL' >> /etc/sudoers
|
||||
USER user
|
||||
WORKDIR /home/user
|
||||
|
||||
ENV ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.9/bin/llvm-symbolizer
|
||||
|
|
|
@ -18,6 +18,7 @@ RUN apt-get update && \
|
|||
libgomp1 \
|
||||
libomp5 \
|
||||
libomp-dev \
|
||||
llvm-3.9 \
|
||||
make \
|
||||
mono-devel \
|
||||
ninja-build \
|
||||
|
@ -35,4 +36,4 @@ RUN useradd -m user && \
|
|||
echo 'user ALL=(root) NOPASSWD: ALL' >> /etc/sudoers
|
||||
USER user
|
||||
WORKDIR /home/user
|
||||
|
||||
ENV ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.9/bin/llvm-symbolizer
|
||||
|
|
|
@ -5,6 +5,7 @@ FROM ${DOCKER_IMAGE_BASE}
|
|||
# Build arguments. This can be changed when invoking
|
||||
# `docker build`.
|
||||
ARG ASAN_BUILD
|
||||
ARG ASAN_DSO
|
||||
ARG BUILD_DOCS
|
||||
ARG CC
|
||||
ARG CXX
|
||||
|
@ -13,8 +14,10 @@ ARG JAVA_BINDINGS
|
|||
ARG NO_SUPPRESS_OUTPUT
|
||||
ARG PYTHON_BINDINGS
|
||||
ARG PYTHON_EXECUTABLE=/usr/bin/python2.7
|
||||
ARG RUN_API_EXAMPLES
|
||||
ARG RUN_SYSTEM_TESTS
|
||||
ARG RUN_UNIT_TESTS
|
||||
ARG SANITIZER_PRINT_SUPPRESSIONS
|
||||
ARG TARGET_ARCH
|
||||
ARG TEST_INSTALL
|
||||
ARG UBSAN_BUILD
|
||||
|
@ -32,6 +35,7 @@ ARG Z3_VERBOSE_BUILD_OUTPUT
|
|||
|
||||
ENV \
|
||||
ASAN_BUILD=${ASAN_BUILD} \
|
||||
ASAN_DSO=${ASAN_DSO} \
|
||||
BUILD_DOCS=${BUILD_DOCS} \
|
||||
CC=${CC} \
|
||||
CXX=${CXX} \
|
||||
|
@ -40,6 +44,8 @@ ENV \
|
|||
NO_SUPPRESS_OUTPUT=${NO_SUPPRESS_OUTPUT} \
|
||||
PYTHON_BINDINGS=${PYTHON_BINDINGS} \
|
||||
PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} \
|
||||
SANITIZER_PRINT_SUPPRESSIONS=${SANITIZER_PRINT_SUPPRESSIONS} \
|
||||
RUN_API_EXAMPLES=${RUN_API_EXAMPLES} \
|
||||
RUN_SYSTEM_TESTS=${RUN_SYSTEM_TESTS} \
|
||||
RUN_UNIT_TESTS=${RUN_UNIT_TESTS} \
|
||||
TARGET_ARCH=${TARGET_ARCH} \
|
||||
|
@ -50,6 +56,7 @@ ENV \
|
|||
USE_OPENMP=${USE_OPENMP} \
|
||||
Z3_SRC_DIR=${Z3_SRC_DIR} \
|
||||
Z3_BUILD_DIR=/home/user/z3_build \
|
||||
Z3_BUILD_TYPE=${Z3_BUILD_TYPE} \
|
||||
Z3_CMAKE_GENERATOR=${Z3_CMAKE_GENERATOR} \
|
||||
Z3_VERBOSE_BUILD_OUTPUT=${Z3_VERBOSE_BUILD_OUTPUT} \
|
||||
Z3_STATIC_BUILD=${Z3_STATIC_BUILD} \
|
||||
|
@ -62,7 +69,8 @@ ENV \
|
|||
|
||||
# Build Z3
|
||||
RUN mkdir -p "${Z3_SRC_DIR}" && \
|
||||
mkdir -p "${Z3_SRC_DIR}/contrib/ci/scripts"
|
||||
mkdir -p "${Z3_SRC_DIR}/contrib/ci/scripts" && \
|
||||
mkdir -p "${Z3_SRC_DIR}/contrib/suppressions/sanitizers"
|
||||
# Deliberately leave out `contrib`
|
||||
ADD /cmake ${Z3_SRC_DIR}/cmake/
|
||||
ADD /doc ${Z3_SRC_DIR}/doc/
|
||||
|
@ -89,7 +97,13 @@ RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_docs.sh
|
|||
# Test examples
|
||||
ADD \
|
||||
/contrib/ci/scripts/test_z3_examples_cmake.sh \
|
||||
/contrib/ci/scripts/sanitizer_env.sh \
|
||||
${Z3_SRC_DIR}/contrib/ci/scripts/
|
||||
ADD \
|
||||
/contrib/suppressions/sanitizers/asan.txt \
|
||||
/contrib/suppressions/sanitizers/lsan.txt \
|
||||
/contrib/suppressions/sanitizers/ubsan.txt \
|
||||
${Z3_SRC_DIR}/contrib/suppressions/sanitizers/
|
||||
RUN ${Z3_SRC_DIR}/contrib/ci/scripts/test_z3_examples_cmake.sh
|
||||
|
||||
# Run unit tests
|
||||
|
|
|
@ -30,8 +30,10 @@ the future.
|
|||
* `JAVA_BINDINGS` - Build and test Java API bindings (`0` or `1`)
|
||||
* `NO_SUPPRESS_OUTPUT` - Don't suppress output of some commands (`0` or `1`)
|
||||
* `PYTHON_BINDINGS` - Build and test Python API bindings (`0` or `1`)
|
||||
* `RUN_API_EXAMPLES` - Build and run API examples (`0` or `1`)
|
||||
* `RUN_SYSTEM_TESTS` - Run system tests (`0` or `1`)
|
||||
* `RUN_UNIT_TESTS` - Run unit tests (`BUILD_ONLY` or `BUILD_AND_RUN` or `SKIP`)
|
||||
* `SANITIZER_PRINT_SUPPRESSIONS` - Show ASan/UBSan suppressions (`0` or `1`)
|
||||
* `TARGET_ARCH` - Target architecture (`x86_64` or `i686`)
|
||||
* `TEST_INSTALL` - Test running `install` target (`0` or `1`)
|
||||
* `UBSAN_BUILD` - Do [UndefinedBehaviourSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) build (`0` or `1`)
|
||||
|
|
|
@ -22,6 +22,7 @@ set -o pipefail
|
|||
: ${USE_LTO?"USE_LTO must be specified"}
|
||||
: ${Z3_INSTALL_PREFIX?"Z3_INSTALL_PREFIX must be specified"}
|
||||
: ${Z3_WARNINGS_AS_ERRORS?"Z3_WARNINGS_AS_ERRORS must be specified"}
|
||||
: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"}
|
||||
|
||||
ADDITIONAL_Z3_OPTS=()
|
||||
|
||||
|
@ -105,6 +106,16 @@ fi
|
|||
# Set compiler flags
|
||||
source ${SCRIPT_DIR}/set_compiler_flags.sh
|
||||
|
||||
if [ "X${UBSAN_BUILD}" = "X1" ]; then
|
||||
# HACK: When building with UBSan the C++ linker
|
||||
# must be used to avoid the following linker errors.
|
||||
# undefined reference to `__ubsan_vptr_type_cache'
|
||||
# undefined reference to `__ubsan_handle_dynamic_type_cache_miss'
|
||||
ADDITIONAL_Z3_OPTS+=( \
|
||||
'-DZ3_C_EXAMPLES_FORCE_CXX_LINKER=ON' \
|
||||
)
|
||||
fi
|
||||
|
||||
# Sanity check
|
||||
if [ ! -e "${Z3_SRC_DIR}/CMakeLists.txt" ]; then
|
||||
echo "Z3_SRC_DIR is invalid"
|
||||
|
|
|
@ -9,8 +9,13 @@ export DOTNET_BINDINGS="${DOTNET_BINDINGS:-1}"
|
|||
export JAVA_BINDINGS="${JAVA_BINDINGS:-1}"
|
||||
export NO_SUPPRESS_OUTPUT="${NO_SUPPRESS_OUTPUT:-0}"
|
||||
export PYTHON_BINDINGS="${PYTHON_BINDINGS:-1}"
|
||||
export RUN_API_EXAMPLES="${RUN_API_EXAMPLES:-1}"
|
||||
export RUN_SYSTEM_TESTS="${RUN_SYSTEM_TESTS:-1}"
|
||||
export RUN_UNIT_TESTS="${RUN_UNIT_TESTS:-BUILD_AND_RUN}"
|
||||
# Don't print suppressions by default because that breaks the Z3
|
||||
# regression tests because they don't expect them to appear in Z3's
|
||||
# output.
|
||||
export SANITIZER_PRINT_SUPPRESSIONS="${SANITIZER_PRINT_SUPPRESSIONS:-0}"
|
||||
export TARGET_ARCH="${TARGET_ARCH:-x86_64}"
|
||||
export TEST_INSTALL="${TEST_INSTALL:-1}"
|
||||
export UBSAN_BUILD="${UBSAN_BUILD:-0}"
|
||||
|
@ -49,6 +54,7 @@ unset PLATFORM
|
|||
# NOTE: The following variables are not set here because
|
||||
# they are specific to the CI implementation
|
||||
# PYTHON_EXECUTABLE
|
||||
# ASAN_DSO
|
||||
# Z3_SRC_DIR
|
||||
# Z3_BUILD_DIR
|
||||
# Z3_SYSTEM_TEST_DIR
|
||||
|
|
|
@ -34,8 +34,8 @@ function run_quiet() {
|
|||
fi
|
||||
# Clean up
|
||||
rm "${STDOUT}" "${STDERR}"
|
||||
[ $( echo "${OLD_SETTINGS}" | grep -c 'e') -ne 0 ] && set -e
|
||||
[ $( echo "${OLD_SETTINGS}" | grep -c 'x') -ne 0 ] && set -x
|
||||
[ "$( echo "${OLD_SETTINGS}" | grep -c 'e')" != "0" ] && set -e
|
||||
[ "$( echo "${OLD_SETTINGS}" | grep -c 'x')" != "0" ] && set -x
|
||||
return ${EXIT_STATUS}
|
||||
fi
|
||||
}
|
||||
|
|
82
contrib/ci/scripts/sanitizer_env.sh
Normal file
82
contrib/ci/scripts/sanitizer_env.sh
Normal file
|
@ -0,0 +1,82 @@
|
|||
# This script is intended to be included by other
|
||||
# scripts and should not be executed directly
|
||||
|
||||
: ${Z3_SRC_DIR?"Z3_SRC_DIR must be specified"}
|
||||
: ${ASAN_BUILD?"ASAN_BUILD must be specified"}
|
||||
: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"}
|
||||
|
||||
if [ "X${ASAN_BUILD}" = "X1" ]; then
|
||||
# Use suppression files
|
||||
export LSAN_OPTIONS="suppressions=${Z3_SRC_DIR}/contrib/suppressions/sanitizers/lsan.txt"
|
||||
# NOTE: If you get bad stacktraces try using `fast_unwind_on_malloc=0`
|
||||
# NOTE: `malloc_context_size` controls size of recorded stacktrace for allocations.
|
||||
# If the reported stacktraces appear incomplete try increasing the value.
|
||||
export ASAN_OPTIONS="malloc_context_size=100,suppressions=${Z3_SRC_DIR}/contrib/suppressions/sanitizers/asan.txt"
|
||||
|
||||
: ${SANITIZER_PRINT_SUPPRESSIONS?"SANITIZER_PRINT_SUPPRESSIONS must be specified"}
|
||||
if [ "X${SANITIZER_PRINT_SUPPRESSIONS}" = "X1" ]; then
|
||||
export LSAN_OPTIONS="${LSAN_OPTIONS},print_suppressions=1"
|
||||
export ASAN_OPTIONS="${ASAN_OPTIONS},print_suppressions=1"
|
||||
else
|
||||
export LSAN_OPTIONS="${LSAN_OPTIONS},print_suppressions=0"
|
||||
export ASAN_OPTIONS="${ASAN_OPTIONS},print_suppressions=0"
|
||||
fi
|
||||
|
||||
: ${ASAN_SYMBOLIZER_PATH?"ASAN_SYMBOLIZER_PATH must be specified"}
|
||||
|
||||
# Run command without checking for leaks
|
||||
function run_no_lsan() {
|
||||
ASAN_OPTIONS="${ASAN_OPTIONS},detect_leaks=0" "${@}"
|
||||
}
|
||||
|
||||
# Check path to ASan DSO
|
||||
: ${ASAN_DSO?"ASAN_DSO must be specified"}
|
||||
if [ ! -e "${ASAN_DSO}" ]; then
|
||||
echo "ASAN_DSO (${ASAN_DSO}) does not exist"
|
||||
exit 1
|
||||
fi
|
||||
# FIXME: We'll need to refactor this when we can do UBSan builds
|
||||
# against a UBSan DSO.
|
||||
function run_non_native_binding() {
|
||||
# We need to preload the ASan DSO that libz3
|
||||
# will have undefined references to.
|
||||
# Don't run leak checking because we get lots reported leaks
|
||||
# in the language runtime (e.g. python).
|
||||
PLATFORM="$(uname -s)"
|
||||
case "${PLATFORM}" in
|
||||
Linux*)
|
||||
LD_PRELOAD="${ASAN_DSO}" run_no_lsan "${@}"
|
||||
;;
|
||||
Darwin*)
|
||||
DYLD_INSERT_LIBRARIES="${ASAN_DSO}" run_no_lsan "${@}"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown platform \"${PLATFORM}\""
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
unset PLATFORM
|
||||
}
|
||||
else
|
||||
# In non-ASan build just run directly
|
||||
function run_no_lsan() {
|
||||
"${@}"
|
||||
}
|
||||
function run_non_native_binding() {
|
||||
"${@}"
|
||||
}
|
||||
fi
|
||||
|
||||
if [ "X${UBSAN_BUILD}" = "X1" ]; then
|
||||
# `halt_on_error=1,abort_on_error=1` means that on the first UBSan error
|
||||
# the program will terminate by calling `abort(). Without this UBSan will
|
||||
# allow execution to continue. We also use a suppression file.
|
||||
export UBSAN_OPTIONS="halt_on_error=1,abort_on_error=1,suppressions=${Z3_SRC_DIR}/contrib/suppressions/sanitizers/ubsan.txt"
|
||||
|
||||
: ${SANITIZER_PRINT_SUPPRESSIONS?"SANITIZER_PRINT_SUPPRESSIONS must be specified"}
|
||||
if [ "X${SANITIZER_PRINT_SUPPRESSIONS}" = "X1" ]; then
|
||||
export UBSAN_OPTIONS="${UBSAN_OPTIONS},print_suppressions=1"
|
||||
else
|
||||
export UBSAN_OPTIONS="${UBSAN_OPTIONS},print_suppressions=0"
|
||||
fi
|
||||
fi
|
|
@ -14,6 +14,13 @@ set -o pipefail
|
|||
: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"}
|
||||
: ${DOTNET_BINDINGS?"DOTNET_BINDINGS must be specified"}
|
||||
: ${JAVA_BINDINGS?"JAVA_BINDINGS must be specified"}
|
||||
: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"}
|
||||
: ${RUN_API_EXAMPLES?"RUN_API_EXAMPLES must be specified"}
|
||||
|
||||
if [ "X${RUN_API_EXAMPLES}" = "X0" ]; then
|
||||
echo "Skipping run of API examples"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Set compiler flags
|
||||
source ${SCRIPT_DIR}/set_compiler_flags.sh
|
||||
|
@ -21,6 +28,9 @@ source ${SCRIPT_DIR}/set_compiler_flags.sh
|
|||
# Set CMake generator args
|
||||
source ${SCRIPT_DIR}/set_generator_args.sh
|
||||
|
||||
# Sanitizer environment variables
|
||||
source ${SCRIPT_DIR}/sanitizer_env.sh
|
||||
|
||||
cd "${Z3_BUILD_DIR}"
|
||||
|
||||
# Build and run C example
|
||||
|
@ -38,26 +48,43 @@ run_quiet examples/tptp_build_dir/z3_tptp5 -help
|
|||
|
||||
# Build an run c_maxsat_example
|
||||
cmake --build $(pwd) --target c_maxsat_example "${GENERATOR_ARGS[@]}"
|
||||
run_quiet \
|
||||
# FIXME: It is known that the maxsat example leaks memory and the
|
||||
# the Z3 developers have stated this is "wontfix".
|
||||
# See https://github.com/Z3Prover/z3/issues/1299
|
||||
run_no_lsan \
|
||||
run_quiet \
|
||||
examples/c_maxsat_example_build_dir/c_maxsat_example \
|
||||
${Z3_SRC_DIR}/examples/maxsat/ex.smt
|
||||
|
||||
if [ "X${UBSAN_BUILD}" = "X1" ]; then
|
||||
# FIXME: We really need libz3 to link against a shared UBSan runtime.
|
||||
# Right now we link against the static runtime which breaks all the
|
||||
# non-native language bindings.
|
||||
echo "FIXME: Can't run other examples when building with UBSan"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
if [ "X${PYTHON_BINDINGS}" = "X1" ]; then
|
||||
# Run python examples
|
||||
# `all_interval_series.py` produces a lot of output so just throw
|
||||
# away output.
|
||||
# TODO: This example is slow should we remove it from testing?
|
||||
run_quiet ${PYTHON_EXECUTABLE} python/all_interval_series.py
|
||||
run_quiet ${PYTHON_EXECUTABLE} python/complex.py
|
||||
run_quiet ${PYTHON_EXECUTABLE} python/example.py
|
||||
if [ "X${ASAN_BUILD}" = "X1" -a "X${Z3_BUILD_TYPE}" = "XDebug" ]; then
|
||||
# Too slow when doing ASan Debug build
|
||||
echo "Skipping all_interval_series.py under ASan Debug build"
|
||||
else
|
||||
run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/all_interval_series.py
|
||||
fi
|
||||
run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/complex.py
|
||||
run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/example.py
|
||||
# FIXME: `hamiltonian.py` example is disabled because its too slow.
|
||||
#${PYTHON_EXECUTABLE} python/hamiltonian.py
|
||||
run_quiet ${PYTHON_EXECUTABLE} python/marco.py
|
||||
run_quiet ${PYTHON_EXECUTABLE} python/mss.py
|
||||
run_quiet ${PYTHON_EXECUTABLE} python/socrates.py
|
||||
run_quiet ${PYTHON_EXECUTABLE} python/visitor.py
|
||||
run_quiet ${PYTHON_EXECUTABLE} python/z3test.py
|
||||
run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/marco.py
|
||||
run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/mss.py
|
||||
run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/socrates.py
|
||||
run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/visitor.py
|
||||
run_quiet run_non_native_binding ${PYTHON_EXECUTABLE} python/z3test.py
|
||||
fi
|
||||
|
||||
if [ "X${DOTNET_BINDINGS}" = "X1" ]; then
|
||||
|
@ -65,7 +92,7 @@ if [ "X${DOTNET_BINDINGS}" = "X1" ]; then
|
|||
# FIXME: Move compliation step into CMake target
|
||||
mcs ${Z3_SRC_DIR}/examples/dotnet/Program.cs /target:exe /out:dotnet_test.exe /reference:Microsoft.Z3.dll /r:System.Numerics.dll
|
||||
# Run .NET example
|
||||
run_quiet mono ./dotnet_test.exe
|
||||
run_quiet run_non_native_binding mono ./dotnet_test.exe
|
||||
fi
|
||||
|
||||
if [ "X${JAVA_BINDINGS}" = "X1" ]; then
|
||||
|
@ -82,6 +109,14 @@ if [ "X${JAVA_BINDINGS}" = "X1" ]; then
|
|||
# Assume Linux for now
|
||||
export LD_LIBRARY_PATH=$(pwd):${LD_LIBRARY_PATH}
|
||||
fi
|
||||
run_quiet java -cp .:examples/java:com.microsoft.z3.jar JavaExample
|
||||
if [ "X${ASAN_BUILD}" = "X1" ]; then
|
||||
# The JVM seems to crash (SEGV) if we pre-load ASan
|
||||
# so don't run it for now.
|
||||
echo "Skipping JavaExample under ASan build"
|
||||
else
|
||||
run_quiet \
|
||||
run_non_native_binding \
|
||||
java -cp .:examples/java:com.microsoft.z3.jar JavaExample
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
@ -10,12 +10,17 @@ set -o pipefail
|
|||
: ${PYTHON_BINDINGS?"PYTHON_BINDINGS must be specified"}
|
||||
: ${PYTHON_EXECUTABLE?"PYTHON_EXECUTABLE must be specified"}
|
||||
: ${Z3_SYSTEM_TEST_DIR?"Z3_SYSTEM_TEST_DIR must be specified"}
|
||||
: ${UBSAN_BUILD?"UBSAN_BUILD must be specified"}
|
||||
|
||||
if [ "X${RUN_SYSTEM_TESTS}" != "X1" ]; then
|
||||
echo "Skipping system tests"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Sanitizer environment variables
|
||||
SCRIPT_DIR="$( cd ${BASH_SOURCE[0]%/*} ; echo $PWD )"
|
||||
source ${SCRIPT_DIR}/sanitizer_env.sh
|
||||
|
||||
Z3_EXE="${Z3_BUILD_DIR}/z3"
|
||||
Z3_LIB_DIR="${Z3_BUILD_DIR}"
|
||||
|
||||
|
@ -23,7 +28,7 @@ Z3_LIB_DIR="${Z3_BUILD_DIR}"
|
|||
Z3_SYSTEM_TEST_GIT_URL="${Z3_GIT_URL:-https://github.com/Z3Prover/z3test.git}"
|
||||
|
||||
# Clone repo to destination
|
||||
mkdir -p "${Z3_SYSTEM_TEST_GIT_URL}"
|
||||
mkdir -p "${Z3_SYSTEM_TEST_DIR}"
|
||||
git clone "${Z3_SYSTEM_TEST_GIT_URL}" "${Z3_SYSTEM_TEST_DIR}"
|
||||
cd "${Z3_SYSTEM_TEST_DIR}"
|
||||
|
||||
|
@ -48,7 +53,18 @@ fi
|
|||
|
||||
if [ "X${PYTHON_BINDINGS}" = "X1" ]; then
|
||||
# Run python binding tests
|
||||
${PYTHON_EXECUTABLE} scripts/test_pyscripts.py "${Z3_LIB_DIR}" regressions/python/
|
||||
if [ "X${UBSAN_BUILD}" = "X1" ]; then
|
||||
# FIXME: We need to build libz3 with a shared UBSan runtime for the bindings
|
||||
# to work.
|
||||
echo "FIXME: Skipping python binding tests when building with UBSan"
|
||||
elif [ "X${ASAN_BUILD}" = "X1" ]; then
|
||||
# FIXME: The `test_pyscripts.py` doesn't propagate LD_PRELOAD
|
||||
# so under ASan the tests fail to run
|
||||
# to work.
|
||||
echo "FIXME: Skipping python binding tests when building with ASan"
|
||||
else
|
||||
run_non_native_binding ${PYTHON_EXECUTABLE} scripts/test_pyscripts.py "${Z3_LIB_DIR}" regressions/python/
|
||||
fi
|
||||
fi
|
||||
|
||||
# FIXME: Run `scripts/test_cs.py` once it has been modified to support mono
|
||||
|
|
|
@ -13,6 +13,9 @@ set -o pipefail
|
|||
# Set CMake generator args
|
||||
source ${SCRIPT_DIR}/set_generator_args.sh
|
||||
|
||||
# Sanitizer environment variables
|
||||
source ${SCRIPT_DIR}/sanitizer_env.sh
|
||||
|
||||
cd "${Z3_BUILD_DIR}"
|
||||
|
||||
function build_unit_tests() {
|
||||
|
|
|
@ -84,6 +84,14 @@ if [ -n "${ASAN_BUILD}" ]; then
|
|||
BUILD_OPTS+=("--build-arg" "ASAN_BUILD=${ASAN_BUILD}")
|
||||
fi
|
||||
|
||||
if [ -n "${ASAN_DSO}" ]; then
|
||||
BUILD_OPTS+=("--build-arg" "ASAN_DSO=${ASAN_DSO}")
|
||||
fi
|
||||
|
||||
if [ -n "${SANITIZER_PRINT_SUPPRESSIONS}" ]; then
|
||||
BUILD_OPTS+=("--build-arg" "SANITIZER_PRINT_SUPPRESSIONS=${SANITIZER_PRINT_SUPPRESSIONS}")
|
||||
fi
|
||||
|
||||
if [ -n "${UBSAN_BUILD}" ]; then
|
||||
BUILD_OPTS+=("--build-arg" "UBSAN_BUILD=${UBSAN_BUILD}")
|
||||
fi
|
||||
|
@ -92,6 +100,10 @@ if [ -n "${TEST_INSTALL}" ]; then
|
|||
BUILD_OPTS+=("--build-arg" "TEST_INSTALL=${TEST_INSTALL}")
|
||||
fi
|
||||
|
||||
if [ -n "${RUN_API_EXAMPLES}" ]; then
|
||||
BUILD_OPTS+=("--build-arg" "RUN_API_EXAMPLES=${RUN_API_EXAMPLES}")
|
||||
fi
|
||||
|
||||
if [ -n "${RUN_SYSTEM_TESTS}" ]; then
|
||||
BUILD_OPTS+=("--build-arg" "RUN_SYSTEM_TESTS=${RUN_SYSTEM_TESTS}")
|
||||
fi
|
||||
|
|
7
contrib/suppressions/README.md
Normal file
7
contrib/suppressions/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Suppression files
|
||||
|
||||
This directory contains suppression files used by various
|
||||
program analysis tools.
|
||||
|
||||
Suppression files tell a program analysis tool to suppress
|
||||
various warnings/errors.
|
3
contrib/suppressions/maintainers.txt
Normal file
3
contrib/suppressions/maintainers.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Maintainers
|
||||
|
||||
- Dan Liew (@delcypher)
|
4
contrib/suppressions/sanitizers/README.md
Normal file
4
contrib/suppressions/sanitizers/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Sanitizer supression files
|
||||
|
||||
This directory contains files used to suppress
|
||||
ASan/LSan/UBSan warnings/errors.
|
1
contrib/suppressions/sanitizers/asan.txt
Normal file
1
contrib/suppressions/sanitizers/asan.txt
Normal file
|
@ -0,0 +1 @@
|
|||
# AddressSanitizer suppression file
|
5
contrib/suppressions/sanitizers/lsan.txt
Normal file
5
contrib/suppressions/sanitizers/lsan.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
# LeakSanitizer suppression file
|
||||
|
||||
# Ignore Clang OpenMP leaks.
|
||||
# See https://github.com/Z3Prover/z3/issues/1308
|
||||
leak:___kmp_allocate
|
7
contrib/suppressions/sanitizers/ubsan.txt
Normal file
7
contrib/suppressions/sanitizers/ubsan.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
# UndefinedBehavior sanitizer suppression file
|
||||
# FIXME: UBSan doesn't usually have false positives so we need to fix all of these!
|
||||
|
||||
# Occurs when running tptp example
|
||||
# See https://github.com/Z3Prover/z3/issues/964
|
||||
null:rational.h
|
||||
null:mpq.h
|
|
@ -7,6 +7,30 @@ else()
|
|||
set(EXTERNAL_PROJECT_BUILD_ALWAYS_ARG "")
|
||||
endif()
|
||||
|
||||
option(Z3_C_EXAMPLES_FORCE_CXX_LINKER
|
||||
"Force C++ linker when building C example projects" OFF)
|
||||
|
||||
if (Z3_C_EXAMPLES_FORCE_CXX_LINKER)
|
||||
# HACK: This is a workaround for UBSan.
|
||||
message(STATUS "Forcing C++ linker to be used when building example C projects")
|
||||
set(EXTERNAL_C_PROJ_USE_CXX_LINKER_ARG
|
||||
"-DFORCE_CXX_LINKER=ON"
|
||||
)
|
||||
else()
|
||||
set(EXTERNAL_C_PROJ_USE_CXX_LINKER_ARG "")
|
||||
endif()
|
||||
|
||||
if (DEFINED CMAKE_CONFIGURATION_TYPES)
|
||||
message(WARNING
|
||||
"Cannot set built type of external project when building with a "
|
||||
"multi-configuration generator")
|
||||
set(EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG "")
|
||||
else()
|
||||
set(EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG
|
||||
"-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
|
||||
)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
# Build example project using libz3's C API as an external project
|
||||
################################################################################
|
||||
|
@ -14,7 +38,10 @@ ExternalProject_Add(c_example
|
|||
DEPENDS libz3
|
||||
# Configure step
|
||||
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/c"
|
||||
CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}"
|
||||
CMAKE_ARGS
|
||||
"-DZ3_DIR=${CMAKE_BINARY_DIR}"
|
||||
"${EXTERNAL_C_PROJ_USE_CXX_LINKER_ARG}"
|
||||
"${EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG}"
|
||||
# Build step
|
||||
${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG}
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/c_example_build_dir"
|
||||
|
@ -30,7 +57,10 @@ ExternalProject_Add(c_maxsat_example
|
|||
DEPENDS libz3
|
||||
# Configure step
|
||||
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/maxsat"
|
||||
CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}"
|
||||
CMAKE_ARGS
|
||||
"-DZ3_DIR=${CMAKE_BINARY_DIR}"
|
||||
"${EXTERNAL_C_PROJ_USE_CXX_LINKER_ARG}"
|
||||
"${EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG}"
|
||||
# Build step
|
||||
${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG}
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/c_maxsat_example_build_dir"
|
||||
|
@ -47,7 +77,9 @@ ExternalProject_Add(cpp_example
|
|||
DEPENDS libz3
|
||||
# Configure step
|
||||
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/c++"
|
||||
CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}"
|
||||
CMAKE_ARGS
|
||||
"-DZ3_DIR=${CMAKE_BINARY_DIR}"
|
||||
"${EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG}"
|
||||
# Build step
|
||||
${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG}
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/cpp_example_build_dir"
|
||||
|
@ -63,7 +95,9 @@ ExternalProject_Add(z3_tptp5
|
|||
DEPENDS libz3
|
||||
# Configure step
|
||||
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tptp"
|
||||
CMAKE_ARGS "-DZ3_DIR=${CMAKE_BINARY_DIR}"
|
||||
CMAKE_ARGS
|
||||
"-DZ3_DIR=${CMAKE_BINARY_DIR}"
|
||||
"${EXTERNAL_PROJECT_CMAKE_BUILD_TYPE_ARG}"
|
||||
# Build step
|
||||
${EXTERNAL_PROJECT_BUILD_ALWAYS_ARG}
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/tptp_build_dir"
|
||||
|
|
|
@ -7,6 +7,19 @@
|
|||
# the C++ standard library in resulting in a link failure.
|
||||
project(Z3_C_EXAMPLE C CXX)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
# Set C version required to C99
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "3.1")
|
||||
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR
|
||||
("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 ")
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
endif()
|
||||
|
||||
find_package(Z3
|
||||
REQUIRED
|
||||
CONFIG
|
||||
|
@ -22,6 +35,17 @@ message(STATUS "Found Z3 ${Z3_VERSION_STRING}")
|
|||
message(STATUS "Z3_DIR: ${Z3_DIR}")
|
||||
|
||||
add_executable(c_example test_capi.c)
|
||||
|
||||
option(FORCE_CXX_LINKER "Force linker with C++ linker" OFF)
|
||||
if (FORCE_CXX_LINKER)
|
||||
# This is a hack for avoiding UBSan linking errors
|
||||
message(STATUS "Forcing use of C++ linker")
|
||||
set_target_properties(c_example
|
||||
PROPERTIES
|
||||
LINKER_LANGUAGE CXX
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(c_example PRIVATE ${Z3_C_INCLUDE_DIRS})
|
||||
target_link_libraries(c_example PRIVATE ${Z3_LIBRARIES})
|
||||
|
||||
|
|
|
@ -2842,9 +2842,208 @@ void fpa_example() {
|
|||
Z3_del_context(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Demonstrates some basic features of model construction
|
||||
*/
|
||||
|
||||
void mk_model_example() {
|
||||
Z3_context ctx;
|
||||
Z3_model m;
|
||||
Z3_sort intSort;
|
||||
Z3_symbol aSymbol, bSymbol, cSymbol;
|
||||
Z3_func_decl aFuncDecl, bFuncDecl, cFuncDecl;
|
||||
Z3_ast aApp, bApp, cApp;
|
||||
Z3_sort int2intArraySort;
|
||||
Z3_ast zeroNumeral, oneNumeral, twoNumeral, threeNumeral, fourNumeral;
|
||||
Z3_sort arrayDomain[1];
|
||||
Z3_func_decl cAsFuncDecl;
|
||||
Z3_func_interp cAsFuncInterp;
|
||||
Z3_ast_vector zeroArgs;
|
||||
Z3_ast_vector oneArgs;
|
||||
Z3_ast cFuncDeclAsArray;
|
||||
Z3_string modelAsString;
|
||||
|
||||
printf("\nmk_model_example\n");
|
||||
ctx = mk_context();
|
||||
// Construct empty model
|
||||
m = Z3_mk_model(ctx);
|
||||
Z3_model_inc_ref(ctx, m);
|
||||
|
||||
// Create constants "a" and "b"
|
||||
intSort = Z3_mk_int_sort(ctx);
|
||||
aSymbol = Z3_mk_string_symbol(ctx, "a");
|
||||
aFuncDecl = Z3_mk_func_decl(ctx, aSymbol,
|
||||
/*domain_size=*/0,
|
||||
/*domain=*/NULL,
|
||||
/*range=*/intSort);
|
||||
aApp = Z3_mk_app(ctx, aFuncDecl,
|
||||
/*num_args=*/0,
|
||||
/*args=*/NULL);
|
||||
bSymbol = Z3_mk_string_symbol(ctx, "b");
|
||||
bFuncDecl = Z3_mk_func_decl(ctx, bSymbol,
|
||||
/*domain_size=*/0,
|
||||
/*domain=*/NULL,
|
||||
/*range=*/intSort);
|
||||
bApp = Z3_mk_app(ctx, bFuncDecl,
|
||||
/*num_args=*/0,
|
||||
/*args=*/NULL);
|
||||
|
||||
// Create array "c" that maps int to int.
|
||||
cSymbol = Z3_mk_string_symbol(ctx, "c");
|
||||
int2intArraySort = Z3_mk_array_sort(ctx,
|
||||
/*domain=*/intSort,
|
||||
/*range=*/intSort);
|
||||
cFuncDecl = Z3_mk_func_decl(ctx, cSymbol,
|
||||
/*domain_size=*/0,
|
||||
/*domain=*/NULL,
|
||||
/*range=*/int2intArraySort);
|
||||
cApp = Z3_mk_app(ctx, cFuncDecl,
|
||||
/*num_args=*/0,
|
||||
/*args=*/NULL);
|
||||
|
||||
// Create numerals to be used in model
|
||||
zeroNumeral = Z3_mk_int(ctx, 0, intSort);
|
||||
oneNumeral = Z3_mk_int(ctx, 1, intSort);
|
||||
twoNumeral = Z3_mk_int(ctx, 2, intSort);
|
||||
threeNumeral = Z3_mk_int(ctx, 3, intSort);
|
||||
fourNumeral = Z3_mk_int(ctx, 4, intSort);
|
||||
|
||||
// Add assignments to model
|
||||
// a == 1
|
||||
Z3_add_const_interp(ctx, m, aFuncDecl, oneNumeral);
|
||||
// b == 2
|
||||
Z3_add_const_interp(ctx, m, bFuncDecl, twoNumeral);
|
||||
|
||||
// Create a fresh function that represents
|
||||
// reading from array.
|
||||
arrayDomain[0] = intSort;
|
||||
cAsFuncDecl = Z3_mk_fresh_func_decl(ctx,
|
||||
/*prefix=*/"",
|
||||
/*domain_size*/ 1,
|
||||
/*domain=*/arrayDomain,
|
||||
/*sort=*/intSort);
|
||||
// Create function interpretation with default
|
||||
// value of "0".
|
||||
cAsFuncInterp =
|
||||
Z3_add_func_interp(ctx, m, cAsFuncDecl,
|
||||
/*default_value=*/zeroNumeral);
|
||||
Z3_func_interp_inc_ref(ctx, cAsFuncInterp);
|
||||
// Add [0] = 3
|
||||
zeroArgs = Z3_mk_ast_vector(ctx);
|
||||
Z3_ast_vector_inc_ref(ctx, zeroArgs);
|
||||
Z3_ast_vector_push(ctx, zeroArgs, zeroNumeral);
|
||||
Z3_func_interp_add_entry(ctx, cAsFuncInterp, zeroArgs, threeNumeral);
|
||||
// Add [1] = 4
|
||||
oneArgs = Z3_mk_ast_vector(ctx);
|
||||
Z3_ast_vector_inc_ref(ctx, oneArgs);
|
||||
Z3_ast_vector_push(ctx, oneArgs, oneNumeral);
|
||||
Z3_func_interp_add_entry(ctx, cAsFuncInterp, oneArgs, fourNumeral);
|
||||
|
||||
// Now use the `(_ as_array)` to associate
|
||||
// the `cAsFuncInterp` with the `cFuncDecl`
|
||||
// in the model
|
||||
cFuncDeclAsArray = Z3_mk_as_array(ctx, cAsFuncDecl);
|
||||
Z3_add_const_interp(ctx, m, cFuncDecl, cFuncDeclAsArray);
|
||||
|
||||
// Print the model
|
||||
modelAsString = Z3_model_to_string(ctx, m);
|
||||
printf("Model:\n%s\n", modelAsString);
|
||||
|
||||
// Check the interpretations we expect to be present
|
||||
// are.
|
||||
{
|
||||
Z3_func_decl expectedInterpretations[3] = {aFuncDecl, bFuncDecl, cFuncDecl};
|
||||
int index;
|
||||
for (index = 0;
|
||||
index < sizeof(expectedInterpretations) / sizeof(Z3_func_decl);
|
||||
++index) {
|
||||
Z3_func_decl d = expectedInterpretations[index];
|
||||
if (Z3_model_has_interp(ctx, m, d)) {
|
||||
printf("Found interpretation for \"%s\"\n",
|
||||
Z3_ast_to_string(ctx, Z3_func_decl_to_ast(ctx, d)));
|
||||
} else {
|
||||
printf("Missing interpretation");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Evaluate a + b under model
|
||||
Z3_ast addArgs[] = {aApp, bApp};
|
||||
Z3_ast aPlusB = Z3_mk_add(ctx,
|
||||
/*num_args=*/2,
|
||||
/*args=*/addArgs);
|
||||
Z3_ast aPlusBEval = NULL;
|
||||
Z3_bool aPlusBEvalSuccess =
|
||||
Z3_model_eval(ctx, m, aPlusB,
|
||||
/*model_completion=*/Z3_FALSE, &aPlusBEval);
|
||||
if (aPlusBEvalSuccess != Z3_TRUE) {
|
||||
printf("Failed to evaluate model\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
{
|
||||
int aPlusBValue = 0;
|
||||
Z3_bool getAPlusBValueSuccess =
|
||||
Z3_get_numeral_int(ctx, aPlusBEval, &aPlusBValue);
|
||||
if (getAPlusBValueSuccess != Z3_TRUE) {
|
||||
printf("Failed to get integer value for a+b\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("Evaluated a + b = %d\n", aPlusBValue);
|
||||
if (aPlusBValue != 3) {
|
||||
printf("a+b did not evaluate to expected value\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Evaluate c[0] + c[1] + c[2] under model
|
||||
Z3_ast c0 = Z3_mk_select(ctx, cApp, zeroNumeral);
|
||||
Z3_ast c1 = Z3_mk_select(ctx, cApp, oneNumeral);
|
||||
Z3_ast c2 = Z3_mk_select(ctx, cApp, twoNumeral);
|
||||
Z3_ast arrayAddArgs[] = {c0, c1, c2};
|
||||
Z3_ast arrayAdd = Z3_mk_add(ctx,
|
||||
/*num_args=*/3,
|
||||
/*args=*/arrayAddArgs);
|
||||
Z3_ast arrayAddEval = NULL;
|
||||
Z3_bool arrayAddEvalSuccess =
|
||||
Z3_model_eval(ctx, m, arrayAdd,
|
||||
/*model_completion=*/Z3_FALSE, &arrayAddEval);
|
||||
if (arrayAddEvalSuccess != Z3_TRUE) {
|
||||
printf("Failed to evaluate model\n");
|
||||
exit(1);
|
||||
}
|
||||
{
|
||||
int arrayAddValue = 0;
|
||||
Z3_bool getArrayAddValueSuccess =
|
||||
Z3_get_numeral_int(ctx, arrayAddEval, &arrayAddValue);
|
||||
if (getArrayAddValueSuccess != Z3_TRUE) {
|
||||
printf("Failed to get integer value for c[0] + c[1] + c[2]\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("Evaluated c[0] + c[1] + c[2] = %d\n", arrayAddValue);
|
||||
if (arrayAddValue != 7) {
|
||||
printf("c[0] + c[1] + c[2] did not evaluate to expected value\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Z3_ast_vector_dec_ref(ctx, oneArgs);
|
||||
Z3_ast_vector_dec_ref(ctx, zeroArgs);
|
||||
Z3_func_interp_dec_ref(ctx, cAsFuncInterp);
|
||||
Z3_model_dec_ref(ctx, m);
|
||||
Z3_del_context(ctx);
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
/*@}*/
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
#ifdef LOG_Z3_CALLS
|
||||
Z3_open_log("z3.log");
|
||||
|
@ -2888,5 +3087,6 @@ int main() {
|
|||
substitute_example();
|
||||
substitute_vars_example();
|
||||
fpa_example();
|
||||
mk_model_example();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,16 @@ add_executable(c_maxsat_example maxsat.c)
|
|||
target_include_directories(c_maxsat_example PRIVATE ${Z3_C_INCLUDE_DIRS})
|
||||
target_link_libraries(c_maxsat_example PRIVATE ${Z3_LIBRARIES})
|
||||
|
||||
option(FORCE_CXX_LINKER "Force linker with C++ linker" OFF)
|
||||
if (FORCE_CXX_LINKER)
|
||||
# This is a hack for avoiding UBSan linking errors
|
||||
message(STATUS "Forcing use of C++ linker")
|
||||
set_target_properties(c_maxsat_example
|
||||
PROPERTIES
|
||||
LINKER_LANGUAGE CXX
|
||||
)
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_SYSTEM_NAME}" MATCHES "[Ww]indows")
|
||||
# On Windows we need to copy the Z3 libraries
|
||||
# into the same directory as the executable
|
||||
|
|
|
@ -37,20 +37,20 @@ def init_project_def():
|
|||
add_lib('nlsat_tactic', ['nlsat', 'sat_tactic', 'arith_tactics'], 'nlsat/tactic')
|
||||
add_lib('subpaving_tactic', ['core_tactics', 'subpaving'], 'math/subpaving/tactic')
|
||||
add_lib('aig_tactic', ['tactic'], 'tactic/aig')
|
||||
add_lib('solver', ['model', 'tactic'])
|
||||
add_lib('proofs', ['rewriter', 'util'], 'ast/proofs')
|
||||
add_lib('solver', ['model', 'tactic', 'proofs'])
|
||||
add_lib('ackermannization', ['model', 'rewriter', 'ast', 'solver', 'tactic'], 'ackermannization')
|
||||
add_lib('interp', ['solver'])
|
||||
add_lib('cmd_context', ['solver', 'rewriter', 'interp'])
|
||||
add_lib('extra_cmds', ['cmd_context', 'subpaving_tactic', 'arith_tactics'], 'cmd_context/extra_cmds')
|
||||
add_lib('smt2parser', ['cmd_context', 'parser_util'], 'parsers/smt2')
|
||||
add_lib('proof_checker', ['rewriter'], 'ast/proof_checker')
|
||||
add_lib('fpa', ['ast', 'util', 'rewriter', 'model'], 'ast/fpa')
|
||||
add_lib('pattern', ['normal_forms', 'smt2parser', 'rewriter'], 'ast/pattern')
|
||||
add_lib('bit_blaster', ['rewriter', 'rewriter'], 'ast/rewriter/bit_blaster')
|
||||
add_lib('smt_params', ['ast', 'rewriter', 'pattern', 'bit_blaster'], 'smt/params')
|
||||
add_lib('proto_model', ['model', 'rewriter', 'smt_params'], 'smt/proto_model')
|
||||
add_lib('smt', ['bit_blaster', 'macros', 'normal_forms', 'cmd_context', 'proto_model',
|
||||
'substitution', 'grobner', 'euclid', 'simplex', 'proof_checker', 'pattern', 'parser_util', 'fpa', 'lp'])
|
||||
'substitution', 'grobner', 'euclid', 'simplex', 'proofs', 'pattern', 'parser_util', 'fpa', 'lp'])
|
||||
add_lib('bv_tactics', ['tactic', 'bit_blaster', 'core_tactics'], 'tactic/bv')
|
||||
add_lib('fuzzing', ['ast'], 'test/fuzzing')
|
||||
add_lib('smt_tactic', ['smt'], 'smt/tactic')
|
||||
|
|
|
@ -72,6 +72,7 @@ IS_FREEBSD=False
|
|||
IS_OPENBSD=False
|
||||
IS_CYGWIN=False
|
||||
IS_CYGWIN_MINGW=False
|
||||
IS_MSYS2=False
|
||||
VERBOSE=True
|
||||
DEBUG_MODE=False
|
||||
SHOW_CPPS = True
|
||||
|
@ -152,6 +153,9 @@ def is_cygwin():
|
|||
def is_cygwin_mingw():
|
||||
return IS_CYGWIN_MINGW
|
||||
|
||||
def is_msys2():
|
||||
return IS_MSYS2
|
||||
|
||||
def norm_path(p):
|
||||
return os.path.expanduser(os.path.normpath(p))
|
||||
|
||||
|
@ -227,7 +231,7 @@ def rmf(fname):
|
|||
|
||||
def exec_compiler_cmd(cmd):
|
||||
r = exec_cmd(cmd)
|
||||
if is_windows() or is_cygwin_mingw():
|
||||
if is_windows() or is_cygwin_mingw() or is_cygwin() or is_msys2():
|
||||
rmf('a.exe')
|
||||
else:
|
||||
rmf('a.out')
|
||||
|
@ -606,6 +610,13 @@ elif os.name == 'posix':
|
|||
IS_CYGWIN=True
|
||||
if (CC != None and "mingw" in CC):
|
||||
IS_CYGWIN_MINGW=True
|
||||
elif os.uname()[0].startswith('MSYS_NT'):
|
||||
IS_MSYS2=True
|
||||
if os.uname()[4] == 'x86_64':
|
||||
LINUX_X64=True
|
||||
else:
|
||||
LINUX_X64=False
|
||||
|
||||
|
||||
def display_help(exit_code):
|
||||
print("mk_make.py: Z3 Makefile generator\n")
|
||||
|
@ -1229,7 +1240,7 @@ def get_so_ext():
|
|||
sysname = os.uname()[0]
|
||||
if sysname == 'Darwin':
|
||||
return 'dylib'
|
||||
elif sysname == 'Linux' or sysname == 'FreeBSD' or sysname == 'OpenBSD':
|
||||
elif sysname == 'Linux' or sysname == 'FreeBSD' or sysname == 'OpenBSD' or sysname.startswith('MSYS_NT'):
|
||||
return 'so'
|
||||
elif sysname == 'CYGWIN':
|
||||
return 'dll'
|
||||
|
@ -1783,6 +1794,8 @@ class JavaDLLComponent(Component):
|
|||
t = t.replace('PLATFORM', 'openbsd')
|
||||
elif IS_CYGWIN:
|
||||
t = t.replace('PLATFORM', 'cygwin')
|
||||
elif IS_MSYS2:
|
||||
t = t.replace('PLATFORM', 'win32')
|
||||
else:
|
||||
t = t.replace('PLATFORM', 'win32')
|
||||
out.write(t)
|
||||
|
@ -2446,7 +2459,7 @@ def mk_config():
|
|||
if sysname == 'Darwin':
|
||||
SO_EXT = '.dylib'
|
||||
SLIBFLAGS = '-dynamiclib'
|
||||
elif sysname == 'Linux':
|
||||
elif sysname == 'Linux' or sysname.startswith('MSYS_NT'):
|
||||
CXXFLAGS = '%s -D_LINUX_' % CXXFLAGS
|
||||
OS_DEFINES = '-D_LINUX_'
|
||||
SO_EXT = '.so'
|
||||
|
|
|
@ -67,7 +67,7 @@ add_subdirectory(interp)
|
|||
add_subdirectory(cmd_context)
|
||||
add_subdirectory(cmd_context/extra_cmds)
|
||||
add_subdirectory(parsers/smt2)
|
||||
add_subdirectory(ast/proof_checker)
|
||||
add_subdirectory(ast/proofs)
|
||||
add_subdirectory(ast/fpa)
|
||||
add_subdirectory(ast/macros)
|
||||
add_subdirectory(ast/pattern)
|
||||
|
|
|
@ -34,6 +34,19 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_array_sort_n(Z3_context c, unsigned n, Z3_sort const* domain, Z3_sort range) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_array_sort_n(c, n, domain, range);
|
||||
RESET_ERROR_CODE();
|
||||
vector<parameter> params;
|
||||
for (unsigned i = 0; i < n; ++i) params.push_back(parameter(to_sort(domain[i])));
|
||||
params.push_back(parameter(to_sort(range)));
|
||||
sort * ty = mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, params.size(), params.c_ptr());
|
||||
mk_c(c)->save_ast_trail(ty);
|
||||
RETURN_Z3(of_sort(ty));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_select(c, a, i);
|
||||
|
@ -57,6 +70,35 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_select_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_select_n(c, a, n, idxs);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(a);
|
||||
// expr * _i = to_expr(i);
|
||||
sort * a_ty = m.get_sort(_a);
|
||||
// sort * i_ty = m.get_sort(_i);
|
||||
if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<sort> domain;
|
||||
ptr_vector<expr> args;
|
||||
args.push_back(_a);
|
||||
domain.push_back(a_ty);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
args.push_back(to_expr(idxs[i]));
|
||||
domain.push_back(m.get_sort(to_expr(idxs[i])));
|
||||
}
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_SELECT, 2, a_ty->get_parameters(), domain.size(), domain.c_ptr());
|
||||
app * r = m.mk_app(d, args.size(), args.c_ptr());
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_store(c, a, i, v);
|
||||
|
@ -82,6 +124,37 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_store_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs, Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_store_n(c, a, n, idxs, v);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(a);
|
||||
expr * _v = to_expr(v);
|
||||
sort * a_ty = m.get_sort(_a);
|
||||
sort * v_ty = m.get_sort(_v);
|
||||
if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<sort> domain;
|
||||
ptr_vector<expr> args;
|
||||
args.push_back(_a);
|
||||
domain.push_back(a_ty);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
args.push_back(to_expr(idxs[i]));
|
||||
domain.push_back(m.get_sort(to_expr(idxs[i])));
|
||||
}
|
||||
args.push_back(_v);
|
||||
domain.push_back(v_ty);
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_STORE, 2, a_ty->get_parameters(), domain.size(), domain.c_ptr());
|
||||
app * r = m.mk_app(d, args.size(), args.c_ptr());
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_map(Z3_context c, Z3_func_decl f, unsigned n, Z3_ast const* args) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_map(c, f, n, args);
|
||||
|
@ -188,6 +261,18 @@ extern "C" {
|
|||
MK_BINARY(Z3_mk_set_subset, mk_c(c)->get_array_fid(), OP_SET_SUBSET, SKIP);
|
||||
MK_BINARY(Z3_mk_array_ext, mk_c(c)->get_array_fid(), OP_ARRAY_EXT, SKIP);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_as_array(Z3_context c, Z3_func_decl f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_as_array(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
array_util a(m);
|
||||
app * r = a.mk_as_array(to_func_decl(f));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_ast(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_set_member(Z3_context c, Z3_ast elem, Z3_ast set) {
|
||||
return Z3_mk_select(c, set, elem);
|
||||
}
|
||||
|
@ -222,7 +307,8 @@ extern "C" {
|
|||
CHECK_VALID_AST(t, 0);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT) {
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(1).get_ast());
|
||||
unsigned n = to_sort(t)->get_num_parameters();
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(n-1).get_ast());
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
|
|
|
@ -249,7 +249,7 @@ extern "C" {
|
|||
params_ref _p;
|
||||
_p.set_bool("proof", true); // this is currently useless
|
||||
|
||||
scoped_proof_mode spm(mk_c(c)->m(), PGM_FINE);
|
||||
scoped_proof_mode spm(mk_c(c)->m(), PGM_ENABLED);
|
||||
scoped_ptr<solver_factory> sf = mk_smt_solver_factory();
|
||||
scoped_ptr<solver> m_solver((*sf)(mk_c(c)->m(), _p, true, true, true, ::symbol::null));
|
||||
m_solver.get()->updt_params(_p); // why do we have to do this?
|
||||
|
|
|
@ -255,8 +255,13 @@ extern "C" {
|
|||
LOG_Z3_add_const_interp(c, m, f, a);
|
||||
RESET_ERROR_CODE();
|
||||
func_decl* d = to_func_decl(f);
|
||||
if (d->get_arity() != 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
}
|
||||
else {
|
||||
model* mdl = to_model_ref(m);
|
||||
mdl->register_decl(d, to_expr(a));
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
|
|
|
@ -288,15 +288,16 @@ extern "C" {
|
|||
Z3_optimize opt,
|
||||
std::istream& s) {
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
cmd_context ctx(false, &m);
|
||||
install_opt_cmds(ctx, to_optimize_ptr(opt));
|
||||
ctx.set_ignore_check(true);
|
||||
if (!parse_smt2_commands(ctx, s)) {
|
||||
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &m);
|
||||
install_opt_cmds(*ctx.get(), to_optimize_ptr(opt));
|
||||
ctx->set_ignore_check(true);
|
||||
if (!parse_smt2_commands(*ctx.get(), s)) {
|
||||
ctx = nullptr;
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return;
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
to_optimize_ptr(opt)->add_hard_constraint(*it);
|
||||
}
|
||||
|
@ -325,9 +326,6 @@ extern "C" {
|
|||
std::ostringstream strm;
|
||||
strm << "Could not open file " << s;
|
||||
throw default_exception(strm.str());
|
||||
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return;
|
||||
}
|
||||
Z3_optimize_from_stream(c, d, is);
|
||||
Z3_CATCH;
|
||||
|
|
|
@ -57,7 +57,7 @@ extern "C" {
|
|||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
std::ostringstream* outs = alloc(std::ostringstream);
|
||||
scoped_ptr<std::ostringstream> outs = alloc(std::ostringstream);
|
||||
bool ok = false;
|
||||
|
||||
RESET_ERROR_CODE();
|
||||
|
@ -70,7 +70,7 @@ extern "C" {
|
|||
ok = false;
|
||||
}
|
||||
mk_c(c)->m_smtlib_error_buffer = outs->str();
|
||||
dealloc(outs);
|
||||
outs = nullptr;
|
||||
if (!ok) {
|
||||
mk_c(c)->reset_parser();
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
|
@ -90,7 +90,7 @@ extern "C" {
|
|||
LOG_Z3_parse_smtlib_file(c, file_name, num_sorts, sort_names, types, num_decls, decl_names, decls);
|
||||
bool ok = false;
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream* outs = alloc(std::ostringstream);
|
||||
scoped_ptr<std::ostringstream> outs = alloc(std::ostringstream);
|
||||
init_smtlib_parser(c, num_sorts, sort_names, types, num_decls, decl_names, decls);
|
||||
mk_c(c)->m_smtlib_parser->set_error_stream(*outs);
|
||||
try {
|
||||
|
@ -100,7 +100,7 @@ extern "C" {
|
|||
ok = false;
|
||||
}
|
||||
mk_c(c)->m_smtlib_error_buffer = outs->str();
|
||||
dealloc(outs);
|
||||
outs = nullptr;
|
||||
if (!ok) {
|
||||
mk_c(c)->reset_parser();
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
|
@ -263,24 +263,24 @@ extern "C" {
|
|||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
cmd_context ctx(false, &(mk_c(c)->m()));
|
||||
ctx.set_ignore_check(true);
|
||||
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &(mk_c(c)->m()));
|
||||
ctx->set_ignore_check(true);
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
ctx.insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
|
||||
ctx->insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
|
||||
}
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
psort* ps = ctx.pm().mk_psort_cnst(to_sort(sorts[i]));
|
||||
ctx.insert(ctx.pm().mk_psort_user_decl(0, to_symbol(sort_names[i]), ps));
|
||||
psort* ps = ctx->pm().mk_psort_cnst(to_sort(sorts[i]));
|
||||
ctx->insert(ctx->pm().mk_psort_user_decl(0, to_symbol(sort_names[i]), ps));
|
||||
}
|
||||
if (!parse_smt2_commands(ctx, is)) {
|
||||
if (!parse_smt2_commands(*ctx.get(), is)) {
|
||||
ctx = nullptr;
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return of_ast_vector(v);
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
v->m_ast_vector.push_back(*it);
|
||||
}
|
||||
|
|
|
@ -63,9 +63,11 @@ extern "C" {
|
|||
RESET_ERROR_CODE();
|
||||
if (!mk_c(c)->m().is_bool(to_expr(body))) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
if (num_patterns > 0 && num_no_patterns > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
return nullptr;
|
||||
}
|
||||
expr * const* ps = reinterpret_cast<expr * const*>(patterns);
|
||||
expr * const* no_ps = reinterpret_cast<expr * const*>(no_patterns);
|
||||
|
@ -76,7 +78,7 @@ extern "C" {
|
|||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
if (!v(num_decls, ps[i], 0, 0)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_PATTERN);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -452,6 +452,7 @@ extern "C" {
|
|||
unsigned sz = __assumptions.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
if (!is_expr(__assumptions[i])) {
|
||||
_assumptions.finalize(); _consequences.finalize(); _variables.finalize();
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
|
@ -461,6 +462,7 @@ extern "C" {
|
|||
sz = __variables.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
if (!is_expr(__variables[i])) {
|
||||
_assumptions.finalize(); _consequences.finalize(); _variables.finalize();
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
|
@ -481,6 +483,7 @@ extern "C" {
|
|||
}
|
||||
catch (z3_exception & ex) {
|
||||
to_solver_ref(s)->set_reason_unknown(eh);
|
||||
_assumptions.finalize(); _consequences.finalize(); _variables.finalize();
|
||||
mk_c(c)->handle_exception(ex);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
|
|
|
@ -140,18 +140,17 @@ namespace z3 {
|
|||
class context {
|
||||
bool m_enable_exceptions;
|
||||
Z3_context m_ctx;
|
||||
static void Z3_API error_handler(Z3_context /*c*/, Z3_error_code /*e*/) { /* do nothing */ }
|
||||
void init(config & c) {
|
||||
m_ctx = Z3_mk_context_rc(c);
|
||||
m_enable_exceptions = true;
|
||||
Z3_set_error_handler(m_ctx, error_handler);
|
||||
Z3_set_error_handler(m_ctx, 0);
|
||||
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||
}
|
||||
|
||||
void init_interp(config & c) {
|
||||
m_ctx = Z3_mk_interpolation_context(c);
|
||||
m_enable_exceptions = true;
|
||||
Z3_set_error_handler(m_ctx, error_handler);
|
||||
Z3_set_error_handler(m_ctx, 0);
|
||||
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||
}
|
||||
|
||||
|
@ -251,6 +250,8 @@ namespace z3 {
|
|||
Example: Given a context \c c, <tt>c.array_sort(c.int_sort(), c.bool_sort())</tt> is an array sort from integer to Boolean.
|
||||
*/
|
||||
sort array_sort(sort d, sort r);
|
||||
sort array_sort(sort_vector const& d, sort r);
|
||||
|
||||
/**
|
||||
\brief Return an enumeration sort: enum_names[0], ..., enum_names[n-1].
|
||||
\c cs and \c ts are output parameters. The method stores in \c cs the constants corresponding to the enumerated elements,
|
||||
|
@ -2328,6 +2329,11 @@ namespace z3 {
|
|||
inline sort context::re_sort(sort& s) { Z3_sort r = Z3_mk_re_sort(m_ctx, s); check_error(); return sort(*this, r); }
|
||||
|
||||
inline sort context::array_sort(sort d, sort r) { Z3_sort s = Z3_mk_array_sort(m_ctx, d, r); check_error(); return sort(*this, s); }
|
||||
inline sort context::array_sort(sort_vector const& d, sort r) {
|
||||
array<Z3_sort> dom(d);
|
||||
Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s);
|
||||
}
|
||||
|
||||
inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
|
||||
array<Z3_symbol> _enum_names(n);
|
||||
for (unsigned i = 0; i < n; i++) { _enum_names[i] = Z3_mk_string_symbol(*this, enum_names[i]); }
|
||||
|
@ -2574,11 +2580,32 @@ namespace z3 {
|
|||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
inline expr select(expr const & a, expr_vector const & i) {
|
||||
check_context(a, i);
|
||||
array<Z3_ast> idxs(i);
|
||||
Z3_ast r = Z3_mk_select_n(a.ctx(), a, idxs.size(), idxs.ptr());
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr store(expr const & a, int i, expr const & v) { return store(a, a.ctx().num_val(i, a.get_sort().array_domain()), v); }
|
||||
inline expr store(expr const & a, expr i, int v) { return store(a, i, a.ctx().num_val(v, a.get_sort().array_range())); }
|
||||
inline expr store(expr const & a, int i, int v) {
|
||||
return store(a, a.ctx().num_val(i, a.get_sort().array_domain()), a.ctx().num_val(v, a.get_sort().array_range()));
|
||||
}
|
||||
inline expr store(expr const & a, expr_vector const & i, expr const & v) {
|
||||
check_context(a, i); check_context(a, v);
|
||||
array<Z3_ast> idxs(i);
|
||||
Z3_ast r = Z3_mk_store_n(a.ctx(), a, idxs.size(), idxs.ptr(), v);
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr as_array(func_decl & f) {
|
||||
Z3_ast r = Z3_mk_as_array(f.ctx(), f);
|
||||
f.check_error();
|
||||
return expr(f.ctx(), r);
|
||||
}
|
||||
|
||||
#define MK_EXPR1(_fn, _arg) \
|
||||
Z3_ast r = _fn(_arg.ctx(), _arg); \
|
||||
|
|
|
@ -63,6 +63,13 @@ namespace Microsoft.Z3
|
|||
Contract.Requires(domain != null);
|
||||
Contract.Requires(range != null);
|
||||
}
|
||||
internal ArraySort(Context ctx, Sort[] domain, Sort range)
|
||||
: base(ctx, Native.Z3_mk_array_sort_n(ctx.nCtx, (uint)domain.Length, AST.ArrayToNative(domain), range.NativeObject))
|
||||
{
|
||||
Contract.Requires(ctx != null);
|
||||
Contract.Requires(domain != null);
|
||||
Contract.Requires(range != null);
|
||||
}
|
||||
#endregion
|
||||
};
|
||||
|
||||
|
|
|
@ -274,6 +274,20 @@ namespace Microsoft.Z3
|
|||
return new ArraySort(this, domain, range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new n-ary array sort.
|
||||
/// </summary>
|
||||
public ArraySort MkArraySort(Sort[] domain, Sort range)
|
||||
{
|
||||
Contract.Requires(domain != null);
|
||||
Contract.Requires(range != null);
|
||||
Contract.Ensures(Contract.Result<ArraySort>() != null);
|
||||
|
||||
CheckContextMatch<Sort>(domain);
|
||||
CheckContextMatch(range);
|
||||
return new ArraySort(this, domain, range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new tuple sort.
|
||||
/// </summary>
|
||||
|
@ -2113,6 +2127,7 @@ namespace Microsoft.Z3
|
|||
return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Array read.
|
||||
/// </summary>
|
||||
|
@ -2123,8 +2138,8 @@ namespace Microsoft.Z3
|
|||
/// The node <c>a</c> must have an array sort <c>[domain -> range]</c>,
|
||||
/// and <c>i</c> must have the sort <c>domain</c>.
|
||||
/// The sort of the result is <c>range</c>.
|
||||
/// <seealso cref="MkArraySort"/>
|
||||
/// <seealso cref="MkStore"/>
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkStore(ArrayExpr, Expr, Expr)"/>
|
||||
/// </remarks>
|
||||
public Expr MkSelect(ArrayExpr a, Expr i)
|
||||
{
|
||||
|
@ -2137,6 +2152,30 @@ namespace Microsoft.Z3
|
|||
return Expr.Create(this, Native.Z3_mk_select(nCtx, a.NativeObject, i.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Array read.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The argument <c>a</c> is the array and <c>args</c> are the indices
|
||||
/// of the array that gets read.
|
||||
///
|
||||
/// The node <c>a</c> must have an array sort <c>[domain1,..,domaink -> range]</c>,
|
||||
/// and <c>args</c> must have the sort <c>domain1,..,domaink</c>.
|
||||
/// The sort of the result is <c>range</c>.
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkStore(ArrayExpr, Expr, Expr)"/>
|
||||
/// </remarks>
|
||||
public Expr MkSelect(ArrayExpr a, params Expr[] args)
|
||||
{
|
||||
Contract.Requires(a != null);
|
||||
Contract.Requires(args != null && Contract.ForAll(args, n => n != null));
|
||||
Contract.Ensures(Contract.Result<Expr>() != null);
|
||||
|
||||
CheckContextMatch(a);
|
||||
CheckContextMatch<Expr>(args);
|
||||
return Expr.Create(this, Native.Z3_mk_select_n(nCtx, a.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Array update.
|
||||
/// </summary>
|
||||
|
@ -2151,8 +2190,9 @@ namespace Microsoft.Z3
|
|||
/// on all indices except for <c>i</c>, where it maps to <c>v</c>
|
||||
/// (and the <c>select</c> of <c>a</c> with
|
||||
/// respect to <c>i</c> may be a different value).
|
||||
/// <seealso cref="MkArraySort"/>
|
||||
/// <seealso cref="MkSelect"/>
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr[])"/>
|
||||
/// </remarks>
|
||||
public ArrayExpr MkStore(ArrayExpr a, Expr i, Expr v)
|
||||
{
|
||||
|
@ -2167,14 +2207,45 @@ namespace Microsoft.Z3
|
|||
return new ArrayExpr(this, Native.Z3_mk_store(nCtx, a.NativeObject, i.NativeObject, v.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Array update.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The node <c>a</c> must have an array sort <c>[domain1,..,domaink -> range]</c>,
|
||||
/// <c>args</c> must have sort <c>domain1,..,domaink</c>,
|
||||
/// <c>v</c> must have sort range. The sort of the result is <c>[domain -> range]</c>.
|
||||
/// The semantics of this function is given by the theory of arrays described in the SMT-LIB
|
||||
/// standard. See http://smtlib.org for more details.
|
||||
/// The result of this function is an array that is equal to <c>a</c>
|
||||
/// (with respect to <c>select</c>)
|
||||
/// on all indices except for <c>args</c>, where it maps to <c>v</c>
|
||||
/// (and the <c>select</c> of <c>a</c> with
|
||||
/// respect to <c>args</c> may be a different value).
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr[])"/>
|
||||
/// </remarks>
|
||||
public ArrayExpr MkStore(ArrayExpr a, Expr[] args, Expr v)
|
||||
{
|
||||
Contract.Requires(a != null);
|
||||
Contract.Requires(args != null);
|
||||
Contract.Requires(v != null);
|
||||
Contract.Ensures(Contract.Result<ArrayExpr>() != null);
|
||||
|
||||
CheckContextMatch<Expr>(args);
|
||||
CheckContextMatch(a);
|
||||
CheckContextMatch(v);
|
||||
return new ArrayExpr(this, Native.Z3_mk_store_n(nCtx, a.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args), v.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a constant array.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The resulting term is an array, such that a <c>select</c>on an arbitrary index
|
||||
/// produces the value <c>v</c>.
|
||||
/// <seealso cref="MkArraySort"/>
|
||||
/// <seealso cref="MkSelect"/>
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
|
||||
/// </remarks>
|
||||
public ArrayExpr MkConstArray(Sort domain, Expr v)
|
||||
{
|
||||
|
@ -2194,9 +2265,9 @@ namespace Microsoft.Z3
|
|||
/// Eeach element of <c>args</c> must be of an array sort <c>[domain_i -> range_i]</c>.
|
||||
/// The function declaration <c>f</c> must have type <c> range_1 .. range_n -> range</c>.
|
||||
/// <c>v</c> must have sort range. The sort of the result is <c>[domain_i -> range]</c>.
|
||||
/// <seealso cref="MkArraySort"/>
|
||||
/// <seealso cref="MkSelect"/>
|
||||
/// <seealso cref="MkStore"/>
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
|
||||
/// <seealso cref="MkStore(ArrayExpr, Expr, Expr)"/>
|
||||
/// </remarks>
|
||||
public ArrayExpr MkMap(FuncDecl f, params ArrayExpr[] args)
|
||||
{
|
||||
|
|
|
@ -56,4 +56,10 @@ public class ArraySort extends Sort
|
|||
super(ctx, Native.mkArraySort(ctx.nCtx(), domain.getNativeObject(),
|
||||
range.getNativeObject()));
|
||||
}
|
||||
|
||||
ArraySort(Context ctx, Sort[] domains, Sort range)
|
||||
{
|
||||
super(ctx, Native.mkArraySortN(ctx.nCtx(), domains.length, AST.arrayToNative(domains),
|
||||
range.getNativeObject()));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -224,6 +224,17 @@ public class Context implements AutoCloseable {
|
|||
return new ArraySort(this, domain, range);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new array sort.
|
||||
**/
|
||||
public ArraySort mkArraySort(Sort[] domains, Sort range)
|
||||
{
|
||||
checkContextMatch(domains);
|
||||
checkContextMatch(range);
|
||||
return new ArraySort(this, domains, range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new string sort
|
||||
**/
|
||||
|
@ -414,7 +425,7 @@ public class Context implements AutoCloseable {
|
|||
* that is passed in as argument is updated with value v,
|
||||
* the remaining fields of t are unchanged.
|
||||
**/
|
||||
public Expr MkUpdateField(FuncDecl field, Expr t, Expr v)
|
||||
public Expr mkUpdateField(FuncDecl field, Expr t, Expr v)
|
||||
throws Z3Exception
|
||||
{
|
||||
return Expr.create (this,
|
||||
|
@ -706,7 +717,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Mk an expression representing {@code not(a)}.
|
||||
* Create an expression representing {@code not(a)}.
|
||||
**/
|
||||
public BoolExpr mkNot(BoolExpr a)
|
||||
{
|
||||
|
@ -1679,6 +1690,28 @@ public class Context implements AutoCloseable {
|
|||
i.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Array read.
|
||||
* Remarks: The argument {@code a} is the array and
|
||||
* {@code args} are the indices of the array that gets read.
|
||||
*
|
||||
* The node {@code a} must have an array sort
|
||||
* {@code [domains -> range]}, and {@code args} must have the sorts
|
||||
* {@code domains}. The sort of the result is {@code range}.
|
||||
*
|
||||
* @see #mkArraySort
|
||||
* @see #mkStore
|
||||
|
||||
**/
|
||||
public Expr mkSelect(ArrayExpr a, Expr[] args)
|
||||
{
|
||||
checkContextMatch(a);
|
||||
checkContextMatch(args);
|
||||
return Expr.create(
|
||||
this,
|
||||
Native.mkSelectN(nCtx(), a.getNativeObject(), args.length, AST.arrayToNative(args)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Array update.
|
||||
* Remarks: The node {@code a} must have an array sort
|
||||
|
@ -1704,6 +1737,31 @@ public class Context implements AutoCloseable {
|
|||
i.getNativeObject(), v.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Array update.
|
||||
* Remarks: The node {@code a} must have an array sort
|
||||
* {@code [domains -> range]}, {@code i} must have sort
|
||||
* {@code domain}, {@code v} must have sort range. The sort of the
|
||||
* result is {@code [domains -> range]}. The semantics of this function
|
||||
* is given by the theory of arrays described in the SMT-LIB standard. See
|
||||
* http://smtlib.org for more details. The result of this function is an
|
||||
* array that is equal to {@code a} (with respect to
|
||||
* {@code select}) on all indices except for {@code args}, where it
|
||||
* maps to {@code v} (and the {@code select} of {@code a}
|
||||
* with respect to {@code args} may be a different value).
|
||||
* @see #mkArraySort
|
||||
* @see #mkSelect
|
||||
|
||||
**/
|
||||
public ArrayExpr mkStore(ArrayExpr a, Expr[] args, Expr v)
|
||||
{
|
||||
checkContextMatch(a);
|
||||
checkContextMatch(args);
|
||||
checkContextMatch(v);
|
||||
return new ArrayExpr(this, Native.mkStoreN(nCtx(), a.getNativeObject(),
|
||||
args.length, AST.arrayToNative(args), v.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a constant array.
|
||||
* Remarks: The resulting term is an array, such
|
||||
|
@ -2104,7 +2162,7 @@ public class Context implements AutoCloseable {
|
|||
/**
|
||||
* Create a range expression.
|
||||
*/
|
||||
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
|
||||
public ReExpr mkRange(SeqExpr lo, SeqExpr hi)
|
||||
{
|
||||
checkContextMatch(lo, hi);
|
||||
return (ReExpr) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
|
||||
|
|
|
@ -1881,6 +1881,17 @@ extern "C" {
|
|||
*/
|
||||
Z3_sort Z3_API Z3_mk_array_sort(Z3_context c, Z3_sort domain, Z3_sort range);
|
||||
|
||||
/**
|
||||
\brief Create an array type with N arguments
|
||||
|
||||
\sa Z3_mk_select_n
|
||||
\sa Z3_mk_store_n
|
||||
|
||||
def_API('Z3_mk_array_sort_n', SORT, (_in(CONTEXT), _in(UINT), _in_array(1, SORT), _in(SORT)))
|
||||
*/
|
||||
Z3_sort Z3_API Z3_mk_array_sort_n(Z3_context c, unsigned n, Z3_sort const * domain, Z3_sort range);
|
||||
|
||||
|
||||
/**
|
||||
\brief Create a tuple type.
|
||||
|
||||
|
@ -2973,6 +2984,15 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i);
|
||||
|
||||
/**
|
||||
\brief n-ary Array read.
|
||||
The argument \c a is the array and \c idxs are the indices of the array that gets read.
|
||||
|
||||
def_API('Z3_mk_select_n', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST)))
|
||||
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_select_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs);
|
||||
|
||||
/**
|
||||
\brief Array update.
|
||||
|
||||
|
@ -2991,6 +3011,14 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v);
|
||||
|
||||
/**
|
||||
\brief n-ary Array update.
|
||||
|
||||
def_API('Z3_mk_store_n', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST), _in(AST)))
|
||||
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_store_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs, Z3_ast v);
|
||||
|
||||
/**
|
||||
\brief Create the constant array.
|
||||
|
||||
|
@ -3031,6 +3059,15 @@ extern "C" {
|
|||
def_API('Z3_mk_array_default', AST, (_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_array_default(Z3_context c, Z3_ast array);
|
||||
|
||||
/**
|
||||
\brief Create array with the same interpretation as a function.
|
||||
The array satisfies the property (f x) = (select (_ as-array f) x)
|
||||
for every argument x.
|
||||
|
||||
def_API('Z3_mk_as_array', AST, (_in(CONTEXT), _in(FUNC_DECL)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_as_array(Z3_context c, Z3_func_decl f);
|
||||
/*@}*/
|
||||
|
||||
/** @name Sets */
|
||||
|
@ -3854,6 +3891,7 @@ extern "C" {
|
|||
|
||||
/**
|
||||
\brief Return the domain of the given array sort.
|
||||
In the case of a multi-dimensional array, this function returns the sort of the first dimension.
|
||||
|
||||
\pre Z3_get_sort_kind(c, t) == Z3_ARRAY_SORT
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ z3_add_component(ast
|
|||
ast_printer.cpp
|
||||
ast_smt2_pp.cpp
|
||||
ast_smt_pp.cpp
|
||||
ast_pp_dot.cpp
|
||||
ast_translation.cpp
|
||||
ast_util.cpp
|
||||
bv_decl_plugin.cpp
|
||||
|
|
|
@ -242,7 +242,9 @@ func_decl* array_decl_plugin::mk_select(unsigned arity, sort * const * domain) {
|
|||
parameter const* parameters = s->get_parameters();
|
||||
|
||||
if (num_parameters != arity) {
|
||||
m_manager->raise_exception("select requires as many arguments as the size of the domain");
|
||||
std::stringstream strm;
|
||||
strm << "select requires " << num_parameters << " arguments, but was provided with " << arity << " arguments";
|
||||
m_manager->raise_exception(strm.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
ptr_buffer<sort> new_domain; // we need this because of coercions.
|
||||
|
@ -314,7 +316,7 @@ func_decl * array_decl_plugin::mk_array_ext(unsigned arity, sort * const * domai
|
|||
return 0;
|
||||
}
|
||||
sort * r = to_sort(s->get_parameter(i).get_ast());
|
||||
parameter param(s);
|
||||
parameter param(i);
|
||||
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, func_decl_info(m_family_id, OP_ARRAY_EXT, 1, ¶m));
|
||||
}
|
||||
|
||||
|
@ -592,3 +594,9 @@ sort * array_util::mk_array_sort(unsigned arity, sort* const* domain, sort* rang
|
|||
params.push_back(parameter(range));
|
||||
return m_manager.mk_sort(m_fid, ARRAY_SORT, params.size(), params.c_ptr());
|
||||
}
|
||||
|
||||
func_decl* array_util::mk_array_ext(sort *domain, unsigned i) {
|
||||
sort * domains[2] = { domain, domain };
|
||||
parameter p(i);
|
||||
return m_manager.mk_func_decl(m_fid, OP_ARRAY_EXT, 1, &p, 2, domains);
|
||||
}
|
||||
|
|
|
@ -143,6 +143,7 @@ public:
|
|||
bool is_const(expr* n) const { return is_app_of(n, m_fid, OP_CONST_ARRAY); }
|
||||
bool is_map(expr* n) const { return is_app_of(n, m_fid, OP_ARRAY_MAP); }
|
||||
bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); }
|
||||
bool is_as_array(expr * n, func_decl*& f) const { return is_as_array(n) && (f = get_as_array_func_decl(n), true); }
|
||||
bool is_select(func_decl* f) const { return is_decl_of(f, m_fid, OP_SELECT); }
|
||||
bool is_store(func_decl* f) const { return is_decl_of(f, m_fid, OP_STORE); }
|
||||
bool is_const(func_decl* f) const { return is_decl_of(f, m_fid, OP_CONST_ARRAY); }
|
||||
|
@ -182,13 +183,15 @@ public:
|
|||
return mk_const_array(s, m_manager.mk_true());
|
||||
}
|
||||
|
||||
func_decl * mk_array_ext(sort* domain, unsigned i);
|
||||
|
||||
sort * mk_array_sort(sort* dom, sort* range) { return mk_array_sort(1, &dom, range); }
|
||||
|
||||
sort * mk_array_sort(unsigned arity, sort* const* domain, sort* range);
|
||||
|
||||
app * mk_as_array(sort * s, func_decl * f) {
|
||||
app * mk_as_array(func_decl * f) {
|
||||
parameter param(f);
|
||||
return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, ¶m, 0, 0, s);
|
||||
return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, ¶m, 0, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
111
src/ast/ast.cpp
111
src/ast/ast.cpp
|
@ -768,7 +768,7 @@ func_decl * basic_decl_plugin::mk_compressed_proof_decl(char const * name, basic
|
|||
|
||||
func_decl * basic_decl_plugin::mk_proof_decl(char const * name, basic_op_kind k, unsigned num_parents, ptr_vector<func_decl> & cache) {
|
||||
if (num_parents >= cache.size()) {
|
||||
cache.resize(num_parents+1, 0);
|
||||
cache.resize(num_parents+1);
|
||||
}
|
||||
if (cache[num_parents] == 0) {
|
||||
cache[num_parents] = mk_proof_decl(name, k, num_parents);
|
||||
|
@ -805,7 +805,6 @@ func_decl * basic_decl_plugin::mk_proof_decl(char const* name, basic_op_kind k,
|
|||
}
|
||||
|
||||
func_decl * basic_decl_plugin::mk_proof_decl(basic_op_kind k, unsigned num_parents) {
|
||||
SASSERT(k == PR_UNDEF || m_manager->proofs_enabled());
|
||||
switch (static_cast<basic_op_kind>(k)) {
|
||||
//
|
||||
// A description of the semantics of the proof
|
||||
|
@ -2631,7 +2630,7 @@ bool ast_manager::is_fully_interp(sort * s) const {
|
|||
// -----------------------------------
|
||||
|
||||
proof * ast_manager::mk_proof(family_id fid, decl_kind k, unsigned num_args, expr * const * args) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
return mk_app(fid, k, num_args, args);
|
||||
}
|
||||
|
@ -2667,8 +2666,7 @@ proof * ast_manager::mk_goal(expr * f) {
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_modus_ponens(proof * p1, proof * p2) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (!p1 || !p2) return nullptr;
|
||||
SASSERT(has_fact(p1));
|
||||
SASSERT(has_fact(p2));
|
||||
CTRACE("mk_modus_ponens", !(is_implies(get_fact(p2)) || is_iff(get_fact(p2)) || is_oeq(get_fact(p2))),
|
||||
|
@ -2689,14 +2687,10 @@ proof * ast_manager::mk_modus_ponens(proof * p1, proof * p2) {
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_reflexivity(expr * e) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_REFLEXIVITY, mk_eq(e, e));
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_oeq_reflexivity(expr * e) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_REFLEXIVITY, mk_oeq(e, e));
|
||||
}
|
||||
|
||||
|
@ -2710,8 +2704,7 @@ proof * ast_manager::mk_commutativity(app * f) {
|
|||
\brief Given a proof of p, return a proof of (p <=> true)
|
||||
*/
|
||||
proof * ast_manager::mk_iff_true(proof * pr) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (!pr) return pr;
|
||||
SASSERT(has_fact(pr));
|
||||
SASSERT(is_bool(get_fact(pr)));
|
||||
return mk_app(m_basic_family_id, PR_IFF_TRUE, pr, mk_iff(get_fact(pr), mk_true()));
|
||||
|
@ -2721,8 +2714,7 @@ proof * ast_manager::mk_iff_true(proof * pr) {
|
|||
\brief Given a proof of (not p), return a proof of (p <=> false)
|
||||
*/
|
||||
proof * ast_manager::mk_iff_false(proof * pr) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (!pr) return pr;
|
||||
SASSERT(has_fact(pr));
|
||||
SASSERT(is_not(get_fact(pr)));
|
||||
expr * p = to_app(get_fact(pr))->get_arg(0);
|
||||
|
@ -2730,10 +2722,7 @@ proof * ast_manager::mk_iff_false(proof * pr) {
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_symmetry(proof * p) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (!p)
|
||||
return p;
|
||||
if (!p) return p;
|
||||
if (is_reflexivity(p))
|
||||
return p;
|
||||
if (is_symmetry(p))
|
||||
|
@ -2746,8 +2735,6 @@ proof * ast_manager::mk_symmetry(proof * p) {
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_transitivity(proof * p1, proof * p2) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (!p1)
|
||||
return p2;
|
||||
if (!p2)
|
||||
|
@ -2792,8 +2779,6 @@ proof * ast_manager::mk_transitivity(proof * p1, proof * p2, proof * p3, proof *
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_transitivity(unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
SASSERT(num_proofs > 0);
|
||||
proof * r = proofs[0];
|
||||
for (unsigned i = 1; i < num_proofs; i++)
|
||||
|
@ -2802,11 +2787,8 @@ proof * ast_manager::mk_transitivity(unsigned num_proofs, proof * const * proofs
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_transitivity(unsigned num_proofs, proof * const * proofs, expr * n1, expr * n2) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (fine_grain_proofs())
|
||||
return mk_transitivity(num_proofs, proofs);
|
||||
SASSERT(num_proofs > 0);
|
||||
if (num_proofs == 0)
|
||||
return nullptr;
|
||||
if (num_proofs == 1)
|
||||
return proofs[0];
|
||||
DEBUG_CODE({
|
||||
|
@ -2822,8 +2804,6 @@ proof * ast_manager::mk_transitivity(unsigned num_proofs, proof * const * proofs
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_monotonicity(func_decl * R, app * f1, app * f2, unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
SASSERT(f1->get_num_args() == f2->get_num_args());
|
||||
SASSERT(f1->get_decl() == f2->get_decl());
|
||||
ptr_buffer<expr> args;
|
||||
|
@ -2833,8 +2813,6 @@ proof * ast_manager::mk_monotonicity(func_decl * R, app * f1, app * f2, unsigned
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_congruence(app * f1, app * f2, unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
SASSERT(get_sort(f1) == get_sort(f2));
|
||||
sort * s = get_sort(f1);
|
||||
sort * d[2] = { s, s };
|
||||
|
@ -2842,8 +2820,6 @@ proof * ast_manager::mk_congruence(app * f1, app * f2, unsigned num_proofs, proo
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_oeq_congruence(app * f1, app * f2, unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
SASSERT(get_sort(f1) == get_sort(f2));
|
||||
sort * s = get_sort(f1);
|
||||
sort * d[2] = { s, s };
|
||||
|
@ -2851,11 +2827,7 @@ proof * ast_manager::mk_oeq_congruence(app * f1, app * f2, unsigned num_proofs,
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_quant_intro(quantifier * q1, quantifier * q2, proof * p) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (!p) {
|
||||
return 0;
|
||||
}
|
||||
if (!p) return nullptr;
|
||||
SASSERT(q1->get_num_decls() == q2->get_num_decls());
|
||||
SASSERT(has_fact(p));
|
||||
SASSERT(is_iff(get_fact(p)));
|
||||
|
@ -2863,8 +2835,7 @@ proof * ast_manager::mk_quant_intro(quantifier * q1, quantifier * q2, proof * p)
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_oeq_quant_intro(quantifier * q1, quantifier * q2, proof * p) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (!p) return nullptr;
|
||||
SASSERT(q1->get_num_decls() == q2->get_num_decls());
|
||||
SASSERT(has_fact(p));
|
||||
SASSERT(is_oeq(get_fact(p)));
|
||||
|
@ -2872,25 +2843,26 @@ proof * ast_manager::mk_oeq_quant_intro(quantifier * q1, quantifier * q2, proof
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_distributivity(expr * s, expr * r) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_DISTRIBUTIVITY, mk_eq(s, r));
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_rewrite(expr * s, expr * t) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_REWRITE, mk_eq(s, t));
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_oeq_rewrite(expr * s, expr * t) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_REWRITE, mk_oeq(s, t));
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_rewrite_star(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
|
@ -2899,37 +2871,43 @@ proof * ast_manager::mk_rewrite_star(expr * s, expr * t, unsigned num_proofs, pr
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_pull_quant(expr * e, quantifier * q) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_PULL_QUANT, mk_iff(e, q));
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_pull_quant_star(expr * e, quantifier * q) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_PULL_QUANT_STAR, mk_iff(e, q));
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_push_quant(quantifier * q, expr * e) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_PUSH_QUANT, mk_iff(q, e));
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_elim_unused_vars(quantifier * q, expr * e) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_ELIM_UNUSED_VARS, mk_iff(q, e));
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_der(quantifier * q, expr * e) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_DER, mk_iff(q, e));
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_quant_inst(expr * not_q_or_i, unsigned num_bind, expr* const* binding) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
vector<parameter> params;
|
||||
for (unsigned i = 0; i < num_bind; ++i) {
|
||||
|
@ -2964,7 +2942,8 @@ bool ast_manager::is_rewrite(expr const* e, expr*& r1, expr*& r2) const {
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_def_axiom(expr * ax) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
SASSERT(proofs_enabled());
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_DEF_AXIOM, ax);
|
||||
}
|
||||
|
@ -3006,7 +2985,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
|
|||
new_lits.push_back(lit);
|
||||
}
|
||||
DEBUG_CODE({
|
||||
for (unsigned i = 1; m_proof_mode == PGM_FINE && i < num_proofs; i++) {
|
||||
for (unsigned i = 1; proofs_enabled() && i < num_proofs; i++) {
|
||||
CTRACE("mk_unit_resolution_bug", !found.get(i, false),
|
||||
for (unsigned j = 0; j < num_proofs; j++) {
|
||||
if (j == i) tout << "Index " << i << " was not found:\n";
|
||||
|
@ -3085,14 +3064,11 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_hypothesis(expr * h) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
return mk_app(m_basic_family_id, PR_HYPOTHESIS, h);
|
||||
}
|
||||
|
||||
proof * ast_manager::mk_lemma(proof * p, expr * lemma) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (!p) return p;
|
||||
SASSERT(has_fact(p));
|
||||
CTRACE("mk_lemma", !is_false(get_fact(p)), tout << mk_ll_pp(p, *this) << "\n";);
|
||||
SASSERT(is_false(get_fact(p)));
|
||||
|
@ -3105,7 +3081,7 @@ proof * ast_manager::mk_def_intro(expr * new_def) {
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_apply_defs(expr * n, expr * def, unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
|
@ -3114,10 +3090,7 @@ proof * ast_manager::mk_apply_defs(expr * n, expr * def, unsigned num_proofs, pr
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_iff_oeq(proof * p) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
return m_undef_proof;
|
||||
if (!p)
|
||||
return p;
|
||||
if (!p) return p;
|
||||
|
||||
SASSERT(has_fact(p));
|
||||
SASSERT(is_iff(get_fact(p)) || is_oeq(get_fact(p)));
|
||||
|
@ -3141,7 +3114,7 @@ bool ast_manager::check_nnf_proof_parents(unsigned num_proofs, proof * const * p
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_nnf_pos(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
check_nnf_proof_parents(num_proofs, proofs);
|
||||
ptr_buffer<expr> args;
|
||||
|
@ -3151,7 +3124,7 @@ proof * ast_manager::mk_nnf_pos(expr * s, expr * t, unsigned num_proofs, proof *
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_nnf_neg(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
check_nnf_proof_parents(num_proofs, proofs);
|
||||
ptr_buffer<expr> args;
|
||||
|
@ -3161,7 +3134,7 @@ proof * ast_manager::mk_nnf_neg(expr * s, expr * t, unsigned num_proofs, proof *
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_nnf_star(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
|
@ -3170,7 +3143,7 @@ proof * ast_manager::mk_nnf_star(expr * s, expr * t, unsigned num_proofs, proof
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_skolemization(expr * q, expr * e) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
SASSERT(is_bool(q));
|
||||
SASSERT(is_bool(e));
|
||||
|
@ -3178,7 +3151,7 @@ proof * ast_manager::mk_skolemization(expr * q, expr * e) {
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_cnf_star(expr * s, expr * t, unsigned num_proofs, proof * const * proofs) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
ptr_buffer<expr> args;
|
||||
args.append(num_proofs, (expr**) proofs);
|
||||
|
@ -3187,7 +3160,7 @@ proof * ast_manager::mk_cnf_star(expr * s, expr * t, unsigned num_proofs, proof
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_and_elim(proof * p, unsigned i) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
SASSERT(has_fact(p));
|
||||
SASSERT(is_and(get_fact(p)));
|
||||
|
@ -3198,7 +3171,7 @@ proof * ast_manager::mk_and_elim(proof * p, unsigned i) {
|
|||
}
|
||||
|
||||
proof * ast_manager::mk_not_or_elim(proof * p, unsigned i) {
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
SASSERT(has_fact(p));
|
||||
SASSERT(is_not(get_fact(p)));
|
||||
|
@ -3221,7 +3194,7 @@ proof * ast_manager::mk_th_lemma(
|
|||
unsigned num_params, parameter const* params
|
||||
)
|
||||
{
|
||||
if (m_proof_mode == PGM_DISABLED)
|
||||
if (proofs_disabled())
|
||||
return m_undef_proof;
|
||||
|
||||
ptr_buffer<expr> args;
|
||||
|
|
|
@ -121,6 +121,20 @@ public:
|
|||
explicit parameter(unsigned ext_id, bool):m_kind(PARAM_EXTERNAL), m_ext_id(ext_id) {}
|
||||
parameter(parameter const&);
|
||||
|
||||
parameter(parameter && other) : m_kind(other.m_kind) {
|
||||
switch (other.m_kind) {
|
||||
case PARAM_INT: m_int = other.get_int(); break;
|
||||
case PARAM_AST: m_ast = other.get_ast(); break;
|
||||
case PARAM_SYMBOL: m_symbol = other.m_symbol; break;
|
||||
case PARAM_RATIONAL: m_rational = 0; std::swap(m_rational, other.m_rational); break;
|
||||
case PARAM_DOUBLE: m_dval = other.m_dval; break;
|
||||
case PARAM_EXTERNAL: m_ext_id = other.m_ext_id; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
~parameter();
|
||||
|
||||
parameter& operator=(parameter const& other);
|
||||
|
@ -1382,8 +1396,7 @@ public:
|
|||
|
||||
enum proof_gen_mode {
|
||||
PGM_DISABLED,
|
||||
PGM_COARSE,
|
||||
PGM_FINE
|
||||
PGM_ENABLED
|
||||
};
|
||||
|
||||
// -----------------------------------
|
||||
|
@ -2076,15 +2089,14 @@ protected:
|
|||
proof * mk_proof(family_id fid, decl_kind k, expr * arg1, expr * arg2);
|
||||
proof * mk_proof(family_id fid, decl_kind k, expr * arg1, expr * arg2, expr * arg3);
|
||||
|
||||
proof * mk_undef_proof() const { return m_undef_proof; }
|
||||
|
||||
public:
|
||||
bool proofs_enabled() const { return m_proof_mode != PGM_DISABLED; }
|
||||
bool proofs_disabled() const { return m_proof_mode == PGM_DISABLED; }
|
||||
bool coarse_grain_proofs() const { return m_proof_mode == PGM_COARSE; }
|
||||
bool fine_grain_proofs() const { return m_proof_mode == PGM_FINE; }
|
||||
proof_gen_mode proof_mode() const { return m_proof_mode; }
|
||||
void toggle_proof_mode(proof_gen_mode m) { m_proof_mode = m; } // APIs for creating proof objects return [undef]
|
||||
|
||||
proof * mk_undef_proof() const { return m_undef_proof; }
|
||||
|
||||
bool is_proof(expr const * n) const { return is_app(n) && to_app(n)->get_decl()->get_range() == m_proof_sort; }
|
||||
|
||||
|
|
133
src/ast/ast_pp_dot.cpp
Normal file
133
src/ast/ast_pp_dot.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*++
|
||||
|
||||
Abstract: Pretty-printer for proofs in Graphviz format
|
||||
|
||||
--*/
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/map.h"
|
||||
#include "ast/ast_pp_dot.h"
|
||||
|
||||
// string escaping for DOT
|
||||
std::string escape_dot(std::string const & s) {
|
||||
std::string res;
|
||||
res.reserve(s.size()); // preallocate
|
||||
for (auto c : s) {
|
||||
if (c == '\n')
|
||||
res.append("\\l");
|
||||
else
|
||||
res.push_back(c);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// map from proofs to unique IDs
|
||||
typedef obj_map<const expr, unsigned> expr2id;
|
||||
|
||||
// temporary structure for traversing the proof and printing it
|
||||
struct ast_pp_dot_st {
|
||||
ast_manager & m_manager;
|
||||
std::ostream & m_out;
|
||||
const ast_pp_dot * m_pp;
|
||||
unsigned m_next_id;
|
||||
expr2id m_id_map;
|
||||
obj_hashtable<const expr> m_printed;
|
||||
svector<const expr *> m_to_print;
|
||||
bool m_first;
|
||||
|
||||
ast_pp_dot_st(const ast_pp_dot * pp, std::ostream & out) :
|
||||
m_manager(pp->get_manager()),
|
||||
m_out(out),
|
||||
m_pp(pp),
|
||||
m_next_id(0),
|
||||
m_id_map(),
|
||||
m_printed(),
|
||||
m_to_print(),
|
||||
m_first(true) {}
|
||||
|
||||
~ast_pp_dot_st() {};
|
||||
|
||||
void push_term(const expr * a) { m_to_print.push_back(a); }
|
||||
|
||||
void pp_loop() {
|
||||
// DFS traversal
|
||||
while (!m_to_print.empty()) {
|
||||
const expr * a = m_to_print.back();
|
||||
m_to_print.pop_back();
|
||||
if (!m_printed.contains(a)) {
|
||||
m_printed.insert(a);
|
||||
if (m().is_proof(a))
|
||||
pp_step(to_app(a));
|
||||
else
|
||||
pp_atomic_step(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
inline ast_manager & m() const { return m_manager; }
|
||||
|
||||
// label for an expression
|
||||
std::string label_of_expr(const expr * e) const {
|
||||
expr_ref er((expr*)e, m());
|
||||
std::ostringstream out;
|
||||
out << er << std::flush;
|
||||
return escape_dot(out.str());
|
||||
}
|
||||
|
||||
void pp_atomic_step(const expr * e) {
|
||||
unsigned id = get_id(e);
|
||||
m_out << "node_" << id << " [shape=box,color=\"yellow\",style=\"filled\",label=\"" << label_of_expr(e) << "\"] ;" << std::endl;
|
||||
}
|
||||
|
||||
void pp_step(const proof * p) {
|
||||
TRACE("pp_ast_dot_step", tout << " :kind " << p->get_kind() << " :num-args " << p->get_num_args() << "\n";);
|
||||
if (m().has_fact(p)) {
|
||||
// print result
|
||||
expr* p_res = m().get_fact(p); // result of proof step
|
||||
unsigned id = get_id(p);
|
||||
unsigned num_parents = m().get_num_parents(p);
|
||||
const char* color =
|
||||
m_first ? (m_first=false,"color=\"red\"") : num_parents==0 ? "color=\"yellow\"": "";
|
||||
m_out << "node_" << id <<
|
||||
" [shape=box,style=\"filled\",label=\"" << label_of_expr(p_res) << "\""
|
||||
<< color << "]" << std::endl;
|
||||
// now print edges to parents (except last one, which is the result)
|
||||
std::string label = p->get_decl()->get_name().str();
|
||||
for (unsigned i = 0 ; i < num_parents; ++i) {
|
||||
expr* parent = m().get_parent(p, i);
|
||||
// explore parent, also print a link to it
|
||||
push_term(to_app(parent));
|
||||
m_out << "node_" << id << " -> " << "node_" << get_id((expr*)parent)
|
||||
<< "[label=\"" << label << "\"];" << std::endl;;
|
||||
}
|
||||
} else {
|
||||
pp_atomic_step(p);
|
||||
}
|
||||
}
|
||||
|
||||
// find a unique ID for this proof
|
||||
unsigned get_id(const expr * e) {
|
||||
unsigned id = 0;
|
||||
if (!m_id_map.find(e, id)) {
|
||||
id = m_next_id++;
|
||||
m_id_map.insert(e, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// main printer
|
||||
std::ostream & ast_pp_dot::pp(std::ostream & out) const {
|
||||
out << "digraph proof { " << std::endl;
|
||||
ast_pp_dot_st pp_st(this, out);
|
||||
pp_st.push_term(m_pr);
|
||||
pp_st.pp_loop();
|
||||
out << std::endl << " } " << std::endl << std::flush;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const ast_pp_dot & p) { return p.pp(out); }
|
||||
|
24
src/ast/ast_pp_dot.h
Normal file
24
src/ast/ast_pp_dot.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*++
|
||||
|
||||
Abstract: Pretty-printer for proofs in Graphviz format
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include "ast_pp.h"
|
||||
|
||||
class ast_pp_dot {
|
||||
ast_manager & m_manager;
|
||||
proof * const m_pr;
|
||||
|
||||
public:
|
||||
ast_pp_dot(proof *pr, ast_manager &m) : m_manager(m), m_pr(pr) {}
|
||||
ast_pp_dot(proof_ref &e) : m_manager(e.m()), m_pr(e.get()) {}
|
||||
|
||||
std::ostream & pp(std::ostream & out) const;
|
||||
ast_manager & get_manager() const { return m_manager; }
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const ast_pp_dot & p);
|
|
@ -36,6 +36,26 @@ format * smt2_pp_environment::pp_fdecl_name(symbol const & s0, unsigned & len, b
|
|||
symbol s = m_renaming.get_symbol(s0, is_skolem);
|
||||
len = static_cast<unsigned>(strlen(s.bare_str()));
|
||||
return mk_string(m, s.bare_str());
|
||||
#if 0
|
||||
if (is_smt2_quoted_symbol(s)) {
|
||||
std::string str = mk_smt2_quoted_symbol(s);
|
||||
len = static_cast<unsigned>(str.length());
|
||||
return mk_string(m, str.c_str());
|
||||
}
|
||||
else if (s.is_numerical()) {
|
||||
std::string str = s.str();
|
||||
len = static_cast<unsigned>(str.length());
|
||||
return mk_string(m, str.c_str());
|
||||
}
|
||||
else if (!s.bare_str()) {
|
||||
len = 4;
|
||||
return mk_string(m, "null");
|
||||
}
|
||||
else {
|
||||
len = static_cast<unsigned>(strlen(s.bare_str()));
|
||||
return mk_string(m, s.bare_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
format * smt2_pp_environment::pp_fdecl_name(func_decl * f, unsigned & len) const {
|
||||
|
|
|
@ -863,8 +863,7 @@ app * bv_util::mk_numeral(rational const & val, sort* s) const {
|
|||
}
|
||||
|
||||
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
|
||||
parameter p1(val);
|
||||
parameter p[2] = { p1, parameter(static_cast<int>(bv_size)) };
|
||||
parameter p[2] = { parameter(val), parameter(static_cast<int>(bv_size)) };
|
||||
return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ public:
|
|||
m_trail_lim.resize(new_sz);
|
||||
}
|
||||
}
|
||||
unsigned scope_level() const { return m_trail_lim.size(); }
|
||||
bool empty() const { return m_subst.empty(); }
|
||||
expr* find(expr * e) { proof* pr; expr* d = 0; if (find(e, d, pr)) return d; else return e; }
|
||||
bool find(expr * s, expr * & def, proof * & def_pr) { return m_subst.find(s, def, def_pr); }
|
||||
|
|
|
@ -250,7 +250,7 @@ bv2fpa_converter::array_model bv2fpa_converter::convert_array_func_interp(model_
|
|||
am.new_float_fd = m.mk_fresh_func_decl(arity, array_domain.c_ptr(), rng);
|
||||
am.new_float_fi = convert_func_interp(mc, am.new_float_fd, bv_f);
|
||||
am.bv_fd = bv_f;
|
||||
am.result = arr_util.mk_as_array(f->get_range(), am.new_float_fd);
|
||||
am.result = arr_util.mk_as_array(am.new_float_fd);
|
||||
return am;
|
||||
}
|
||||
|
||||
|
|
|
@ -3076,8 +3076,6 @@ void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const *
|
|||
split_fp(x, sgn, e, s);
|
||||
mk_is_nan(x, x_is_nan);
|
||||
|
||||
sort * fp_srt = m.get_sort(x);
|
||||
|
||||
expr_ref unspec(m);
|
||||
mk_to_ieee_bv_unspecified(f, num, args, unspec);
|
||||
|
||||
|
|
|
@ -207,8 +207,8 @@ struct nnf::imp {
|
|||
unsigned m_new_child:1;
|
||||
unsigned m_cache_result:1;
|
||||
unsigned m_spos; // top of the result stack, when the frame was created.
|
||||
frame(expr_ref& n, bool pol, bool in_q, bool cache_res, unsigned spos):
|
||||
m_curr(n),
|
||||
frame(expr_ref && n, bool pol, bool in_q, bool cache_res, unsigned spos):
|
||||
m_curr(std::move(n)),
|
||||
m_i(0),
|
||||
m_pol(pol),
|
||||
m_in_q(in_q),
|
||||
|
@ -216,6 +216,16 @@ struct nnf::imp {
|
|||
m_cache_result(cache_res),
|
||||
m_spos(spos) {
|
||||
}
|
||||
frame(frame && other):
|
||||
m_curr(std::move(other.m_curr)),
|
||||
m_i(other.m_i),
|
||||
m_pol(other.m_pol),
|
||||
m_in_q(other.m_in_q),
|
||||
m_new_child(other.m_new_child),
|
||||
m_cache_result(other.m_cache_result),
|
||||
m_spos(other.m_spos) {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// There are four caches:
|
||||
|
@ -324,8 +334,7 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
void push_frame(expr * t, bool pol, bool in_q, bool cache_res) {
|
||||
expr_ref tr(t, m());
|
||||
m_frame_stack.push_back(frame(tr, pol, in_q, cache_res, m_result_stack.size()));
|
||||
m_frame_stack.push_back(frame(expr_ref(t, m()), pol, in_q, cache_res, m_result_stack.size()));
|
||||
}
|
||||
|
||||
static unsigned get_cache_idx(bool pol, bool in_q) {
|
||||
|
|
|
@ -229,7 +229,7 @@ struct pull_quant::imp {
|
|||
proofs.push_back(m_manager.mk_pull_quant(arg, to_quantifier(new_arg)));
|
||||
}
|
||||
pull_quant1(to_app(n)->get_decl(), new_args.size(), new_args.c_ptr(), r);
|
||||
if (m_manager.fine_grain_proofs()) {
|
||||
if (m_manager.proofs_enabled()) {
|
||||
app * r1 = m_manager.mk_app(to_app(n)->get_decl(), new_args.size(), new_args.c_ptr());
|
||||
proof * p1 = proofs.empty() ? 0 : m_manager.mk_congruence(to_app(n), r1, proofs.size(), proofs.c_ptr());
|
||||
proof * p2 = r1 == r ? 0 : m_manager.mk_pull_quant(r1, to_quantifier(r));
|
||||
|
@ -240,7 +240,7 @@ struct pull_quant::imp {
|
|||
expr_ref new_expr(m_manager);
|
||||
pull_quant1(to_quantifier(n)->get_expr(), new_expr);
|
||||
pull_quant1(to_quantifier(n), new_expr, r);
|
||||
if (m_manager.fine_grain_proofs()) {
|
||||
if (m_manager.proofs_enabled()) {
|
||||
quantifier * q1 = m_manager.update_quantifier(to_quantifier(n), new_expr);
|
||||
proof * p1 = 0;
|
||||
if (n != q1) {
|
||||
|
|
|
@ -179,11 +179,11 @@ expr_pattern_match::compile(expr* q)
|
|||
}
|
||||
|
||||
if (m_regs.size() <= max_reg) {
|
||||
m_regs.resize(max_reg+1, 0);
|
||||
m_regs.resize(max_reg+1);
|
||||
}
|
||||
if (m_bound_dom.size() <= num_bound) {
|
||||
m_bound_dom.resize(num_bound+1, 0);
|
||||
m_bound_rng.resize(num_bound+1, 0);
|
||||
m_bound_dom.resize(num_bound+1);
|
||||
m_bound_rng.resize(num_bound+1);
|
||||
}
|
||||
|
||||
instr.m_kind = YIELD;
|
||||
|
|
|
@ -606,7 +606,7 @@ bool pattern_inference_cfg::reduce_quantifier(
|
|||
result = m.update_quantifier_weight(tmp, new_weight);
|
||||
TRACE("pattern_inference", tout << "found patterns in database, weight: " << new_weight << "\n" << mk_pp(new_q, m) << "\n";);
|
||||
}
|
||||
if (m.fine_grain_proofs())
|
||||
if (m.proofs_enabled())
|
||||
result_pr = m.mk_rewrite(q, new_q);
|
||||
return true;
|
||||
}
|
||||
|
@ -671,7 +671,7 @@ bool pattern_inference_cfg::reduce_quantifier(
|
|||
quantifier_ref new_q(m.update_quantifier(q, new_patterns.size(), (expr**) new_patterns.c_ptr(), new_body), m);
|
||||
if (weight != q->get_weight())
|
||||
new_q = m.update_quantifier_weight(new_q, weight);
|
||||
if (m.fine_grain_proofs()) {
|
||||
if (m.proofs_enabled()) {
|
||||
proof* new_body_pr = m.mk_reflexivity(new_body);
|
||||
result_pr = m.mk_quant_intro(q, new_q, new_body_pr);
|
||||
}
|
||||
|
@ -689,7 +689,7 @@ bool pattern_inference_cfg::reduce_quantifier(
|
|||
warning_msg("pulled nested quantifier to be able to find an useable pattern (quantifier id: %s)", q->get_qid().str().c_str());
|
||||
}
|
||||
new_q = m.update_quantifier(result2, new_patterns.size(), (expr**) new_patterns.c_ptr(), result2->get_expr());
|
||||
if (m.fine_grain_proofs()) {
|
||||
if (m.proofs_enabled()) {
|
||||
result_pr = m.mk_transitivity(new_pr, m.mk_quant_intro(result2, new_q, m.mk_reflexivity(new_q->get_expr())));
|
||||
}
|
||||
TRACE("pattern_inference", tout << "pulled quantifier:\n" << mk_pp(new_q, m) << "\n";);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
z3_add_component(proof_checker
|
||||
z3_add_component(proofs
|
||||
SOURCES
|
||||
proof_checker.cpp
|
||||
proof_utils.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
rewriter
|
||||
)
|
|
@ -4,10 +4,9 @@ Copyright (c) 2015 Microsoft Corporation
|
|||
|
||||
--*/
|
||||
|
||||
#include "ast/proof_checker/proof_checker.h"
|
||||
#include "ast/proofs/proof_checker.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
// include "spc_decl_plugin.h"
|
||||
#include "ast/ast_smt_pp.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
|
@ -1,15 +1,343 @@
|
|||
|
||||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
Copyright (c) 2017 Arie Gurfinkel
|
||||
|
||||
Module Name:
|
||||
|
||||
proof_utils.cpp
|
||||
|
||||
Abstract:
|
||||
Utilities to traverse and manipulate proofs
|
||||
|
||||
Author:
|
||||
Bernhard Gleiss
|
||||
Arie Gurfinkel
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "muz/base/dl_util.h"
|
||||
#include "muz/base/proof_utils.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/proofs/proof_utils.h"
|
||||
#include "ast/proofs/proof_checker.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "util/container_util.h"
|
||||
|
||||
|
||||
proof_post_order::proof_post_order(proof* root, ast_manager& manager) : m(manager)
|
||||
{m_todo.push_back(root);}
|
||||
|
||||
bool proof_post_order::hasNext()
|
||||
{return !m_todo.empty();}
|
||||
|
||||
/*
|
||||
* iterative post-order depth-first search (DFS) through the proof DAG
|
||||
*/
|
||||
proof* proof_post_order::next()
|
||||
{
|
||||
while (!m_todo.empty()) {
|
||||
proof* currentNode = m_todo.back();
|
||||
|
||||
// if we haven't already visited the current unit
|
||||
if (!m_visited.is_marked(currentNode)) {
|
||||
bool existsUnvisitedParent = false;
|
||||
|
||||
// add unprocessed premises to stack for DFS.
|
||||
// If there is at least one unprocessed premise, don't compute the result
|
||||
// for currentProof now, but wait until those unprocessed premises are processed.
|
||||
for (unsigned i = 0; i < m.get_num_parents(currentNode); ++i) {
|
||||
SASSERT(m.is_proof(currentNode->get_arg(i)));
|
||||
proof* premise = to_app(currentNode->get_arg(i));
|
||||
|
||||
// if we haven't visited the current premise yet
|
||||
if (!m_visited.is_marked(premise)) {
|
||||
// add it to the stack
|
||||
m_todo.push_back(premise);
|
||||
existsUnvisitedParent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if we already visited all parent-inferences, we can visit the inference too
|
||||
if (!existsUnvisitedParent) {
|
||||
m_visited.mark(currentNode, true);
|
||||
m_todo.pop_back();
|
||||
return currentNode;
|
||||
}
|
||||
} else {
|
||||
m_todo.pop_back();
|
||||
}
|
||||
}
|
||||
// we have already iterated through all inferences
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
class reduce_hypotheses {
|
||||
ast_manager &m;
|
||||
// tracking all created expressions
|
||||
expr_ref_vector m_pinned;
|
||||
|
||||
// cache for the transformation
|
||||
obj_map<proof, proof*> m_cache;
|
||||
|
||||
// map from unit literals to their hypotheses-free derivations
|
||||
obj_map<expr, proof*> m_units;
|
||||
|
||||
// -- all hypotheses in the the proof
|
||||
obj_hashtable<expr> m_hyps;
|
||||
|
||||
// marks hypothetical proofs
|
||||
ast_mark m_hypmark;
|
||||
|
||||
|
||||
// stack
|
||||
ptr_vector<proof> m_todo;
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_cache.reset();
|
||||
m_units.reset();
|
||||
m_hyps.reset();
|
||||
m_hypmark.reset();
|
||||
m_pinned.reset();
|
||||
}
|
||||
|
||||
bool compute_mark1(proof *pr)
|
||||
{
|
||||
bool hyp_mark = false;
|
||||
// lemmas clear all hypotheses
|
||||
if (!m.is_lemma(pr)) {
|
||||
for (unsigned i = 0, sz = m.get_num_parents(pr); i < sz; ++i) {
|
||||
if (m_hypmark.is_marked(m.get_parent(pr, i))) {
|
||||
hyp_mark = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_hypmark.mark(pr, hyp_mark);
|
||||
return hyp_mark;
|
||||
}
|
||||
|
||||
void compute_marks(proof* pr) {
|
||||
proof *p;
|
||||
proof_post_order pit(pr, m);
|
||||
while (pit.hasNext()) {
|
||||
p = pit.next();
|
||||
if (m.is_hypothesis(p)) {
|
||||
m_hypmark.mark(p, true);
|
||||
m_hyps.insert(m.get_fact(p));
|
||||
}
|
||||
else {
|
||||
bool hyp_mark = compute_mark1(p);
|
||||
// collect units that are hyp-free and are used as hypotheses somewhere
|
||||
if (!hyp_mark && m.has_fact(p) && m_hyps.contains(m.get_fact(p))) {
|
||||
m_units.insert(m.get_fact(p), p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void find_units(proof *pr)
|
||||
{
|
||||
// optional. not implemented yet.
|
||||
}
|
||||
|
||||
void reduce(proof* pf, proof_ref &out)
|
||||
{
|
||||
proof *res = NULL;
|
||||
|
||||
m_todo.reset();
|
||||
m_todo.push_back(pf);
|
||||
ptr_buffer<proof> args;
|
||||
bool dirty = false;
|
||||
|
||||
while (!m_todo.empty()) {
|
||||
proof *p, *tmp, *pp;
|
||||
unsigned todo_sz;
|
||||
|
||||
p = m_todo.back();
|
||||
if (m_cache.find(p, tmp)) {
|
||||
res = tmp;
|
||||
m_todo.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
dirty = false;
|
||||
args.reset();
|
||||
todo_sz = m_todo.size();
|
||||
for (unsigned i = 0, sz = m.get_num_parents(p); i < sz; ++i) {
|
||||
pp = m.get_parent(p, i);
|
||||
if (m_cache.find(pp, tmp)) {
|
||||
args.push_back(tmp);
|
||||
dirty = dirty || pp != tmp;
|
||||
} else {
|
||||
m_todo.push_back(pp);
|
||||
}
|
||||
}
|
||||
|
||||
if (todo_sz < m_todo.size()) { continue; }
|
||||
else { m_todo.pop_back(); }
|
||||
|
||||
if (m.is_hypothesis(p)) {
|
||||
// hyp: replace by a corresponding unit
|
||||
if (m_units.find(m.get_fact(p), tmp)) {
|
||||
res = tmp;
|
||||
} else { res = p; }
|
||||
}
|
||||
|
||||
else if (!dirty) { res = p; }
|
||||
|
||||
else if (m.is_lemma(p)) {
|
||||
//lemma: reduce the premise; remove reduced consequences from conclusion
|
||||
SASSERT(args.size() == 1);
|
||||
res = mk_lemma_core(args.get(0), m.get_fact(p));
|
||||
compute_mark1(res);
|
||||
} else if (m.is_unit_resolution(p)) {
|
||||
// unit: reduce untis; reduce the first premise; rebuild unit resolution
|
||||
res = mk_unit_resolution_core(args.size(), args.c_ptr());
|
||||
compute_mark1(res);
|
||||
} else {
|
||||
// other: reduce all premises; reapply
|
||||
if (m.has_fact(p)) { args.push_back(to_app(m.get_fact(p))); }
|
||||
SASSERT(p->get_decl()->get_arity() == args.size());
|
||||
res = m.mk_app(p->get_decl(), args.size(), (expr * const*)args.c_ptr());
|
||||
m_pinned.push_back(res);
|
||||
compute_mark1(res);
|
||||
}
|
||||
|
||||
SASSERT(res);
|
||||
m_cache.insert(p, res);
|
||||
|
||||
if (m.has_fact(res) && m.is_false(m.get_fact(res))) { break; }
|
||||
}
|
||||
|
||||
out = res;
|
||||
}
|
||||
|
||||
// returns true if (hypothesis (not a)) would be reduced
|
||||
bool is_reduced(expr *a)
|
||||
{
|
||||
expr_ref e(m);
|
||||
if (m.is_not(a)) { e = to_app(a)->get_arg(0); }
|
||||
else { e = m.mk_not(a); }
|
||||
|
||||
return m_units.contains(e);
|
||||
}
|
||||
|
||||
proof *mk_lemma_core(proof *pf, expr *fact)
|
||||
{
|
||||
ptr_buffer<expr> args;
|
||||
expr_ref lemma(m);
|
||||
|
||||
if (m.is_or(fact)) {
|
||||
for (unsigned i = 0, sz = to_app(fact)->get_num_args(); i < sz; ++i) {
|
||||
expr *a = to_app(fact)->get_arg(i);
|
||||
if (!is_reduced(a))
|
||||
{ args.push_back(a); }
|
||||
}
|
||||
} else if (!is_reduced(fact))
|
||||
{ args.push_back(fact); }
|
||||
|
||||
|
||||
if (args.size() == 0) { return pf; }
|
||||
else if (args.size() == 1) {
|
||||
lemma = args.get(0);
|
||||
} else {
|
||||
lemma = m.mk_or(args.size(), args.c_ptr());
|
||||
}
|
||||
proof* res = m.mk_lemma(pf, lemma);
|
||||
m_pinned.push_back(res);
|
||||
|
||||
if (m_hyps.contains(lemma))
|
||||
{ m_units.insert(lemma, res); }
|
||||
return res;
|
||||
}
|
||||
|
||||
proof *mk_unit_resolution_core(unsigned num_args, proof* const *args)
|
||||
{
|
||||
|
||||
ptr_buffer<proof> pf_args;
|
||||
pf_args.push_back(args [0]);
|
||||
|
||||
app *cls_fact = to_app(m.get_fact(args[0]));
|
||||
ptr_buffer<expr> cls;
|
||||
if (m.is_or(cls_fact)) {
|
||||
for (unsigned i = 0, sz = cls_fact->get_num_args(); i < sz; ++i)
|
||||
{ cls.push_back(cls_fact->get_arg(i)); }
|
||||
} else { cls.push_back(cls_fact); }
|
||||
|
||||
// construct new resovent
|
||||
ptr_buffer<expr> new_fact_cls;
|
||||
bool found;
|
||||
// XXX quadratic
|
||||
for (unsigned i = 0, sz = cls.size(); i < sz; ++i) {
|
||||
found = false;
|
||||
for (unsigned j = 1; j < num_args; ++j) {
|
||||
if (m.is_complement(cls.get(i), m.get_fact(args [j]))) {
|
||||
found = true;
|
||||
pf_args.push_back(args [j]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
new_fact_cls.push_back(cls.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
SASSERT(new_fact_cls.size() + pf_args.size() - 1 == cls.size());
|
||||
expr_ref new_fact(m);
|
||||
new_fact = mk_or(m, new_fact_cls.size(), new_fact_cls.c_ptr());
|
||||
|
||||
// create new proof step
|
||||
proof *res = m.mk_unit_resolution(pf_args.size(), pf_args.c_ptr(), new_fact);
|
||||
m_pinned.push_back(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
// reduce all units, if any unit reduces to false return true and put its proof into out
|
||||
bool reduce_units(proof_ref &out)
|
||||
{
|
||||
proof_ref res(m);
|
||||
for (auto entry : m_units) {
|
||||
reduce(entry.get_value(), res);
|
||||
if (m.is_false(m.get_fact(res))) {
|
||||
out = res;
|
||||
return true;
|
||||
}
|
||||
res.reset();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
reduce_hypotheses(ast_manager &m) : m(m), m_pinned(m) {}
|
||||
|
||||
|
||||
void operator()(proof_ref &pr)
|
||||
{
|
||||
compute_marks(pr);
|
||||
if (!reduce_units(pr)) {
|
||||
reduce(pr.get(), pr);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
void reduce_hypotheses(proof_ref &pr) {
|
||||
ast_manager &m = pr.get_manager();
|
||||
class reduce_hypotheses hypred(m);
|
||||
hypred(pr);
|
||||
DEBUG_CODE(proof_checker pc(m);
|
||||
expr_ref_vector side(m);
|
||||
SASSERT(pc.check(pr, side));
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
|
||||
class reduce_hypotheses0 {
|
||||
typedef obj_hashtable<expr> expr_set;
|
||||
ast_manager& m;
|
||||
// reference for any expression created by the tranformation
|
||||
|
@ -85,7 +413,7 @@ class reduce_hypotheses {
|
|||
m_hyprefs.push_back(hyps);
|
||||
inherited = false;
|
||||
}
|
||||
datalog::set_union(*hyps, *hyps1);
|
||||
set_union(*hyps, *hyps1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +465,7 @@ class reduce_hypotheses {
|
|||
}
|
||||
|
||||
public:
|
||||
reduce_hypotheses(ast_manager& m): m(m), m_refs(m) {}
|
||||
reduce_hypotheses0(ast_manager& m): m(m), m_refs(m) {}
|
||||
|
||||
void operator()(proof_ref& pr) {
|
||||
proof_ref tmp(m);
|
||||
|
@ -416,7 +744,7 @@ public:
|
|||
|
||||
void proof_utils::reduce_hypotheses(proof_ref& pr) {
|
||||
ast_manager& m = pr.get_manager();
|
||||
class reduce_hypotheses reduce(m);
|
||||
class reduce_hypotheses0 reduce(m);
|
||||
reduce(pr);
|
||||
CTRACE("proof_utils", !is_closed(m, pr), tout << mk_pp(pr, m) << "\n";);
|
||||
}
|
238
src/ast/proofs/proof_utils.h
Normal file
238
src/ast/proofs/proof_utils.h
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
proof_utils.h
|
||||
|
||||
Abstract:
|
||||
Utilities to traverse and manipulate proofs
|
||||
|
||||
Author:
|
||||
Bernhard Gleiss
|
||||
Arie Gurfinkel
|
||||
Nikolaj Bjorner
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef PROOF_UTILS_H_
|
||||
#define PROOF_UTILS_H_
|
||||
#include "ast/ast.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/rewriter/bool_rewriter.h"
|
||||
#include "ast/proofs/proof_checker.h"
|
||||
|
||||
/*
|
||||
* iterator, which traverses the proof in depth-first post-order.
|
||||
*/
|
||||
|
||||
class proof_post_order {
|
||||
public:
|
||||
proof_post_order(proof* refutation, ast_manager& manager);
|
||||
bool hasNext();
|
||||
proof* next();
|
||||
|
||||
private:
|
||||
ptr_vector<proof> m_todo;
|
||||
ast_mark m_visited; // the proof nodes we have already visited
|
||||
ast_manager& m;
|
||||
};
|
||||
|
||||
void reduce_hypotheses(proof_ref &pr);
|
||||
|
||||
|
||||
class proof_utils {
|
||||
public:
|
||||
/**
|
||||
\brief reduce the set of hypotheses used in the proof.
|
||||
*/
|
||||
static void reduce_hypotheses(proof_ref& pr);
|
||||
|
||||
/**
|
||||
\brief Check that a proof does not contain open hypotheses.
|
||||
*/
|
||||
static bool is_closed(ast_manager& m, proof* p);
|
||||
|
||||
/**
|
||||
\brief Permute unit resolution rule with th-lemma
|
||||
*/
|
||||
static void permute_unit_resolution(proof_ref& pr);
|
||||
|
||||
/**
|
||||
\brief Push instantiations created in hyper-resolutions up to leaves.
|
||||
This produces a "ground" proof where leaves are annotated by instantiations.
|
||||
*/
|
||||
static void push_instantiations_up(proof_ref& pr);
|
||||
|
||||
|
||||
};
|
||||
|
||||
class elim_aux_assertions {
|
||||
|
||||
static bool matches_fact(expr_ref_vector &args, expr* &match) {
|
||||
ast_manager &m = args.get_manager();
|
||||
expr *fact = args.back();
|
||||
for (unsigned i = 0, sz = args.size() - 1; i < sz; ++i) {
|
||||
expr *arg = args.get(i);
|
||||
if (m.is_proof(arg) &&
|
||||
m.has_fact(to_app(arg)) &&
|
||||
m.get_fact(to_app(arg)) == fact) {
|
||||
match = arg;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
app_ref m_aux;
|
||||
public:
|
||||
elim_aux_assertions(app_ref aux) : m_aux(aux) {}
|
||||
|
||||
void mk_or_core(expr_ref_vector &args, expr_ref &res)
|
||||
{
|
||||
ast_manager &m = args.get_manager();
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0, sz = args.size(); i < sz; ++i) {
|
||||
if (m.is_false(args.get(i))) { continue; }
|
||||
if (i != j) { args [j] = args.get(i); }
|
||||
++j;
|
||||
}
|
||||
SASSERT(j >= 1);
|
||||
res = j > 1 ? m.mk_or(j, args.c_ptr()) : args.get(0);
|
||||
}
|
||||
|
||||
void mk_app(func_decl *decl, expr_ref_vector &args, expr_ref &res)
|
||||
{
|
||||
ast_manager &m = args.get_manager();
|
||||
bool_rewriter brwr(m);
|
||||
|
||||
if (m.is_or(decl))
|
||||
{ mk_or_core(args, res); }
|
||||
else if (m.is_iff(decl) && args.size() == 2)
|
||||
// avoiding simplifying equalities. In particular,
|
||||
// we don't want (= (not a) (not b)) to be reduced to (= a b)
|
||||
{ res = m.mk_iff(args.get(0), args.get(1)); }
|
||||
else
|
||||
{ brwr.mk_app(decl, args.size(), args.c_ptr(), res); }
|
||||
}
|
||||
|
||||
void operator()(ast_manager &m, proof *pr, proof_ref &res)
|
||||
{
|
||||
DEBUG_CODE(proof_checker pc(m);
|
||||
expr_ref_vector side(m);
|
||||
SASSERT(pc.check(pr, side));
|
||||
);
|
||||
obj_map<app, app*> cache;
|
||||
bool_rewriter brwr(m);
|
||||
|
||||
// for reference counting of new proofs
|
||||
app_ref_vector pinned(m);
|
||||
|
||||
ptr_vector<app> todo;
|
||||
todo.push_back(pr);
|
||||
|
||||
expr_ref not_aux(m);
|
||||
not_aux = m.mk_not(m_aux);
|
||||
|
||||
expr_ref_vector args(m);
|
||||
|
||||
while (!todo.empty()) {
|
||||
app *p, *r;
|
||||
expr *a;
|
||||
|
||||
p = todo.back();
|
||||
if (cache.find(pr, r)) {
|
||||
todo.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
SASSERT(!todo.empty() || pr == p);
|
||||
bool dirty = false;
|
||||
unsigned todo_sz = todo.size();
|
||||
args.reset();
|
||||
for (unsigned i = 0, sz = p->get_num_args(); i < sz; ++i) {
|
||||
expr* arg = p->get_arg(i);
|
||||
if (arg == m_aux.get()) {
|
||||
dirty = true;
|
||||
args.push_back(m.mk_true());
|
||||
} else if (arg == not_aux.get()) {
|
||||
dirty = true;
|
||||
args.push_back(m.mk_false());
|
||||
}
|
||||
// skip (asserted m_aux)
|
||||
else if (m.is_asserted(arg, a) && a == m_aux.get()) {
|
||||
dirty = true;
|
||||
}
|
||||
// skip (hypothesis m_aux)
|
||||
else if (m.is_hypothesis(arg, a) && a == m_aux.get()) {
|
||||
dirty = true;
|
||||
} else if (is_app(arg) && cache.find(to_app(arg), r)) {
|
||||
dirty |= (arg != r);
|
||||
args.push_back(r);
|
||||
} else if (is_app(arg))
|
||||
{ todo.push_back(to_app(arg)); }
|
||||
else
|
||||
// -- not an app
|
||||
{ args.push_back(arg); }
|
||||
|
||||
}
|
||||
if (todo_sz < todo.size()) {
|
||||
// -- process parents
|
||||
args.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
// ready to re-create
|
||||
app_ref newp(m);
|
||||
if (!dirty) { newp = p; }
|
||||
else if (m.is_unit_resolution(p)) {
|
||||
if (args.size() == 2)
|
||||
// unit resolution with m_aux that got collapsed to nothing
|
||||
{ newp = to_app(args.get(0)); }
|
||||
else {
|
||||
ptr_vector<proof> parents;
|
||||
for (unsigned i = 0, sz = args.size() - 1; i < sz; ++i)
|
||||
{ parents.push_back(to_app(args.get(i))); }
|
||||
SASSERT(parents.size() == args.size() - 1);
|
||||
newp = m.mk_unit_resolution(parents.size(), parents.c_ptr());
|
||||
// XXX the old and new facts should be
|
||||
// equivalent. The test here is much
|
||||
// stronger. It might need to be relaxed.
|
||||
SASSERT(m.get_fact(newp) == args.back());
|
||||
pinned.push_back(newp);
|
||||
}
|
||||
} else if (matches_fact(args, a)) {
|
||||
newp = to_app(a);
|
||||
} else {
|
||||
expr_ref papp(m);
|
||||
mk_app(p->get_decl(), args, papp);
|
||||
newp = to_app(papp.get());
|
||||
pinned.push_back(newp);
|
||||
}
|
||||
cache.insert(p, newp);
|
||||
todo.pop_back();
|
||||
CTRACE("virtual",
|
||||
p->get_decl_kind() == PR_TH_LEMMA &&
|
||||
p->get_decl()->get_parameter(0).get_symbol() == "arith" &&
|
||||
p->get_decl()->get_num_parameters() > 1 &&
|
||||
p->get_decl()->get_parameter(1).get_symbol() == "farkas",
|
||||
tout << "Old pf: " << mk_pp(p, m) << "\n"
|
||||
<< "New pf: " << mk_pp(newp, m) << "\n";);
|
||||
}
|
||||
|
||||
proof *r;
|
||||
VERIFY(cache.find(pr, r));
|
||||
|
||||
DEBUG_CODE(
|
||||
proof_checker pc(m);
|
||||
expr_ref_vector side(m);
|
||||
SASSERT(pc.check(r, side));
|
||||
);
|
||||
|
||||
res = r ;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -272,7 +272,7 @@ void bit_blaster_tpl<Cfg>::mk_multiplier(unsigned sz, expr * const * a_bits, exp
|
|||
zero = m().mk_false();
|
||||
|
||||
vector< expr_ref_vector > pps;
|
||||
pps.resize(sz, m());
|
||||
pps.resize(sz, expr_ref_vector(m()));
|
||||
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
checkpoint();
|
||||
|
|
|
@ -119,17 +119,15 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
|
|||
// BV -> float
|
||||
SASSERT(bvs1 == sbits + ebits);
|
||||
unsynch_mpz_manager & mpzm = m_fm.mpz_manager();
|
||||
unsynch_mpq_manager & mpqm = m_fm.mpq_manager();
|
||||
scoped_mpz sig(mpzm), exp(mpzm);
|
||||
|
||||
const mpz & sm1 = m_fm.m_powers2(sbits - 1);
|
||||
const mpz & em1 = m_fm.m_powers2(ebits);
|
||||
|
||||
scoped_mpq q(mpqm);
|
||||
mpqm.set(q, r1.to_mpq());
|
||||
SASSERT(mpzm.is_one(q.get().denominator()));
|
||||
const mpq & q = r1.to_mpq();
|
||||
SASSERT(mpzm.is_one(q.denominator()));
|
||||
scoped_mpz z(mpzm);
|
||||
z = q.get().numerator();
|
||||
z = q.numerator();
|
||||
|
||||
mpzm.rem(z, sm1, sig);
|
||||
mpzm.div(z, sm1, z);
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
|
||||
class scoped_proof : public scoped_proof_mode {
|
||||
public:
|
||||
scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_FINE) {}
|
||||
scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_ENABLED) {}
|
||||
};
|
||||
|
||||
class scoped_no_proof : public scoped_proof_mode {
|
||||
|
|
|
@ -256,7 +256,7 @@ void substitution_tree::insert(expr * new_expr) {
|
|||
sort * s = to_var(new_expr)->get_sort();
|
||||
unsigned id = s->get_decl_id();
|
||||
if (id >= m_vars.size())
|
||||
m_vars.resize(id+1, 0);
|
||||
m_vars.resize(id+1);
|
||||
if (m_vars[id] == 0)
|
||||
m_vars[id] = alloc(var_ref_vector, m_manager);
|
||||
var_ref_vector * v = m_vars[id];
|
||||
|
@ -277,7 +277,7 @@ void substitution_tree::insert(app * new_expr) {
|
|||
unsigned id = d->get_decl_id();
|
||||
|
||||
if (id >= m_roots.size())
|
||||
m_roots.resize(id+1, 0);
|
||||
m_roots.resize(id+1);
|
||||
|
||||
if (!m_roots[id]) {
|
||||
// there is no tree for the function symbol heading new_expr
|
||||
|
|
|
@ -58,7 +58,7 @@ void used_vars::process(expr * n, unsigned delta) {
|
|||
if (idx >= delta) {
|
||||
idx = idx - delta;
|
||||
if (idx >= m_found_vars.size())
|
||||
m_found_vars.resize(idx + 1, 0);
|
||||
m_found_vars.resize(idx + 1);
|
||||
m_found_vars[idx] = to_var(n)->get_sort();
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -20,6 +20,7 @@ Notes:
|
|||
#include "util/version.h"
|
||||
#include "ast/ast_smt_pp.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_pp_dot.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/pp.h"
|
||||
|
@ -202,6 +203,26 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", {
|
|||
}
|
||||
});
|
||||
|
||||
ATOMIC_CMD(get_proof_graph_cmd, "get-proof-graph", "retrieve proof and print it in graphviz", {
|
||||
if (!ctx.produce_proofs())
|
||||
throw cmd_exception("proof construction is not enabled, use command (set-option :produce-proofs true)");
|
||||
if (!ctx.has_manager() ||
|
||||
ctx.cs_state() != cmd_context::css_unsat)
|
||||
throw cmd_exception("proof is not available");
|
||||
proof_ref pr(ctx.m());
|
||||
pr = ctx.get_check_sat_result()->get_proof();
|
||||
if (pr == 0)
|
||||
throw cmd_exception("proof is not available");
|
||||
if (ctx.well_sorted_check_enabled() && !is_well_sorted(ctx.m(), pr)) {
|
||||
throw cmd_exception("proof is not well sorted");
|
||||
}
|
||||
|
||||
context_params& params = ctx.params();
|
||||
const std::string& file = params.m_dot_proof_file;
|
||||
std::ofstream out(file);
|
||||
out << ast_pp_dot(pr) << std::endl;
|
||||
});
|
||||
|
||||
static void print_core(cmd_context& ctx) {
|
||||
ptr_vector<expr> core;
|
||||
ctx.get_check_sat_result()->get_unsat_core(core);
|
||||
|
@ -840,6 +861,7 @@ void install_basic_cmds(cmd_context & ctx) {
|
|||
ctx.insert(alloc(get_assignment_cmd));
|
||||
ctx.insert(alloc(get_assertions_cmd));
|
||||
ctx.insert(alloc(get_proof_cmd));
|
||||
ctx.insert(alloc(get_proof_graph_cmd));
|
||||
ctx.insert(alloc(get_unsat_core_cmd));
|
||||
ctx.insert(alloc(set_option_cmd));
|
||||
ctx.insert(alloc(get_option_cmd));
|
||||
|
|
|
@ -492,6 +492,7 @@ cmd_context::~cmd_context() {
|
|||
finalize_tactic_cmds();
|
||||
finalize_probes();
|
||||
reset(true);
|
||||
m_mc0 = 0;
|
||||
m_solver = 0;
|
||||
m_check_sat_result = 0;
|
||||
}
|
||||
|
@ -775,7 +776,6 @@ bool cmd_context::is_func_decl(symbol const & s) const {
|
|||
}
|
||||
|
||||
void cmd_context::insert(symbol const & s, func_decl * f) {
|
||||
m_check_sat_result = 0;
|
||||
if (!m_check_logic(f)) {
|
||||
throw cmd_exception(m_check_logic.get_last_error());
|
||||
}
|
||||
|
@ -806,7 +806,6 @@ void cmd_context::insert(symbol const & s, func_decl * f) {
|
|||
}
|
||||
|
||||
void cmd_context::insert(symbol const & s, psort_decl * p) {
|
||||
m_check_sat_result = 0;
|
||||
if (m_psort_decls.contains(s)) {
|
||||
throw cmd_exception("sort already defined ", s);
|
||||
}
|
||||
|
@ -820,7 +819,6 @@ void cmd_context::insert(symbol const & s, psort_decl * p) {
|
|||
|
||||
void cmd_context::insert(symbol const & s, unsigned arity, sort *const* domain, expr * t) {
|
||||
expr_ref _t(t, m());
|
||||
m_check_sat_result = 0;
|
||||
if (m_builtin_decls.contains(s)) {
|
||||
throw cmd_exception("invalid macro/named expression, builtin symbol ", s);
|
||||
}
|
||||
|
@ -1081,16 +1079,31 @@ void cmd_context::mk_app(symbol const & s, unsigned num_args, expr * const * arg
|
|||
if (fs.more_than_one())
|
||||
throw cmd_exception("ambiguous constant reference, more than one constant with the same sort, use a qualified expression (as <symbol> <sort>) to disumbiguate ", s);
|
||||
func_decl * f = fs.first();
|
||||
if (f == 0)
|
||||
if (f == 0) {
|
||||
throw cmd_exception("unknown constant ", s);
|
||||
}
|
||||
if (f->get_arity() != 0)
|
||||
throw cmd_exception("invalid function application, missing arguments ", s);
|
||||
result = m().mk_const(f);
|
||||
}
|
||||
else {
|
||||
func_decl * f = fs.find(m(), num_args, args, range);
|
||||
if (f == 0)
|
||||
throw cmd_exception("unknown constant ", s);
|
||||
if (f == 0) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "unknown constant " << s << " ";
|
||||
buffer << " (";
|
||||
bool first = true;
|
||||
for (unsigned i = 0; i < num_args; ++i, first = false) {
|
||||
if (!first) buffer << " ";
|
||||
buffer << mk_pp(m().get_sort(args[i]), m());
|
||||
}
|
||||
buffer << ") ";
|
||||
if (range) buffer << mk_pp(range, m()) << " ";
|
||||
for (unsigned i = 0; i < fs.get_num_entries(); ++i) {
|
||||
buffer << "\ndeclared: " << mk_pp(fs.get_entry(i), m()) << " ";
|
||||
}
|
||||
throw cmd_exception(buffer.str().c_str());
|
||||
}
|
||||
if (well_sorted_check_enabled())
|
||||
m().check_sort(f, num_args, args);
|
||||
result = m().mk_app(f, num_args, args);
|
||||
|
@ -1250,8 +1263,8 @@ void cmd_context::reset(bool finalize) {
|
|||
reset_macros();
|
||||
reset_func_decls();
|
||||
restore_assertions(0);
|
||||
if (m_solver)
|
||||
m_solver = 0;
|
||||
m_mc0 = 0;
|
||||
m_scopes.reset();
|
||||
m_opt = 0;
|
||||
m_pp_env = 0;
|
||||
|
@ -1624,7 +1637,9 @@ void cmd_context::validate_check_sat_result(lbool r) {
|
|||
throw cmd_exception("check annotation that says unsat");
|
||||
#else
|
||||
diagnostic_stream() << "BUG: incompleteness" << std::endl;
|
||||
exit(ERR_INCOMPLETENESS);
|
||||
// WORKAROUND: `exit()` causes LSan to be invoked and produce
|
||||
// many false positives.
|
||||
_Exit(ERR_INCOMPLETENESS);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -1634,7 +1649,9 @@ void cmd_context::validate_check_sat_result(lbool r) {
|
|||
throw cmd_exception("check annotation that says sat");
|
||||
#else
|
||||
diagnostic_stream() << "BUG: unsoundness" << std::endl;
|
||||
exit(ERR_UNSOUNDNESS);
|
||||
// WORKAROUND: `exit()` causes LSan to be invoked and produce
|
||||
// many false positives.
|
||||
_Exit(ERR_UNSOUNDNESS);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -194,6 +194,7 @@ protected:
|
|||
|
||||
static std::ostringstream g_error_stream;
|
||||
|
||||
generic_model_converter_ref m_mc0;
|
||||
ast_manager * m_manager;
|
||||
bool m_own_manager;
|
||||
bool m_manager_initialized;
|
||||
|
@ -304,7 +305,6 @@ protected:
|
|||
void erase_macro(symbol const& s);
|
||||
bool macros_find(symbol const& s, unsigned n, expr*const* args, expr*& t) const;
|
||||
|
||||
generic_model_converter_ref m_mc0;
|
||||
|
||||
public:
|
||||
cmd_context(bool main_ctx = true, ast_manager * m = 0, symbol const & l = symbol::null);
|
||||
|
|
|
@ -111,6 +111,9 @@ void context_params::set(char const * param, char const * value) {
|
|||
else if (p == "trace_file_name") {
|
||||
m_trace_file_name = value;
|
||||
}
|
||||
else if (p == "dot_proof_file") {
|
||||
m_dot_proof_file = value;
|
||||
}
|
||||
else if (p == "unsat_core") {
|
||||
set_bool(m_unsat_core, param, value);
|
||||
}
|
||||
|
@ -146,6 +149,7 @@ void context_params::updt_params(params_ref const & p) {
|
|||
m_dump_models = p.get_bool("dump_models", m_dump_models);
|
||||
m_trace = p.get_bool("trace", m_trace);
|
||||
m_trace_file_name = p.get_str("trace_file_name", "z3.log");
|
||||
m_dot_proof_file = p.get_str("dot_proof_file", "proof.dot");
|
||||
m_unsat_core = p.get_bool("unsat_core", m_unsat_core);
|
||||
m_debug_ref_count = p.get_bool("debug_ref_count", m_debug_ref_count);
|
||||
m_smtlib2_compliant = p.get_bool("smtlib2_compliant", m_smtlib2_compliant);
|
||||
|
@ -161,6 +165,7 @@ void context_params::collect_param_descrs(param_descrs & d) {
|
|||
d.insert("dump_models", CPK_BOOL, "dump models whenever check-sat returns sat", "false");
|
||||
d.insert("trace", CPK_BOOL, "trace generation for VCC", "false");
|
||||
d.insert("trace_file_name", CPK_STRING, "trace out file name (see option 'trace')", "z3.log");
|
||||
d.insert("dot_proof_file", CPK_STRING, "file in which to output graphical proofs", "proof.dot");
|
||||
d.insert("debug_ref_count", CPK_BOOL, "debug support for AST reference counting", "false");
|
||||
d.insert("smtlib2_compliant", CPK_BOOL, "enable/disable SMT-LIB 2.0 compliance", "false");
|
||||
collect_solver_param_descrs(d);
|
||||
|
@ -192,7 +197,7 @@ void context_params::get_solver_params(ast_manager const & m, params_ref & p, bo
|
|||
|
||||
ast_manager * context_params::mk_ast_manager() {
|
||||
ast_manager * r = alloc(ast_manager,
|
||||
m_proof ? PGM_FINE : PGM_DISABLED,
|
||||
m_proof ? PGM_ENABLED : PGM_DISABLED,
|
||||
m_trace ? m_trace_file_name.c_str() : 0);
|
||||
if (m_smtlib2_compliant)
|
||||
r->enable_int_real_coercions(false);
|
||||
|
|
|
@ -30,6 +30,7 @@ class context_params {
|
|||
public:
|
||||
bool m_auto_config;
|
||||
bool m_proof;
|
||||
std::string m_dot_proof_file;
|
||||
bool m_interpolants;
|
||||
bool m_debug_ref_count;
|
||||
bool m_trace;
|
||||
|
|
|
@ -147,7 +147,7 @@ static void compute_interpolant_and_maybe_check(cmd_context & ctx, expr * t, par
|
|||
ast_manager &_m = ctx.m();
|
||||
// TODO: the following is a HACK to enable proofs in the old smt solver
|
||||
// When we stop using that solver, this hack can be removed
|
||||
scoped_proof_mode spm(_m,PGM_FINE);
|
||||
scoped_proof_mode spm(_m,PGM_ENABLED);
|
||||
ctx.params().get_solver_params(_m, p, proofs_enabled, models_enabled, unsat_core_enabled);
|
||||
p.set_bool("proof", true);
|
||||
scoped_ptr<solver> sp = (ctx.get_interpolating_solver_factory())(_m, p, true, models_enabled, false, ctx.get_logic());
|
||||
|
|
|
@ -57,9 +57,9 @@ typedef ast raw_ast;
|
|||
|
||||
/** Wrapper around an ast pointer */
|
||||
class ast_i {
|
||||
protected:
|
||||
protected:
|
||||
raw_ast *_ast;
|
||||
public:
|
||||
public:
|
||||
raw_ast * const &raw() const {return _ast;}
|
||||
ast_i(raw_ast *a){_ast = a;}
|
||||
|
||||
|
@ -86,7 +86,7 @@ class ast_i {
|
|||
/** Reference counting verison of above */
|
||||
class ast_r : public ast_i {
|
||||
ast_manager *_m;
|
||||
public:
|
||||
public:
|
||||
ast_r(ast_manager *m, raw_ast *a) : ast_i(a) {
|
||||
_m = m;
|
||||
m->inc_ref(a);
|
||||
|
@ -108,7 +108,7 @@ class ast_r : public ast_i {
|
|||
return *this;
|
||||
}
|
||||
|
||||
~ast_r(){
|
||||
~ast_r() {
|
||||
if(_ast)
|
||||
_m->dec_ref(_ast);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "interp/iz3profiling.h"
|
||||
#include "interp/iz3interp.h"
|
||||
#include "interp/iz3proof_itp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
@ -1851,6 +1852,21 @@ public:
|
|||
}
|
||||
break;
|
||||
}
|
||||
case PR_TRANSITIVITY_STAR: {
|
||||
// assume the premises are x = y, y = z, z = u, u = v, ..
|
||||
|
||||
ast x = arg(conc(prem(proof,0)),0);
|
||||
ast y = arg(conc(prem(proof,0)),1);
|
||||
ast z = arg(conc(prem(proof,1)),1);
|
||||
res = iproof->make_transitivity(x,y,z,args[0],args[1]);
|
||||
|
||||
for (unsigned i = 2; i < nprems; ++i) {
|
||||
y = z;
|
||||
z = arg(conc(prem(proof,i)),1);
|
||||
res = iproof->make_transitivity(x,y,z,res,args[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PR_QUANT_INTRO:
|
||||
case PR_MONOTONICITY:
|
||||
{
|
||||
|
@ -2029,6 +2045,7 @@ public:
|
|||
break;
|
||||
}
|
||||
default:
|
||||
IF_VERBOSE(0, verbose_stream() << "Unsupported proof rule: " << expr_ref((expr*)proof.raw(), *proof.mgr()) << "\n";);
|
||||
// pfgoto(proof);
|
||||
// SASSERT(0 && "translate_main: unsupported proof rule");
|
||||
throw unsupported();
|
||||
|
|
|
@ -36,7 +36,7 @@ class iz3translation : public iz3base {
|
|||
|
||||
/** This is thrown when the proof cannot be translated. */
|
||||
struct unsupported: public iz3_exception {
|
||||
unsupported(): iz3_exception("unsupported") {}
|
||||
unsupported(): iz3_exception("unsupported") { }
|
||||
};
|
||||
|
||||
static iz3translation *create(iz3mgr &mgr,
|
||||
|
|
|
@ -24,6 +24,7 @@ Revision History:
|
|||
|
||||
#include "math/automata/symbolic_automata.h"
|
||||
#include "util/hashtable.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
|
||||
|
||||
|
@ -311,7 +312,7 @@ symbolic_automata<T, M>::mk_determinstic_param(automaton_t& a, bool flip_accepta
|
|||
s2id.insert(set, p_state_id++); // the index to the initial state is 0
|
||||
id2s.push_back(set);
|
||||
|
||||
svector<uint_set> todo; //States to visit
|
||||
::vector<uint_set> todo; //States to visit
|
||||
todo.push_back(set);
|
||||
|
||||
uint_set state;
|
||||
|
|
|
@ -162,7 +162,7 @@ private:
|
|||
void checkpoint();
|
||||
|
||||
public:
|
||||
interval_manager(reslimit& lim, C const & c);
|
||||
interval_manager(reslimit& lim, C && c);
|
||||
~interval_manager();
|
||||
|
||||
numeral_manager & m() const { return m_c.m(); }
|
||||
|
|
|
@ -31,7 +31,7 @@ Revision History:
|
|||
// #define TRACE_NTH_ROOT
|
||||
|
||||
template<typename C>
|
||||
interval_manager<C>::interval_manager(reslimit& lim, C const & c): m_limit(lim), m_c(c) {
|
||||
interval_manager<C>::interval_manager(reslimit& lim, C && c): m_limit(lim), m_c(std::move(c)) {
|
||||
m().set(m_minus_one, -1);
|
||||
m().set(m_one, 1);
|
||||
m_pi_n = 0;
|
||||
|
|
|
@ -2632,10 +2632,14 @@ namespace algebraic_numbers {
|
|||
scoped_mpz neg_n(qm());
|
||||
qm().set(neg_n, v.numerator());
|
||||
qm().neg(neg_n);
|
||||
mpz const coeffs[2] = { neg_n.get(), v.denominator() };
|
||||
unsynch_mpz_manager zmgr;
|
||||
// FIXME: remove these copies
|
||||
mpz coeffs[2] = { zmgr.dup(neg_n.get()), zmgr.dup(v.denominator()) };
|
||||
out << "(";
|
||||
upm().display(out, 2, coeffs, "#");
|
||||
out << ", 1)"; // first root of the polynomial d*# - n
|
||||
zmgr.del(coeffs[0]);
|
||||
zmgr.del(coeffs[1]);
|
||||
}
|
||||
else {
|
||||
algebraic_cell * c = a.to_algebraic();
|
||||
|
@ -2678,10 +2682,14 @@ namespace algebraic_numbers {
|
|||
scoped_mpz neg_n(qm());
|
||||
qm().set(neg_n, v.numerator());
|
||||
qm().neg(neg_n);
|
||||
mpz const coeffs[2] = { neg_n.get(), v.denominator() };
|
||||
unsynch_mpz_manager zmgr;
|
||||
// FIXME: remove these copies
|
||||
mpz coeffs[2] = { zmgr.dup(neg_n.get()), zmgr.dup(v.denominator()) };
|
||||
out << "(root-obj ";
|
||||
upm().display_smt2(out, 2, coeffs, "x");
|
||||
out << " 1)"; // first root of the polynomial d*# - n
|
||||
zmgr.del(coeffs[0]);
|
||||
zmgr.del(coeffs[1]);
|
||||
}
|
||||
else {
|
||||
algebraic_cell * c = a.to_algebraic();
|
||||
|
|
|
@ -3536,10 +3536,11 @@ namespace polynomial {
|
|||
iccp(p, max_var(p), i, c, pp);
|
||||
}
|
||||
|
||||
void pp(polynomial const * p, var x, polynomial_ref & pp) {
|
||||
polynomial_ref pp(polynomial const * p, var x) {
|
||||
scoped_numeral i(m_manager);
|
||||
polynomial_ref c(pm());
|
||||
iccp(p, x, i, c, pp);
|
||||
polynomial_ref c(pm()), result(pm());
|
||||
iccp(p, x, i, c, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool is_primitive(polynomial const * p, var x) {
|
||||
|
@ -3598,7 +3599,7 @@ namespace polynomial {
|
|||
if (is_zero(rem)) {
|
||||
TRACE("polynomial", tout << "rem is zero...\npp_v: " << pp_v << "\n";);
|
||||
flip_sign_if_lm_neg(pp_v);
|
||||
pp(pp_v, x, r);
|
||||
r = pp(pp_v, x);
|
||||
r = mul(d_a, d_r, r);
|
||||
return;
|
||||
}
|
||||
|
@ -3849,7 +3850,7 @@ namespace polynomial {
|
|||
TRACE("mgcd", tout << "new combined:\n" << C_star << "\n";);
|
||||
}
|
||||
}
|
||||
pp(C_star, x, candidate);
|
||||
candidate = pp(C_star, x);
|
||||
TRACE("mgcd", tout << "candidate:\n" << candidate << "\n";);
|
||||
scoped_numeral lc_candidate(m());
|
||||
lc_candidate = univ_coeff(candidate, degree(candidate, x));
|
||||
|
@ -4821,10 +4822,9 @@ namespace polynomial {
|
|||
|
||||
polynomial * mk_x_minus_y(var x, var y) {
|
||||
numeral zero(0);
|
||||
numeral one(1);
|
||||
numeral minus_one; // It is not safe to initialize with -1 when numeral_manager is GF_2
|
||||
m_manager.set(minus_one, -1);
|
||||
numeral as[2] = { one, minus_one };
|
||||
numeral as[2] = { numeral(1), std::move(minus_one) };
|
||||
var xs[2] = { x, y };
|
||||
return mk_linear(2, as, xs, zero);
|
||||
}
|
||||
|
@ -4844,8 +4844,7 @@ namespace polynomial {
|
|||
|
||||
polynomial * mk_x_plus_y(var x, var y) {
|
||||
numeral zero(0);
|
||||
numeral one(1);
|
||||
numeral as[2] = { one, one };
|
||||
numeral as[2] = { numeral(1), numeral(1) };
|
||||
var xs[2] = { x, y };
|
||||
return mk_linear(2, as, xs, zero);
|
||||
}
|
||||
|
@ -6619,8 +6618,8 @@ namespace polynomial {
|
|||
polynomial_ref cf1(pm()); m_wrapper.content(f1, x, cf1);
|
||||
polynomial_ref cf2(pm()); m_wrapper.content(f2, x, cf2);
|
||||
tout << "content(f1): " << cf1 << "\ncontent(f2): " << cf2 << "\n";);
|
||||
pp(f1, x, f1);
|
||||
pp(f2, x, f2);
|
||||
f1 = pp(f1, x);
|
||||
f2 = pp(f2, x);
|
||||
TRACE("factor", tout << "f1: " << f1 << "\nf2: " << f2 << "\n";);
|
||||
DEBUG_CODE({
|
||||
polynomial_ref f1f2(pm());
|
||||
|
@ -7150,7 +7149,7 @@ namespace polynomial {
|
|||
}
|
||||
|
||||
void manager::primitive(polynomial const * p, var x, polynomial_ref & pp) {
|
||||
m_imp->pp(p, x, pp);
|
||||
pp = m_imp->pp(p, x);
|
||||
}
|
||||
|
||||
void manager::icpp(polynomial const * p, var x, numeral & i, polynomial_ref & c, polynomial_ref & pp) {
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace upolynomial {
|
|||
for (unsigned i = 0; i < p.size(); ++ i) {
|
||||
numeral p_i; // no need to delete, we keep it pushed in zp_p
|
||||
zp_nm.set(p_i, p[i]);
|
||||
zp_p.push_back(p_i);
|
||||
zp_p.push_back(std::move(p_i));
|
||||
}
|
||||
zp_upm.trim(zp_p);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace simplex {
|
|||
struct row_entry {
|
||||
numeral m_coeff;
|
||||
var_t m_var;
|
||||
row_entry(numeral const& c, var_t v): m_coeff(c), m_var(v) {}
|
||||
row_entry(numeral && c, var_t v) : m_coeff(std::move(c)), m_var(v) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -61,7 +61,7 @@ namespace simplex {
|
|||
int m_col_idx;
|
||||
int m_next_free_row_entry_idx;
|
||||
};
|
||||
_row_entry(numeral const & c, var_t v): row_entry(c, v), m_col_idx(0) {}
|
||||
_row_entry(numeral && c, var_t v) : row_entry(std::move(c), v), m_col_idx(0) {}
|
||||
_row_entry() : row_entry(numeral(), dead_id), m_col_idx(0) {}
|
||||
bool is_dead() const { return row_entry::m_var == dead_id; }
|
||||
};
|
||||
|
|
|
@ -739,7 +739,7 @@ void context_t<C>::del_sum(polynomial * p) {
|
|||
|
||||
template<typename C>
|
||||
var context_t<C>::mk_sum(numeral const & c, unsigned sz, numeral const * as, var const * xs) {
|
||||
m_num_buffer.reserve(num_vars(), numeral());
|
||||
m_num_buffer.reserve(num_vars());
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
SASSERT(xs[i] < num_vars());
|
||||
nm().set(m_num_buffer[xs[i]], as[i]);
|
||||
|
|
|
@ -117,7 +117,7 @@ bool func_interp::is_fi_entry_expr(expr * e, ptr_vector<expr> & args) {
|
|||
(m_arity > 1 && (!m().is_and(c) || to_app(c)->get_num_args() != m_arity)))
|
||||
return false;
|
||||
|
||||
args.resize(m_arity, 0);
|
||||
args.resize(m_arity);
|
||||
for (unsigned i = 0; i < m_arity; i++) {
|
||||
expr * ci = (m_arity == 1 && i == 0) ? c : to_app(c)->get_arg(i);
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ z3_add_component(muz
|
|||
dl_rule_transformer.cpp
|
||||
dl_util.cpp
|
||||
hnf.cpp
|
||||
proof_utils.cpp
|
||||
rule_properties.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
aig_tactic
|
||||
|
|
|
@ -53,7 +53,7 @@ Example from Boogie:
|
|||
|
||||
#include "muz/base/dl_boogie_proof.h"
|
||||
#include "model/model_pp.h"
|
||||
#include "muz/base/proof_utils.h"
|
||||
#include "ast/proofs/proof_utils.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
|
||||
|
|
|
@ -454,6 +454,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
void context::add_rule(expr* rl, symbol const& name, unsigned bound) {
|
||||
SASSERT(rl);
|
||||
m_rule_fmls.push_back(rl);
|
||||
m_rule_names.push_back(name);
|
||||
m_rule_bounds.push_back(bound);
|
||||
|
@ -461,7 +462,7 @@ namespace datalog {
|
|||
|
||||
void context::flush_add_rules() {
|
||||
datalog::rule_manager& rm = get_rule_manager();
|
||||
scoped_proof_mode _scp(m, generate_proof_trace()?PGM_FINE:PGM_DISABLED);
|
||||
scoped_proof_mode _scp(m, generate_proof_trace()?PGM_ENABLED:PGM_DISABLED);
|
||||
while (m_rule_fmls_head < m_rule_fmls.size()) {
|
||||
expr* fml = m_rule_fmls[m_rule_fmls_head].get();
|
||||
proof* p = generate_proof_trace()?m.mk_asserted(fml):0;
|
||||
|
|
|
@ -141,7 +141,7 @@ namespace datalog {
|
|||
|
||||
|
||||
void rule_manager::mk_rule(expr* fml, proof* p, rule_set& rules, symbol const& name) {
|
||||
scoped_proof_mode _sc(m, m_ctx.generate_proof_trace()?PGM_FINE:PGM_DISABLED);
|
||||
scoped_proof_mode _sc(m, m_ctx.generate_proof_trace()?PGM_ENABLED:PGM_DISABLED);
|
||||
proof_ref pr(p, m);
|
||||
expr_ref fml1(m);
|
||||
bind_variables(fml, true, fml1);
|
||||
|
@ -343,7 +343,7 @@ namespace datalog {
|
|||
}
|
||||
TRACE("dl", tout << rule_expr << "\n";);
|
||||
|
||||
scoped_proof_mode _sc(m, m_ctx.generate_proof_trace()?PGM_FINE:PGM_DISABLED);
|
||||
scoped_proof_mode _sc(m, m_ctx.generate_proof_trace()?PGM_ENABLED:PGM_DISABLED);
|
||||
proof_ref pr(m);
|
||||
if (m_ctx.generate_proof_trace()) {
|
||||
pr = m.mk_asserted(rule_expr);
|
||||
|
|
|
@ -11,7 +11,7 @@ Abstract:
|
|||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2010-05-20.
|
||||
Krystof Hoder 2010
|
||||
|
||||
Revision History:
|
||||
|
||||
|
@ -31,6 +31,7 @@ Revision History:
|
|||
#include "util/statistics.h"
|
||||
#include "util/stopwatch.h"
|
||||
#include "util/lbool.h"
|
||||
#include "util/container_util.h"
|
||||
|
||||
namespace datalog {
|
||||
|
||||
|
@ -381,129 +382,6 @@ namespace datalog {
|
|||
*/
|
||||
void apply_subst(expr_ref_vector& tgt, expr_ref_vector const& sub);
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// container functions
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
template<class Set1, class Set2>
|
||||
void set_intersection(Set1 & tgt, const Set2 & src) {
|
||||
svector<typename Set1::data> to_remove;
|
||||
typename Set1::iterator vit = tgt.begin();
|
||||
typename Set1::iterator vend = tgt.end();
|
||||
for(;vit!=vend;++vit) {
|
||||
typename Set1::data itm=*vit;
|
||||
if(!src.contains(itm)) {
|
||||
to_remove.push_back(itm);
|
||||
}
|
||||
}
|
||||
while(!to_remove.empty()) {
|
||||
tgt.remove(to_remove.back());
|
||||
to_remove.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
template<class Set>
|
||||
void set_difference(Set & tgt, const Set & to_remove) {
|
||||
typename Set::iterator vit = to_remove.begin();
|
||||
typename Set::iterator vend = to_remove.end();
|
||||
for(;vit!=vend;++vit) {
|
||||
typename Set::data itm=*vit;
|
||||
tgt.remove(itm);
|
||||
}
|
||||
}
|
||||
|
||||
template<class Set1, class Set2>
|
||||
void set_union(Set1 & tgt, const Set2 & to_add) {
|
||||
typename Set2::iterator vit = to_add.begin();
|
||||
typename Set2::iterator vend = to_add.end();
|
||||
for(;vit!=vend;++vit) {
|
||||
typename Set1::data itm=*vit;
|
||||
tgt.insert(itm);
|
||||
}
|
||||
}
|
||||
|
||||
void idx_set_union(idx_set & tgt, const idx_set & src);
|
||||
|
||||
template<class T>
|
||||
void unite_disjoint_maps(T & tgt, const T & src) {
|
||||
typename T::iterator it = src.begin();
|
||||
typename T::iterator end = src.end();
|
||||
for(; it!=end; ++it) {
|
||||
SASSERT(!tgt.contains(it->m_key));
|
||||
tgt.insert(it->m_key, it->m_value);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void collect_map_range(T & acc, const U & map) {
|
||||
typename U::iterator it = map.begin();
|
||||
typename U::iterator end = map.end();
|
||||
for(; it!=end; ++it) {
|
||||
acc.push_back(it->m_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void print_container(const T & begin, const T & end, std::ostream & out) {
|
||||
T it = begin;
|
||||
out << "(";
|
||||
bool first = true;
|
||||
for(; it!=end; ++it) {
|
||||
if(first) { first = false; } else { out << ","; }
|
||||
out << (*it);
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void print_container(const T & cont, std::ostream & out) {
|
||||
print_container(cont.begin(), cont.end(), out);
|
||||
}
|
||||
|
||||
template<class T, class M>
|
||||
void print_container(const ref_vector<T,M> & cont, std::ostream & out) {
|
||||
print_container(cont.c_ptr(), cont.c_ptr() + cont.size(), out);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void print_map(const T & cont, std::ostream & out) {
|
||||
typename T::iterator it = cont.begin();
|
||||
typename T::iterator end = cont.end();
|
||||
out << "(";
|
||||
bool first = true;
|
||||
for(; it!=end; ++it) {
|
||||
if(first) { first = false; } else { out << ","; }
|
||||
out << it->m_key << "->" << it->m_value;
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
|
||||
template<class It, class V>
|
||||
unsigned find_index(const It & begin, const It & end, const V & val) {
|
||||
unsigned idx = 0;
|
||||
It it = begin;
|
||||
for(; it!=end; it++, idx++) {
|
||||
if(*it==val) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
bool containers_equal(const T & begin1, const T & end1, const U & begin2, const U & end2) {
|
||||
T it1 = begin1;
|
||||
U it2 = begin2;
|
||||
for(; it1!=end1 && it2!=end2; ++it1, ++it2) {
|
||||
if(*it1!=*it2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return it1==end1 && it2==end2;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
bool vectors_equal(const T & c1, const U & c2) {
|
||||
|
@ -521,6 +399,8 @@ namespace datalog {
|
|||
return true;
|
||||
}
|
||||
|
||||
void idx_set_union(idx_set & tgt, const idx_set & src);
|
||||
|
||||
template<class T>
|
||||
struct default_obj_chash {
|
||||
unsigned operator()(T const& cont, unsigned i) const {
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
proof_utils.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Utilities for transforming proofs.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-10-12.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef PROOF_UTILS_H_
|
||||
#define PROOF_UTILS_H_
|
||||
|
||||
class proof_utils {
|
||||
public:
|
||||
/**
|
||||
\brief reduce the set of hypotheses used in the proof.
|
||||
*/
|
||||
static void reduce_hypotheses(proof_ref& pr);
|
||||
|
||||
/**
|
||||
\brief Check that a proof does not contain open hypotheses.
|
||||
*/
|
||||
static bool is_closed(ast_manager& m, proof* p);
|
||||
|
||||
/**
|
||||
\brief Permute unit resolution rule with th-lemma
|
||||
*/
|
||||
static void permute_unit_resolution(proof_ref& pr);
|
||||
|
||||
/**
|
||||
\brief Push instantiations created in hyper-resolutions up to leaves.
|
||||
This produces a "ground" proof where leaves are annotated by instantiations.
|
||||
*/
|
||||
static void push_instantiations_up(proof_ref& pr);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -189,11 +189,12 @@ public:
|
|||
m_bound = bound;
|
||||
m_arg_idx++;
|
||||
}
|
||||
virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); }
|
||||
virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); m_t = nullptr; }
|
||||
virtual void prepare(cmd_context& ctx) { m_arg_idx = 0; m_name = symbol::null; m_bound = UINT_MAX; }
|
||||
virtual void finalize(cmd_context & ctx) {
|
||||
}
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
if (!m_t) throw cmd_exception("invalid rule, expected formula");
|
||||
m_dl_ctx->add_rule(m_t, m_name, m_bound);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -41,9 +41,8 @@ Notes:
|
|||
#include "ast/ast_smt2_pp.h"
|
||||
#include "qe/qe_lite.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/proof_checker/proof_checker.h"
|
||||
#include "ast/proofs/proof_checker.h"
|
||||
#include "smt/smt_value_sort.h"
|
||||
#include "muz/base/proof_utils.h"
|
||||
#include "muz/base/dl_boogie_proof.h"
|
||||
#include "ast/scoped_proof.h"
|
||||
#include "tactic/core/blast_term_ite_tactic.h"
|
||||
|
@ -1825,7 +1824,7 @@ namespace pdr {
|
|||
m_core_generalizers.push_back(alloc(core_multi_generalizer, *this, 0));
|
||||
}
|
||||
if (!classify.is_bool()) {
|
||||
m.toggle_proof_mode(PGM_FINE);
|
||||
m.toggle_proof_mode(PGM_ENABLED);
|
||||
m_fparams.m_arith_bound_prop = BP_NONE;
|
||||
m_fparams.m_arith_auto_config_simplex = true;
|
||||
m_fparams.m_arith_propagate_eqs = false;
|
||||
|
|
|
@ -31,7 +31,7 @@ Revision History:
|
|||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "tactic/arith/arith_bounds_tactic.h"
|
||||
#include "muz/base/proof_utils.h"
|
||||
#include "ast/proofs/proof_utils.h"
|
||||
#include "ast/reg_decl_plugins.h"
|
||||
|
||||
|
||||
|
@ -372,7 +372,7 @@ namespace pdr {
|
|||
|
||||
farkas_learner::farkas_learner(smt_params& params, ast_manager& outer_mgr)
|
||||
: m_proof_params(get_proof_params(params)),
|
||||
m_pr(PGM_FINE),
|
||||
m_pr(PGM_ENABLED),
|
||||
m_constr(0),
|
||||
m_combine_farkas_coefficients(true),
|
||||
p2o(m_pr, outer_mgr),
|
||||
|
@ -733,8 +733,8 @@ namespace pdr {
|
|||
}
|
||||
else {
|
||||
expr_set* hyps3 = alloc(expr_set);
|
||||
datalog::set_union(*hyps3, *hyps);
|
||||
datalog::set_union(*hyps3, *hyps2);
|
||||
set_union(*hyps3, *hyps);
|
||||
set_union(*hyps3, *hyps2);
|
||||
hyps = hyps3;
|
||||
hyprefs.push_back(hyps);
|
||||
}
|
||||
|
@ -795,7 +795,7 @@ namespace pdr {
|
|||
case PR_LEMMA: {
|
||||
expr_set* hyps2 = alloc(expr_set);
|
||||
hyprefs.push_back(hyps2);
|
||||
datalog::set_union(*hyps2, *hyps);
|
||||
set_union(*hyps2, *hyps);
|
||||
hyps = hyps2;
|
||||
expr* fml = m.get_fact(p);
|
||||
hyps->remove(fml);
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace pdr {
|
|||
m_gen(n, core0, uses_level1);
|
||||
new_cores.push_back(std::make_pair(core0, uses_level1));
|
||||
obj_hashtable<expr> core_exprs, core1_exprs;
|
||||
datalog::set_union(core_exprs, core0);
|
||||
set_union(core_exprs, core0);
|
||||
for (unsigned i = 0; i < old_core.size(); ++i) {
|
||||
expr* lit = old_core[i].get();
|
||||
if (core_exprs.contains(lit)) {
|
||||
|
@ -94,8 +94,8 @@ namespace pdr {
|
|||
if (core1.size() < old_core.size()) {
|
||||
new_cores.push_back(std::make_pair(core1, uses_level1));
|
||||
core1_exprs.reset();
|
||||
datalog::set_union(core1_exprs, core1);
|
||||
datalog::set_intersection(core_exprs, core1_exprs);
|
||||
set_union(core1_exprs, core1);
|
||||
set_intersection(core_exprs, core1_exprs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace datalog {
|
|||
void set_reg(reg_idx i, reg_type val) {
|
||||
if (i >= m_registers.size()) {
|
||||
check_overflow(i);
|
||||
m_registers.resize(i+1,0);
|
||||
m_registers.resize(i+1);
|
||||
}
|
||||
if (m_registers[i]) {
|
||||
m_registers[i]->deallocate();
|
||||
|
|
|
@ -465,7 +465,7 @@ namespace datalog {
|
|||
|
||||
unsigned sz = r.get_signature().size();
|
||||
ptr_vector<expr> subst_arg;
|
||||
subst_arg.resize(sz, 0);
|
||||
subst_arg.resize(sz);
|
||||
unsigned ofs = sz-1;
|
||||
for (unsigned i=0; i<sz; i++) {
|
||||
SASSERT(!r.is_undefined(i) || !contains_var(m_new_rule, i));
|
||||
|
|
|
@ -7,7 +7,6 @@ z3_add_component(spacer
|
|||
spacer_farkas_learner.cpp
|
||||
spacer_generalizers.cpp
|
||||
spacer_manager.cpp
|
||||
spacer_marshal.cpp
|
||||
spacer_prop_solver.cpp
|
||||
spacer_smt_context_manager.cpp
|
||||
spacer_sym_mux.cpp
|
||||
|
@ -15,11 +14,9 @@ z3_add_component(spacer
|
|||
spacer_itp_solver.cpp
|
||||
spacer_virtual_solver.cpp
|
||||
spacer_legacy_mbp.cpp
|
||||
spacer_proof_utils.cpp
|
||||
spacer_unsat_core_learner.cpp
|
||||
spacer_unsat_core_plugin.cpp
|
||||
spacer_matrix.cpp
|
||||
spacer_min_cut.cpp
|
||||
spacer_antiunify.cpp
|
||||
spacer_mev_array.cpp
|
||||
spacer_qe_project.cpp
|
||||
|
|
|
@ -40,7 +40,7 @@ Notes:
|
|||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/proof_checker/proof_checker.h"
|
||||
#include "ast/proofs/proof_checker.h"
|
||||
#include "smt/smt_value_sort.h"
|
||||
#include "ast/scoped_proof.h"
|
||||
#include "muz/spacer/spacer_qe_project.h"
|
||||
|
@ -2139,7 +2139,7 @@ void context::reset_lemma_generalizers()
|
|||
void context::init_lemma_generalizers(datalog::rule_set& rules)
|
||||
{
|
||||
reset_lemma_generalizers();
|
||||
m.toggle_proof_mode(PGM_FINE);
|
||||
m.toggle_proof_mode(PGM_ENABLED);
|
||||
smt_params &fparams = m_pm.fparams ();
|
||||
if (!m_params.spacer_eq_prop ()) {
|
||||
fparams.m_arith_bound_prop = BP_NONE;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue