mirror of
https://github.com/Z3Prover/z3
synced 2025-04-14 12:58:44 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
e9d615e309
|
@ -240,7 +240,7 @@ if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||||
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_USE_THREAD_LOCAL")
|
list(APPEND Z3_COMPONENT_CXX_DEFINES "-D_USE_THREAD_LOCAL")
|
||||||
endif()
|
endif()
|
||||||
elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||||
# Does OSX really not need any special flags?
|
# Does macOS really not need any special flags?
|
||||||
message(STATUS "Platform: Darwin")
|
message(STATUS "Platform: Darwin")
|
||||||
elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
|
elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
|
||||||
message(STATUS "Platform: FreeBSD")
|
message(STATUS "Platform: FreeBSD")
|
||||||
|
@ -380,9 +380,17 @@ endif()
|
||||||
################################################################################
|
################################################################################
|
||||||
# FIXME: Support ARM "-mfpu=vfp -mfloat-abi=hard"
|
# FIXME: Support ARM "-mfpu=vfp -mfloat-abi=hard"
|
||||||
if (("${TARGET_ARCHITECTURE}" STREQUAL "x86_64") OR ("${TARGET_ARCHITECTURE}" STREQUAL "i686"))
|
if (("${TARGET_ARCHITECTURE}" STREQUAL "x86_64") OR ("${TARGET_ARCHITECTURE}" STREQUAL "i686"))
|
||||||
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel"))
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
|
||||||
|
# Intel's compiler requires linking with libiomp5
|
||||||
|
list(APPEND Z3_DEPENDENT_LIBS "iomp5")
|
||||||
|
endif()
|
||||||
set(SSE_FLAGS "-mfpmath=sse" "-msse" "-msse2")
|
set(SSE_FLAGS "-mfpmath=sse" "-msse" "-msse2")
|
||||||
# FIXME: Remove "x.." when CMP0054 is set to NEW
|
# FIXME: Remove "x.." when CMP0054 is set to NEW
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
|
||||||
|
set(SSE_FLAGS "-mfpmath=sse" "-msse" "-msse2")
|
||||||
|
# Intel's compiler requires linking with libiomp5
|
||||||
|
list(APPEND Z3_DEPENDENT_LIBS "iomp5")
|
||||||
elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
|
elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
|
||||||
set(SSE_FLAGS "/arch:SSE2")
|
set(SSE_FLAGS "/arch:SSE2")
|
||||||
else()
|
else()
|
||||||
|
|
|
@ -12,8 +12,8 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z
|
||||||
|
|
||||||
## Build status
|
## Build status
|
||||||
|
|
||||||
| Windows x64 | Windows x86 | Windows x64 | Ubuntu x64 | Debian x64 | OSX | TravisCI |
|
| Windows x64 | Windows x86 | Windows x64 | Ubuntu x64 | Debian x64 | macOS | TravisCI |
|
||||||
| ----------- | ----------- | ----------- | ---------- | ---------- | --- | -------- |
|
| ----------- | ----------- | ----------- | ---------- | ---------- | ----- | -------- |
|
||||||
[](https://z3build.visualstudio.com/Z3Build/_build/index?definitionId=4) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=4) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=7) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=3) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=5) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [](https://travis-ci.org/Z3Prover/z3)
|
[](https://z3build.visualstudio.com/Z3Build/_build/index?definitionId=4) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=4) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=7) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=3) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=5) | [](https://cz3.visualstudio.com/Z3/_build/index?definitionId=2) | [](https://travis-ci.org/Z3Prover/z3)
|
||||||
|
|
||||||
[1]: #building-z3-on-windows-using-visual-studio-command-prompt
|
[1]: #building-z3-on-windows-using-visual-studio-command-prompt
|
||||||
|
@ -75,7 +75,7 @@ A 32 bit build should work similarly (but is untested); the same is true for 32/
|
||||||
By default, it will install z3 executable at ``PREFIX/bin``, libraries at
|
By default, it will install z3 executable at ``PREFIX/bin``, libraries at
|
||||||
``PREFIX/lib``, and include files at ``PREFIX/include``, where ``PREFIX``
|
``PREFIX/lib``, and include files at ``PREFIX/include``, where ``PREFIX``
|
||||||
installation prefix if inferred by the ``mk_make.py`` script. It is usually
|
installation prefix if inferred by the ``mk_make.py`` script. It is usually
|
||||||
``/usr`` for most Linux distros, and ``/usr/local`` for FreeBSD and OSX. Use
|
``/usr`` for most Linux distros, and ``/usr/local`` for FreeBSD and macOS. Use
|
||||||
the ``--prefix=`` command line option to change the install prefix. For example:
|
the ``--prefix=`` command line option to change the install prefix. For example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -21,7 +21,7 @@ Version 4.8.0
|
||||||
extracting models from apply_result have been replaced.
|
extracting models from apply_result have been replaced.
|
||||||
- An optional mode handles xor constraints using a custom xor propagator.
|
- An optional mode handles xor constraints using a custom xor propagator.
|
||||||
It is off by default and its value not demonstrated.
|
It is off by default and its value not demonstrated.
|
||||||
- The SAT solver includes new inprocessing technques that are available during simplification.
|
- The SAT solver includes new inprocessing techniques that are available during simplification.
|
||||||
It performs asymmetric tautology elimination by default, and one can turn on more powerful inprocessing techniques
|
It performs asymmetric tautology elimination by default, and one can turn on more powerful inprocessing techniques
|
||||||
(known as ACCE, ABCE, CCE). Asymmetric branching also uses features introduced in Lingeling by exploiting binary implication graphs.
|
(known as ACCE, ABCE, CCE). Asymmetric branching also uses features introduced in Lingeling by exploiting binary implication graphs.
|
||||||
Use sat.acce=true to enable the full repertoire of inprocessing methods. By default, clauses that are "eliminated" by acce are tagged
|
Use sat.acce=true to enable the full repertoire of inprocessing methods. By default, clauses that are "eliminated" by acce are tagged
|
||||||
|
@ -318,7 +318,7 @@ First source code release (October 2, 2012)
|
||||||
|
|
||||||
- Added support for numbers in scientific notation at Z3_ast Z3_mk_numeral(__in Z3_context c, __in Z3_string numeral, __in Z3_sort ty).
|
- Added support for numbers in scientific notation at Z3_ast Z3_mk_numeral(__in Z3_context c, __in Z3_string numeral, __in Z3_sort ty).
|
||||||
|
|
||||||
- New builtin symbols in the arithmetic theory: pi, euler, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh. The first two are constants, and the others are unary functions. These symbols are not available if the a SMT 2.0 logic is specified (e.g., QF_LRA, QF_NRA, QF_LIA, etc) because these symbols are not defined in these logics. That is, the new symbols are only available if the logic is not specified.
|
- New builtin symbols in the arithmetic theory: pi, euler, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh. The first two are constants, and the others are unary functions. These symbols are not available if a SMT 2.0 logic is specified (e.g., QF_LRA, QF_NRA, QF_LIA, etc) because these symbols are not defined in these logics. That is, the new symbols are only available if the logic is not specified.
|
||||||
|
|
||||||
Version 4.1
|
Version 4.1
|
||||||
===========
|
===========
|
||||||
|
|
|
@ -5,6 +5,6 @@ in the build directory.
|
||||||
|
|
||||||
This command will create the executable cpp_example.
|
This command will create the executable cpp_example.
|
||||||
On Windows, you can just execute it.
|
On Windows, you can just execute it.
|
||||||
On OSX and Linux, you must install z3 first using
|
On macOS and Linux, you must install z3 first using
|
||||||
sudo make install
|
sudo make install
|
||||||
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX) with the build directory. You need that to be able to find the Z3 shared library.
|
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS) with the build directory. You need that to be able to find the Z3 shared library.
|
||||||
|
|
|
@ -5,7 +5,7 @@ in the build directory.
|
||||||
|
|
||||||
This command will create the executable c_example.
|
This command will create the executable c_example.
|
||||||
On Windows, you can just execute it.
|
On Windows, you can just execute it.
|
||||||
On OSX and Linux, you must install z3 first using
|
On macOS and Linux, you must install z3 first using
|
||||||
sudo make install
|
sudo make install
|
||||||
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX) with the build directory. You need that to be able to find the Z3 shared library.
|
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS) with the build directory. You need that to be able to find the Z3 shared library.
|
||||||
|
|
||||||
|
|
|
@ -10,5 +10,5 @@ which can be run on Windows via
|
||||||
|
|
||||||
On Linux and FreeBSD, we must use
|
On Linux and FreeBSD, we must use
|
||||||
LD_LIBRARY_PATH=. java -cp com.microsoft.z3.jar:. JavaExample
|
LD_LIBRARY_PATH=. java -cp com.microsoft.z3.jar:. JavaExample
|
||||||
On OSX, the corresponding option is DYLD_LIBRARY_PATH:
|
On macOS, the corresponding option is DYLD_LIBRARY_PATH:
|
||||||
DYLD_LIBRARY_PATH=. java -cp com.microsoft.z3.jar:. JavaExample
|
DYLD_LIBRARY_PATH=. java -cp com.microsoft.z3.jar:. JavaExample
|
||||||
|
|
|
@ -5,8 +5,8 @@ in the build directory.
|
||||||
|
|
||||||
This command will create the executable maxsat.
|
This command will create the executable maxsat.
|
||||||
On Windows, you can just execute it.
|
On Windows, you can just execute it.
|
||||||
On OSX and Linux, you must install z3 first using
|
On macOS and Linux, you must install z3 first using
|
||||||
sudo make install
|
sudo make install
|
||||||
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX) with the build directory. You need that to be able to find the Z3 shared library.
|
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS) with the build directory. You need that to be able to find the Z3 shared library.
|
||||||
|
|
||||||
This directory contains a test file (ex.smt) that can be used as input for the maxsat test application.
|
This directory contains a test file (ex.smt) that can be used as input for the maxsat test application.
|
||||||
|
|
|
@ -20,4 +20,4 @@ ocamlfind ocamlopt -o ml_example -package Z3 -linkpkg ml_example.ml
|
||||||
|
|
||||||
Note that the resulting binaries depend on the shared z3 library
|
Note that the resulting binaries depend on the shared z3 library
|
||||||
(libz3.dll/.so/.dylb), which needs to be in the PATH (Windows), LD_LIBRARY_PATH
|
(libz3.dll/.so/.dylb), which needs to be in the PATH (Windows), LD_LIBRARY_PATH
|
||||||
(Linux), or DYLD_LIBRARY_PATH (OSX).
|
(Linux), or DYLD_LIBRARY_PATH (macOS).
|
||||||
|
|
|
@ -65,8 +65,7 @@ let model_converter_test ( ctx : context ) =
|
||||||
| None -> raise (TestFailedException "")
|
| None -> raise (TestFailedException "")
|
||||||
| Some (m) ->
|
| Some (m) ->
|
||||||
Printf.printf "Solver says: %s\n" (string_of_status q) ;
|
Printf.printf "Solver says: %s\n" (string_of_status q) ;
|
||||||
Printf.printf "Model: \n%s\n" (Model.to_string m) ;
|
Printf.printf "Model: \n%s\n" (Model.to_string m)
|
||||||
Printf.printf "Converted Model: \n%s\n" (Model.to_string (convert_model ar 0 m))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
(**
|
(**
|
||||||
|
@ -331,11 +330,13 @@ let _ =
|
||||||
let bs = (Boolean.mk_sort ctx) in
|
let bs = (Boolean.mk_sort ctx) in
|
||||||
let ints = (Integer.mk_sort ctx) in
|
let ints = (Integer.mk_sort ctx) in
|
||||||
let rs = (Real.mk_sort ctx) in
|
let rs = (Real.mk_sort ctx) in
|
||||||
|
let v = (Arithmetic.Integer.mk_numeral_i ctx 8000000000) in
|
||||||
Printf.printf "int symbol: %s\n" (Symbol.to_string is);
|
Printf.printf "int symbol: %s\n" (Symbol.to_string is);
|
||||||
Printf.printf "string symbol: %s\n" (Symbol.to_string ss);
|
Printf.printf "string symbol: %s\n" (Symbol.to_string ss);
|
||||||
Printf.printf "bool sort: %s\n" (Sort.to_string bs);
|
Printf.printf "bool sort: %s\n" (Sort.to_string bs);
|
||||||
Printf.printf "int sort: %s\n" (Sort.to_string ints);
|
Printf.printf "int sort: %s\n" (Sort.to_string ints);
|
||||||
Printf.printf "real sort: %s\n" (Sort.to_string rs);
|
Printf.printf "real sort: %s\n" (Sort.to_string rs);
|
||||||
|
Printf.printf "integer: %s\n" (Expr.to_string v);
|
||||||
basic_tests ctx ;
|
basic_tests ctx ;
|
||||||
quantifier_example1 ctx ;
|
quantifier_example1 ctx ;
|
||||||
fpa_example ctx ;
|
fpa_example ctx ;
|
||||||
|
|
50
examples/python/data/horn1.smt2
Normal file
50
examples/python/data/horn1.smt2
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
(declare-rel Goal (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool))
|
||||||
|
(declare-rel Invariant (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool))
|
||||||
|
(declare-var A Bool)
|
||||||
|
(declare-var B Bool)
|
||||||
|
(declare-var C Bool)
|
||||||
|
(declare-var D Bool)
|
||||||
|
(declare-var E Bool)
|
||||||
|
(declare-var F Bool)
|
||||||
|
(declare-var G Bool)
|
||||||
|
(declare-var H Bool)
|
||||||
|
(declare-var I Bool)
|
||||||
|
(declare-var J Bool)
|
||||||
|
(declare-var K Bool)
|
||||||
|
(declare-var L Bool)
|
||||||
|
(declare-var M Bool)
|
||||||
|
(declare-var N Bool)
|
||||||
|
(declare-var O Bool)
|
||||||
|
(declare-var P Bool)
|
||||||
|
(declare-var Q Bool)
|
||||||
|
(declare-var R Bool)
|
||||||
|
(declare-var S Bool)
|
||||||
|
(declare-var T Bool)
|
||||||
|
(declare-var U Bool)
|
||||||
|
(declare-var V Bool)
|
||||||
|
(declare-var W Bool)
|
||||||
|
(declare-var X Bool)
|
||||||
|
(rule (=> (not (or L K J I H G F E D C B A)) (Invariant L K J I H G F E D C B A)))
|
||||||
|
(rule (let ((a!1 (and (Invariant X W V U T S R Q P O N M)
|
||||||
|
(=> (not (and true)) (not F))
|
||||||
|
(=> (not (and true)) (not E))
|
||||||
|
(=> (not (and W)) (not D))
|
||||||
|
(=> (not (and W)) (not C))
|
||||||
|
(=> (not (and U)) (not B))
|
||||||
|
(=> (not (and U)) (not A))
|
||||||
|
(= L (xor F X))
|
||||||
|
(= K (xor E W))
|
||||||
|
(= J (xor D V))
|
||||||
|
(= I (xor C U))
|
||||||
|
(= H (xor B T))
|
||||||
|
(= G (xor A S))
|
||||||
|
(=> D (not E))
|
||||||
|
(=> C (not E))
|
||||||
|
(=> B (not C))
|
||||||
|
(=> A (not C))
|
||||||
|
((_ at-most 5) L K J I H G))))
|
||||||
|
(=> a!1 (Invariant L K J I H G F E D C B A))))
|
||||||
|
(rule (=> (and (Invariant L K J I H G F E D C B A) L (not K) J (not I) H G)
|
||||||
|
(Goal L K J I H G F E D C B A)))
|
||||||
|
|
||||||
|
(query Goal)
|
44
examples/python/data/horn2.smt2
Normal file
44
examples/python/data/horn2.smt2
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
(declare-rel Invariant (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool))
|
||||||
|
(declare-rel Goal (Bool Bool Bool Bool Bool Bool Bool Bool Bool Bool))
|
||||||
|
(declare-var A Bool)
|
||||||
|
(declare-var B Bool)
|
||||||
|
(declare-var C Bool)
|
||||||
|
(declare-var D Bool)
|
||||||
|
(declare-var E Bool)
|
||||||
|
(declare-var F Bool)
|
||||||
|
(declare-var G Bool)
|
||||||
|
(declare-var H Bool)
|
||||||
|
(declare-var I Bool)
|
||||||
|
(declare-var J Bool)
|
||||||
|
(declare-var K Bool)
|
||||||
|
(declare-var L Bool)
|
||||||
|
(declare-var M Bool)
|
||||||
|
(declare-var N Bool)
|
||||||
|
(declare-var O Bool)
|
||||||
|
(declare-var P Bool)
|
||||||
|
(declare-var Q Bool)
|
||||||
|
(declare-var R Bool)
|
||||||
|
(declare-var S Bool)
|
||||||
|
(declare-var T Bool)
|
||||||
|
(rule (=> (not (or J I H G F E D C B A)) (Invariant J I H G F E D C B A)))
|
||||||
|
(rule (let ((a!1 (and (Invariant T S R Q P O N M L K)
|
||||||
|
(=> (not (and true)) (not E))
|
||||||
|
(=> (not (and T)) (not D))
|
||||||
|
(=> (not (and S)) (not C))
|
||||||
|
(=> (not (and R)) (not B))
|
||||||
|
(=> (not (and Q)) (not A))
|
||||||
|
(= J (xor E T))
|
||||||
|
(= I (xor D S))
|
||||||
|
(= H (xor C R))
|
||||||
|
(= G (xor B Q))
|
||||||
|
(= F (xor A P))
|
||||||
|
(=> D (not E))
|
||||||
|
(=> C (not D))
|
||||||
|
(=> B (not C))
|
||||||
|
(=> A (not B))
|
||||||
|
((_ at-most 3) J I H G F))))
|
||||||
|
(=> a!1 (Invariant J I H G F E D C B A))))
|
||||||
|
(rule (=> (and (Invariant J I H G F E D C B A) (not J) (not I) (not H) (not G) F)
|
||||||
|
(Goal J I H G F E D C B A)))
|
||||||
|
|
||||||
|
(query Goal)
|
|
@ -20,7 +20,7 @@
|
||||||
# export PYTHONPATH=MYZ3/bin/python
|
# export PYTHONPATH=MYZ3/bin/python
|
||||||
# python example.py
|
# python example.py
|
||||||
|
|
||||||
# Running this example on OSX:
|
# Running this example on macOS:
|
||||||
# export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:MYZ3/bin
|
# export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:MYZ3/bin
|
||||||
# export PYTHONPATH=MYZ3/bin/python
|
# export PYTHONPATH=MYZ3/bin/python
|
||||||
# python example.py
|
# python example.py
|
||||||
|
|
438
examples/python/mini_ic3.py
Normal file
438
examples/python/mini_ic3.py
Normal file
|
@ -0,0 +1,438 @@
|
||||||
|
from z3 import *
|
||||||
|
import heapq
|
||||||
|
|
||||||
|
|
||||||
|
# Simplistic (and fragile) converter from
|
||||||
|
# a class of Horn clauses corresponding to
|
||||||
|
# a transition system into a transition system
|
||||||
|
# representation as <init, trans, goal>
|
||||||
|
# It assumes it is given three Horn clauses
|
||||||
|
# of the form:
|
||||||
|
# init(x) => Invariant(x)
|
||||||
|
# Invariant(x) and trans(x,x') => Invariant(x')
|
||||||
|
# Invariant(x) and goal(x) => Goal(x)
|
||||||
|
# where Invariant and Goal are uninterpreted predicates
|
||||||
|
|
||||||
|
class Horn2Transitions:
|
||||||
|
def __init__(self):
|
||||||
|
self.trans = True
|
||||||
|
self.init = True
|
||||||
|
self.goal = True
|
||||||
|
self.index = 0
|
||||||
|
|
||||||
|
def parse(self, file):
|
||||||
|
fp = Fixedpoint()
|
||||||
|
goals = fp.parse_file(file)
|
||||||
|
for r in fp.get_rules():
|
||||||
|
if not is_quantifier(r):
|
||||||
|
continue
|
||||||
|
b = r.body()
|
||||||
|
if not is_implies(b):
|
||||||
|
continue
|
||||||
|
f = b.arg(0)
|
||||||
|
g = b.arg(1)
|
||||||
|
if self.is_goal(f, g):
|
||||||
|
continue
|
||||||
|
if self.is_transition(f, g):
|
||||||
|
continue
|
||||||
|
if self.is_init(f, g):
|
||||||
|
continue
|
||||||
|
|
||||||
|
def is_pred(self, p, name):
|
||||||
|
return is_app(p) and p.decl().name() == name
|
||||||
|
|
||||||
|
def is_goal(self, body, head):
|
||||||
|
if not self.is_pred(head, "Goal"):
|
||||||
|
return False
|
||||||
|
pred, inv = self.is_body(body)
|
||||||
|
if pred is None:
|
||||||
|
return False
|
||||||
|
self.goal = self.subst_vars("x", inv, pred)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_body(self, body):
|
||||||
|
if not is_and(body):
|
||||||
|
return None, None
|
||||||
|
fmls = [f for f in body.children() if self.is_inv(f) is None]
|
||||||
|
inv = None
|
||||||
|
for f in body.children():
|
||||||
|
if self.is_inv(f) is not None:
|
||||||
|
inv = f;
|
||||||
|
break
|
||||||
|
return And(fmls), inv
|
||||||
|
|
||||||
|
def is_inv(self, f):
|
||||||
|
if self.is_pred(f, "Invariant"):
|
||||||
|
return f
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_transition(self, body, head):
|
||||||
|
pred, inv0 = self.is_body(body)
|
||||||
|
if pred is None:
|
||||||
|
return False
|
||||||
|
inv1 = self.is_inv(head)
|
||||||
|
if inv1 is None:
|
||||||
|
return False
|
||||||
|
pred = self.subst_vars("x", inv0, pred)
|
||||||
|
self.xs = self.vars
|
||||||
|
pred = self.subst_vars("xn", inv1, pred)
|
||||||
|
self.xns = self.vars
|
||||||
|
self.trans = pred
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_init(self, body, head):
|
||||||
|
for f in body.children():
|
||||||
|
if self.is_inv(f) is not None:
|
||||||
|
return False
|
||||||
|
inv = self.is_inv(head)
|
||||||
|
if inv is None:
|
||||||
|
return False
|
||||||
|
self.init = self.subst_vars("x", inv, body)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def subst_vars(self, prefix, inv, fml):
|
||||||
|
subst = self.mk_subst(prefix, inv)
|
||||||
|
self.vars = [ v for (k,v) in subst ]
|
||||||
|
return substitute(fml, subst)
|
||||||
|
|
||||||
|
def mk_subst(self, prefix, inv):
|
||||||
|
self.index = 0
|
||||||
|
return [(f, self.mk_bool(prefix)) for f in inv.children()]
|
||||||
|
|
||||||
|
def mk_bool(self, prefix):
|
||||||
|
self.index += 1
|
||||||
|
return Bool("%s%d" % (prefix, self.index))
|
||||||
|
|
||||||
|
# Produce a finite domain solver.
|
||||||
|
# The theory QF_FD covers bit-vector formulas
|
||||||
|
# and pseudo-Boolean constraints.
|
||||||
|
# By default cardinality and pseudo-Boolean
|
||||||
|
# constraints are converted to clauses. To override
|
||||||
|
# this default for cardinality constraints
|
||||||
|
# we set sat.cardinality.solver to True
|
||||||
|
|
||||||
|
def fd_solver():
|
||||||
|
s = SolverFor("QF_FD")
|
||||||
|
s.set("sat.cardinality.solver", True)
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
# negate, avoid double negation
|
||||||
|
def negate(f):
|
||||||
|
if is_not(f):
|
||||||
|
return f.arg(0)
|
||||||
|
else:
|
||||||
|
return Not(f)
|
||||||
|
|
||||||
|
def cube2clause(cube):
|
||||||
|
return Or([negate(f) for f in cube])
|
||||||
|
|
||||||
|
class State:
|
||||||
|
def __init__(self, s):
|
||||||
|
self.R = set([])
|
||||||
|
self.solver = s
|
||||||
|
|
||||||
|
def add(self, clause):
|
||||||
|
if clause not in self.R:
|
||||||
|
self.R |= { clause }
|
||||||
|
self.solver.add(clause)
|
||||||
|
|
||||||
|
class Goal:
|
||||||
|
def __init__(self, cube, parent, level):
|
||||||
|
self.level = level
|
||||||
|
self.cube = cube
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
def is_seq(f):
|
||||||
|
return isinstance(f, list) or isinstance(f, tuple) or isinstance(f, AstVector)
|
||||||
|
|
||||||
|
# Check if the initial state is bad
|
||||||
|
def check_disjoint(a, b):
|
||||||
|
s = fd_solver()
|
||||||
|
s.add(a)
|
||||||
|
s.add(b)
|
||||||
|
return unsat == s.check()
|
||||||
|
|
||||||
|
|
||||||
|
# Remove clauses that are subsumed
|
||||||
|
def prune(R):
|
||||||
|
removed = set([])
|
||||||
|
s = fd_solver()
|
||||||
|
for f1 in R:
|
||||||
|
s.push()
|
||||||
|
for f2 in R:
|
||||||
|
if f2 not in removed:
|
||||||
|
s.add(Not(f2) if f1.eq(f2) else f2)
|
||||||
|
if s.check() == unsat:
|
||||||
|
removed |= { f1 }
|
||||||
|
s.pop()
|
||||||
|
return R - removed
|
||||||
|
|
||||||
|
class MiniIC3:
|
||||||
|
def __init__(self, init, trans, goal, x0, xn):
|
||||||
|
self.x0 = x0
|
||||||
|
self.xn = xn
|
||||||
|
self.init = init
|
||||||
|
self.bad = goal
|
||||||
|
self.trans = trans
|
||||||
|
self.min_cube_solver = fd_solver()
|
||||||
|
self.min_cube_solver.add(Not(trans))
|
||||||
|
self.goals = []
|
||||||
|
s = State(fd_solver())
|
||||||
|
s.add(init)
|
||||||
|
s.solver.add(trans)
|
||||||
|
self.states = [s]
|
||||||
|
self.s_bad = fd_solver()
|
||||||
|
self.s_good = fd_solver()
|
||||||
|
self.s_bad.add(self.bad)
|
||||||
|
self.s_good.add(Not(self.bad))
|
||||||
|
|
||||||
|
def next(self, f):
|
||||||
|
if is_seq(f):
|
||||||
|
return [self.next(f1) for f1 in f]
|
||||||
|
return substitute(f, zip(self.x0, self.xn))
|
||||||
|
|
||||||
|
def prev(self, f):
|
||||||
|
if is_seq(f):
|
||||||
|
return [self.prev(f1) for f1 in f]
|
||||||
|
return substitute(f, zip(self.xn, self.x0))
|
||||||
|
|
||||||
|
def add_solver(self):
|
||||||
|
s = fd_solver()
|
||||||
|
s.add(self.trans)
|
||||||
|
self.states += [State(s)]
|
||||||
|
|
||||||
|
def R(self, i):
|
||||||
|
return And(self.states[i].R)
|
||||||
|
|
||||||
|
# Check if there are two states next to each other that have the same clauses.
|
||||||
|
def is_valid(self):
|
||||||
|
i = 1
|
||||||
|
while i + 1 < len(self.states):
|
||||||
|
if not (self.states[i].R - self.states[i+1].R):
|
||||||
|
return And(prune(self.states[i].R))
|
||||||
|
i += 1
|
||||||
|
return None
|
||||||
|
|
||||||
|
def value2literal(self, m, x):
|
||||||
|
value = m.eval(x)
|
||||||
|
if is_true(value):
|
||||||
|
return x
|
||||||
|
if is_false(value):
|
||||||
|
return Not(x)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def values2literals(self, m, xs):
|
||||||
|
p = [self.value2literal(m, x) for x in xs]
|
||||||
|
return [x for x in p if x is not None]
|
||||||
|
|
||||||
|
def project0(self, m):
|
||||||
|
return self.values2literals(m, self.x0)
|
||||||
|
|
||||||
|
def projectN(self, m):
|
||||||
|
return self.values2literals(m, self.xn)
|
||||||
|
|
||||||
|
# Determine if there is a cube for the current state
|
||||||
|
# that is potentially reachable.
|
||||||
|
def unfold(self):
|
||||||
|
core = []
|
||||||
|
self.s_bad.push()
|
||||||
|
R = self.R(len(self.states)-1)
|
||||||
|
self.s_bad.add(R)
|
||||||
|
is_sat = self.s_bad.check()
|
||||||
|
if is_sat == sat:
|
||||||
|
m = self.s_bad.model()
|
||||||
|
props = self.project0(m)
|
||||||
|
self.s_good.push()
|
||||||
|
self.s_good.add(R)
|
||||||
|
is_sat2 = self.s_good.check(props)
|
||||||
|
assert is_sat2 == unsat
|
||||||
|
core = self.s_good.unsat_core()
|
||||||
|
self.s_good.pop()
|
||||||
|
self.s_bad.pop()
|
||||||
|
return is_sat, core
|
||||||
|
|
||||||
|
# Block a cube by asserting the clause corresponding to its negation
|
||||||
|
def block_cube(self, i, cube):
|
||||||
|
self.assert_clause(i, cube2clause(cube))
|
||||||
|
|
||||||
|
# Add a clause to levels 0 until i
|
||||||
|
def assert_clause(self, i, clause):
|
||||||
|
for j in range(i + 1):
|
||||||
|
self.states[j].add(clause)
|
||||||
|
|
||||||
|
# minimize cube that is core of Dual solver.
|
||||||
|
# this assumes that props & cube => Trans
|
||||||
|
def minimize_cube(self, cube, lits):
|
||||||
|
is_sat = self.min_cube_solver.check(lits + [c for c in cube])
|
||||||
|
assert is_sat == unsat
|
||||||
|
core = self.min_cube_solver.unsat_core()
|
||||||
|
assert core
|
||||||
|
return [c for c in core if c in set(cube)]
|
||||||
|
|
||||||
|
# push a goal on a heap
|
||||||
|
def push_heap(self, goal):
|
||||||
|
heapq.heappush(self.goals, (goal.level, goal))
|
||||||
|
|
||||||
|
# A state s0 and level f0 such that
|
||||||
|
# not(s0) is f0-1 inductive
|
||||||
|
def ic3_blocked(self, s0, f0):
|
||||||
|
self.push_heap(Goal(self.next(s0), None, f0))
|
||||||
|
while self.goals:
|
||||||
|
f, g = heapq.heappop(self.goals)
|
||||||
|
sys.stdout.write("%d." % f)
|
||||||
|
sys.stdout.flush()
|
||||||
|
# Not(g.cube) is f-1 invariant
|
||||||
|
if f == 0:
|
||||||
|
print("")
|
||||||
|
return g
|
||||||
|
cube, f, is_sat = self.is_inductive(f, g.cube)
|
||||||
|
if is_sat == unsat:
|
||||||
|
self.block_cube(f, self.prev(cube))
|
||||||
|
if f < f0:
|
||||||
|
self.push_heap(Goal(g.cube, g.parent, f + 1))
|
||||||
|
elif is_sat == sat:
|
||||||
|
self.push_heap(Goal(cube, g, f - 1))
|
||||||
|
self.push_heap(g)
|
||||||
|
else:
|
||||||
|
return is_sat
|
||||||
|
print("")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Rudimentary generalization:
|
||||||
|
# If the cube is already unsat with respect to transition relation
|
||||||
|
# extract a core (not necessarily minimal)
|
||||||
|
# otherwise, just return the cube.
|
||||||
|
def generalize(self, cube, f):
|
||||||
|
s = self.states[f - 1].solver
|
||||||
|
if unsat == s.check(cube):
|
||||||
|
return s.unsat_core(), f
|
||||||
|
return cube, f
|
||||||
|
|
||||||
|
# Check if the negation of cube is inductive at level f
|
||||||
|
def is_inductive(self, f, cube):
|
||||||
|
s = self.states[f - 1].solver
|
||||||
|
s.push()
|
||||||
|
s.add(self.prev(Not(And(cube))))
|
||||||
|
is_sat = s.check(cube)
|
||||||
|
if is_sat == sat:
|
||||||
|
m = s.model()
|
||||||
|
s.pop()
|
||||||
|
if is_sat == sat:
|
||||||
|
cube = self.next(self.minimize_cube(self.project0(m), self.projectN(m)))
|
||||||
|
elif is_sat == unsat:
|
||||||
|
cube, f = self.generalize(cube, f)
|
||||||
|
return cube, f, is_sat
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if not check_disjoint(self.init, self.bad):
|
||||||
|
return "goal is reached in initial state"
|
||||||
|
level = 0
|
||||||
|
while True:
|
||||||
|
inv = self.is_valid()
|
||||||
|
if inv is not None:
|
||||||
|
return inv
|
||||||
|
is_sat, cube = self.unfold()
|
||||||
|
if is_sat == unsat:
|
||||||
|
level += 1
|
||||||
|
print("Unfold %d" % level)
|
||||||
|
sys.stdout.flush()
|
||||||
|
self.add_solver()
|
||||||
|
elif is_sat == sat:
|
||||||
|
cex = self.ic3_blocked(cube, level)
|
||||||
|
if cex is not None:
|
||||||
|
return cex
|
||||||
|
else:
|
||||||
|
return is_sat
|
||||||
|
|
||||||
|
def test(file):
|
||||||
|
h2t = Horn2Transitions()
|
||||||
|
h2t.parse(file)
|
||||||
|
mp = MiniIC3(h2t.init, h2t.trans, h2t.goal, h2t.xs, h2t.xns)
|
||||||
|
result = mp.run()
|
||||||
|
if isinstance(result, Goal):
|
||||||
|
g = result
|
||||||
|
print("Trace")
|
||||||
|
while g:
|
||||||
|
print(g.level, g.cube)
|
||||||
|
g = g.parent
|
||||||
|
return
|
||||||
|
if isinstance(result, ExprRef):
|
||||||
|
print("Invariant:\n%s " % result)
|
||||||
|
return
|
||||||
|
print(result)
|
||||||
|
|
||||||
|
test("data/horn1.smt2")
|
||||||
|
test("data/horn2.smt2")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
# TBD: Quip variant of IC3
|
||||||
|
|
||||||
|
must = True
|
||||||
|
may = False
|
||||||
|
|
||||||
|
class QGoal:
|
||||||
|
def __init__(self, cube, parent, level, must):
|
||||||
|
self.level = level
|
||||||
|
self.cube = cube
|
||||||
|
self.parent = parent
|
||||||
|
self.must = must
|
||||||
|
|
||||||
|
class Quip(MiniIC3):
|
||||||
|
|
||||||
|
# prev & tras -> r', such that r' intersects with cube
|
||||||
|
def add_reachable(self, prev, cube):
|
||||||
|
s = fd_solver()
|
||||||
|
s.add(self.trans)
|
||||||
|
s.add(prev)
|
||||||
|
s.add(Or(cube))
|
||||||
|
is_sat = s.check()
|
||||||
|
assert is_sat == sat
|
||||||
|
m = s.model();
|
||||||
|
result = self.values2literals(m, cube)
|
||||||
|
assert result
|
||||||
|
self.reachable.add(result)
|
||||||
|
|
||||||
|
# A state s0 and level f0 such that
|
||||||
|
# not(s0) is f0-1 inductive
|
||||||
|
def quip_blocked(self, s0, f0):
|
||||||
|
self.push_heap(QGoal(self.next(s0), None, f0, must))
|
||||||
|
while self.goals:
|
||||||
|
f, g = heapq.heappop(self.goals)
|
||||||
|
sys.stdout.write("%d." % f)
|
||||||
|
sys.stdout.flush()
|
||||||
|
if f == 0:
|
||||||
|
if g.must:
|
||||||
|
print("")
|
||||||
|
return g
|
||||||
|
self.add_reachable(self.init, p.parent.cube)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# TBD
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if not check_disjoint(self.init, self.bad):
|
||||||
|
return "goal is reached in initial state"
|
||||||
|
level = 0
|
||||||
|
while True:
|
||||||
|
inv = self.is_valid()
|
||||||
|
if inv is not None:
|
||||||
|
return inv
|
||||||
|
is_sat, cube = self.unfold()
|
||||||
|
if is_sat == unsat:
|
||||||
|
level += 1
|
||||||
|
print("Unfold %d" % level)
|
||||||
|
sys.stdout.flush()
|
||||||
|
self.add_solver()
|
||||||
|
elif is_sat == sat:
|
||||||
|
cex = self.quipie_blocked(cube, level)
|
||||||
|
if cex is not None:
|
||||||
|
return cex
|
||||||
|
else:
|
||||||
|
return is_sat
|
||||||
|
|
||||||
|
"""
|
|
@ -5,9 +5,9 @@ in the build directory.
|
||||||
|
|
||||||
This command will create the executable tptp.
|
This command will create the executable tptp.
|
||||||
On Windows, you can just execute it.
|
On Windows, you can just execute it.
|
||||||
On OSX and Linux, you must install z3 first using
|
On macOS and Linux, you must install z3 first using
|
||||||
sudo make install
|
sudo make install
|
||||||
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX)
|
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (macOS)
|
||||||
with the build directory. You need that to be able to
|
with the build directory. You need that to be able to
|
||||||
find the Z3 shared library.
|
find the Z3 shared library.
|
||||||
|
|
||||||
|
|
22
package/Microsoft.Z3.x64.nuspec
Normal file
22
package/Microsoft.Z3.x64.nuspec
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>Microsoft.Z3.x64</id>
|
||||||
|
<version>$(releaseVersion)</version>
|
||||||
|
<copyright>© Microsoft Corporation. All rights reserved.</copyright>
|
||||||
|
<authors>Microsoft</authors>
|
||||||
|
<owners>Microsoft,Z3Prover</owners>
|
||||||
|
<iconUrl>$(iconUrlFromReleaseCommit)</iconUrl>
|
||||||
|
<projectUrl>https://github.com/Z3Prover/z3</projectUrl>
|
||||||
|
<licenseUrl>$(licenseUrlFromReleaseCommit)</licenseUrl>
|
||||||
|
<repository
|
||||||
|
type="git"
|
||||||
|
url="https://github.com/Z3Prover/z3.git"
|
||||||
|
branch="master"
|
||||||
|
commit="$(releaseCommitHash)"
|
||||||
|
/>
|
||||||
|
<requireLicenseAcceptance>true</requireLicenseAcceptance>
|
||||||
|
<description>Z3 is a constraint/SMT solver and theorem prover from Microsoft Research.</description>
|
||||||
|
<tags>smt constraint solver theorem prover</tags>
|
||||||
|
</metadata>
|
||||||
|
</package>
|
10
package/Microsoft.Z3.x64.targets
Normal file
10
package/Microsoft.Z3.x64.targets
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="$(MSBuildThisFileDirectory)libz3.dll">
|
||||||
|
<Visible>false</Visible>
|
||||||
|
<Link>libz3.dll</Link>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
36
package/PackageCreationDirections.md
Normal file
36
package/PackageCreationDirections.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# Z3 NuGet packaging
|
||||||
|
|
||||||
|
## Creation
|
||||||
|
|
||||||
|
1. After tagging a commit for release, sign Microsoft.Z3.dll and libz3.dll (both x86 and x64 versions) with Microsoft's Authenticode certificate
|
||||||
|
2. Test the signed DLLs with the `Get-AuthenticodeSignature` PowerShell commandlet
|
||||||
|
3. Create the following directory structure for the x64 package (for x86, substitute the "x64" strings for "x86" and use x86 DLLs):
|
||||||
|
```
|
||||||
|
+-- Microsoft.Z3.x64
|
||||||
|
| +-- Microsoft.Z3.x64.nuspec
|
||||||
|
| +-- lib
|
||||||
|
| +-- net40
|
||||||
|
| +-- Microsoft.Z3.dll
|
||||||
|
| +-- build
|
||||||
|
| +-- Microsoft.Z3.x64.targets
|
||||||
|
| +-- libz3.dll
|
||||||
|
```
|
||||||
|
4. Open the nuspec file and fill in the appropriate macro values (note that for all URLs, preserve link integrity by linking to a specific commit):
|
||||||
|
* $(releaseVersion) - the Z3 version being released in this package
|
||||||
|
* $(iconUrlFromReleaseCommit) - URL for the Z3 icon file
|
||||||
|
* $(licenseUrlFromReleaseCommit) - URL for the Z3 repo license
|
||||||
|
* $(releaseCommitHash) - hash of the release commit
|
||||||
|
5. Run `nuget pack Microsoft.Z3.x64\Microsoft.Z3.x64.nuspec`
|
||||||
|
6. Test the resulting nupkg file (described below) then submit the package for signing before uploading to NuGet.org
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
1. Create a directory on your machine at C:\nuget-test-source
|
||||||
|
2. Put the Microsoft.Z3.x64.nupkg file in the directory
|
||||||
|
3. Open Visual Studio 2017, create a new C# project, then right click the project and click "Manage NuGet packages"
|
||||||
|
4. Add a new package source - your C:\nuget-test-source directory
|
||||||
|
5. Find the Microsoft.Z3.x64 package, ensuring in preview window that icon is present and all fields correct
|
||||||
|
6. Install the Microsoft.Z3.x64 package, ensuring you are asked to accept the license
|
||||||
|
7. Build your project. Check the output directory to ensure both Microsoft.Z3.dll and libz3.dll are present
|
||||||
|
8. Import Microsoft.Z3 to your project then add a simple line of code like `using (var ctx = new Context()) { }`; build then run your project to ensure the assemblies load properly
|
||||||
|
|
BIN
package/icon.jpg
Normal file
BIN
package/icon.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
|
@ -10,7 +10,7 @@ from mk_util import *
|
||||||
# Z3 Project definition
|
# Z3 Project definition
|
||||||
def init_project_def():
|
def init_project_def():
|
||||||
set_version(4, 8, 0, 0)
|
set_version(4, 8, 0, 0)
|
||||||
add_lib('util', [])
|
add_lib('util', [], includes2install = ['z3_version.h'])
|
||||||
add_lib('polynomial', ['util'], 'math/polynomial')
|
add_lib('polynomial', ['util'], 'math/polynomial')
|
||||||
add_lib('sat', ['util'])
|
add_lib('sat', ['util'])
|
||||||
add_lib('nlsat', ['polynomial', 'sat'])
|
add_lib('nlsat', ['polynomial', 'sat'])
|
||||||
|
|
|
@ -396,7 +396,7 @@ def check_java():
|
||||||
libdirs = m.group(1).split(',')
|
libdirs = m.group(1).split(',')
|
||||||
for libdir in libdirs:
|
for libdir in libdirs:
|
||||||
q = os.path.dirname(libdir)
|
q = os.path.dirname(libdir)
|
||||||
if cdirs.count(q) == 0:
|
if cdirs.count(q) == 0 and len(q) > 0:
|
||||||
cdirs.append(q)
|
cdirs.append(q)
|
||||||
t.close()
|
t.close()
|
||||||
|
|
||||||
|
@ -1668,9 +1668,6 @@ class DotNetDLLComponent(Component):
|
||||||
'/noconfig',
|
'/noconfig',
|
||||||
'/nostdlib+',
|
'/nostdlib+',
|
||||||
'/reference:mscorlib.dll',
|
'/reference:mscorlib.dll',
|
||||||
# Under mono this isn't neccessary as mono will search the system
|
|
||||||
# library paths for libz3.so
|
|
||||||
'/linkresource:{}.dll'.format(get_component(Z3_DLL_COMPONENT).dll_name),
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2805,8 +2802,8 @@ def get_full_version_string(major, minor, build, revision):
|
||||||
# Update files with the version number
|
# Update files with the version number
|
||||||
def mk_version_dot_h(major, minor, build, revision):
|
def mk_version_dot_h(major, minor, build, revision):
|
||||||
c = get_component(UTIL_COMPONENT)
|
c = get_component(UTIL_COMPONENT)
|
||||||
version_template = os.path.join(c.src_dir, 'version.h.in')
|
version_template = os.path.join(c.src_dir, 'z3_version.h.in')
|
||||||
version_header_output = os.path.join(c.src_dir, 'version.h')
|
version_header_output = os.path.join(c.src_dir, 'z3_version.h')
|
||||||
# Note the substitution names are what is used by the CMake
|
# Note the substitution names are what is used by the CMake
|
||||||
# builds system. If you change these you should change them
|
# builds system. If you change these you should change them
|
||||||
# in the CMake build too
|
# in the CMake build too
|
||||||
|
|
|
@ -166,6 +166,8 @@ foreach (header ${libz3_public_headers})
|
||||||
set_property(TARGET libz3 APPEND PROPERTY
|
set_property(TARGET libz3 APPEND PROPERTY
|
||||||
PUBLIC_HEADER "${CMAKE_SOURCE_DIR}/src/api/${header}")
|
PUBLIC_HEADER "${CMAKE_SOURCE_DIR}/src/api/${header}")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
set_property(TARGET libz3 APPEND PROPERTY
|
||||||
|
PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/util/z3_version.h")
|
||||||
|
|
||||||
install(TARGETS libz3
|
install(TARGETS libz3
|
||||||
EXPORT Z3_EXPORTED_TARGETS
|
EXPORT Z3_EXPORTED_TARGETS
|
||||||
|
|
|
@ -468,7 +468,7 @@ extern "C" {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_get_decl_symbol_parameter(c, d, idx);
|
LOG_Z3_get_decl_symbol_parameter(c, d, idx);
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
CHECK_VALID_AST(d, 0);
|
CHECK_VALID_AST(d, nullptr);
|
||||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -486,7 +486,7 @@ extern "C" {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_get_decl_sort_parameter(c, d, idx);
|
LOG_Z3_get_decl_sort_parameter(c, d, idx);
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
CHECK_VALID_AST(d, 0);
|
CHECK_VALID_AST(d, nullptr);
|
||||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||||
RETURN_Z3(nullptr);
|
RETURN_Z3(nullptr);
|
||||||
|
@ -504,7 +504,7 @@ extern "C" {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_get_decl_ast_parameter(c, d, idx);
|
LOG_Z3_get_decl_ast_parameter(c, d, idx);
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
CHECK_VALID_AST(d, 0);
|
CHECK_VALID_AST(d, nullptr);
|
||||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||||
RETURN_Z3(nullptr);
|
RETURN_Z3(nullptr);
|
||||||
|
@ -522,7 +522,7 @@ extern "C" {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_get_decl_func_decl_parameter(c, d, idx);
|
LOG_Z3_get_decl_func_decl_parameter(c, d, idx);
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
CHECK_VALID_AST(d, 0);
|
CHECK_VALID_AST(d, nullptr);
|
||||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||||
RETURN_Z3(nullptr);
|
RETURN_Z3(nullptr);
|
||||||
|
@ -596,7 +596,7 @@ extern "C" {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_get_domain(c, d, i);
|
LOG_Z3_get_domain(c, d, i);
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
CHECK_VALID_AST(d, 0);
|
CHECK_VALID_AST(d, nullptr);
|
||||||
if (i >= to_func_decl(d)->get_arity()) {
|
if (i >= to_func_decl(d)->get_arity()) {
|
||||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||||
RETURN_Z3(nullptr);
|
RETURN_Z3(nullptr);
|
||||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
||||||
--*/
|
--*/
|
||||||
#include<typeinfo>
|
#include<typeinfo>
|
||||||
#include "api/api_context.h"
|
#include "api/api_context.h"
|
||||||
#include "util/version.h"
|
#include "util/z3_version.h"
|
||||||
#include "ast/ast_pp.h"
|
#include "ast/ast_pp.h"
|
||||||
#include "ast/ast_ll_pp.h"
|
#include "ast/ast_ll_pp.h"
|
||||||
#include "api/api_log_macros.h"
|
#include "api/api_log_macros.h"
|
||||||
|
|
|
@ -379,10 +379,8 @@ extern "C" {
|
||||||
for (unsigned i = 0; i < coll.m_rules.size(); ++i) {
|
for (unsigned i = 0; i < coll.m_rules.size(); ++i) {
|
||||||
to_fixedpoint_ref(d)->add_rule(coll.m_rules[i].get(), coll.m_names[i]);
|
to_fixedpoint_ref(d)->add_rule(coll.m_rules[i].get(), coll.m_names[i]);
|
||||||
}
|
}
|
||||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
for (expr * e : ctx.assertions()) {
|
||||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
to_fixedpoint_ref(d)->ctx().assert_expr(e);
|
||||||
for (; it != end; ++it) {
|
|
||||||
to_fixedpoint_ref(d)->ctx().assert_expr(*it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return of_ast_vector(v);
|
return of_ast_vector(v);
|
||||||
|
@ -717,5 +715,4 @@ extern "C" {
|
||||||
Z3_CATCH_RETURN(nullptr);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*++
|
|
||||||
Copyright (c) 2017 Arie Gurfinkel
|
|
||||||
|
|
||||||
Module Name:
|
|
||||||
|
|
||||||
api_datalog_spacer.inc
|
|
||||||
|
|
||||||
Abstract:
|
|
||||||
|
|
||||||
Spacer-specific datalog API
|
|
||||||
|
|
||||||
Author:
|
|
||||||
|
|
||||||
Arie Gurfinkel (arie)
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
this file is included at the bottom of api_datalog.cpp
|
|
||||||
|
|
||||||
--*/
|
|
||||||
Z3_lbool Z3_API Z3_fixedpoint_query_from_lvl (Z3_context c, Z3_fixedpoint d, Z3_ast q, unsigned lvl) {
|
|
||||||
Z3_TRY;
|
|
||||||
LOG_Z3_fixedpoint_query_from_lvl (c, d, q, lvl);
|
|
||||||
RESET_ERROR_CODE();
|
|
||||||
lbool r = l_undef;
|
|
||||||
unsigned timeout = to_fixedpoint(d)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
|
|
||||||
unsigned rlimit = to_fixedpoint(d)->m_params.get_uint("rlimit", mk_c(c)->get_rlimit());
|
|
||||||
{
|
|
||||||
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
|
|
||||||
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
|
|
||||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
|
||||||
scoped_timer timer(timeout, &eh);
|
|
||||||
try {
|
|
||||||
r = to_fixedpoint_ref(d)->ctx().query_from_lvl (to_expr(q), lvl);
|
|
||||||
}
|
|
||||||
catch (z3_exception& ex) {
|
|
||||||
mk_c(c)->handle_exception(ex);
|
|
||||||
r = l_undef;
|
|
||||||
}
|
|
||||||
to_fixedpoint_ref(d)->ctx().cleanup();
|
|
||||||
}
|
|
||||||
return of_lbool(r);
|
|
||||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
|
||||||
}
|
|
||||||
|
|
||||||
Z3_ast Z3_API Z3_fixedpoint_get_ground_sat_answer(Z3_context c, Z3_fixedpoint d) {
|
|
||||||
Z3_TRY;
|
|
||||||
LOG_Z3_fixedpoint_get_ground_sat_answer(c, d);
|
|
||||||
RESET_ERROR_CODE();
|
|
||||||
expr* e = to_fixedpoint_ref(d)->ctx().get_ground_sat_answer();
|
|
||||||
mk_c(c)->save_ast_trail(e);
|
|
||||||
RETURN_Z3(of_expr(e));
|
|
||||||
Z3_CATCH_RETURN(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Z3_ast_vector Z3_API Z3_fixedpoint_get_rules_along_trace(
|
|
||||||
Z3_context c,
|
|
||||||
Z3_fixedpoint d)
|
|
||||||
{
|
|
||||||
Z3_TRY;
|
|
||||||
LOG_Z3_fixedpoint_get_rules_along_trace(c, d);
|
|
||||||
ast_manager& m = mk_c(c)->m();
|
|
||||||
Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
|
|
||||||
mk_c(c)->save_object(v);
|
|
||||||
expr_ref_vector rules(m);
|
|
||||||
svector<symbol> names;
|
|
||||||
|
|
||||||
to_fixedpoint_ref(d)->ctx().get_rules_along_trace_as_formulas(rules, names);
|
|
||||||
for (unsigned i = 0; i < rules.size(); ++i) {
|
|
||||||
v->m_ast_vector.push_back(rules[i].get());
|
|
||||||
}
|
|
||||||
RETURN_Z3(of_ast_vector(v));
|
|
||||||
Z3_CATCH_RETURN(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Z3_symbol Z3_API Z3_fixedpoint_get_rule_names_along_trace(
|
|
||||||
Z3_context c,
|
|
||||||
Z3_fixedpoint d)
|
|
||||||
{
|
|
||||||
Z3_TRY;
|
|
||||||
LOG_Z3_fixedpoint_get_rule_names_along_trace(c, d);
|
|
||||||
ast_manager& m = mk_c(c)->m();
|
|
||||||
Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, *mk_c(c), m);
|
|
||||||
mk_c(c)->save_object(v);
|
|
||||||
expr_ref_vector rules(m);
|
|
||||||
svector<symbol> names;
|
|
||||||
std::stringstream ss;
|
|
||||||
|
|
||||||
to_fixedpoint_ref(d)->ctx().get_rules_along_trace_as_formulas(rules, names);
|
|
||||||
for (unsigned i = 0; i < names.size(); ++i) {
|
|
||||||
ss << ";" << names[i].str();
|
|
||||||
}
|
|
||||||
RETURN_Z3(of_symbol(symbol(ss.str().substr(1).c_str())));
|
|
||||||
Z3_CATCH_RETURN(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Z3_API Z3_fixedpoint_add_invariant(Z3_context c, Z3_fixedpoint d, Z3_func_decl pred, Z3_ast property) {
|
|
||||||
Z3_TRY;
|
|
||||||
LOG_Z3_fixedpoint_add_invariant(c, d, pred, property);
|
|
||||||
RESET_ERROR_CODE();
|
|
||||||
to_fixedpoint_ref(d)->ctx ().add_invariant(to_func_decl(pred), to_expr(property));
|
|
||||||
Z3_CATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
Z3_ast Z3_API Z3_fixedpoint_get_reachable(Z3_context c, Z3_fixedpoint d, Z3_func_decl pred) {
|
|
||||||
Z3_TRY;
|
|
||||||
LOG_Z3_fixedpoint_get_reachable(c, d, pred);
|
|
||||||
RESET_ERROR_CODE();
|
|
||||||
expr_ref r = to_fixedpoint_ref(d)->ctx().get_reachable(to_func_decl(pred));
|
|
||||||
mk_c(c)->save_ast_trail(r);
|
|
||||||
RETURN_Z3(of_expr(r.get()));
|
|
||||||
Z3_CATCH_RETURN(nullptr);
|
|
||||||
}
|
|
||||||
|
|
|
@ -163,7 +163,7 @@ extern "C" {
|
||||||
if (to_goal_ref(g)->mc())
|
if (to_goal_ref(g)->mc())
|
||||||
(*to_goal_ref(g)->mc())(m_ref->m_model);
|
(*to_goal_ref(g)->mc())(m_ref->m_model);
|
||||||
RETURN_Z3(of_model(m_ref));
|
RETURN_Z3(of_model(m_ref));
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Z3_goal Z3_API Z3_goal_translate(Z3_context c, Z3_goal g, Z3_context target) {
|
Z3_goal Z3_API Z3_goal_translate(Z3_context c, Z3_goal g, Z3_context target) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
||||||
#include "api/z3.h"
|
#include "api/z3.h"
|
||||||
#include "api/api_log_macros.h"
|
#include "api/api_log_macros.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "util/version.h"
|
#include "util/z3_version.h"
|
||||||
|
|
||||||
std::ostream * g_z3_log = nullptr;
|
std::ostream * g_z3_log = nullptr;
|
||||||
bool g_z3_log_enabled = false;
|
bool g_z3_log_enabled = false;
|
||||||
|
|
|
@ -124,10 +124,16 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o) {
|
Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o, unsigned num_assumptions, Z3_ast const assumptions[]) {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_optimize_check(c, o);
|
LOG_Z3_optimize_check(c, o, num_assumptions, assumptions);
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
|
for (unsigned i = 0; i < num_assumptions; i++) {
|
||||||
|
if (!is_expr(to_ast(assumptions[i]))) {
|
||||||
|
SET_ERROR_CODE(Z3_INVALID_ARG, "assumption is not an expression");
|
||||||
|
return Z3_L_UNDEF;
|
||||||
|
}
|
||||||
|
}
|
||||||
lbool r = l_undef;
|
lbool r = l_undef;
|
||||||
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
|
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
|
||||||
unsigned timeout = to_optimize_ptr(o)->get_params().get_uint("timeout", mk_c(c)->get_timeout());
|
unsigned timeout = to_optimize_ptr(o)->get_params().get_uint("timeout", mk_c(c)->get_timeout());
|
||||||
|
@ -137,7 +143,9 @@ extern "C" {
|
||||||
scoped_timer timer(timeout, &eh);
|
scoped_timer timer(timeout, &eh);
|
||||||
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
|
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
|
||||||
try {
|
try {
|
||||||
r = to_optimize_ptr(o)->optimize();
|
expr_ref_vector asms(mk_c(c)->m());
|
||||||
|
asms.append(num_assumptions, to_exprs(assumptions));
|
||||||
|
r = to_optimize_ptr(o)->optimize(asms);
|
||||||
}
|
}
|
||||||
catch (z3_exception& ex) {
|
catch (z3_exception& ex) {
|
||||||
if (!mk_c(c)->m().canceled()) {
|
if (!mk_c(c)->m().canceled()) {
|
||||||
|
@ -157,6 +165,22 @@ extern "C" {
|
||||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Z3_ast_vector Z3_API Z3_optimize_get_unsat_core(Z3_context c, Z3_optimize o) {
|
||||||
|
Z3_TRY;
|
||||||
|
LOG_Z3_optimize_get_unsat_core(c, o);
|
||||||
|
RESET_ERROR_CODE();
|
||||||
|
expr_ref_vector core(mk_c(c)->m());
|
||||||
|
to_optimize_ptr(o)->get_unsat_core(core);
|
||||||
|
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||||
|
mk_c(c)->save_object(v);
|
||||||
|
for (expr* e : core) {
|
||||||
|
v->m_ast_vector.push_back(e);
|
||||||
|
}
|
||||||
|
RETURN_Z3(of_ast_vector(v));
|
||||||
|
Z3_CATCH_RETURN(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Z3_string Z3_API Z3_optimize_get_reason_unknown(Z3_context c, Z3_optimize o) {
|
Z3_string Z3_API Z3_optimize_get_reason_unknown(Z3_context c, Z3_optimize o) {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_optimize_to_string(c, o);
|
LOG_Z3_optimize_to_string(c, o);
|
||||||
|
@ -330,10 +354,8 @@ extern "C" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
for (expr * e : ctx->assertions()) {
|
||||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
to_optimize_ptr(opt)->add_hard_constraint(e);
|
||||||
for (; it != end; ++it) {
|
|
||||||
to_optimize_ptr(opt)->add_hard_constraint(*it);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,10 +71,8 @@ extern "C" {
|
||||||
SET_ERROR_CODE(Z3_PARSER_ERROR, errstrm.str().c_str());
|
SET_ERROR_CODE(Z3_PARSER_ERROR, errstrm.str().c_str());
|
||||||
return of_ast_vector(v);
|
return of_ast_vector(v);
|
||||||
}
|
}
|
||||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
for (expr * e : ctx->assertions()) {
|
||||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
v->m_ast_vector.push_back(e);
|
||||||
for (; it != end; ++it) {
|
|
||||||
v->m_ast_vector.push_back(*it);
|
|
||||||
}
|
}
|
||||||
return of_ast_vector(v);
|
return of_ast_vector(v);
|
||||||
Z3_CATCH_RETURN(nullptr);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*++
|
/*++
|
||||||
Copyright (c) 2018 Microsoft Corporation
|
Copyright (c) Microsoft Corporation, Arie Gurfinkel 2017
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
|
@ -70,39 +70,39 @@ extern "C"
|
||||||
}
|
}
|
||||||
|
|
||||||
Z3_ast Z3_API Z3_qe_model_project_skolem (Z3_context c,
|
Z3_ast Z3_API Z3_qe_model_project_skolem (Z3_context c,
|
||||||
Z3_model m,
|
Z3_model mdl,
|
||||||
unsigned num_bounds,
|
unsigned num_bounds,
|
||||||
Z3_app const bound[],
|
Z3_app const bound[],
|
||||||
Z3_ast body,
|
Z3_ast body,
|
||||||
Z3_ast_map map)
|
Z3_ast_map map)
|
||||||
{
|
{
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_qe_model_project_skolem (c, m, num_bounds, bound, body, map);
|
LOG_Z3_qe_model_project_skolem (c, mdl, num_bounds, bound, body, map);
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
|
|
||||||
ast_manager& man = mk_c(c)->m ();
|
ast_manager& m = mk_c(c)->m();
|
||||||
app_ref_vector vars(man);
|
app_ref_vector vars(m);
|
||||||
if (!to_apps(num_bounds, bound, vars)) {
|
if (!to_apps(num_bounds, bound, vars)) {
|
||||||
RETURN_Z3(nullptr);
|
RETURN_Z3(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_ref result (mk_c(c)->m ());
|
expr_ref result (m);
|
||||||
result = to_expr (body);
|
result = to_expr (body);
|
||||||
model_ref model (to_model_ref (m));
|
model_ref model (to_model_ref (mdl));
|
||||||
expr_map emap (man);
|
expr_map emap (m);
|
||||||
|
|
||||||
spacer::qe_project (mk_c(c)->m (), vars, result, model, emap);
|
spacer::qe_project(m, vars, result, model, emap);
|
||||||
mk_c(c)->save_ast_trail (result.get ());
|
mk_c(c)->save_ast_trail(result);
|
||||||
|
|
||||||
obj_map<ast, ast*> &map_z3 = to_ast_map_ref(map);
|
obj_map<ast, ast*> &map_z3 = to_ast_map_ref(map);
|
||||||
|
|
||||||
for (expr_map::iterator it = emap.begin(), end = emap.end(); it != end; ++it){
|
for (auto& kv : emap) {
|
||||||
man.inc_ref(&(it->get_key()));
|
m.inc_ref(kv.m_key);
|
||||||
man.inc_ref(it->get_value());
|
m.inc_ref(kv.m_value);
|
||||||
map_z3.insert(&(it->get_key()), it->get_value());
|
map_z3.insert(kv.m_key, kv.m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return of_expr (result.get ());
|
return of_expr (result);
|
||||||
Z3_CATCH_RETURN(nullptr);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,9 +124,9 @@ extern "C"
|
||||||
|
|
||||||
expr_ref result (mk_c(c)->m ());
|
expr_ref result (mk_c(c)->m ());
|
||||||
result = mk_and (lits);
|
result = mk_and (lits);
|
||||||
mk_c(c)->save_ast_trail (result.get ());
|
mk_c(c)->save_ast_trail (result);
|
||||||
|
|
||||||
return of_expr (result.get ());
|
return of_expr (result);
|
||||||
Z3_CATCH_RETURN(nullptr);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,8 +138,8 @@ extern "C"
|
||||||
ast_ref_vector &vVars = to_ast_vector_ref (vars);
|
ast_ref_vector &vVars = to_ast_vector_ref (vars);
|
||||||
|
|
||||||
app_ref_vector vApps (mk_c(c)->m());
|
app_ref_vector vApps (mk_c(c)->m());
|
||||||
for (unsigned i = 0; i < vVars.size (); ++i) {
|
for (ast* v : vVars) {
|
||||||
app *a = to_app (vVars.get (i));
|
app * a = to_app(v);
|
||||||
if (a->get_kind () != AST_APP) {
|
if (a->get_kind () != AST_APP) {
|
||||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||||
RETURN_Z3(nullptr);
|
RETURN_Z3(nullptr);
|
||||||
|
@ -162,7 +162,7 @@ extern "C"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mk_c(c)->save_ast_trail (result.get ());
|
mk_c(c)->save_ast_trail (result);
|
||||||
return of_expr (result);
|
return of_expr (result);
|
||||||
Z3_CATCH_RETURN(nullptr);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ extern "C" {
|
||||||
expr_ref result(mk_c(c)->m());
|
expr_ref result(mk_c(c)->m());
|
||||||
if (num_decls == 0) {
|
if (num_decls == 0) {
|
||||||
SET_ERROR_CODE(Z3_INVALID_USAGE, nullptr);
|
SET_ERROR_CODE(Z3_INVALID_USAGE, nullptr);
|
||||||
RETURN_Z3(0);
|
RETURN_Z3(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
sort* const* ts = reinterpret_cast<sort * const*>(types);
|
sort* const* ts = reinterpret_cast<sort * const*>(types);
|
||||||
|
@ -166,7 +166,7 @@ extern "C" {
|
||||||
result = mk_c(c)->m().mk_lambda(names.size(), ts, names.c_ptr(), to_expr(body));
|
result = mk_c(c)->m().mk_lambda(names.size(), ts, names.c_ptr(), to_expr(body));
|
||||||
mk_c(c)->save_ast_trail(result.get());
|
mk_c(c)->save_ast_trail(result.get());
|
||||||
return of_ast(result.get());
|
return of_ast(result.get());
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Z3_ast Z3_API Z3_mk_lambda_const(Z3_context c,
|
Z3_ast Z3_API Z3_mk_lambda_const(Z3_context c,
|
||||||
|
@ -178,7 +178,7 @@ extern "C" {
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
if (num_decls == 0) {
|
if (num_decls == 0) {
|
||||||
SET_ERROR_CODE(Z3_INVALID_USAGE, nullptr);
|
SET_ERROR_CODE(Z3_INVALID_USAGE, nullptr);
|
||||||
RETURN_Z3(0);
|
RETURN_Z3(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
svector<symbol> _names;
|
svector<symbol> _names;
|
||||||
|
@ -196,7 +196,7 @@ extern "C" {
|
||||||
result = mk_c(c)->m().mk_lambda(_vars.size(), _vars.c_ptr(), _names.c_ptr(), result);
|
result = mk_c(c)->m().mk_lambda(_vars.size(), _vars.c_ptr(), _names.c_ptr(), result);
|
||||||
mk_c(c)->save_ast_trail(result.get());
|
mk_c(c)->save_ast_trail(result.get());
|
||||||
return of_ast(result.get());
|
return of_ast(result.get());
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -157,10 +157,8 @@ extern "C" {
|
||||||
bool initialized = to_solver(s)->m_solver.get() != nullptr;
|
bool initialized = to_solver(s)->m_solver.get() != nullptr;
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
init_solver(c, s);
|
init_solver(c, s);
|
||||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
for (expr * e : ctx->assertions()) {
|
||||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
to_solver_ref(s)->assert_expr(e);
|
||||||
for (; it != end; ++it) {
|
|
||||||
to_solver_ref(s)->assert_expr(*it);
|
|
||||||
}
|
}
|
||||||
to_solver_ref(s)->set_model_converter(ctx->get_model_converter());
|
to_solver_ref(s)->set_model_converter(ctx->get_model_converter());
|
||||||
}
|
}
|
||||||
|
@ -179,6 +177,7 @@ extern "C" {
|
||||||
LOG_Z3_solver_from_file(c, s, file_name);
|
LOG_Z3_solver_from_file(c, s, file_name);
|
||||||
char const* ext = get_extension(file_name);
|
char const* ext = get_extension(file_name);
|
||||||
std::ifstream is(file_name);
|
std::ifstream is(file_name);
|
||||||
|
init_solver(c, s);
|
||||||
if (!is) {
|
if (!is) {
|
||||||
SET_ERROR_CODE(Z3_FILE_ACCESS_ERROR, nullptr);
|
SET_ERROR_CODE(Z3_FILE_ACCESS_ERROR, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -368,7 +367,22 @@ extern "C" {
|
||||||
v->m_ast_vector.push_back(f);
|
v->m_ast_vector.push_back(f);
|
||||||
}
|
}
|
||||||
RETURN_Z3(of_ast_vector(v));
|
RETURN_Z3(of_ast_vector(v));
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Z3_ast_vector Z3_API Z3_solver_get_non_units(Z3_context c, Z3_solver s) {
|
||||||
|
Z3_TRY;
|
||||||
|
LOG_Z3_solver_get_non_units(c, s);
|
||||||
|
RESET_ERROR_CODE();
|
||||||
|
init_solver(c, s);
|
||||||
|
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||||
|
mk_c(c)->save_object(v);
|
||||||
|
expr_ref_vector fmls = to_solver_ref(s)->get_non_units(mk_c(c)->m());
|
||||||
|
for (expr* f : fmls) {
|
||||||
|
v->m_ast_vector.push_back(f);
|
||||||
|
}
|
||||||
|
RETURN_Z3(of_ast_vector(v));
|
||||||
|
Z3_CATCH_RETURN(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Z3_lbool _solver_check(Z3_context c, Z3_solver s, unsigned num_assumptions, Z3_ast const assumptions[]) {
|
static Z3_lbool _solver_check(Z3_context c, Z3_solver s, unsigned num_assumptions, Z3_ast const assumptions[]) {
|
||||||
|
@ -615,7 +629,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
catch (z3_exception & ex) {
|
catch (z3_exception & ex) {
|
||||||
mk_c(c)->handle_exception(ex);
|
mk_c(c)->handle_exception(ex);
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||||
|
@ -628,7 +642,7 @@ extern "C" {
|
||||||
to_ast_vector_ref(vs).push_back(a);
|
to_ast_vector_ref(vs).push_back(a);
|
||||||
}
|
}
|
||||||
RETURN_Z3(of_ast_vector(v));
|
RETURN_Z3(of_ast_vector(v));
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,14 @@ namespace z3 {
|
||||||
unsat, sat, unknown
|
unsat, sat, unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum rounding_mode {
|
||||||
|
RNA,
|
||||||
|
RNE,
|
||||||
|
RTP,
|
||||||
|
RTN,
|
||||||
|
RTZ
|
||||||
|
};
|
||||||
|
|
||||||
inline check_result to_check_result(Z3_lbool l) {
|
inline check_result to_check_result(Z3_lbool l) {
|
||||||
if (l == Z3_L_TRUE) return sat;
|
if (l == Z3_L_TRUE) return sat;
|
||||||
else if (l == Z3_L_FALSE) return unsat;
|
else if (l == Z3_L_FALSE) return unsat;
|
||||||
|
@ -137,12 +145,17 @@ namespace z3 {
|
||||||
/**
|
/**
|
||||||
\brief A Context manages all other Z3 objects, global configuration options, etc.
|
\brief A Context manages all other Z3 objects, global configuration options, etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
class context {
|
class context {
|
||||||
|
private:
|
||||||
bool m_enable_exceptions;
|
bool m_enable_exceptions;
|
||||||
|
rounding_mode m_rounding_mode;
|
||||||
Z3_context m_ctx;
|
Z3_context m_ctx;
|
||||||
void init(config & c) {
|
void init(config & c) {
|
||||||
m_ctx = Z3_mk_context_rc(c);
|
m_ctx = Z3_mk_context_rc(c);
|
||||||
m_enable_exceptions = true;
|
m_enable_exceptions = true;
|
||||||
|
m_rounding_mode = RNA;
|
||||||
Z3_set_error_handler(m_ctx, 0);
|
Z3_set_error_handler(m_ctx, 0);
|
||||||
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||||
}
|
}
|
||||||
|
@ -247,6 +260,26 @@ namespace z3 {
|
||||||
*/
|
*/
|
||||||
sort array_sort(sort d, sort r);
|
sort array_sort(sort d, sort r);
|
||||||
sort array_sort(sort_vector const& d, sort r);
|
sort array_sort(sort_vector const& d, sort r);
|
||||||
|
/**
|
||||||
|
\brief Return a floating point sort.
|
||||||
|
\c ebits is a number of exponent bits,
|
||||||
|
\c sbits is a number of significand bits,
|
||||||
|
\pre where ebits must be larger than 1 and sbits must be larger than 2.
|
||||||
|
*/
|
||||||
|
sort fpa_sort(unsigned ebits, unsigned sbits);
|
||||||
|
/**
|
||||||
|
\brief Return a FloatingPoint sort with given precision bitwidth (16, 32, 64 or 128).
|
||||||
|
*/
|
||||||
|
template<size_t precision>
|
||||||
|
sort fpa_sort();
|
||||||
|
/**
|
||||||
|
\brief Return a RoundingMode sort.
|
||||||
|
*/
|
||||||
|
sort fpa_rounding_mode();
|
||||||
|
/**
|
||||||
|
\breif Sets RoundingMode of FloatingPoints.
|
||||||
|
*/
|
||||||
|
void set_rounding_mode(rounding_mode rm);
|
||||||
/**
|
/**
|
||||||
\brief Return an enumeration sort: enum_names[0], ..., enum_names[n-1].
|
\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,
|
\c cs and \c ts are output parameters. The method stores in \c cs the constants corresponding to the enumerated elements,
|
||||||
|
@ -284,6 +317,10 @@ namespace z3 {
|
||||||
expr int_const(char const * name);
|
expr int_const(char const * name);
|
||||||
expr real_const(char const * name);
|
expr real_const(char const * name);
|
||||||
expr bv_const(char const * name, unsigned sz);
|
expr bv_const(char const * name, unsigned sz);
|
||||||
|
expr fpa_const(char const * name, unsigned ebits, unsigned sbits);
|
||||||
|
|
||||||
|
template<size_t precision>
|
||||||
|
expr fpa_const(char const * name);
|
||||||
|
|
||||||
expr bool_val(bool b);
|
expr bool_val(bool b);
|
||||||
|
|
||||||
|
@ -307,6 +344,9 @@ namespace z3 {
|
||||||
expr bv_val(char const * n, unsigned sz);
|
expr bv_val(char const * n, unsigned sz);
|
||||||
expr bv_val(unsigned n, bool const* bits);
|
expr bv_val(unsigned n, bool const* bits);
|
||||||
|
|
||||||
|
expr fpa_val(double n);
|
||||||
|
expr fpa_val(float n);
|
||||||
|
|
||||||
expr string_val(char const* s);
|
expr string_val(char const* s);
|
||||||
expr string_val(std::string const& s);
|
expr string_val(std::string const& s);
|
||||||
|
|
||||||
|
@ -465,6 +505,7 @@ namespace z3 {
|
||||||
public:
|
public:
|
||||||
sort(context & c):ast(c) {}
|
sort(context & c):ast(c) {}
|
||||||
sort(context & c, Z3_sort s):ast(c, reinterpret_cast<Z3_ast>(s)) {}
|
sort(context & c, Z3_sort s):ast(c, reinterpret_cast<Z3_ast>(s)) {}
|
||||||
|
sort(context & c, Z3_ast a):ast(c, a) {}
|
||||||
sort(sort const & s):ast(s) {}
|
sort(sort const & s):ast(s) {}
|
||||||
operator Z3_sort() const { return reinterpret_cast<Z3_sort>(m_ast); }
|
operator Z3_sort() const { return reinterpret_cast<Z3_sort>(m_ast); }
|
||||||
/**
|
/**
|
||||||
|
@ -523,6 +564,10 @@ namespace z3 {
|
||||||
\brief Return true if this sort is a Finite domain sort.
|
\brief Return true if this sort is a Finite domain sort.
|
||||||
*/
|
*/
|
||||||
bool is_finite_domain() const { return sort_kind() == Z3_FINITE_DOMAIN_SORT; }
|
bool is_finite_domain() const { return sort_kind() == Z3_FINITE_DOMAIN_SORT; }
|
||||||
|
/**
|
||||||
|
\brief Return true if this sort is a Floating point sort.
|
||||||
|
*/
|
||||||
|
bool is_fpa() const { return sort_kind() == Z3_FLOATING_POINT_SORT; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return the size of this Bit-vector sort.
|
\brief Return the size of this Bit-vector sort.
|
||||||
|
@ -531,6 +576,9 @@ namespace z3 {
|
||||||
*/
|
*/
|
||||||
unsigned bv_size() const { assert(is_bv()); unsigned r = Z3_get_bv_sort_size(ctx(), *this); check_error(); return r; }
|
unsigned bv_size() const { assert(is_bv()); unsigned r = Z3_get_bv_sort_size(ctx(), *this); check_error(); return r; }
|
||||||
|
|
||||||
|
unsigned fpa_ebits() const { assert(is_fpa()); unsigned r = Z3_fpa_get_ebits(ctx(), *this); check_error(); return r; }
|
||||||
|
|
||||||
|
unsigned fpa_sbits() const { assert(is_fpa()); unsigned r = Z3_fpa_get_sbits(ctx(), *this); check_error(); return r; }
|
||||||
/**
|
/**
|
||||||
\brief Return the domain of this Array sort.
|
\brief Return the domain of this Array sort.
|
||||||
|
|
||||||
|
@ -644,6 +692,10 @@ namespace z3 {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
bool is_finite_domain() const { return get_sort().is_finite_domain(); }
|
bool is_finite_domain() const { return get_sort().is_finite_domain(); }
|
||||||
|
/**
|
||||||
|
\brief Return true if this is a FloatingPoint expression. .
|
||||||
|
*/
|
||||||
|
bool is_fpa() const { return get_sort().is_fpa(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return true if this expression is a numeral.
|
\brief Return true if this expression is a numeral.
|
||||||
|
@ -803,6 +855,17 @@ namespace z3 {
|
||||||
|
|
||||||
operator Z3_app() const { assert(is_app()); return reinterpret_cast<Z3_app>(m_ast); }
|
operator Z3_app() const { assert(is_app()); return reinterpret_cast<Z3_app>(m_ast); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Return a RoundingMode sort.
|
||||||
|
*/
|
||||||
|
sort fpa_rounding_mode() {
|
||||||
|
assert(is_fpa());
|
||||||
|
Z3_sort s = ctx().fpa_rounding_mode();
|
||||||
|
check_error();
|
||||||
|
return sort(ctx(), s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return the declaration associated with this application.
|
\brief Return the declaration associated with this application.
|
||||||
This method assumes the expression is an application.
|
This method assumes the expression is an application.
|
||||||
|
@ -992,15 +1055,26 @@ namespace z3 {
|
||||||
friend expr nor(expr const& a, expr const& b);
|
friend expr nor(expr const& a, expr const& b);
|
||||||
friend expr xnor(expr const& a, expr const& b);
|
friend expr xnor(expr const& a, expr const& b);
|
||||||
|
|
||||||
|
friend expr min(expr const& a, expr const& b);
|
||||||
|
friend expr max(expr const& a, expr const& b);
|
||||||
|
|
||||||
expr rotate_left(unsigned i) { Z3_ast r = Z3_mk_rotate_left(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
|
expr rotate_left(unsigned i) { Z3_ast r = Z3_mk_rotate_left(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
|
||||||
expr rotate_right(unsigned i) { Z3_ast r = Z3_mk_rotate_right(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
|
expr rotate_right(unsigned i) { Z3_ast r = Z3_mk_rotate_right(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
|
||||||
expr repeat(unsigned i) { Z3_ast r = Z3_mk_repeat(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
|
expr repeat(unsigned i) { Z3_ast r = Z3_mk_repeat(ctx(), i, *this); ctx().check_error(); return expr(ctx(), r); }
|
||||||
|
|
||||||
|
friend expr abs(expr const & a);
|
||||||
|
friend expr sqrt(expr const & a, expr const & rm);
|
||||||
|
|
||||||
friend expr operator~(expr const & a);
|
friend expr operator~(expr const & a);
|
||||||
expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); ctx().check_error(); return expr(ctx(), r); }
|
expr extract(unsigned hi, unsigned lo) const { Z3_ast r = Z3_mk_extract(ctx(), hi, lo, *this); ctx().check_error(); return expr(ctx(), r); }
|
||||||
unsigned lo() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 1)); }
|
unsigned lo() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 1)); }
|
||||||
unsigned hi() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 0)); }
|
unsigned hi() const { assert (is_app() && Z3_get_decl_num_parameters(ctx(), decl()) == 2); return static_cast<unsigned>(Z3_get_decl_int_parameter(ctx(), decl(), 0)); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief FloatingPoint fused multiply-add.
|
||||||
|
*/
|
||||||
|
friend expr fma(expr const& a, expr const& b, expr const& c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief sequence and regular expression operations.
|
\brief sequence and regular expression operations.
|
||||||
+ is overloaded as sequence concatenation and regular expression union.
|
+ is overloaded as sequence concatenation and regular expression union.
|
||||||
|
@ -1109,7 +1183,13 @@ namespace z3 {
|
||||||
inline expr mod(expr const & a, int b) { return mod(a, a.ctx().num_val(b, a.get_sort())); }
|
inline expr mod(expr const & a, int b) { return mod(a, a.ctx().num_val(b, a.get_sort())); }
|
||||||
inline expr mod(int a, expr const & b) { return mod(b.ctx().num_val(a, b.get_sort()), b); }
|
inline expr mod(int a, expr const & b) { return mod(b.ctx().num_val(a, b.get_sort()), b); }
|
||||||
|
|
||||||
inline expr rem(expr const& a, expr const& b) { _Z3_MK_BIN_(a, b, Z3_mk_rem); }
|
inline expr rem(expr const& a, expr const& b) {
|
||||||
|
if (a.is_fpa() && b.is_fpa()) {
|
||||||
|
_Z3_MK_BIN_(a, b, Z3_mk_fpa_rem);
|
||||||
|
} else {
|
||||||
|
_Z3_MK_BIN_(a, b, Z3_mk_rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
inline expr rem(expr const & a, int b) { return rem(a, a.ctx().num_val(b, a.get_sort())); }
|
inline expr rem(expr const & a, int b) { return rem(a, a.ctx().num_val(b, a.get_sort())); }
|
||||||
inline expr rem(int a, expr const & b) { return rem(b.ctx().num_val(a, b.get_sort()), b); }
|
inline expr rem(int a, expr const & b) { return rem(b.ctx().num_val(a, b.get_sort()), b); }
|
||||||
|
|
||||||
|
@ -1158,8 +1238,8 @@ namespace z3 {
|
||||||
a.check_error();
|
a.check_error();
|
||||||
return expr(a.ctx(), r);
|
return expr(a.ctx(), r);
|
||||||
}
|
}
|
||||||
inline expr operator==(expr const & a, int b) { assert(a.is_arith() || a.is_bv()); return a == a.ctx().num_val(b, a.get_sort()); }
|
inline expr operator==(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a == a.ctx().num_val(b, a.get_sort()); }
|
||||||
inline expr operator==(int a, expr const & b) { assert(b.is_arith() || b.is_bv()); return b.ctx().num_val(a, b.get_sort()) == b; }
|
inline expr operator==(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) == b; }
|
||||||
|
|
||||||
inline expr operator!=(expr const & a, expr const & b) {
|
inline expr operator!=(expr const & a, expr const & b) {
|
||||||
check_context(a, b);
|
check_context(a, b);
|
||||||
|
@ -1168,8 +1248,8 @@ namespace z3 {
|
||||||
a.check_error();
|
a.check_error();
|
||||||
return expr(a.ctx(), r);
|
return expr(a.ctx(), r);
|
||||||
}
|
}
|
||||||
inline expr operator!=(expr const & a, int b) { assert(a.is_arith() || a.is_bv()); return a != a.ctx().num_val(b, a.get_sort()); }
|
inline expr operator!=(expr const & a, int b) { assert(a.is_arith() || a.is_bv() || a.is_fpa()); return a != a.ctx().num_val(b, a.get_sort()); }
|
||||||
inline expr operator!=(int a, expr const & b) { assert(b.is_arith() || b.is_bv()); return b.ctx().num_val(a, b.get_sort()) != b; }
|
inline expr operator!=(int a, expr const & b) { assert(b.is_arith() || b.is_bv() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) != b; }
|
||||||
|
|
||||||
inline expr operator+(expr const & a, expr const & b) {
|
inline expr operator+(expr const & a, expr const & b) {
|
||||||
check_context(a, b);
|
check_context(a, b);
|
||||||
|
@ -1188,6 +1268,9 @@ namespace z3 {
|
||||||
Z3_ast _args[2] = { a, b };
|
Z3_ast _args[2] = { a, b };
|
||||||
r = Z3_mk_re_union(a.ctx(), 2, _args);
|
r = Z3_mk_re_union(a.ctx(), 2, _args);
|
||||||
}
|
}
|
||||||
|
else if (a.is_fpa() && b.is_fpa()) {
|
||||||
|
r = Z3_mk_fpa_add(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// operator is not supported by given arguments.
|
// operator is not supported by given arguments.
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -1208,6 +1291,9 @@ namespace z3 {
|
||||||
else if (a.is_bv() && b.is_bv()) {
|
else if (a.is_bv() && b.is_bv()) {
|
||||||
r = Z3_mk_bvmul(a.ctx(), a, b);
|
r = Z3_mk_bvmul(a.ctx(), a, b);
|
||||||
}
|
}
|
||||||
|
else if (a.is_fpa() && b.is_fpa()) {
|
||||||
|
r = Z3_mk_fpa_mul(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// operator is not supported by given arguments.
|
// operator is not supported by given arguments.
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -1245,6 +1331,9 @@ namespace z3 {
|
||||||
else if (a.is_bv() && b.is_bv()) {
|
else if (a.is_bv() && b.is_bv()) {
|
||||||
r = Z3_mk_bvsdiv(a.ctx(), a, b);
|
r = Z3_mk_bvsdiv(a.ctx(), a, b);
|
||||||
}
|
}
|
||||||
|
else if (a.is_fpa() && b.is_fpa()) {
|
||||||
|
r = Z3_mk_fpa_div(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// operator is not supported by given arguments.
|
// operator is not supported by given arguments.
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -1263,6 +1352,9 @@ namespace z3 {
|
||||||
else if (a.is_bv()) {
|
else if (a.is_bv()) {
|
||||||
r = Z3_mk_bvneg(a.ctx(), a);
|
r = Z3_mk_bvneg(a.ctx(), a);
|
||||||
}
|
}
|
||||||
|
else if (a.is_fpa()) {
|
||||||
|
r = Z3_mk_fpa_neg(a.ctx(), a);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// operator is not supported by given arguments.
|
// operator is not supported by given arguments.
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -1281,6 +1373,9 @@ namespace z3 {
|
||||||
else if (a.is_bv() && b.is_bv()) {
|
else if (a.is_bv() && b.is_bv()) {
|
||||||
r = Z3_mk_bvsub(a.ctx(), a, b);
|
r = Z3_mk_bvsub(a.ctx(), a, b);
|
||||||
}
|
}
|
||||||
|
else if (a.is_fpa() && b.is_fpa()) {
|
||||||
|
r = Z3_mk_fpa_sub(a.ctx(), a.ctx().fpa_rounding_mode(), a, b);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// operator is not supported by given arguments.
|
// operator is not supported by given arguments.
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -1300,6 +1395,9 @@ namespace z3 {
|
||||||
else if (a.is_bv() && b.is_bv()) {
|
else if (a.is_bv() && b.is_bv()) {
|
||||||
r = Z3_mk_bvsle(a.ctx(), a, b);
|
r = Z3_mk_bvsle(a.ctx(), a, b);
|
||||||
}
|
}
|
||||||
|
else if (a.is_fpa() && b.is_fpa()) {
|
||||||
|
r = Z3_mk_fpa_leq(a.ctx(), a, b);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// operator is not supported by given arguments.
|
// operator is not supported by given arguments.
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -1322,6 +1420,9 @@ namespace z3 {
|
||||||
else if (a.is_bv() && b.is_bv()) {
|
else if (a.is_bv() && b.is_bv()) {
|
||||||
r = Z3_mk_bvslt(a.ctx(), a, b);
|
r = Z3_mk_bvslt(a.ctx(), a, b);
|
||||||
}
|
}
|
||||||
|
else if (a.is_fpa() && b.is_fpa()) {
|
||||||
|
r = Z3_mk_fpa_lt(a.ctx(), a, b);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// operator is not supported by given arguments.
|
// operator is not supported by given arguments.
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -1341,6 +1442,9 @@ namespace z3 {
|
||||||
else if (a.is_bv() && b.is_bv()) {
|
else if (a.is_bv() && b.is_bv()) {
|
||||||
r = Z3_mk_bvsgt(a.ctx(), a, b);
|
r = Z3_mk_bvsgt(a.ctx(), a, b);
|
||||||
}
|
}
|
||||||
|
else if (a.is_fpa() && b.is_fpa()) {
|
||||||
|
r = Z3_mk_fpa_gt(a.ctx(), a, b);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// operator is not supported by given arguments.
|
// operator is not supported by given arguments.
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -1366,17 +1470,30 @@ namespace z3 {
|
||||||
inline expr nand(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvnand(a.ctx(), a, b); return expr(a.ctx(), r); }
|
inline expr nand(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvnand(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||||
inline expr nor(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvnor(a.ctx(), a, b); return expr(a.ctx(), r); }
|
inline expr nor(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvnor(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||||
inline expr xnor(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvxnor(a.ctx(), a, b); return expr(a.ctx(), r); }
|
inline expr xnor(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_bvxnor(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||||
|
inline expr min(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_fpa_min(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||||
|
inline expr max(expr const& a, expr const& b) { check_context(a, b); Z3_ast r = Z3_mk_fpa_max(a.ctx(), a, b); return expr(a.ctx(), r); }
|
||||||
|
inline expr abs(expr const & a) { Z3_ast r = Z3_mk_fpa_abs(a.ctx(), a); return expr(a.ctx(), r); }
|
||||||
|
inline expr sqrt(expr const & a, expr const& rm) {
|
||||||
|
check_context(a, rm);
|
||||||
|
assert(a.is_fpa());
|
||||||
|
Z3_ast r = Z3_mk_fpa_sqrt(a.ctx(), rm, a);
|
||||||
|
return expr(a.ctx(), r);
|
||||||
|
}
|
||||||
inline expr operator~(expr const & a) { Z3_ast r = Z3_mk_bvnot(a.ctx(), a); return expr(a.ctx(), r); }
|
inline expr operator~(expr const & a) { Z3_ast r = Z3_mk_bvnot(a.ctx(), a); return expr(a.ctx(), r); }
|
||||||
|
|
||||||
|
inline expr fma(expr const& a, expr const& b, expr const& c, expr const& rm) {
|
||||||
|
check_context(a, b); check_context(a, c); check_context(a, rm);
|
||||||
|
assert(a.is_fpa() && b.is_fpa() && c.is_fpa());
|
||||||
|
Z3_ast r = Z3_mk_fpa_fma(a.ctx(), rm, a, b, c);
|
||||||
|
a.check_error();
|
||||||
|
return expr(a.ctx(), r);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Create the if-then-else expression <tt>ite(c, t, e)</tt>
|
\brief Create the if-then-else expression <tt>ite(c, t, e)</tt>
|
||||||
|
|
||||||
\pre c.is_bool()
|
\pre c.is_bool()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline expr ite(expr const & c, expr const & t, expr const & e) {
|
inline expr ite(expr const & c, expr const & t, expr const & e) {
|
||||||
check_context(c, t); check_context(c, e);
|
check_context(c, t); check_context(c, e);
|
||||||
assert(c.is_bool());
|
assert(c.is_bool());
|
||||||
|
@ -2038,6 +2155,8 @@ namespace z3 {
|
||||||
stats statistics() const { Z3_stats r = Z3_solver_get_statistics(ctx(), m_solver); check_error(); return stats(ctx(), r); }
|
stats statistics() const { Z3_stats r = Z3_solver_get_statistics(ctx(), m_solver); check_error(); return stats(ctx(), r); }
|
||||||
expr_vector unsat_core() const { Z3_ast_vector r = Z3_solver_get_unsat_core(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
expr_vector unsat_core() const { Z3_ast_vector r = Z3_solver_get_unsat_core(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
||||||
expr_vector assertions() const { Z3_ast_vector r = Z3_solver_get_assertions(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
expr_vector assertions() const { Z3_ast_vector r = Z3_solver_get_assertions(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
||||||
|
expr_vector non_units() const { Z3_ast_vector r = Z3_solver_get_non_units(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
||||||
|
expr_vector units() const { Z3_ast_vector r = Z3_solver_get_units(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); }
|
||||||
expr proof() const { Z3_ast r = Z3_solver_get_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); }
|
expr proof() const { Z3_ast r = Z3_solver_get_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); }
|
||||||
friend std::ostream & operator<<(std::ostream & out, solver const & s);
|
friend std::ostream & operator<<(std::ostream & out, solver const & s);
|
||||||
|
|
||||||
|
@ -2453,8 +2572,20 @@ namespace z3 {
|
||||||
void pop() {
|
void pop() {
|
||||||
Z3_optimize_pop(ctx(), m_opt);
|
Z3_optimize_pop(ctx(), m_opt);
|
||||||
}
|
}
|
||||||
check_result check() { Z3_lbool r = Z3_optimize_check(ctx(), m_opt); check_error(); return to_check_result(r); }
|
check_result check() { Z3_lbool r = Z3_optimize_check(ctx(), m_opt, 0, 0); check_error(); return to_check_result(r); }
|
||||||
|
check_result check(expr_vector const& asms) {
|
||||||
|
unsigned n = asms.size();
|
||||||
|
array<Z3_ast> _asms(n);
|
||||||
|
for (unsigned i = 0; i < n; i++) {
|
||||||
|
check_context(*this, asms[i]);
|
||||||
|
_asms[i] = asms[i];
|
||||||
|
}
|
||||||
|
Z3_lbool r = Z3_optimize_check(ctx(), m_opt, n, _asms.ptr());
|
||||||
|
check_error();
|
||||||
|
return to_check_result(r);
|
||||||
|
}
|
||||||
model get_model() const { Z3_model m = Z3_optimize_get_model(ctx(), m_opt); check_error(); return model(ctx(), m); }
|
model get_model() const { Z3_model m = Z3_optimize_get_model(ctx(), m_opt); check_error(); return model(ctx(), m); }
|
||||||
|
expr_vector unsat_core() const { Z3_ast_vector r = Z3_optimize_get_unsat_core(ctx(), m_opt); check_error(); return expr_vector(ctx(), r); }
|
||||||
void set(params const & p) { Z3_optimize_set_params(ctx(), m_opt, p); check_error(); }
|
void set(params const & p) { Z3_optimize_set_params(ctx(), m_opt, p); check_error(); }
|
||||||
expr lower(handle const& h) {
|
expr lower(handle const& h) {
|
||||||
Z3_ast r = Z3_optimize_get_lower(ctx(), m_opt, h.h());
|
Z3_ast r = Z3_optimize_get_lower(ctx(), m_opt, h.h());
|
||||||
|
@ -2548,6 +2679,32 @@ namespace z3 {
|
||||||
inline sort context::string_sort() { Z3_sort s = Z3_mk_string_sort(m_ctx); check_error(); return sort(*this, s); }
|
inline sort context::string_sort() { Z3_sort s = Z3_mk_string_sort(m_ctx); check_error(); return sort(*this, s); }
|
||||||
inline sort context::seq_sort(sort& s) { Z3_sort r = Z3_mk_seq_sort(m_ctx, s); check_error(); return sort(*this, r); }
|
inline sort context::seq_sort(sort& s) { Z3_sort r = Z3_mk_seq_sort(m_ctx, s); check_error(); return sort(*this, r); }
|
||||||
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::re_sort(sort& s) { Z3_sort r = Z3_mk_re_sort(m_ctx, s); check_error(); return sort(*this, r); }
|
||||||
|
inline sort context::fpa_sort(unsigned ebits, unsigned sbits) { Z3_sort s = Z3_mk_fpa_sort(m_ctx, ebits, sbits); check_error(); return sort(*this, s); }
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline sort context::fpa_sort<16>() { return fpa_sort(5, 11); }
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline sort context::fpa_sort<32>() { return fpa_sort(8, 24); }
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline sort context::fpa_sort<64>() { return fpa_sort(11, 53); }
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline sort context::fpa_sort<128>() { return fpa_sort(15, 113); }
|
||||||
|
|
||||||
|
inline sort context::fpa_rounding_mode() {
|
||||||
|
switch (m_rounding_mode) {
|
||||||
|
case RNA: return sort(*this, Z3_mk_fpa_rna(m_ctx));
|
||||||
|
case RNE: return sort(*this, Z3_mk_fpa_rne(m_ctx));
|
||||||
|
case RTP: return sort(*this, Z3_mk_fpa_rtp(m_ctx));
|
||||||
|
case RTN: return sort(*this, Z3_mk_fpa_rtn(m_ctx));
|
||||||
|
case RTZ: return sort(*this, Z3_mk_fpa_rtz(m_ctx));
|
||||||
|
default: return sort(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void context::set_rounding_mode(rounding_mode rm) { m_rounding_mode = rm; }
|
||||||
|
|
||||||
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 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) {
|
inline sort context::array_sort(sort_vector const& d, sort r) {
|
||||||
|
@ -2667,6 +2824,10 @@ namespace z3 {
|
||||||
inline expr context::int_const(char const * name) { return constant(name, int_sort()); }
|
inline expr context::int_const(char const * name) { return constant(name, int_sort()); }
|
||||||
inline expr context::real_const(char const * name) { return constant(name, real_sort()); }
|
inline expr context::real_const(char const * name) { return constant(name, real_sort()); }
|
||||||
inline expr context::bv_const(char const * name, unsigned sz) { return constant(name, bv_sort(sz)); }
|
inline expr context::bv_const(char const * name, unsigned sz) { return constant(name, bv_sort(sz)); }
|
||||||
|
inline expr context::fpa_const(char const * name, unsigned ebits, unsigned sbits) { return constant(name, fpa_sort(ebits, sbits)); }
|
||||||
|
|
||||||
|
template<size_t precision>
|
||||||
|
inline expr context::fpa_const(char const * name) { return constant(name, fpa_sort<precision>()); }
|
||||||
|
|
||||||
inline expr context::bool_val(bool b) { return b ? expr(*this, Z3_mk_true(m_ctx)) : expr(*this, Z3_mk_false(m_ctx)); }
|
inline expr context::bool_val(bool b) { return b ? expr(*this, Z3_mk_true(m_ctx)) : expr(*this, Z3_mk_false(m_ctx)); }
|
||||||
|
|
||||||
|
@ -2694,6 +2855,9 @@ namespace z3 {
|
||||||
Z3_ast r = Z3_mk_bv_numeral(m_ctx, n, _bits.ptr()); check_error(); return expr(*this, r);
|
Z3_ast r = Z3_mk_bv_numeral(m_ctx, n, _bits.ptr()); check_error(); return expr(*this, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline expr context::fpa_val(double n) { sort s = fpa_sort<64>(); Z3_ast r = Z3_mk_fpa_numeral_double(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||||
|
inline expr context::fpa_val(float n) { sort s = fpa_sort<32>(); Z3_ast r = Z3_mk_fpa_numeral_float(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||||
|
|
||||||
inline expr context::string_val(char const* s) { Z3_ast r = Z3_mk_string(m_ctx, s); check_error(); return expr(*this, r); }
|
inline expr context::string_val(char const* s) { Z3_ast r = Z3_mk_string(m_ctx, s); check_error(); return expr(*this, r); }
|
||||||
inline expr context::string_val(std::string const& s) { Z3_ast r = Z3_mk_string(m_ctx, s.c_str()); check_error(); return expr(*this, r); }
|
inline expr context::string_val(std::string const& s) { Z3_ast r = Z3_mk_string(m_ctx, s.c_str()); check_error(); return expr(*this, r); }
|
||||||
|
|
||||||
|
|
|
@ -147,11 +147,6 @@ if (DOTNET_TOOLCHAIN_IS_WINDOWS)
|
||||||
"/nostdlib+"
|
"/nostdlib+"
|
||||||
"/reference:mscorlib.dll"
|
"/reference:mscorlib.dll"
|
||||||
)
|
)
|
||||||
# FIXME: This flag only works when the working directory of csc.exe is
|
|
||||||
# the directory containing the ``libz3`` target. I can't get this to work
|
|
||||||
# correctly with multi-configuration generators (i.e. Visual Studio) so
|
|
||||||
# just don't set the flag for now.
|
|
||||||
#list(APPEND CSC_FLAGS "/linkresource:$<TARGET_FILE_NAME:libz3>")
|
|
||||||
elseif (DOTNET_TOOLCHAIN_IS_MONO)
|
elseif (DOTNET_TOOLCHAIN_IS_MONO)
|
||||||
# We need to give the assembly a strong name so that it can be installed
|
# We need to give the assembly a strong name so that it can be installed
|
||||||
# into the GAC.
|
# into the GAC.
|
||||||
|
|
|
@ -183,9 +183,9 @@ namespace Microsoft.Z3
|
||||||
/// don't use strict inequalities) meets the objectives.
|
/// don't use strict inequalities) meets the objectives.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
///
|
///
|
||||||
public Status Check()
|
public Status Check(params Expr[] assumptions)
|
||||||
{
|
{
|
||||||
Z3_lbool r = (Z3_lbool)Native.Z3_optimize_check(Context.nCtx, NativeObject);
|
Z3_lbool r = (Z3_lbool)Native.Z3_optimize_check(Context.nCtx, NativeObject, (uint)assumptions.Length, AST.ArrayToNative(assumptions));
|
||||||
switch (r)
|
switch (r)
|
||||||
{
|
{
|
||||||
case Z3_lbool.Z3_L_TRUE:
|
case Z3_lbool.Z3_L_TRUE:
|
||||||
|
@ -236,6 +236,25 @@ namespace Microsoft.Z3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The unsat core of the last <c>Check</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The unsat core is a subset of <c>assumptions</c>
|
||||||
|
/// The result is empty if <c>Check</c> was not invoked before,
|
||||||
|
/// if its results was not <c>UNSATISFIABLE</c>, or if core production is disabled.
|
||||||
|
/// </remarks>
|
||||||
|
public BoolExpr[] UnsatCore
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Contract.Ensures(Contract.Result<Expr[]>() != null);
|
||||||
|
|
||||||
|
ASTVector core = new ASTVector(Context, Native.Z3_optimize_get_unsat_core(Context.nCtx, NativeObject));
|
||||||
|
return core.ToBoolExprArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Declare an arithmetical maximization objective.
|
/// Declare an arithmetical maximization objective.
|
||||||
/// Return a handle to the objective. The handle is used as
|
/// Return a handle to the objective. The handle is used as
|
||||||
|
|
|
@ -1977,6 +1977,22 @@ public class Context implements AutoCloseable {
|
||||||
return (SeqExpr) Expr.create(this, Native.mkString(nCtx(), s));
|
return (SeqExpr) Expr.create(this, Native.mkString(nCtx(), s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an integer expression to a string.
|
||||||
|
*/
|
||||||
|
public SeqExpr intToString(Expr e)
|
||||||
|
{
|
||||||
|
return (SeqExpr) Expr.create(this, Native.mkIntToStr(nCtx(), e.getNativeObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an integer expression to a string.
|
||||||
|
*/
|
||||||
|
public IntExpr stringToInt(Expr e)
|
||||||
|
{
|
||||||
|
return (IntExpr) Expr.create(this, Native.mkStrToInt(nCtx(), e.getNativeObject()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concatenate sequences.
|
* Concatenate sequences.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -161,9 +161,23 @@ public class Optimize extends Z3Object {
|
||||||
* Produce a model that (when the objectives are bounded and
|
* Produce a model that (when the objectives are bounded and
|
||||||
* don't use strict inequalities) meets the objectives.
|
* don't use strict inequalities) meets the objectives.
|
||||||
**/
|
**/
|
||||||
public Status Check()
|
public Status Check(Expr... assumptions)
|
||||||
{
|
{
|
||||||
Z3_lbool r = Z3_lbool.fromInt(Native.optimizeCheck(getContext().nCtx(), getNativeObject()));
|
Z3_lbool r;
|
||||||
|
if (assumptions == null) {
|
||||||
|
r = Z3_lbool.fromInt(
|
||||||
|
Native.optimizeCheck(
|
||||||
|
getContext().nCtx(),
|
||||||
|
getNativeObject(), 0, null));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = Z3_lbool.fromInt(
|
||||||
|
Native.optimizeCheck(
|
||||||
|
getContext().nCtx(),
|
||||||
|
getNativeObject(),
|
||||||
|
assumptions.length,
|
||||||
|
AST.arrayToNative(assumptions)));
|
||||||
|
}
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case Z3_L_TRUE:
|
case Z3_L_TRUE:
|
||||||
return Status.SATISFIABLE;
|
return Status.SATISFIABLE;
|
||||||
|
@ -209,6 +223,21 @@ public class Optimize extends Z3Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unsat core of the last {@code Check}.
|
||||||
|
* Remarks: The unsat core
|
||||||
|
* is a subset of {@code Assumptions} The result is empty if
|
||||||
|
* {@code Check} was not invoked before, if its results was not
|
||||||
|
* {@code UNSATISFIABLE}, or if core production is disabled.
|
||||||
|
*
|
||||||
|
* @throws Z3Exception
|
||||||
|
**/
|
||||||
|
public BoolExpr[] getUnsatCore()
|
||||||
|
{
|
||||||
|
ASTVector core = new ASTVector(getContext(), Native.optimizeGetUnsatCore(getContext().nCtx(), getNativeObject()));
|
||||||
|
return core.ToBoolExprArray();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare an arithmetical maximization objective.
|
* Declare an arithmetical maximization objective.
|
||||||
* Return a handle to the objective. The handle is used as
|
* Return a handle to the objective. The handle is used as
|
||||||
|
|
|
@ -43,6 +43,14 @@ let mk_list f n =
|
||||||
in
|
in
|
||||||
mk_list' 0 []
|
mk_list' 0 []
|
||||||
|
|
||||||
|
let check_int32 v = v = Int32.to_int (Int32.of_int v)
|
||||||
|
|
||||||
|
let mk_int_expr ctx v ty =
|
||||||
|
if not (check_int32 v) then
|
||||||
|
Z3native.mk_numeral ctx (string_of_int v) ty
|
||||||
|
else
|
||||||
|
Z3native.mk_int ctx v ty
|
||||||
|
|
||||||
let mk_context (settings:(string * string) list) =
|
let mk_context (settings:(string * string) list) =
|
||||||
let cfg = Z3native.mk_config () in
|
let cfg = Z3native.mk_config () in
|
||||||
let f e = Z3native.set_param_value cfg (fst e) (snd e) in
|
let f e = Z3native.set_param_value cfg (fst e) (snd e) in
|
||||||
|
@ -531,7 +539,7 @@ end = struct
|
||||||
let mk_fresh_const (ctx:context) (prefix:string) (range:Sort.sort) = Z3native.mk_fresh_const ctx prefix range
|
let mk_fresh_const (ctx:context) (prefix:string) (range:Sort.sort) = Z3native.mk_fresh_const ctx prefix range
|
||||||
let mk_app (ctx:context) (f:FuncDecl.func_decl) (args:expr list) = expr_of_func_app ctx f args
|
let mk_app (ctx:context) (f:FuncDecl.func_decl) (args:expr list) = expr_of_func_app ctx f args
|
||||||
let mk_numeral_string (ctx:context) (v:string) (ty:Sort.sort) = Z3native.mk_numeral ctx v ty
|
let mk_numeral_string (ctx:context) (v:string) (ty:Sort.sort) = Z3native.mk_numeral ctx v ty
|
||||||
let mk_numeral_int (ctx:context) (v:int) (ty:Sort.sort) = Z3native.mk_int ctx v ty
|
let mk_numeral_int (ctx:context) (v:int) (ty:Sort.sort) = mk_int_expr ctx v ty
|
||||||
let equal (a:expr) (b:expr) = AST.equal a b
|
let equal (a:expr) (b:expr) = AST.equal a b
|
||||||
let compare (a:expr) (b:expr) = AST.compare a b
|
let compare (a:expr) (b:expr) = AST.compare a b
|
||||||
end
|
end
|
||||||
|
@ -1036,7 +1044,7 @@ struct
|
||||||
let mk_mod = Z3native.mk_mod
|
let mk_mod = Z3native.mk_mod
|
||||||
let mk_rem = Z3native.mk_rem
|
let mk_rem = Z3native.mk_rem
|
||||||
let mk_numeral_s (ctx:context) (v:string) = Z3native.mk_numeral ctx v (mk_sort ctx)
|
let mk_numeral_s (ctx:context) (v:string) = Z3native.mk_numeral ctx v (mk_sort ctx)
|
||||||
let mk_numeral_i (ctx:context) (v:int) = Z3native.mk_int ctx v (mk_sort ctx)
|
let mk_numeral_i (ctx:context) (v:int) = mk_int_expr ctx v (mk_sort ctx)
|
||||||
let mk_int2real = Z3native.mk_int2real
|
let mk_int2real = Z3native.mk_int2real
|
||||||
let mk_int2bv = Z3native.mk_int2bv
|
let mk_int2bv = Z3native.mk_int2bv
|
||||||
end
|
end
|
||||||
|
@ -1061,11 +1069,13 @@ struct
|
||||||
let mk_numeral_nd (ctx:context) (num:int) (den:int) =
|
let mk_numeral_nd (ctx:context) (num:int) (den:int) =
|
||||||
if den = 0 then
|
if den = 0 then
|
||||||
raise (Error "Denominator is zero")
|
raise (Error "Denominator is zero")
|
||||||
|
else if not (check_int32 num) || not (check_int32 den) then
|
||||||
|
raise (Error "numerals don't fit in 32 bits")
|
||||||
else
|
else
|
||||||
Z3native.mk_real ctx num den
|
Z3native.mk_real ctx num den
|
||||||
|
|
||||||
let mk_numeral_s (ctx:context) (v:string) = Z3native.mk_numeral ctx v (mk_sort ctx)
|
let mk_numeral_s (ctx:context) (v:string) = Z3native.mk_numeral ctx v (mk_sort ctx)
|
||||||
let mk_numeral_i (ctx:context) (v:int) = Z3native.mk_int ctx v (mk_sort ctx)
|
let mk_numeral_i (ctx:context) (v:int) = mk_int_expr ctx v (mk_sort ctx)
|
||||||
let mk_is_integer = Z3native.mk_is_int
|
let mk_is_integer = Z3native.mk_is_int
|
||||||
let mk_real2int = Z3native.mk_real2int
|
let mk_real2int = Z3native.mk_real2int
|
||||||
|
|
||||||
|
@ -1155,11 +1165,6 @@ struct
|
||||||
let is_bv_xor3 (x:expr) = (AST.is_app x) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) = OP_XOR3)
|
let is_bv_xor3 (x:expr) = (AST.is_app x) && (FuncDecl.get_decl_kind (Expr.get_func_decl x) = OP_XOR3)
|
||||||
let get_size (x:Sort.sort) = Z3native.get_bv_sort_size (Sort.gc x) x
|
let get_size (x:Sort.sort) = Z3native.get_bv_sort_size (Sort.gc x) x
|
||||||
|
|
||||||
let get_int (x:expr) =
|
|
||||||
match Z3native.get_numeral_int (Expr.gc x) x with
|
|
||||||
| true, v -> v
|
|
||||||
| false, _ -> raise (Error "Conversion failed.")
|
|
||||||
|
|
||||||
let numeral_to_string (x:expr) = Z3native.get_numeral_string (Expr.gc x) x
|
let numeral_to_string (x:expr) = Z3native.get_numeral_string (Expr.gc x) x
|
||||||
let mk_const (ctx:context) (name:Symbol.symbol) (size:int) =
|
let mk_const (ctx:context) (name:Symbol.symbol) (size:int) =
|
||||||
Expr.mk_const ctx name (mk_sort ctx size)
|
Expr.mk_const ctx name (mk_sort ctx size)
|
||||||
|
@ -1810,8 +1815,10 @@ struct
|
||||||
| _ -> UNKNOWN
|
| _ -> UNKNOWN
|
||||||
|
|
||||||
let get_model x =
|
let get_model x =
|
||||||
|
try
|
||||||
let q = Z3native.solver_get_model (gc x) x in
|
let q = Z3native.solver_get_model (gc x) x in
|
||||||
if Z3native.is_null_model q then None else Some q
|
if Z3native.is_null_model q then None else Some q
|
||||||
|
with | _ -> None
|
||||||
|
|
||||||
let get_proof x =
|
let get_proof x =
|
||||||
let q = Z3native.solver_get_proof (gc x) x in
|
let q = Z3native.solver_get_proof (gc x) x in
|
||||||
|
@ -1940,15 +1947,17 @@ struct
|
||||||
let minimize (x:optimize) (e:Expr.expr) = mk_handle x (Z3native.optimize_minimize (gc x) x e)
|
let minimize (x:optimize) (e:Expr.expr) = mk_handle x (Z3native.optimize_minimize (gc x) x e)
|
||||||
|
|
||||||
let check (x:optimize) =
|
let check (x:optimize) =
|
||||||
let r = lbool_of_int (Z3native.optimize_check (gc x) x) in
|
let r = lbool_of_int (Z3native.optimize_check (gc x) x) 0 [] in
|
||||||
match r with
|
match r with
|
||||||
| L_TRUE -> Solver.SATISFIABLE
|
| L_TRUE -> Solver.SATISFIABLE
|
||||||
| L_FALSE -> Solver.UNSATISFIABLE
|
| L_FALSE -> Solver.UNSATISFIABLE
|
||||||
| _ -> Solver.UNKNOWN
|
| _ -> Solver.UNKNOWN
|
||||||
|
|
||||||
let get_model (x:optimize) =
|
let get_model (x:optimize) =
|
||||||
|
try
|
||||||
let q = Z3native.optimize_get_model (gc x) x in
|
let q = Z3native.optimize_get_model (gc x) x in
|
||||||
if Z3native.is_null_model q then None else Some q
|
if Z3native.is_null_model q then None else Some q
|
||||||
|
with | _ -> None
|
||||||
|
|
||||||
let get_lower (x:handle) = Z3native.optimize_get_lower (gc x.opt) x.opt x.h
|
let get_lower (x:handle) = Z3native.optimize_get_lower (gc x.opt) x.opt x.h
|
||||||
let get_upper (x:handle) = Z3native.optimize_get_upper (gc x.opt) x.opt x.h
|
let get_upper (x:handle) = Z3native.optimize_get_upper (gc x.opt) x.opt x.h
|
||||||
|
|
|
@ -1152,9 +1152,6 @@ sig
|
||||||
(** Create a new integer sort. *)
|
(** Create a new integer sort. *)
|
||||||
val mk_sort : context -> Sort.sort
|
val mk_sort : context -> Sort.sort
|
||||||
|
|
||||||
(** Retrieve the int value. *)
|
|
||||||
val get_int : Expr.expr -> int
|
|
||||||
|
|
||||||
(** Get a big_int from an integer numeral *)
|
(** Get a big_int from an integer numeral *)
|
||||||
val get_big_int : Expr.expr -> Big_int.big_int
|
val get_big_int : Expr.expr -> Big_int.big_int
|
||||||
|
|
||||||
|
@ -1543,9 +1540,6 @@ sig
|
||||||
(** The size of a bit-vector sort. *)
|
(** The size of a bit-vector sort. *)
|
||||||
val get_size : Sort.sort -> int
|
val get_size : Sort.sort -> int
|
||||||
|
|
||||||
(** Retrieve the int value. *)
|
|
||||||
val get_int : Expr.expr -> int
|
|
||||||
|
|
||||||
(** Returns a string representation of a numeral. *)
|
(** Returns a string representation of a numeral. *)
|
||||||
val numeral_to_string : Expr.expr -> string
|
val numeral_to_string : Expr.expr -> string
|
||||||
|
|
||||||
|
@ -3413,10 +3407,10 @@ sig
|
||||||
(** Parse the given string using the SMT-LIB2 parser.
|
(** Parse the given string using the SMT-LIB2 parser.
|
||||||
|
|
||||||
@return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *)
|
@return A conjunction of assertions in the scope (up to push/pop) at the end of the string. *)
|
||||||
val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr
|
val parse_smtlib2_string : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> AST.ASTVector.ast_vector
|
||||||
|
|
||||||
(** Parse the given file using the SMT-LIB2 parser. *)
|
(** Parse the given file using the SMT-LIB2 parser. *)
|
||||||
val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> Expr.expr
|
val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> AST.ASTVector.ast_vector
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@ If you are using a 64-bit Python interpreter, you should use
|
||||||
msbuild /p:configuration=external /p:platform=x64
|
msbuild /p:configuration=external /p:platform=x64
|
||||||
|
|
||||||
|
|
||||||
On Linux and OSX, you must install Z3Py, before trying example.py.
|
On Linux and macOS, you must install Z3Py, before trying example.py.
|
||||||
To install Z3Py on Linux and OSX, you should execute the following
|
To install Z3Py on Linux and macOS, you should execute the following
|
||||||
command in the Z3 root directory
|
command in the Z3 root directory
|
||||||
|
|
||||||
sudo make install-z3py
|
sudo make install-z3py
|
||||||
|
|
|
@ -73,7 +73,7 @@ def _build_z3():
|
||||||
if subprocess.call(['nmake'], env=build_env,
|
if subprocess.call(['nmake'], env=build_env,
|
||||||
cwd=BUILD_DIR) != 0:
|
cwd=BUILD_DIR) != 0:
|
||||||
raise LibError("Unable to build Z3.")
|
raise LibError("Unable to build Z3.")
|
||||||
else: # linux and osx
|
else: # linux and macOS
|
||||||
if subprocess.call(['make', '-j', str(multiprocessing.cpu_count())],
|
if subprocess.call(['make', '-j', str(multiprocessing.cpu_count())],
|
||||||
env=build_env, cwd=BUILD_DIR) != 0:
|
env=build_env, cwd=BUILD_DIR) != 0:
|
||||||
raise LibError("Unable to build Z3.")
|
raise LibError("Unable to build Z3.")
|
||||||
|
|
|
@ -1258,6 +1258,11 @@ def Consts(names, sort):
|
||||||
names = names.split(" ")
|
names = names.split(" ")
|
||||||
return [Const(name, sort) for name in names]
|
return [Const(name, sort) for name in names]
|
||||||
|
|
||||||
|
def FreshConst(sort, prefix='c'):
|
||||||
|
"""Create a fresh constant of a specified sort"""
|
||||||
|
ctx = _get_ctx(sort.ctx)
|
||||||
|
return _to_expr_ref(Z3_mk_fresh_const(ctx.ref(), prefix, sort.ast), ctx)
|
||||||
|
|
||||||
def Var(idx, s):
|
def Var(idx, s):
|
||||||
"""Create a Z3 free variable. Free variables are used to create quantified formulas.
|
"""Create a Z3 free variable. Free variables are used to create quantified formulas.
|
||||||
|
|
||||||
|
@ -1744,7 +1749,9 @@ class QuantifierRef(BoolRef):
|
||||||
return Z3_get_ast_id(self.ctx_ref(), self.as_ast())
|
return Z3_get_ast_id(self.ctx_ref(), self.as_ast())
|
||||||
|
|
||||||
def sort(self):
|
def sort(self):
|
||||||
"""Return the Boolean sort."""
|
"""Return the Boolean sort or sort of Lambda."""
|
||||||
|
if self.is_lambda():
|
||||||
|
return _sort(self.ctx, self.as_ast())
|
||||||
return BoolSort(self.ctx)
|
return BoolSort(self.ctx)
|
||||||
|
|
||||||
def is_forall(self):
|
def is_forall(self):
|
||||||
|
@ -2176,6 +2183,8 @@ class ArithRef(ExprRef):
|
||||||
>>> (x * y).sort()
|
>>> (x * y).sort()
|
||||||
Real
|
Real
|
||||||
"""
|
"""
|
||||||
|
if isinstance(other, BoolRef):
|
||||||
|
return If(other, self, 0)
|
||||||
a, b = _coerce_exprs(self, other)
|
a, b = _coerce_exprs(self, other)
|
||||||
return ArithRef(_mk_bin(Z3_mk_mul, a, b), self.ctx)
|
return ArithRef(_mk_bin(Z3_mk_mul, a, b), self.ctx)
|
||||||
|
|
||||||
|
@ -4278,7 +4287,7 @@ def get_map_func(a):
|
||||||
_z3_assert(is_map(a), "Z3 array map expression expected.")
|
_z3_assert(is_map(a), "Z3 array map expression expected.")
|
||||||
return FuncDeclRef(Z3_to_func_decl(a.ctx_ref(), Z3_get_decl_ast_parameter(a.ctx_ref(), a.decl().ast, 0)), a.ctx)
|
return FuncDeclRef(Z3_to_func_decl(a.ctx_ref(), Z3_get_decl_ast_parameter(a.ctx_ref(), a.decl().ast, 0)), a.ctx)
|
||||||
|
|
||||||
def ArraySort(d, r):
|
def ArraySort(*sig):
|
||||||
"""Return the Z3 array sort with the given domain and range sorts.
|
"""Return the Z3 array sort with the given domain and range sorts.
|
||||||
|
|
||||||
>>> A = ArraySort(IntSort(), BoolSort())
|
>>> A = ArraySort(IntSort(), BoolSort())
|
||||||
|
@ -4292,12 +4301,23 @@ def ArraySort(d, r):
|
||||||
>>> AA
|
>>> AA
|
||||||
Array(Int, Array(Int, Bool))
|
Array(Int, Array(Int, Bool))
|
||||||
"""
|
"""
|
||||||
|
sig = _get_args(sig)
|
||||||
if __debug__:
|
if __debug__:
|
||||||
_z3_assert(is_sort(d), "Z3 sort expected")
|
_z3_assert(len(sig) > 1, "At least two arguments expected")
|
||||||
_z3_assert(is_sort(r), "Z3 sort expected")
|
arity = len(sig) - 1
|
||||||
_z3_assert(d.ctx == r.ctx, "Context mismatch")
|
r = sig[arity]
|
||||||
|
d = sig[0]
|
||||||
|
if __debug__:
|
||||||
|
for s in sig:
|
||||||
|
_z3_assert(is_sort(s), "Z3 sort expected")
|
||||||
|
_z3_assert(s.ctx == r.ctx, "Context mismatch")
|
||||||
ctx = d.ctx
|
ctx = d.ctx
|
||||||
|
if len(sig) == 2:
|
||||||
return ArraySortRef(Z3_mk_array_sort(ctx.ref(), d.ast, r.ast), ctx)
|
return ArraySortRef(Z3_mk_array_sort(ctx.ref(), d.ast, r.ast), ctx)
|
||||||
|
dom = (Sort * arity)()
|
||||||
|
for i in range(arity):
|
||||||
|
dom[i] = sig[i].ast
|
||||||
|
return ArraySortRef(Z3_mk_array_sort_n(ctx.ref(), arity, dom, r.ast), ctx)
|
||||||
|
|
||||||
def Array(name, dom, rng):
|
def Array(name, dom, rng):
|
||||||
"""Return an array constant named `name` with the given domain and range sorts.
|
"""Return an array constant named `name` with the given domain and range sorts.
|
||||||
|
@ -6603,7 +6623,12 @@ class Solver(Z3PPObject):
|
||||||
_handle_parse_error(e, self.ctx)
|
_handle_parse_error(e, self.ctx)
|
||||||
|
|
||||||
def cube(self, vars = None):
|
def cube(self, vars = None):
|
||||||
"""Get set of cubes"""
|
"""Get set of cubes
|
||||||
|
The method takes an optional set of variables that restrict which
|
||||||
|
variables may be used as a starting point for cubing.
|
||||||
|
If vars is not None, then the first case split is based on a variable in
|
||||||
|
this set.
|
||||||
|
"""
|
||||||
self.cube_vs = AstVector(None, self.ctx)
|
self.cube_vs = AstVector(None, self.ctx)
|
||||||
if vars is not None:
|
if vars is not None:
|
||||||
for v in vars:
|
for v in vars:
|
||||||
|
@ -6619,20 +6644,16 @@ class Solver(Z3PPObject):
|
||||||
return
|
return
|
||||||
|
|
||||||
def cube_vars(self):
|
def cube_vars(self):
|
||||||
|
"""Access the set of variables that were touched by the most recently generated cube.
|
||||||
|
This set of variables can be used as a starting point for additional cubes.
|
||||||
|
The idea is that variables that appear in clauses that are reduced by the most recent
|
||||||
|
cube are likely more useful to cube on."""
|
||||||
return self.cube_vs
|
return self.cube_vs
|
||||||
|
|
||||||
def proof(self):
|
def proof(self):
|
||||||
"""Return a proof for the last `check()`. Proof construction must be enabled."""
|
"""Return a proof for the last `check()`. Proof construction must be enabled."""
|
||||||
return _to_expr_ref(Z3_solver_get_proof(self.ctx.ref(), self.solver), self.ctx)
|
return _to_expr_ref(Z3_solver_get_proof(self.ctx.ref(), self.solver), self.ctx)
|
||||||
|
|
||||||
def from_file(self, filename):
|
|
||||||
"""Parse assertions from a file"""
|
|
||||||
Z3_solver_from_file(self.ctx.ref(), self.solver, filename)
|
|
||||||
|
|
||||||
def from_string(self, s):
|
|
||||||
"""Parse assertions from a string"""
|
|
||||||
Z3_solver_from_string(self.ctx.ref(), self.solver, s)
|
|
||||||
|
|
||||||
def assertions(self):
|
def assertions(self):
|
||||||
"""Return an AST vector containing all added constraints.
|
"""Return an AST vector containing all added constraints.
|
||||||
|
|
||||||
|
@ -6652,6 +6673,11 @@ class Solver(Z3PPObject):
|
||||||
"""
|
"""
|
||||||
return AstVector(Z3_solver_get_units(self.ctx.ref(), self.solver), self.ctx)
|
return AstVector(Z3_solver_get_units(self.ctx.ref(), self.solver), self.ctx)
|
||||||
|
|
||||||
|
def non_units(self):
|
||||||
|
"""Return an AST vector containing all atomic formulas in solver state that are not units.
|
||||||
|
"""
|
||||||
|
return AstVector(Z3_solver_get_non_units(self.ctx.ref(), self.solver), self.ctx)
|
||||||
|
|
||||||
def statistics(self):
|
def statistics(self):
|
||||||
"""Return statistics for the last `check()`.
|
"""Return statistics for the last `check()`.
|
||||||
|
|
||||||
|
@ -7285,9 +7311,14 @@ class Optimize(Z3PPObject):
|
||||||
"""restore to previously created backtracking point"""
|
"""restore to previously created backtracking point"""
|
||||||
Z3_optimize_pop(self.ctx.ref(), self.optimize)
|
Z3_optimize_pop(self.ctx.ref(), self.optimize)
|
||||||
|
|
||||||
def check(self):
|
def check(self, *assumptions):
|
||||||
"""Check satisfiability while optimizing objective functions."""
|
"""Check satisfiability while optimizing objective functions."""
|
||||||
return CheckSatResult(Z3_optimize_check(self.ctx.ref(), self.optimize))
|
assumptions = _get_args(assumptions)
|
||||||
|
num = len(assumptions)
|
||||||
|
_assumptions = (Ast * num)()
|
||||||
|
for i in range(num):
|
||||||
|
_assumptions[i] = assumptions[i].as_ast()
|
||||||
|
return CheckSatResult(Z3_optimize_check(self.ctx.ref(), self.optimize, num, _assumptions))
|
||||||
|
|
||||||
def reason_unknown(self):
|
def reason_unknown(self):
|
||||||
"""Return a string that describes why the last `check()` returned `unknown`."""
|
"""Return a string that describes why the last `check()` returned `unknown`."""
|
||||||
|
@ -7300,6 +7331,9 @@ class Optimize(Z3PPObject):
|
||||||
except Z3Exception:
|
except Z3Exception:
|
||||||
raise Z3Exception("model is not available")
|
raise Z3Exception("model is not available")
|
||||||
|
|
||||||
|
def unsat_core(self):
|
||||||
|
return AstVector(Z3_optimize_get_unsat_core(self.ctx.ref(), self.optimize), self.ctx)
|
||||||
|
|
||||||
def lower(self, obj):
|
def lower(self, obj):
|
||||||
if not isinstance(obj, OptimizeObjective):
|
if not isinstance(obj, OptimizeObjective):
|
||||||
raise Z3Exception("Expecting objective handle returned by maximize/minimize")
|
raise Z3Exception("Expecting objective handle returned by maximize/minimize")
|
||||||
|
@ -8040,7 +8074,7 @@ def substitute(t, *m):
|
||||||
"""
|
"""
|
||||||
if isinstance(m, tuple):
|
if isinstance(m, tuple):
|
||||||
m1 = _get_args(m)
|
m1 = _get_args(m)
|
||||||
if isinstance(m1, list):
|
if isinstance(m1, list) and all(isinstance(p, tuple) for p in m1):
|
||||||
m = m1
|
m = m1
|
||||||
if __debug__:
|
if __debug__:
|
||||||
_z3_assert(is_expr(t), "Z3 expression expected")
|
_z3_assert(is_expr(t), "Z3 expression expected")
|
||||||
|
|
|
@ -6121,6 +6121,14 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
Z3_ast_vector Z3_API Z3_solver_get_units(Z3_context c, Z3_solver s);
|
Z3_ast_vector Z3_API Z3_solver_get_units(Z3_context c, Z3_solver s);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Return the set of non units in the solver state.
|
||||||
|
|
||||||
|
def_API('Z3_solver_get_non_units', AST_VECTOR, (_in(CONTEXT), _in(SOLVER)))
|
||||||
|
*/
|
||||||
|
Z3_ast_vector Z3_API Z3_solver_get_non_units(Z3_context c, Z3_solver s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Check whether the assertions in a given solver are consistent or not.
|
\brief Check whether the assertions in a given solver are consistent or not.
|
||||||
|
|
||||||
|
|
|
@ -117,10 +117,12 @@ extern "C" {
|
||||||
\brief Check consistency and produce optimal values.
|
\brief Check consistency and produce optimal values.
|
||||||
\param c - context
|
\param c - context
|
||||||
\param o - optimization context
|
\param o - optimization context
|
||||||
|
\param num_assumptions - number of additional assumptions
|
||||||
|
\param assumptions - the additional assumptions
|
||||||
|
|
||||||
def_API('Z3_optimize_check', INT, (_in(CONTEXT), _in(OPTIMIZE)))
|
def_API('Z3_optimize_check', INT, (_in(CONTEXT), _in(OPTIMIZE), _in(UINT), _in_array(2, AST)))
|
||||||
*/
|
*/
|
||||||
Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o);
|
Z3_lbool Z3_API Z3_optimize_check(Z3_context c, Z3_optimize o, unsigned num_assumptions, Z3_ast const assumptions[]);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,6 +145,14 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
Z3_model Z3_API Z3_optimize_get_model(Z3_context c, Z3_optimize o);
|
Z3_model Z3_API Z3_optimize_get_model(Z3_context c, Z3_optimize o);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Retrieve the unsat core for the last #Z3_optimize_chec
|
||||||
|
The unsat core is a subset of the assumptions \c a.
|
||||||
|
|
||||||
|
def_API('Z3_optimize_get_unsat_core', AST_VECTOR, (_in(CONTEXT), _in(OPTIMIZE)))
|
||||||
|
*/
|
||||||
|
Z3_ast_vector Z3_API Z3_optimize_get_unsat_core(Z3_context c, Z3_optimize o);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Set parameters on optimization context.
|
\brief Set parameters on optimization context.
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ Revision History:
|
||||||
#include "math/polynomial/algebraic_numbers.h"
|
#include "math/polynomial/algebraic_numbers.h"
|
||||||
#include "util/id_gen.h"
|
#include "util/id_gen.h"
|
||||||
#include "ast/ast_smt2_pp.h"
|
#include "ast/ast_smt2_pp.h"
|
||||||
|
#include "util/gparams.h"
|
||||||
|
|
||||||
struct arith_decl_plugin::algebraic_numbers_wrapper {
|
struct arith_decl_plugin::algebraic_numbers_wrapper {
|
||||||
unsynch_mpq_manager m_qmanager;
|
unsynch_mpq_manager m_qmanager;
|
||||||
|
@ -487,7 +488,7 @@ func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
||||||
if (arity != 1 || domain[0] != m_int_decl || num_parameters != 1 || !parameters[0].is_int()) {
|
if (arity != 1 || domain[0] != m_int_decl || num_parameters != 1 || !parameters[0].is_int()) {
|
||||||
m_manager->raise_exception("invalid divides application. Expects integer parameter and one argument of sort integer");
|
m_manager->raise_exception("invalid divides application. Expects integer parameter and one argument of sort integer");
|
||||||
}
|
}
|
||||||
return m_manager->mk_func_decl(symbol("divides"), 1, &m_int_decl, m_manager->mk_bool_sort(),
|
return m_manager->mk_func_decl(symbol("divisible"), 1, &m_int_decl, m_manager->mk_bool_sort(),
|
||||||
func_decl_info(m_family_id, k, num_parameters, parameters));
|
func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,7 +513,7 @@ func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
||||||
if (num_args != 1 || m_manager->get_sort(args[0]) != m_int_decl || num_parameters != 1 || !parameters[0].is_int()) {
|
if (num_args != 1 || m_manager->get_sort(args[0]) != m_int_decl || num_parameters != 1 || !parameters[0].is_int()) {
|
||||||
m_manager->raise_exception("invalid divides application. Expects integer parameter and one argument of sort integer");
|
m_manager->raise_exception("invalid divides application. Expects integer parameter and one argument of sort integer");
|
||||||
}
|
}
|
||||||
return m_manager->mk_func_decl(symbol("divides"), 1, &m_int_decl, m_manager->mk_bool_sort(),
|
return m_manager->mk_func_decl(symbol("divisible"), 1, &m_int_decl, m_manager->mk_bool_sort(),
|
||||||
func_decl_info(m_family_id, k, num_parameters, parameters));
|
func_decl_info(m_family_id, k, num_parameters, parameters));
|
||||||
}
|
}
|
||||||
if (m_manager->int_real_coercions() && use_coercion(k)) {
|
if (m_manager->int_real_coercions() && use_coercion(k)) {
|
||||||
|
@ -549,8 +550,9 @@ void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
|
||||||
op_names.push_back(builtin_name("*",OP_MUL));
|
op_names.push_back(builtin_name("*",OP_MUL));
|
||||||
op_names.push_back(builtin_name("/",OP_DIV));
|
op_names.push_back(builtin_name("/",OP_DIV));
|
||||||
op_names.push_back(builtin_name("div",OP_IDIV));
|
op_names.push_back(builtin_name("div",OP_IDIV));
|
||||||
// clashes with user-defined functions
|
if (gparams::get_value("smtlib2_compliant") == "true") {
|
||||||
// op_names.push_back(builtin_name("divides",OP_IDIVIDES));
|
op_names.push_back(builtin_name("divisible",OP_IDIVIDES));
|
||||||
|
}
|
||||||
op_names.push_back(builtin_name("rem",OP_REM));
|
op_names.push_back(builtin_name("rem",OP_REM));
|
||||||
op_names.push_back(builtin_name("mod",OP_MOD));
|
op_names.push_back(builtin_name("mod",OP_MOD));
|
||||||
op_names.push_back(builtin_name("to_real",OP_TO_REAL));
|
op_names.push_back(builtin_name("to_real",OP_TO_REAL));
|
||||||
|
|
|
@ -424,7 +424,7 @@ sort * get_sort(expr const * n) {
|
||||||
return to_quantifier(n)->get_sort();
|
return to_quantifier(n)->get_sort();
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1656,6 +1656,12 @@ bool ast_manager::are_distinct(expr* a, expr* b) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func_decl* ast_manager::get_rec_fun_decl(quantifier* q) const {
|
||||||
|
SASSERT(is_rec_fun_def(q));
|
||||||
|
return to_app(to_app(q->get_pattern(0))->get_arg(0))->get_decl();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ast_manager::register_plugin(family_id id, decl_plugin * plugin) {
|
void ast_manager::register_plugin(family_id id, decl_plugin * plugin) {
|
||||||
SASSERT(m_plugins.get(id, 0) == 0);
|
SASSERT(m_plugins.get(id, 0) == 0);
|
||||||
m_plugins.setx(id, plugin, 0);
|
m_plugins.setx(id, plugin, 0);
|
||||||
|
|
|
@ -1632,6 +1632,7 @@ public:
|
||||||
|
|
||||||
bool is_rec_fun_def(quantifier* q) const { return q->get_qid() == m_rec_fun; }
|
bool is_rec_fun_def(quantifier* q) const { return q->get_qid() == m_rec_fun; }
|
||||||
bool is_lambda_def(quantifier* q) const { return q->get_qid() == m_lambda_def; }
|
bool is_lambda_def(quantifier* q) const { return q->get_qid() == m_lambda_def; }
|
||||||
|
func_decl* get_rec_fun_decl(quantifier* q) const;
|
||||||
|
|
||||||
symbol const& rec_fun_qid() const { return m_rec_fun; }
|
symbol const& rec_fun_qid() const { return m_rec_fun; }
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ bool smt_renaming::all_is_legal(char const* s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
smt_renaming::smt_renaming() {
|
smt_renaming::smt_renaming() {
|
||||||
for (unsigned i = 0; i < ARRAYSIZE(m_predef_names); ++i) {
|
for (unsigned i = 0; i < Z3_ARRAYSIZE(m_predef_names); ++i) {
|
||||||
symbol s(m_predef_names[i]);
|
symbol s(m_predef_names[i]);
|
||||||
m_translate.insert(s, sym_b(s, false));
|
m_translate.insert(s, sym_b(s, false));
|
||||||
m_rev_translate.insert(s, s);
|
m_rev_translate.insert(s, s);
|
||||||
|
|
|
@ -152,21 +152,13 @@ namespace format_ns {
|
||||||
|
|
||||||
format * mk_int(ast_manager & m, int i) {
|
format * mk_int(ast_manager & m, int i) {
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
#ifdef _WINDOWS
|
SPRINTF_D(buffer, i);
|
||||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%d", i);
|
|
||||||
#else
|
|
||||||
sprintf(buffer, "%d", i);
|
|
||||||
#endif
|
|
||||||
return mk_string(m, buffer);
|
return mk_string(m, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
format * mk_unsigned(ast_manager & m, unsigned u) {
|
format * mk_unsigned(ast_manager & m, unsigned u) {
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
#ifdef _WINDOWS
|
SPRINTF_U(buffer, u);
|
||||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%u", u);
|
|
||||||
#else
|
|
||||||
sprintf(buffer, "%u", u);
|
|
||||||
#endif
|
|
||||||
return mk_string(m, buffer);
|
return mk_string(m, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ Notes:
|
||||||
#include "ast/ast_smt2_pp.h"
|
#include "ast/ast_smt2_pp.h"
|
||||||
#include "ast/well_sorted.h"
|
#include "ast/well_sorted.h"
|
||||||
#include "ast/rewriter/th_rewriter.h"
|
#include "ast/rewriter/th_rewriter.h"
|
||||||
|
#include "ast/used_vars.h"
|
||||||
|
#include "ast/rewriter/var_subst.h"
|
||||||
|
|
||||||
#include "ast/fpa/fpa2bv_converter.h"
|
#include "ast/fpa/fpa2bv_converter.h"
|
||||||
#include "ast/rewriter/fpa_rewriter.h"
|
#include "ast/rewriter/fpa_rewriter.h"
|
||||||
|
@ -230,6 +232,42 @@ void fpa2bv_converter::mk_var(unsigned base_inx, sort * srt, expr_ref & result)
|
||||||
result = m_util.mk_fp(sgn, e, s);
|
result = m_util.mk_fp(sgn, e, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_ref fpa2bv_converter::extra_quantify(expr * e)
|
||||||
|
{
|
||||||
|
used_vars uv;
|
||||||
|
unsigned nv;
|
||||||
|
|
||||||
|
ptr_buffer<sort> new_decl_sorts;
|
||||||
|
sbuffer<symbol> new_decl_names;
|
||||||
|
expr_ref_buffer subst_map(m);
|
||||||
|
|
||||||
|
uv(e);
|
||||||
|
nv = uv.get_num_vars();
|
||||||
|
subst_map.resize(uv.get_max_found_var_idx_plus_1());
|
||||||
|
|
||||||
|
if (nv == 0)
|
||||||
|
return expr_ref(e, m);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < nv; i++)
|
||||||
|
{
|
||||||
|
if (uv.contains(i)) {
|
||||||
|
TRACE("fpa2bv", tout << "uv[" << i << "] = " << mk_ismt2_pp(uv.get(i), m) << std::endl; );
|
||||||
|
sort * s = uv.get(i);
|
||||||
|
var * v = m.mk_var(i, s);
|
||||||
|
new_decl_sorts.push_back(s);
|
||||||
|
new_decl_names.push_back(symbol(i));
|
||||||
|
subst_map.set(i, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_ref res(m);
|
||||||
|
var_subst vsubst(m);
|
||||||
|
res = vsubst.operator()(e, nv, subst_map.c_ptr());
|
||||||
|
TRACE("fpa2bv", tout << "subst'd = " << mk_ismt2_pp(res, m) << std::endl; );
|
||||||
|
res = m.mk_forall(nv, new_decl_sorts.c_ptr(), new_decl_names.c_ptr(), res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, expr_ref & result)
|
void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, expr_ref & result)
|
||||||
{
|
{
|
||||||
TRACE("fpa2bv", tout << "UF: " << mk_ismt2_pp(f, m) << std::endl; );
|
TRACE("fpa2bv", tout << "UF: " << mk_ismt2_pp(f, m) << std::endl; );
|
||||||
|
@ -252,7 +290,7 @@ void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, e
|
||||||
m_bv_util.mk_extract(sbits+ebits-2, sbits-1, bv_app),
|
m_bv_util.mk_extract(sbits+ebits-2, sbits-1, bv_app),
|
||||||
m_bv_util.mk_extract(sbits-2, 0, bv_app));
|
m_bv_util.mk_extract(sbits-2, 0, bv_app));
|
||||||
new_eq = m.mk_eq(fapp, flt_app);
|
new_eq = m.mk_eq(fapp, flt_app);
|
||||||
m_extra_assertions.push_back(new_eq);
|
m_extra_assertions.push_back(extra_quantify(new_eq));
|
||||||
result = flt_app;
|
result = flt_app;
|
||||||
}
|
}
|
||||||
else if (m_util.is_rm(rng)) {
|
else if (m_util.is_rm(rng)) {
|
||||||
|
@ -263,7 +301,7 @@ void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, e
|
||||||
bv_app = m.mk_app(bv_f, num, args);
|
bv_app = m.mk_app(bv_f, num, args);
|
||||||
flt_app = m_util.mk_bv2rm(bv_app);
|
flt_app = m_util.mk_bv2rm(bv_app);
|
||||||
new_eq = m.mk_eq(fapp, flt_app);
|
new_eq = m.mk_eq(fapp, flt_app);
|
||||||
m_extra_assertions.push_back(new_eq);
|
m_extra_assertions.push_back(extra_quantify(new_eq));
|
||||||
result = flt_app;
|
result = flt_app;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -220,6 +220,8 @@ private:
|
||||||
|
|
||||||
func_decl * mk_bv_uf(func_decl * f, sort * const * domain, sort * range);
|
func_decl * mk_bv_uf(func_decl * f, sort * const * domain, sort * range);
|
||||||
expr_ref nan_wrap(expr * n);
|
expr_ref nan_wrap(expr * n);
|
||||||
|
|
||||||
|
expr_ref extra_quantify(expr * e);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -215,6 +215,12 @@ bool fpa2bv_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
||||||
new_decl_names.push_back(symbol(name_buffer.c_str()));
|
new_decl_names.push_back(symbol(name_buffer.c_str()));
|
||||||
new_decl_sorts.push_back(m_conv.bu().mk_sort(sbits+ebits));
|
new_decl_sorts.push_back(m_conv.bu().mk_sort(sbits+ebits));
|
||||||
}
|
}
|
||||||
|
else if (m_conv.is_rm(s)) {
|
||||||
|
name_buffer.reset();
|
||||||
|
name_buffer << n << ".bv";
|
||||||
|
new_decl_names.push_back(symbol(name_buffer.c_str()));
|
||||||
|
new_decl_sorts.push_back(m_conv.bu().mk_sort(3));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
new_decl_sorts.push_back(s);
|
new_decl_sorts.push_back(s);
|
||||||
new_decl_names.push_back(n);
|
new_decl_names.push_back(n);
|
||||||
|
@ -248,6 +254,11 @@ bool fpa2bv_rewriter_cfg::reduce_var(var * t, expr_ref & result, proof_ref & res
|
||||||
m_conv.bu().mk_extract(ebits - 1, 0, new_var),
|
m_conv.bu().mk_extract(ebits - 1, 0, new_var),
|
||||||
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var));
|
m_conv.bu().mk_extract(sbits+ebits-2, ebits, new_var));
|
||||||
}
|
}
|
||||||
|
else if (m_conv.is_rm(s)) {
|
||||||
|
expr_ref new_var(m());
|
||||||
|
new_var = m().mk_var(t->get_idx(), m_conv.bu().mk_sort(3));
|
||||||
|
new_exp = m_conv.fu().mk_bv2rm(new_var);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
new_exp = m().mk_var(t->get_idx(), s);
|
new_exp = m().mk_var(t->get_idx(), s);
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,7 @@ void defined_names::impl::mk_definition(expr * e, app * n, sort_ref_buffer & var
|
||||||
args.push_back(m.mk_var(q->get_num_decls() - i - 1, q->get_decl_sort(i)));
|
args.push_back(m.mk_var(q->get_num_decls() - i - 1, q->get_decl_sort(i)));
|
||||||
}
|
}
|
||||||
array_util autil(m);
|
array_util autil(m);
|
||||||
func_decl * f = 0;
|
func_decl * f = nullptr;
|
||||||
if (autil.is_as_array(n2, f)) {
|
if (autil.is_as_array(n2, f)) {
|
||||||
n3 = m.mk_app(f, args.size()-1, args.c_ptr() + 1);
|
n3 = m.mk_app(f, args.size()-1, args.c_ptr() + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ class name_nested_formulas : public name_exprs_core {
|
||||||
ast_manager & m;
|
ast_manager & m;
|
||||||
expr * m_root;
|
expr * m_root;
|
||||||
|
|
||||||
pred(ast_manager & m):m(m), m_root(0) {}
|
pred(ast_manager & m):m(m), m_root(nullptr) {}
|
||||||
|
|
||||||
bool operator()(expr * t) override {
|
bool operator()(expr * t) override {
|
||||||
TRACE("name_exprs", tout << "name_nested_formulas::pred:\n" << mk_ismt2_pp(t, m) << "\n";);
|
TRACE("name_exprs", tout << "name_nested_formulas::pred:\n" << mk_ismt2_pp(t, m) << "\n";);
|
||||||
|
|
|
@ -393,10 +393,8 @@ expr_pattern_match::initialize(char const * spec_string) {
|
||||||
VERIFY(parse_smt2_commands(ctx, is));
|
VERIFY(parse_smt2_commands(ctx, is));
|
||||||
ctx.set_print_success(ps);
|
ctx.set_print_success(ps);
|
||||||
|
|
||||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
for (expr * e : ctx.assertions()) {
|
||||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
compile(e);
|
||||||
for (; it != end; ++it) {
|
|
||||||
compile(*it);
|
|
||||||
}
|
}
|
||||||
TRACE("expr_pattern_match", display(tout); );
|
TRACE("expr_pattern_match", display(tout); );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1248,7 +1248,7 @@ void proof_checker::dump_proof(proof const* pr) {
|
||||||
void proof_checker::dump_proof(unsigned num_antecedents, expr * const * antecedents, expr * consequent) {
|
void proof_checker::dump_proof(unsigned num_antecedents, expr * const * antecedents, expr * consequent) {
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
sprintf_s(buffer, ARRAYSIZE(buffer), "proof_lemma_%d.smt2", m_proof_lemma_id);
|
sprintf_s(buffer, Z3_ARRAYSIZE(buffer), "proof_lemma_%d.smt2", m_proof_lemma_id);
|
||||||
#else
|
#else
|
||||||
sprintf(buffer, "proof_lemma_%d.smt2", m_proof_lemma_id);
|
sprintf(buffer, "proof_lemma_%d.smt2", m_proof_lemma_id);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -458,7 +458,7 @@ struct pb2bv_rewriter::imp {
|
||||||
result = m.mk_true();
|
result = m.mk_true();
|
||||||
expr_ref_vector carry(m), new_carry(m);
|
expr_ref_vector carry(m), new_carry(m);
|
||||||
m_base.push_back(bound + rational::one());
|
m_base.push_back(bound + rational::one());
|
||||||
for (rational b_i : m_base) {
|
for (const rational& b_i : m_base) {
|
||||||
unsigned B = b_i.get_unsigned();
|
unsigned B = b_i.get_unsigned();
|
||||||
unsigned d_i = (bound % b_i).get_unsigned();
|
unsigned d_i = (bound % b_i).get_unsigned();
|
||||||
bound = div(bound, b_i);
|
bound = div(bound, b_i);
|
||||||
|
|
|
@ -842,7 +842,9 @@ void seq_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
app* seq_decl_plugin::mk_string(symbol const& s) {
|
app* seq_decl_plugin::mk_string(symbol const& s) {
|
||||||
parameter param(s);
|
zstring canonStr(s.bare_str());
|
||||||
|
symbol canonSym(canonStr.encode().c_str());
|
||||||
|
parameter param(canonSym);
|
||||||
func_decl* f = m_manager->mk_const_decl(m_stringc_sym, m_string,
|
func_decl* f = m_manager->mk_const_decl(m_stringc_sym, m_string,
|
||||||
func_decl_info(m_family_id, OP_STRING_CONST, 1, ¶m));
|
func_decl_info(m_family_id, OP_STRING_CONST, 1, ¶m));
|
||||||
return m_manager->mk_const(f);
|
return m_manager->mk_const(f);
|
||||||
|
|
|
@ -17,7 +17,7 @@ Notes:
|
||||||
--*/
|
--*/
|
||||||
#include "util/gparams.h"
|
#include "util/gparams.h"
|
||||||
#include "util/env_params.h"
|
#include "util/env_params.h"
|
||||||
#include "util/version.h"
|
#include "util/z3_version.h"
|
||||||
#include "ast/ast_smt_pp.h"
|
#include "ast/ast_smt_pp.h"
|
||||||
#include "ast/ast_smt2_pp.h"
|
#include "ast/ast_smt2_pp.h"
|
||||||
#include "ast/ast_pp_dot.h"
|
#include "ast/ast_pp_dot.h"
|
||||||
|
|
|
@ -1315,7 +1315,7 @@ void cmd_context::assert_expr(expr * t) {
|
||||||
m().inc_ref(t);
|
m().inc_ref(t);
|
||||||
m_assertions.push_back(t);
|
m_assertions.push_back(t);
|
||||||
if (produce_unsat_cores())
|
if (produce_unsat_cores())
|
||||||
m_assertion_names.push_back(0);
|
m_assertion_names.push_back(nullptr);
|
||||||
if (m_solver)
|
if (m_solver)
|
||||||
m_solver->assert_expr(t);
|
m_solver->assert_expr(t);
|
||||||
}
|
}
|
||||||
|
@ -1491,13 +1491,24 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
|
||||||
scoped_ctrl_c ctrlc(eh);
|
scoped_ctrl_c ctrlc(eh);
|
||||||
scoped_timer timer(timeout, &eh);
|
scoped_timer timer(timeout, &eh);
|
||||||
scoped_rlimit _rlimit(m().limit(), rlimit);
|
scoped_rlimit _rlimit(m().limit(), rlimit);
|
||||||
|
expr_ref_vector asms(m());
|
||||||
|
asms.append(num_assumptions, assumptions);
|
||||||
if (!m_processing_pareto) {
|
if (!m_processing_pareto) {
|
||||||
ptr_vector<expr> cnstr(m_assertions);
|
expr_ref_vector assertions(m());
|
||||||
cnstr.append(num_assumptions, assumptions);
|
unsigned sz = m_assertions.size();
|
||||||
get_opt()->set_hard_constraints(cnstr);
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
|
if (m_assertion_names.size() > i && m_assertion_names[i]) {
|
||||||
|
asms.push_back(m_assertion_names[i]);
|
||||||
|
assertions.push_back(m().mk_implies(m_assertion_names[i], m_assertions[i]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertions.push_back(m_assertions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get_opt()->set_hard_constraints(assertions);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
r = get_opt()->optimize();
|
r = get_opt()->optimize(asms);
|
||||||
if (r == l_true && get_opt()->is_pareto()) {
|
if (r == l_true && get_opt()->is_pareto()) {
|
||||||
m_processing_pareto = true;
|
m_processing_pareto = true;
|
||||||
}
|
}
|
||||||
|
@ -1805,11 +1816,8 @@ void cmd_context::validate_model() {
|
||||||
cancel_eh<reslimit> eh(m().limit());
|
cancel_eh<reslimit> eh(m().limit());
|
||||||
expr_ref r(m());
|
expr_ref r(m());
|
||||||
scoped_ctrl_c ctrlc(eh);
|
scoped_ctrl_c ctrlc(eh);
|
||||||
ptr_vector<expr>::const_iterator it = begin_assertions();
|
|
||||||
ptr_vector<expr>::const_iterator end = end_assertions();
|
|
||||||
bool invalid_model = false;
|
bool invalid_model = false;
|
||||||
for (; it != end; ++it) {
|
for (expr * a : assertions()) {
|
||||||
expr * a = *it;
|
|
||||||
if (is_ground(a)) {
|
if (is_ground(a)) {
|
||||||
r = nullptr;
|
r = nullptr;
|
||||||
evaluator(a, r);
|
evaluator(a, r);
|
||||||
|
|
|
@ -148,8 +148,8 @@ public:
|
||||||
virtual bool empty() = 0;
|
virtual bool empty() = 0;
|
||||||
virtual void push() = 0;
|
virtual void push() = 0;
|
||||||
virtual void pop(unsigned n) = 0;
|
virtual void pop(unsigned n) = 0;
|
||||||
virtual lbool optimize() = 0;
|
virtual lbool optimize(expr_ref_vector const& asms) = 0;
|
||||||
virtual void set_hard_constraints(ptr_vector<expr> & hard) = 0;
|
virtual void set_hard_constraints(expr_ref_vector const & hard) = 0;
|
||||||
virtual void display_assignment(std::ostream& out) = 0;
|
virtual void display_assignment(std::ostream& out) = 0;
|
||||||
virtual bool is_pareto() = 0;
|
virtual bool is_pareto() = 0;
|
||||||
virtual void set_logic(symbol const& s) = 0;
|
virtual void set_logic(symbol const& s) = 0;
|
||||||
|
@ -452,11 +452,8 @@ public:
|
||||||
|
|
||||||
double get_seconds() const { return m_watch.get_seconds(); }
|
double get_seconds() const { return m_watch.get_seconds(); }
|
||||||
|
|
||||||
ptr_vector<expr>::const_iterator begin_assertions() const { return m_assertions.begin(); }
|
ptr_vector<expr> const& assertions() const { return m_assertions; }
|
||||||
ptr_vector<expr>::const_iterator end_assertions() const { return m_assertions.end(); }
|
ptr_vector<expr> const& assertion_names() const { return m_assertion_names; }
|
||||||
|
|
||||||
ptr_vector<expr>::const_iterator begin_assertion_names() const { return m_assertion_names.begin(); }
|
|
||||||
ptr_vector<expr>::const_iterator end_assertion_names() const { return m_assertion_names.end(); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Hack: consume assertions if there are no scopes.
|
\brief Hack: consume assertions if there are no scopes.
|
||||||
|
|
|
@ -28,20 +28,18 @@ void assert_exprs_from(cmd_context const & ctx, goal & t) {
|
||||||
ast_manager & m = t.m();
|
ast_manager & m = t.m();
|
||||||
bool proofs_enabled = t.proofs_enabled();
|
bool proofs_enabled = t.proofs_enabled();
|
||||||
if (ctx.produce_unsat_cores()) {
|
if (ctx.produce_unsat_cores()) {
|
||||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
ptr_vector<expr>::const_iterator it = ctx.assertions().begin();
|
||||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
ptr_vector<expr>::const_iterator end = ctx.assertions().end();
|
||||||
ptr_vector<expr>::const_iterator it2 = ctx.begin_assertion_names();
|
ptr_vector<expr>::const_iterator it2 = ctx.assertion_names().begin();
|
||||||
SASSERT(end - it == ctx.end_assertion_names() - it2);
|
SASSERT(ctx.assertions().size() == ctx.assertion_names().size());
|
||||||
for (; it != end; ++it, ++it2) {
|
for (; it != end; ++it, ++it2) {
|
||||||
t.assert_expr(*it, proofs_enabled ? m.mk_asserted(*it) : nullptr, m.mk_leaf(*it2));
|
t.assert_expr(*it, proofs_enabled ? m.mk_asserted(*it) : nullptr, m.mk_leaf(*it2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
for (expr * e : ctx.assertions()) {
|
||||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
t.assert_expr(e, proofs_enabled ? m.mk_asserted(e) : nullptr, nullptr);
|
||||||
for (; it != end; ++it) {
|
|
||||||
t.assert_expr(*it, proofs_enabled ? m.mk_asserted(*it) : nullptr, nullptr);
|
|
||||||
}
|
}
|
||||||
SASSERT(ctx.begin_assertion_names() == ctx.end_assertion_names());
|
SASSERT(ctx.assertion_names().empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ public:
|
||||||
class psort_inst_cache;
|
class psort_inst_cache;
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
#if defined(__APPLE__) && defined(__MACH__)
|
||||||
// CMW: for some unknown reason, llvm on OSX does not like the name `psort'
|
// CMW: for some unknown reason, llvm on macOS does not like the name `psort'
|
||||||
#define psort Z3_psort
|
#define psort Z3_psort
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace polynomial {
|
||||||
|
|
||||||
struct lt_var {
|
struct lt_var {
|
||||||
bool operator()(power const & p1, power const & p2) {
|
bool operator()(power const & p1, power const & p2) {
|
||||||
// CMW: The assertion below does not hold on OSX, because
|
// CMW: The assertion below does not hold on macOS, because
|
||||||
// their implementation of std::sort will try to compare
|
// their implementation of std::sort will try to compare
|
||||||
// two items at the same index instead of comparing
|
// two items at the same index instead of comparing
|
||||||
// the indices directly. I suspect that the purpose of
|
// the indices directly. I suspect that the purpose of
|
||||||
|
|
|
@ -351,7 +351,7 @@ bool model::can_inline_def(top_sort& ts, func_decl* f) {
|
||||||
|
|
||||||
|
|
||||||
expr_ref model::cleanup_expr(top_sort& ts, expr* e, unsigned current_partition) {
|
expr_ref model::cleanup_expr(top_sort& ts, expr* e, unsigned current_partition) {
|
||||||
if (!e) return expr_ref(0, m);
|
if (!e) return expr_ref(nullptr, m);
|
||||||
|
|
||||||
TRACE("model", tout << "cleaning up:\n" << mk_pp(e, m) << "\n";);
|
TRACE("model", tout << "cleaning up:\n" << mk_pp(e, m) << "\n";);
|
||||||
|
|
||||||
|
@ -453,7 +453,7 @@ void model::remove_decls(ptr_vector<func_decl> & decls, func_decl_set const & s)
|
||||||
|
|
||||||
expr_ref model::get_inlined_const_interp(func_decl* f) {
|
expr_ref model::get_inlined_const_interp(func_decl* f) {
|
||||||
expr* v = get_const_interp(f);
|
expr* v = get_const_interp(f);
|
||||||
if (!v) return expr_ref(0, m);
|
if (!v) return expr_ref(nullptr, m);
|
||||||
top_sort st(m);
|
top_sort st(m);
|
||||||
expr_ref result1(v, m);
|
expr_ref result1(v, m);
|
||||||
expr_ref result2 = cleanup_expr(st, v, UINT_MAX);
|
expr_ref result2 = cleanup_expr(st, v, UINT_MAX);
|
||||||
|
|
|
@ -358,6 +358,23 @@ namespace datalog {
|
||||||
DEL_VECTOR(m_rules);
|
DEL_VECTOR(m_rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rule_set::replace_rule(rule * r, rule * other) {
|
||||||
|
TRACE("dl", r->display(m_context, tout << "replace:"););
|
||||||
|
func_decl* d = r->get_decl();
|
||||||
|
rule_vector* rules = m_head2rules.find(d);
|
||||||
|
#define REPLACE_VECTOR(_v) \
|
||||||
|
for (unsigned i = (_v).size(); i > 0; ) { \
|
||||||
|
--i; \
|
||||||
|
if ((_v)[i] == r) { \
|
||||||
|
(_v)[i] = other; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
REPLACE_VECTOR(*rules);
|
||||||
|
REPLACE_VECTOR(m_rules);
|
||||||
|
}
|
||||||
|
|
||||||
void rule_set::ensure_closed() {
|
void rule_set::ensure_closed() {
|
||||||
if (!is_closed()) {
|
if (!is_closed()) {
|
||||||
VERIFY(close());
|
VERIFY(close());
|
||||||
|
|
|
@ -203,6 +203,10 @@ namespace datalog {
|
||||||
\brief Remove rule \c r from the rule set.
|
\brief Remove rule \c r from the rule set.
|
||||||
*/
|
*/
|
||||||
void del_rule(rule * r);
|
void del_rule(rule * r);
|
||||||
|
/**
|
||||||
|
\brief Replace a rule \c r with the rule \c other
|
||||||
|
*/
|
||||||
|
void replace_rule(rule * r, rule * other);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Add all rules from a different rule_set.
|
\brief Add all rules from a different rule_set.
|
||||||
|
@ -280,4 +284,3 @@ namespace datalog {
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DL_RULE_SET_H_ */
|
#endif /* DL_RULE_SET_H_ */
|
||||||
|
|
||||||
|
|
|
@ -276,7 +276,7 @@ namespace datalog {
|
||||||
}
|
}
|
||||||
unsigned n = container.size();
|
unsigned n = container.size();
|
||||||
unsigned ofs = 1;
|
unsigned ofs = 1;
|
||||||
int r_i = 1;
|
unsigned r_i = 1;
|
||||||
for(unsigned i=removed_cols[0]+1; i<n; i++) {
|
for(unsigned i=removed_cols[0]+1; i<n; i++) {
|
||||||
if(r_i!=removed_col_cnt && removed_cols[r_i]==i) {
|
if(r_i!=removed_col_cnt && removed_cols[r_i]==i) {
|
||||||
r_i++;
|
r_i++;
|
||||||
|
|
|
@ -177,5 +177,6 @@ def_module_params('fp',
|
||||||
('spacer.dump_threshold', DOUBLE, 5.0, 'Threshold in seconds on dumping benchmarks'),
|
('spacer.dump_threshold', DOUBLE, 5.0, 'Threshold in seconds on dumping benchmarks'),
|
||||||
('spacer.gpdr', BOOL, False, 'Use GPDR solving strategy for non-linear CHC'),
|
('spacer.gpdr', BOOL, False, 'Use GPDR solving strategy for non-linear CHC'),
|
||||||
('spacer.gpdr.bfs', BOOL, True, 'Use BFS exploration strategy for expanding model search'),
|
('spacer.gpdr.bfs', BOOL, True, 'Use BFS exploration strategy for expanding model search'),
|
||||||
|
('spacer.use_bg_invs', BOOL, False, 'Enable external background invariants'),
|
||||||
|
|
||||||
))
|
))
|
||||||
|
|
|
@ -332,10 +332,8 @@ public:
|
||||||
private:
|
private:
|
||||||
void set_background(cmd_context& ctx) {
|
void set_background(cmd_context& ctx) {
|
||||||
datalog::context& dlctx = m_dl_ctx->dlctx();
|
datalog::context& dlctx = m_dl_ctx->dlctx();
|
||||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
for (expr * e : ctx.assertions()) {
|
||||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
dlctx.assert_expr(e);
|
||||||
for (; it != end; ++it) {
|
|
||||||
dlctx.assert_expr(*it);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -493,7 +493,8 @@ lemma::lemma (ast_manager &manager, expr * body, unsigned lvl) :
|
||||||
m_pob(nullptr), m_ctp(nullptr),
|
m_pob(nullptr), m_ctp(nullptr),
|
||||||
m_lvl(lvl), m_init_lvl(m_lvl),
|
m_lvl(lvl), m_init_lvl(m_lvl),
|
||||||
m_bumped(0), m_weakness(WEAKNESS_MAX),
|
m_bumped(0), m_weakness(WEAKNESS_MAX),
|
||||||
m_external(false), m_blocked(false) {
|
m_external(false), m_blocked(false),
|
||||||
|
m_background(false) {
|
||||||
SASSERT(m_body);
|
SASSERT(m_body);
|
||||||
normalize(m_body, m_body);
|
normalize(m_body, m_body);
|
||||||
}
|
}
|
||||||
|
@ -505,7 +506,8 @@ lemma::lemma(pob_ref const &p) :
|
||||||
m_pob(p), m_ctp(nullptr),
|
m_pob(p), m_ctp(nullptr),
|
||||||
m_lvl(p->level()), m_init_lvl(m_lvl),
|
m_lvl(p->level()), m_init_lvl(m_lvl),
|
||||||
m_bumped(0), m_weakness(p->weakness()),
|
m_bumped(0), m_weakness(p->weakness()),
|
||||||
m_external(false), m_blocked(false) {
|
m_external(false), m_blocked(false),
|
||||||
|
m_background(false) {
|
||||||
SASSERT(m_pob);
|
SASSERT(m_pob);
|
||||||
m_pob->get_skolems(m_zks);
|
m_pob->get_skolems(m_zks);
|
||||||
add_binding(m_pob->get_binding());
|
add_binding(m_pob->get_binding());
|
||||||
|
@ -519,8 +521,8 @@ lemma::lemma(pob_ref const &p, expr_ref_vector &cube, unsigned lvl) :
|
||||||
m_pob(p), m_ctp(nullptr),
|
m_pob(p), m_ctp(nullptr),
|
||||||
m_lvl(p->level()), m_init_lvl(m_lvl),
|
m_lvl(p->level()), m_init_lvl(m_lvl),
|
||||||
m_bumped(0), m_weakness(p->weakness()),
|
m_bumped(0), m_weakness(p->weakness()),
|
||||||
m_external(false), m_blocked(false)
|
m_external(false), m_blocked(false),
|
||||||
{
|
m_background(false) {
|
||||||
if (m_pob) {
|
if (m_pob) {
|
||||||
m_pob->get_skolems(m_zks);
|
m_pob->get_skolems(m_zks);
|
||||||
add_binding(m_pob->get_binding());
|
add_binding(m_pob->get_binding());
|
||||||
|
@ -921,10 +923,10 @@ void pred_transformer::simplify_formulas()
|
||||||
{m_frames.simplify_formulas ();}
|
{m_frames.simplify_formulas ();}
|
||||||
|
|
||||||
|
|
||||||
expr_ref pred_transformer::get_formulas(unsigned level) const
|
expr_ref pred_transformer::get_formulas(unsigned level, bool bg) const
|
||||||
{
|
{
|
||||||
expr_ref_vector res(m);
|
expr_ref_vector res(m);
|
||||||
m_frames.get_frame_geq_lemmas (level, res);
|
m_frames.get_frame_geq_lemmas (level, res, bg);
|
||||||
return mk_and(res);
|
return mk_and(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,6 +937,7 @@ bool pred_transformer::propagate_to_next_level (unsigned src_level)
|
||||||
/// \brief adds a lemma to the solver and to child solvers
|
/// \brief adds a lemma to the solver and to child solvers
|
||||||
void pred_transformer::add_lemma_core(lemma* lemma, bool ground_only)
|
void pred_transformer::add_lemma_core(lemma* lemma, bool ground_only)
|
||||||
{
|
{
|
||||||
|
SASSERT(!lemma->is_background());
|
||||||
unsigned lvl = lemma->level();
|
unsigned lvl = lemma->level();
|
||||||
expr* l = lemma->get_expr();
|
expr* l = lemma->get_expr();
|
||||||
SASSERT(!lemma->is_ground() || is_clause(m, l));
|
SASSERT(!lemma->is_ground() || is_clause(m, l));
|
||||||
|
@ -975,8 +978,9 @@ void pred_transformer::add_lemma_core(lemma* lemma, bool ground_only)
|
||||||
next_level(lvl), ground_only); }
|
next_level(lvl), ground_only); }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pred_transformer::add_lemma (expr *e, unsigned lvl) {
|
bool pred_transformer::add_lemma (expr *e, unsigned lvl, bool bg) {
|
||||||
lemma_ref lem = alloc(lemma, m, e, lvl);
|
lemma_ref lem = alloc(lemma, m, e, lvl);
|
||||||
|
lem->set_background(bg);
|
||||||
return m_frames.add_lemma(lem.get());
|
return m_frames.add_lemma(lem.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1217,15 +1221,18 @@ expr_ref pred_transformer::get_origin_summary (model &mdl,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pred_transformer::add_cover(unsigned level, expr* property)
|
void pred_transformer::add_cover(unsigned level, expr* property, bool bg)
|
||||||
{
|
{
|
||||||
|
SASSERT(!bg || is_infty_level(level));
|
||||||
// replace bound variables by local constants.
|
// replace bound variables by local constants.
|
||||||
expr_ref result(property, m), v(m), c(m);
|
expr_ref result(property, m), v(m), c(m);
|
||||||
expr_substitution sub(m);
|
expr_substitution sub(m);
|
||||||
|
proof_ref pr(m);
|
||||||
|
pr = m.mk_asserted(m.mk_true());
|
||||||
for (unsigned i = 0; i < sig_size(); ++i) {
|
for (unsigned i = 0; i < sig_size(); ++i) {
|
||||||
c = m.mk_const(pm.o2n(sig(i), 0));
|
c = m.mk_const(pm.o2n(sig(i), 0));
|
||||||
v = m.mk_var(i, sig(i)->get_range());
|
v = m.mk_var(i, sig(i)->get_range());
|
||||||
sub.insert(v, c);
|
sub.insert(v, c, pr);
|
||||||
}
|
}
|
||||||
scoped_ptr<expr_replacer> rep = mk_default_expr_replacer(m);
|
scoped_ptr<expr_replacer> rep = mk_default_expr_replacer(m);
|
||||||
rep->set_substitution(&sub);
|
rep->set_substitution(&sub);
|
||||||
|
@ -1236,13 +1243,38 @@ void pred_transformer::add_cover(unsigned level, expr* property)
|
||||||
expr_ref_vector lemmas(m);
|
expr_ref_vector lemmas(m);
|
||||||
flatten_and(result, lemmas);
|
flatten_and(result, lemmas);
|
||||||
for (unsigned i = 0, sz = lemmas.size(); i < sz; ++i) {
|
for (unsigned i = 0, sz = lemmas.size(); i < sz; ++i) {
|
||||||
add_lemma(lemmas.get(i), level);
|
add_lemma(lemmas.get(i), level, bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pred_transformer::propagate_to_infinity (unsigned level)
|
void pred_transformer::propagate_to_infinity (unsigned level)
|
||||||
{m_frames.propagate_to_infinity (level);}
|
{m_frames.propagate_to_infinity (level);}
|
||||||
|
|
||||||
|
// compute a conjunction of all background facts
|
||||||
|
void pred_transformer::get_pred_bg_invs(expr_ref_vector& out) {
|
||||||
|
expr_ref inv(m), tmp1(m), tmp2(m);
|
||||||
|
ptr_vector<func_decl> preds;
|
||||||
|
for (auto kv : m_pt_rules) {
|
||||||
|
expr* tag = kv.m_value->tag();
|
||||||
|
datalog::rule const &r = kv.m_value->rule();
|
||||||
|
find_predecessors (r, preds);
|
||||||
|
|
||||||
|
for (unsigned i = 0, preds_sz = preds.size(); i < preds_sz; i++) {
|
||||||
|
func_decl* pre = preds[i];
|
||||||
|
pred_transformer &pt = ctx.get_pred_transformer(pre);
|
||||||
|
const lemma_ref_vector &invs = pt.get_bg_invs();
|
||||||
|
CTRACE("spacer", !invs.empty(),
|
||||||
|
tout << "add-bg-invariant: " << mk_pp (pre, m) << "\n";);
|
||||||
|
for (auto inv : invs) {
|
||||||
|
// tag -> inv1 ... tag -> invn
|
||||||
|
tmp1 = m.mk_implies(tag, inv->get_expr());
|
||||||
|
pm.formula_n2o(tmp1, tmp2, i);
|
||||||
|
out.push_back(tmp2);
|
||||||
|
TRACE("spacer", tout << tmp2 << "\n";);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Returns true if the obligation is already blocked by current lemmas
|
/// \brief Returns true if the obligation is already blocked by current lemmas
|
||||||
|
@ -1293,7 +1325,7 @@ bool pred_transformer::is_qblocked (pob &n) {
|
||||||
|
|
||||||
// assert cti
|
// assert cti
|
||||||
s->assert_expr(n.post());
|
s->assert_expr(n.post());
|
||||||
lbool res = s->check_sat(0, 0);
|
lbool res = s->check_sat(0, nullptr);
|
||||||
|
|
||||||
// if (res == l_false) {
|
// if (res == l_false) {
|
||||||
// expr_ref_vector core(m);
|
// expr_ref_vector core(m);
|
||||||
|
@ -1344,6 +1376,14 @@ lbool pred_transformer::is_reachable(pob& n, expr_ref_vector* core,
|
||||||
|
|
||||||
expr_ref_vector post (m), reach_assumps (m);
|
expr_ref_vector post (m), reach_assumps (m);
|
||||||
post.push_back (n.post ());
|
post.push_back (n.post ());
|
||||||
|
flatten_and(post);
|
||||||
|
|
||||||
|
// if equality propagation is disabled in arithmetic, expand
|
||||||
|
// equality literals into two inequalities to increase the space
|
||||||
|
// for interpolation
|
||||||
|
if (!ctx.use_eq_prop()) {
|
||||||
|
expand_literals(m, post);
|
||||||
|
}
|
||||||
|
|
||||||
// populate reach_assumps
|
// populate reach_assumps
|
||||||
if (n.level () > 0 && !m_all_init) {
|
if (n.level () > 0 && !m_all_init) {
|
||||||
|
@ -1472,7 +1512,7 @@ bool pred_transformer::is_invariant(unsigned level, lemma* lem,
|
||||||
expr_ref lemma_expr(m);
|
expr_ref lemma_expr(m);
|
||||||
lemma_expr = lem->get_expr();
|
lemma_expr = lem->get_expr();
|
||||||
|
|
||||||
expr_ref_vector conj(m), aux(m);
|
expr_ref_vector cand(m), aux(m), conj(m);
|
||||||
expr_ref gnd_lemma(m);
|
expr_ref gnd_lemma(m);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1482,8 +1522,8 @@ bool pred_transformer::is_invariant(unsigned level, lemma* lem,
|
||||||
lemma_expr = gnd_lemma.get();
|
lemma_expr = gnd_lemma.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
conj.push_back(mk_not(m, lemma_expr));
|
cand.push_back(mk_not(m, lemma_expr));
|
||||||
flatten_and (conj);
|
flatten_and (cand);
|
||||||
|
|
||||||
prop_solver::scoped_level _sl(*m_solver, level);
|
prop_solver::scoped_level _sl(*m_solver, level);
|
||||||
prop_solver::scoped_subset_core _sc (*m_solver, true);
|
prop_solver::scoped_subset_core _sc (*m_solver, true);
|
||||||
|
@ -1494,9 +1534,12 @@ bool pred_transformer::is_invariant(unsigned level, lemma* lem,
|
||||||
if (ctx.use_ctp()) {mdl_ref_ptr = &mdl;}
|
if (ctx.use_ctp()) {mdl_ref_ptr = &mdl;}
|
||||||
m_solver->set_core(core);
|
m_solver->set_core(core);
|
||||||
m_solver->set_model(mdl_ref_ptr);
|
m_solver->set_model(mdl_ref_ptr);
|
||||||
expr * bg = m_extend_lit.get ();
|
|
||||||
lbool r = m_solver->check_assumptions (conj, aux, m_transition_clause,
|
conj.push_back(m_extend_lit);
|
||||||
1, &bg, 1);
|
if (ctx.use_bg_invs()) get_pred_bg_invs(conj);
|
||||||
|
|
||||||
|
lbool r = m_solver->check_assumptions (cand, aux, m_transition_clause,
|
||||||
|
conj.size(), conj.c_ptr(), 1);
|
||||||
if (r == l_false) {
|
if (r == l_false) {
|
||||||
solver_level = m_solver->uses_level ();
|
solver_level = m_solver->uses_level ();
|
||||||
lem->reset_ctp();
|
lem->reset_ctp();
|
||||||
|
@ -1527,6 +1570,7 @@ bool pred_transformer::check_inductive(unsigned level, expr_ref_vector& state,
|
||||||
m_solver->set_core(&core);
|
m_solver->set_core(&core);
|
||||||
m_solver->set_model (nullptr);
|
m_solver->set_model (nullptr);
|
||||||
expr_ref_vector aux (m);
|
expr_ref_vector aux (m);
|
||||||
|
if (ctx.use_bg_invs()) get_pred_bg_invs(conj);
|
||||||
conj.push_back (m_extend_lit);
|
conj.push_back (m_extend_lit);
|
||||||
lbool res = m_solver->check_assumptions (state, aux,
|
lbool res = m_solver->check_assumptions (state, aux,
|
||||||
m_transition_clause,
|
m_transition_clause,
|
||||||
|
@ -1941,14 +1985,27 @@ void pred_transformer::update_solver_with_rfs(prop_solver *solver,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// pred_transformer::frames
|
/// pred_transformer::frames
|
||||||
|
|
||||||
|
|
||||||
bool pred_transformer::frames::add_lemma(lemma *new_lemma)
|
bool pred_transformer::frames::add_lemma(lemma *new_lemma)
|
||||||
{
|
{
|
||||||
TRACE("spacer", tout << "add-lemma: " << pp_level(new_lemma->level()) << " "
|
TRACE("spacer", tout << "add-lemma: " << pp_level(new_lemma->level()) << " "
|
||||||
<< m_pt.head()->get_name() << " "
|
<< m_pt.head()->get_name() << " "
|
||||||
<< mk_pp(new_lemma->get_expr(), m_pt.get_ast_manager()) << "\n";);
|
<< mk_pp(new_lemma->get_expr(), m_pt.get_ast_manager()) << "\n";);
|
||||||
|
|
||||||
|
if (new_lemma->is_background()) {
|
||||||
|
SASSERT (is_infty_level(new_lemma->level()));
|
||||||
|
|
||||||
|
for (auto &l : m_bg_invs) {
|
||||||
|
if (l->get_expr() == new_lemma->get_expr()) return false;
|
||||||
|
}
|
||||||
|
TRACE("spacer", tout << "add-external-lemma: "
|
||||||
|
<< pp_level(new_lemma->level()) << " "
|
||||||
|
<< m_pt.head()->get_name() << " "
|
||||||
|
<< mk_pp(new_lemma->get_expr(), m_pt.get_ast_manager()) << "\n";);
|
||||||
|
|
||||||
|
m_bg_invs.push_back(new_lemma);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (auto *old_lemma : m_lemmas) {
|
for (auto *old_lemma : m_lemmas) {
|
||||||
if (old_lemma->get_expr() == new_lemma->get_expr()) {
|
if (old_lemma->get_expr() == new_lemma->get_expr()) {
|
||||||
|
@ -2295,6 +2352,7 @@ void context::updt_params() {
|
||||||
m_use_restarts = m_params.spacer_restarts();
|
m_use_restarts = m_params.spacer_restarts();
|
||||||
m_restart_initial_threshold = m_params.spacer_restart_initial_threshold();
|
m_restart_initial_threshold = m_params.spacer_restart_initial_threshold();
|
||||||
m_pdr_bfs = m_params.spacer_gpdr_bfs();
|
m_pdr_bfs = m_params.spacer_gpdr_bfs();
|
||||||
|
m_use_bg_invs = m_params.spacer_use_bg_invs();
|
||||||
|
|
||||||
if (m_use_gpdr) {
|
if (m_use_gpdr) {
|
||||||
// set options to be compatible with GPDR
|
// set options to be compatible with GPDR
|
||||||
|
@ -2423,36 +2481,38 @@ expr_ref context::get_cover_delta(int level, func_decl* p_orig, func_decl* p)
|
||||||
if (m_rels.find(p, pt)) {
|
if (m_rels.find(p, pt)) {
|
||||||
return pt->get_cover_delta(p_orig, level);
|
return pt->get_cover_delta(p_orig, level);
|
||||||
} else {
|
} else {
|
||||||
IF_VERBOSE(10, verbose_stream() << "did not find predicate " << p->get_name() << "\n";);
|
IF_VERBOSE(10, verbose_stream() << "did not find predicate "
|
||||||
|
<< p->get_name() << "\n";);
|
||||||
return expr_ref(m.mk_true(), m);
|
return expr_ref(m.mk_true(), m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::add_cover(int level, func_decl* p, expr* property)
|
void context::add_cover(int level, func_decl* p, expr* property, bool bg)
|
||||||
{
|
{
|
||||||
|
scoped_proof _pf_(m);
|
||||||
|
|
||||||
pred_transformer* pt = nullptr;
|
pred_transformer* pt = nullptr;
|
||||||
if (!m_rels.find(p, pt)) {
|
if (!m_rels.find(p, pt)) {
|
||||||
pt = alloc(pred_transformer, *this, get_manager(), p);
|
pt = alloc(pred_transformer, *this, get_manager(), p);
|
||||||
m_rels.insert(p, pt);
|
m_rels.insert(p, pt);
|
||||||
IF_VERBOSE(10, verbose_stream() << "did not find predicate " << p->get_name() << "\n";);
|
IF_VERBOSE(10, verbose_stream() << "did not find predicate "
|
||||||
|
<< p->get_name() << "\n";);
|
||||||
}
|
}
|
||||||
unsigned lvl = (level == -1)?infty_level():((unsigned)level);
|
unsigned lvl = (level == -1)?infty_level():((unsigned)level);
|
||||||
pt->add_cover(lvl, property);
|
pt->add_cover(lvl, property, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::add_invariant (func_decl *p, expr *property)
|
void context::add_invariant (func_decl *p, expr *property)
|
||||||
{add_cover (infty_level(), p, property);}
|
{add_cover (infty_level(), p, property, true);}
|
||||||
|
|
||||||
expr_ref context::get_reachable(func_decl *p)
|
expr_ref context::get_reachable(func_decl *p) {
|
||||||
{
|
|
||||||
pred_transformer* pt = nullptr;
|
pred_transformer* pt = nullptr;
|
||||||
if (!m_rels.find(p, pt))
|
if (!m_rels.find(p, pt))
|
||||||
{ return expr_ref(m.mk_false(), m); }
|
{ return expr_ref(m.mk_false(), m); }
|
||||||
return pt->get_reachable();
|
return pt->get_reachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool context::validate()
|
bool context::validate() {
|
||||||
{
|
|
||||||
if (!m_validate_result) { return true; }
|
if (!m_validate_result) { return true; }
|
||||||
|
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
|
@ -2483,7 +2543,7 @@ bool context::validate()
|
||||||
model_ref model;
|
model_ref model;
|
||||||
vector<relation_info> rs;
|
vector<relation_info> rs;
|
||||||
model_converter_ref mc;
|
model_converter_ref mc;
|
||||||
get_level_property(m_inductive_lvl, refs, rs);
|
get_level_property(m_inductive_lvl, refs, rs, use_bg_invs());
|
||||||
inductive_property ex(m, mc, rs);
|
inductive_property ex(m, mc, rs);
|
||||||
ex.to_model(model);
|
ex.to_model(model);
|
||||||
var_subst vs(m, false);
|
var_subst vs(m, false);
|
||||||
|
@ -2624,13 +2684,13 @@ void context::init_lemma_generalizers()
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::get_level_property(unsigned lvl, expr_ref_vector& res,
|
void context::get_level_property(unsigned lvl, expr_ref_vector& res,
|
||||||
vector<relation_info>& rs) const {
|
vector<relation_info>& rs, bool with_bg) const {
|
||||||
for (auto const& kv : m_rels) {
|
for (auto const& kv : m_rels) {
|
||||||
pred_transformer* r = kv.m_value;
|
pred_transformer* r = kv.m_value;
|
||||||
if (r->head() == m_query_pred) {
|
if (r->head() == m_query_pred) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
expr_ref conj = r->get_formulas(lvl);
|
expr_ref conj = r->get_formulas(lvl, with_bg);
|
||||||
m_pm.formula_n2o(0, false, conj);
|
m_pm.formula_n2o(0, false, conj);
|
||||||
res.push_back(conj);
|
res.push_back(conj);
|
||||||
ptr_vector<func_decl> sig(r->head()->get_arity(), r->sig());
|
ptr_vector<func_decl> sig(r->head()->get_arity(), r->sig());
|
||||||
|
@ -2662,7 +2722,7 @@ lbool context::solve(unsigned from_lvl)
|
||||||
IF_VERBOSE(1, {
|
IF_VERBOSE(1, {
|
||||||
expr_ref_vector refs(m);
|
expr_ref_vector refs(m);
|
||||||
vector<relation_info> rs;
|
vector<relation_info> rs;
|
||||||
get_level_property(m_inductive_lvl, refs, rs);
|
get_level_property(m_inductive_lvl, refs, rs, use_bg_invs());
|
||||||
model_converter_ref mc;
|
model_converter_ref mc;
|
||||||
inductive_property ex(m, mc, rs);
|
inductive_property ex(m, mc, rs);
|
||||||
verbose_stream() << ex.to_string();
|
verbose_stream() << ex.to_string();
|
||||||
|
@ -2844,7 +2904,7 @@ model_ref context::get_model()
|
||||||
model_ref model;
|
model_ref model;
|
||||||
expr_ref_vector refs(m);
|
expr_ref_vector refs(m);
|
||||||
vector<relation_info> rs;
|
vector<relation_info> rs;
|
||||||
get_level_property(m_inductive_lvl, refs, rs);
|
get_level_property(m_inductive_lvl, refs, rs, use_bg_invs());
|
||||||
inductive_property ex(m, const_cast<model_converter_ref&>(m_mc), rs);
|
inductive_property ex(m, const_cast<model_converter_ref&>(m_mc), rs);
|
||||||
ex.to_model (model);
|
ex.to_model (model);
|
||||||
return model;
|
return model;
|
||||||
|
@ -2877,7 +2937,7 @@ expr_ref context::mk_unsat_answer() const
|
||||||
{
|
{
|
||||||
expr_ref_vector refs(m);
|
expr_ref_vector refs(m);
|
||||||
vector<relation_info> rs;
|
vector<relation_info> rs;
|
||||||
get_level_property(m_inductive_lvl, refs, rs);
|
get_level_property(m_inductive_lvl, refs, rs, use_bg_invs());
|
||||||
inductive_property ex(m, const_cast<model_converter_ref&>(m_mc), rs);
|
inductive_property ex(m, const_cast<model_converter_ref&>(m_mc), rs);
|
||||||
return ex.to_expr();
|
return ex.to_expr();
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,8 +128,9 @@ class lemma {
|
||||||
unsigned m_init_lvl; // level at which lemma was created
|
unsigned m_init_lvl; // level at which lemma was created
|
||||||
unsigned m_bumped:16;
|
unsigned m_bumped:16;
|
||||||
unsigned m_weakness:16;
|
unsigned m_weakness:16;
|
||||||
unsigned m_external:1;
|
unsigned m_external:1; // external lemma from another solver
|
||||||
unsigned m_blocked:1;
|
unsigned m_blocked:1; // blocked by CTP
|
||||||
|
unsigned m_background:1; // background assumed fact
|
||||||
|
|
||||||
void mk_expr_core();
|
void mk_expr_core();
|
||||||
void mk_cube_core();
|
void mk_cube_core();
|
||||||
|
@ -163,6 +164,9 @@ public:
|
||||||
void set_external(bool ext){m_external = ext;}
|
void set_external(bool ext){m_external = ext;}
|
||||||
bool external() { return m_external;}
|
bool external() { return m_external;}
|
||||||
|
|
||||||
|
void set_background(bool v) {m_background = v;}
|
||||||
|
bool is_background() {return m_background;}
|
||||||
|
|
||||||
bool is_blocked() {return m_blocked;}
|
bool is_blocked() {return m_blocked;}
|
||||||
void set_blocked(bool v) {m_blocked=v;}
|
void set_blocked(bool v) {m_blocked=v;}
|
||||||
|
|
||||||
|
@ -222,6 +226,7 @@ class pred_transformer {
|
||||||
pred_transformer &m_pt; // parent pred_transformer
|
pred_transformer &m_pt; // parent pred_transformer
|
||||||
lemma_ref_vector m_pinned_lemmas; // all created lemmas
|
lemma_ref_vector m_pinned_lemmas; // all created lemmas
|
||||||
lemma_ref_vector m_lemmas; // active lemmas
|
lemma_ref_vector m_lemmas; // active lemmas
|
||||||
|
lemma_ref_vector m_bg_invs; // background (assumed) invariants
|
||||||
unsigned m_size; // num of frames
|
unsigned m_size; // num of frames
|
||||||
|
|
||||||
bool m_sorted; // true if m_lemmas is sorted by m_lt
|
bool m_sorted; // true if m_lemmas is sorted by m_lt
|
||||||
|
@ -230,7 +235,8 @@ class pred_transformer {
|
||||||
void sort ();
|
void sort ();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
frames (pred_transformer &pt) : m_pt (pt), m_size(0), m_sorted (true) {}
|
frames (pred_transformer &pt) : m_pt (pt),
|
||||||
|
m_size(0), m_sorted (true) {}
|
||||||
~frames() {}
|
~frames() {}
|
||||||
void simplify_formulas ();
|
void simplify_formulas ();
|
||||||
|
|
||||||
|
@ -245,16 +251,24 @@ class pred_transformer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void get_frame_geq_lemmas (unsigned level, expr_ref_vector &out) const {
|
void get_frame_geq_lemmas (unsigned level, expr_ref_vector &out,
|
||||||
|
bool with_bg = false) const {
|
||||||
for (auto &lemma : m_lemmas) {
|
for (auto &lemma : m_lemmas) {
|
||||||
if (lemma->level() >= level) {
|
if (lemma->level() >= level) {
|
||||||
out.push_back(lemma->get_expr());
|
out.push_back(lemma->get_expr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (with_bg) {
|
||||||
|
for (auto &lemma : m_bg_invs)
|
||||||
|
out.push_back(lemma->get_expr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lemma_ref_vector& get_bg_invs() const {return m_bg_invs;}
|
||||||
unsigned size() const {return m_size;}
|
unsigned size() const {return m_size;}
|
||||||
unsigned lemma_size() const {return m_lemmas.size ();}
|
unsigned lemma_size() const {return m_lemmas.size ();}
|
||||||
|
unsigned bg_invs_size() const {return m_bg_invs.size();}
|
||||||
|
|
||||||
void add_frame() {m_size++;}
|
void add_frame() {m_size++;}
|
||||||
void inherit_frames (frames &other) {
|
void inherit_frames (frames &other) {
|
||||||
for (auto &other_lemma : other.m_lemmas) {
|
for (auto &other_lemma : other.m_lemmas) {
|
||||||
|
@ -265,6 +279,7 @@ class pred_transformer {
|
||||||
add_lemma(new_lemma.get());
|
add_lemma(new_lemma.get());
|
||||||
}
|
}
|
||||||
m_sorted = false;
|
m_sorted = false;
|
||||||
|
m_bg_invs.append(other.m_bg_invs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool add_lemma (lemma *new_lemma);
|
bool add_lemma (lemma *new_lemma);
|
||||||
|
@ -418,6 +433,11 @@ class pred_transformer {
|
||||||
|
|
||||||
app_ref mk_fresh_rf_tag ();
|
app_ref mk_fresh_rf_tag ();
|
||||||
|
|
||||||
|
// get tagged formulae of all of the background invariants for all of the
|
||||||
|
// predecessors of the current transformer
|
||||||
|
void get_pred_bg_invs(expr_ref_vector &out);
|
||||||
|
const lemma_ref_vector &get_bg_invs() const {return m_frames.get_bg_invs();}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pred_transformer(context& ctx, manager& pm, func_decl* head);
|
pred_transformer(context& ctx, manager& pm, func_decl* head);
|
||||||
~pred_transformer() {}
|
~pred_transformer() {}
|
||||||
|
@ -448,7 +468,7 @@ public:
|
||||||
}
|
}
|
||||||
unsigned get_num_levels() const {return m_frames.size ();}
|
unsigned get_num_levels() const {return m_frames.size ();}
|
||||||
expr_ref get_cover_delta(func_decl* p_orig, int level);
|
expr_ref get_cover_delta(func_decl* p_orig, int level);
|
||||||
void add_cover(unsigned level, expr* property);
|
void add_cover(unsigned level, expr* property, bool bg = false);
|
||||||
expr_ref get_reachable();
|
expr_ref get_reachable();
|
||||||
|
|
||||||
std::ostream& display(std::ostream& strm) const;
|
std::ostream& display(std::ostream& strm) const;
|
||||||
|
@ -484,7 +504,7 @@ public:
|
||||||
bool propagate_to_next_level(unsigned level);
|
bool propagate_to_next_level(unsigned level);
|
||||||
void propagate_to_infinity(unsigned level);
|
void propagate_to_infinity(unsigned level);
|
||||||
/// \brief Add a lemma to the current context and all users
|
/// \brief Add a lemma to the current context and all users
|
||||||
bool add_lemma(expr * lemma, unsigned lvl);
|
bool add_lemma(expr * e, unsigned lvl, bool bg);
|
||||||
bool add_lemma(lemma* lem) {return m_frames.add_lemma(lem);}
|
bool add_lemma(lemma* lem) {return m_frames.add_lemma(lem);}
|
||||||
expr* get_reach_case_var (unsigned idx) const;
|
expr* get_reach_case_var (unsigned idx) const;
|
||||||
bool has_rfs () const { return !m_reach_facts.empty () ;}
|
bool has_rfs () const { return !m_reach_facts.empty () ;}
|
||||||
|
@ -527,7 +547,7 @@ public:
|
||||||
bool check_inductive(unsigned level, expr_ref_vector& state,
|
bool check_inductive(unsigned level, expr_ref_vector& state,
|
||||||
unsigned& assumes_level, unsigned weakness = UINT_MAX);
|
unsigned& assumes_level, unsigned weakness = UINT_MAX);
|
||||||
|
|
||||||
expr_ref get_formulas(unsigned level) const;
|
expr_ref get_formulas(unsigned level, bool bg = false) const;
|
||||||
|
|
||||||
void simplify_formulas();
|
void simplify_formulas();
|
||||||
|
|
||||||
|
@ -958,6 +978,7 @@ class context {
|
||||||
bool m_simplify_formulas_pre;
|
bool m_simplify_formulas_pre;
|
||||||
bool m_simplify_formulas_post;
|
bool m_simplify_formulas_post;
|
||||||
bool m_pdr_bfs;
|
bool m_pdr_bfs;
|
||||||
|
bool m_use_bg_invs;
|
||||||
unsigned m_push_pob_max_depth;
|
unsigned m_push_pob_max_depth;
|
||||||
unsigned m_max_level;
|
unsigned m_max_level;
|
||||||
unsigned m_restart_initial_threshold;
|
unsigned m_restart_initial_threshold;
|
||||||
|
@ -992,7 +1013,8 @@ class context {
|
||||||
|
|
||||||
// Generate inductive property
|
// Generate inductive property
|
||||||
void get_level_property(unsigned lvl, expr_ref_vector& res,
|
void get_level_property(unsigned lvl, expr_ref_vector& res,
|
||||||
vector<relation_info> & rs) const;
|
vector<relation_info> & rs,
|
||||||
|
bool with_bg = false) const;
|
||||||
|
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
|
@ -1027,18 +1049,20 @@ public:
|
||||||
|
|
||||||
|
|
||||||
const fp_params &get_params() const { return m_params; }
|
const fp_params &get_params() const { return m_params; }
|
||||||
bool use_native_mbp () {return m_use_native_mbp;}
|
bool use_eq_prop() const {return m_use_eq_prop;}
|
||||||
bool use_ground_pob () {return m_ground_pob;}
|
bool use_native_mbp() const {return m_use_native_mbp;}
|
||||||
bool use_instantiate () {return m_instantiate;}
|
bool use_ground_pob() const {return m_ground_pob;}
|
||||||
bool weak_abs() {return m_weak_abs;}
|
bool use_instantiate() const {return m_instantiate;}
|
||||||
bool use_qlemmas () {return m_use_qlemmas;}
|
bool weak_abs() const {return m_weak_abs;}
|
||||||
bool use_euf_gen() {return m_use_euf_gen;}
|
bool use_qlemmas() const {return m_use_qlemmas;}
|
||||||
bool simplify_pob() {return m_simplify_pob;}
|
bool use_euf_gen() const {return m_use_euf_gen;}
|
||||||
bool use_ctp() {return m_use_ctp;}
|
bool simplify_pob() const {return m_simplify_pob;}
|
||||||
bool use_inc_clause() {return m_use_inc_clause;}
|
bool use_ctp() const {return m_use_ctp;}
|
||||||
unsigned blast_term_ite_inflation() {return m_blast_term_ite_inflation;}
|
bool use_inc_clause() const {return m_use_inc_clause;}
|
||||||
bool elim_aux() {return m_elim_aux;}
|
unsigned blast_term_ite_inflation() const {return m_blast_term_ite_inflation;}
|
||||||
bool reach_dnf() {return m_reach_dnf;}
|
bool elim_aux() const {return m_elim_aux;}
|
||||||
|
bool reach_dnf() const {return m_reach_dnf;}
|
||||||
|
bool use_bg_invs() const {return m_use_bg_invs;}
|
||||||
|
|
||||||
ast_manager& get_ast_manager() const {return m;}
|
ast_manager& get_ast_manager() const {return m;}
|
||||||
manager& get_manager() {return m_pm;}
|
manager& get_manager() {return m_pm;}
|
||||||
|
@ -1081,7 +1105,7 @@ public:
|
||||||
unsigned get_num_levels(func_decl* p);
|
unsigned get_num_levels(func_decl* p);
|
||||||
|
|
||||||
expr_ref get_cover_delta(int level, func_decl* p_orig, func_decl* p);
|
expr_ref get_cover_delta(int level, func_decl* p_orig, func_decl* p);
|
||||||
void add_cover(int level, func_decl* pred, expr* property);
|
void add_cover(int level, func_decl* pred, expr* property, bool bg = false);
|
||||||
expr_ref get_reachable (func_decl* p);
|
expr_ref get_reachable (func_decl* p);
|
||||||
void add_invariant (func_decl *pred, expr* property);
|
void add_invariant (func_decl *pred, expr* property);
|
||||||
model_ref get_model();
|
model_ref get_model();
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace{
|
||||||
contains_array_op_proc(ast_manager &manager) :
|
contains_array_op_proc(ast_manager &manager) :
|
||||||
m(manager), m_array_fid(m.mk_family_id("array"))
|
m(manager), m_array_fid(m.mk_family_id("array"))
|
||||||
{}
|
{}
|
||||||
virtual bool operator()(expr *e) {
|
bool operator()(expr *e) override {
|
||||||
return is_app(e) && to_app(e)->get_family_id() == m_array_fid;
|
return is_app(e) && to_app(e)->get_family_id() == m_array_fid;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,11 +117,11 @@ class lemma_quantifier_generalizer : public lemma_generalizer {
|
||||||
int m_offset;
|
int m_offset;
|
||||||
public:
|
public:
|
||||||
lemma_quantifier_generalizer(context &ctx, bool normalize_cube = true);
|
lemma_quantifier_generalizer(context &ctx, bool normalize_cube = true);
|
||||||
virtual ~lemma_quantifier_generalizer() {}
|
~lemma_quantifier_generalizer() override {}
|
||||||
virtual void operator()(lemma_ref &lemma);
|
void operator()(lemma_ref &lemma) override;
|
||||||
|
|
||||||
virtual void collect_statistics(statistics& st) const;
|
void collect_statistics(statistics& st) const override;
|
||||||
virtual void reset_statistics() {m_st.reset();}
|
void reset_statistics() override {m_st.reset();}
|
||||||
private:
|
private:
|
||||||
bool generalize(lemma_ref &lemma, app *term);
|
bool generalize(lemma_ref &lemma, app *term);
|
||||||
|
|
||||||
|
|
|
@ -600,7 +600,7 @@ namespace spacer {
|
||||||
proof* hypothesis_reducer::reduce_core(proof* pf) {
|
proof* hypothesis_reducer::reduce_core(proof* pf) {
|
||||||
SASSERT(m.is_false(m.get_fact(pf)));
|
SASSERT(m.is_false(m.get_fact(pf)));
|
||||||
|
|
||||||
proof *res = NULL;
|
proof *res = nullptr;
|
||||||
|
|
||||||
ptr_vector<proof> todo;
|
ptr_vector<proof> todo;
|
||||||
todo.push_back(pf);
|
todo.push_back(pf);
|
||||||
|
|
|
@ -94,6 +94,7 @@ void prop_solver::add_level()
|
||||||
|
|
||||||
void prop_solver::ensure_level(unsigned lvl)
|
void prop_solver::ensure_level(unsigned lvl)
|
||||||
{
|
{
|
||||||
|
if (is_infty_level(lvl)) return;
|
||||||
while (lvl >= level_cnt()) {
|
while (lvl >= level_cnt()) {
|
||||||
add_level();
|
add_level();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,8 @@ namespace spacer {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_infty_level(unsigned lvl) {
|
inline bool is_infty_level(unsigned lvl) {
|
||||||
return lvl == infty_level ();
|
// XXX: level is 16 bits in class pob
|
||||||
|
return lvl >= 65535;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned next_level(unsigned lvl) {
|
inline unsigned next_level(unsigned lvl) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ z3_add_component(transforms
|
||||||
dl_mk_array_eq_rewrite.cpp
|
dl_mk_array_eq_rewrite.cpp
|
||||||
dl_mk_array_instantiation.cpp
|
dl_mk_array_instantiation.cpp
|
||||||
dl_mk_elim_term_ite.cpp
|
dl_mk_elim_term_ite.cpp
|
||||||
|
dl_mk_synchronize.cpp
|
||||||
COMPONENT_DEPENDENCIES
|
COMPONENT_DEPENDENCIES
|
||||||
dataflow
|
dataflow
|
||||||
hilbert
|
hilbert
|
||||||
|
|
376
src/muz/transforms/dl_mk_synchronize.cpp
Normal file
376
src/muz/transforms/dl_mk_synchronize.cpp
Normal file
|
@ -0,0 +1,376 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2017-2018 Saint-Petersburg State University
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
dl_mk_synchronize.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Rule transformer that attempts to merge recursive iterations
|
||||||
|
relaxing the shape of the inductive invariant.
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Dmitry Mordvinov (dvvrd) 2017-05-24
|
||||||
|
Lidiia Chernigovskaia (LChernigovskaya) 2017-10-20
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#include "muz/transforms/dl_mk_synchronize.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace datalog {
|
||||||
|
|
||||||
|
typedef mk_synchronize::item_set_vector item_set_vector;
|
||||||
|
|
||||||
|
mk_synchronize::mk_synchronize(context& ctx, unsigned priority):
|
||||||
|
rule_transformer::plugin(priority, false),
|
||||||
|
m_ctx(ctx),
|
||||||
|
m(ctx.get_manager()),
|
||||||
|
rm(ctx.get_rule_manager())
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool mk_synchronize::is_recursive(rule &r, func_decl &decl) const {
|
||||||
|
func_decl *hdecl = r.get_head()->get_decl();
|
||||||
|
// AG: shouldn't decl appear in the body?
|
||||||
|
if (hdecl == &decl) return true;
|
||||||
|
auto & strata = m_stratifier->get_strats();
|
||||||
|
unsigned num_of_stratum = m_stratifier->get_predicate_strat(hdecl);
|
||||||
|
return strata[num_of_stratum]->contains(&decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mk_synchronize::has_recursive_premise(app * app) const {
|
||||||
|
func_decl* app_decl = app->get_decl();
|
||||||
|
if (m_deps->get_deps(app_decl).contains(app_decl)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
rule_stratifier::comp_vector const & strata = m_stratifier->get_strats();
|
||||||
|
unsigned num_of_stratum = m_stratifier->get_predicate_strat(app_decl);
|
||||||
|
return strata[num_of_stratum]->size() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_set_vector mk_synchronize::add_merged_decls(ptr_vector<app> & apps) {
|
||||||
|
unsigned sz = apps.size();
|
||||||
|
item_set_vector merged_decls;
|
||||||
|
merged_decls.resize(sz);
|
||||||
|
auto & strata = m_stratifier->get_strats();
|
||||||
|
for (unsigned j = 0; j < sz; ++j) {
|
||||||
|
unsigned nos;
|
||||||
|
nos = m_stratifier->get_predicate_strat(apps[j]->get_decl());
|
||||||
|
merged_decls[j] = strata[nos];
|
||||||
|
}
|
||||||
|
return merged_decls;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_synchronize::add_new_rel_symbols(unsigned idx,
|
||||||
|
item_set_vector const & decls,
|
||||||
|
ptr_vector<func_decl> & decls_buf,
|
||||||
|
bool & was_added) {
|
||||||
|
if (idx >= decls.size()) {
|
||||||
|
string_buffer<> buffer;
|
||||||
|
ptr_vector<sort> domain;
|
||||||
|
for (auto &d : decls_buf) {
|
||||||
|
buffer << d->get_name() << "!!";
|
||||||
|
domain.append(d->get_arity(), d->get_domain());
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol new_name = symbol(buffer.c_str());
|
||||||
|
|
||||||
|
if (!m_cache.contains(new_name)) {
|
||||||
|
was_added = true;
|
||||||
|
func_decl* orig = decls_buf[0];
|
||||||
|
func_decl* product_pred = m_ctx.mk_fresh_head_predicate(new_name,
|
||||||
|
symbol::null, domain.size(), domain.c_ptr(), orig);
|
||||||
|
m_cache.insert(new_name, product_pred);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- compute Cartesian product of decls, and create a new
|
||||||
|
// -- predicate for each element of the product
|
||||||
|
for (auto &p : *decls[idx]) {
|
||||||
|
decls_buf[idx] = p;
|
||||||
|
add_new_rel_symbols(idx + 1, decls, decls_buf, was_added);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_synchronize::replace_applications(rule & r, rule_set & rules,
|
||||||
|
ptr_vector<app> & apps) {
|
||||||
|
app_ref replacing = product_application(apps);
|
||||||
|
|
||||||
|
ptr_vector<app> new_tail;
|
||||||
|
svector<bool> new_tail_neg;
|
||||||
|
unsigned n = r.get_tail_size() - apps.size() + 1;
|
||||||
|
unsigned tail_idx = 0;
|
||||||
|
new_tail.resize(n);
|
||||||
|
new_tail_neg.resize(n);
|
||||||
|
new_tail[0] = replacing;
|
||||||
|
new_tail_neg[0] = false;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < r.get_positive_tail_size(); ++i) {
|
||||||
|
app* tail = r.get_tail(i);
|
||||||
|
if (!apps.contains(tail)) {
|
||||||
|
++tail_idx;
|
||||||
|
new_tail[tail_idx] = tail;
|
||||||
|
new_tail_neg[tail_idx] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned i = r.get_positive_tail_size(); i < r.get_uninterpreted_tail_size(); ++i) {
|
||||||
|
++tail_idx;
|
||||||
|
new_tail[tail_idx] = r.get_tail(i);
|
||||||
|
new_tail_neg[tail_idx] = true;
|
||||||
|
}
|
||||||
|
for (unsigned i = r.get_uninterpreted_tail_size(); i < r.get_tail_size(); ++i) {
|
||||||
|
++tail_idx;
|
||||||
|
new_tail[tail_idx] = r.get_tail(i);
|
||||||
|
new_tail_neg[tail_idx] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_ref new_rule(rm);
|
||||||
|
new_rule = rm.mk(r.get_head(), tail_idx + 1,
|
||||||
|
new_tail.c_ptr(), new_tail_neg.c_ptr(), symbol::null, false);
|
||||||
|
rules.replace_rule(&r, new_rule.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_ref mk_synchronize::rename_bound_vars_in_rule(rule * r,
|
||||||
|
unsigned & var_idx) {
|
||||||
|
// AG: shift all variables in a rule so that lowest var index is var_idx?
|
||||||
|
// AG: update var_idx in the process?
|
||||||
|
ptr_vector<sort> sorts;
|
||||||
|
r->get_vars(m, sorts);
|
||||||
|
expr_ref_vector revsub(m);
|
||||||
|
revsub.resize(sorts.size());
|
||||||
|
for (unsigned i = 0; i < sorts.size(); ++i) {
|
||||||
|
if (sorts[i]) {
|
||||||
|
revsub[i] = m.mk_var(var_idx++, sorts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_ref new_rule(rm);
|
||||||
|
new_rule = rm.mk(r);
|
||||||
|
rm.substitute(new_rule, revsub.size(), revsub.c_ptr());
|
||||||
|
return new_rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<rule_ref_vector> mk_synchronize::rename_bound_vars(item_set_vector const & heads,
|
||||||
|
rule_set & rules) {
|
||||||
|
// AG: is every item_set in heads corresponds to rules that are merged?
|
||||||
|
// AG: why are bound variables renamed in the first place?
|
||||||
|
// AG: the data structure seems too complex
|
||||||
|
vector<rule_ref_vector> result;
|
||||||
|
unsigned var_idx = 0;
|
||||||
|
for (auto item : heads) {
|
||||||
|
rule_ref_vector dst_vector(rm);
|
||||||
|
for (auto *head : *item) {
|
||||||
|
for (auto *r : rules.get_predicate_rules(head)) {
|
||||||
|
rule_ref new_rule = rename_bound_vars_in_rule(r, var_idx);
|
||||||
|
dst_vector.push_back(new_rule.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push_back(dst_vector);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_synchronize::add_rec_tail(vector< ptr_vector<app> > & recursive_calls,
|
||||||
|
app_ref_vector & new_tail,
|
||||||
|
svector<bool> & new_tail_neg,
|
||||||
|
unsigned & tail_idx) {
|
||||||
|
unsigned max_sz = 0;
|
||||||
|
for (auto &rc : recursive_calls)
|
||||||
|
max_sz= std::max(rc.size(), max_sz);
|
||||||
|
|
||||||
|
unsigned n = recursive_calls.size();
|
||||||
|
ptr_vector<app> merged_recursive_calls;
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < max_sz; ++j) {
|
||||||
|
merged_recursive_calls.reset();
|
||||||
|
merged_recursive_calls.resize(n);
|
||||||
|
for (unsigned i = 0; i < n; ++i) {
|
||||||
|
unsigned sz = recursive_calls[i].size();
|
||||||
|
merged_recursive_calls[i] =
|
||||||
|
j < sz ? recursive_calls[i][j] : recursive_calls[i][sz - 1];
|
||||||
|
}
|
||||||
|
++tail_idx;
|
||||||
|
new_tail[tail_idx] = product_application(merged_recursive_calls);
|
||||||
|
new_tail_neg[tail_idx] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_synchronize::add_non_rec_tail(rule & r, app_ref_vector & new_tail,
|
||||||
|
svector<bool> & new_tail_neg,
|
||||||
|
unsigned & tail_idx) {
|
||||||
|
for (unsigned i = 0, sz = r.get_positive_tail_size(); i < sz; ++i) {
|
||||||
|
app* tail = r.get_tail(i);
|
||||||
|
if (!is_recursive(r, *tail)) {
|
||||||
|
++tail_idx;
|
||||||
|
new_tail[tail_idx] = tail;
|
||||||
|
new_tail_neg[tail_idx] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned i = r.get_positive_tail_size(),
|
||||||
|
sz = r.get_uninterpreted_tail_size() ; i < sz; ++i) {
|
||||||
|
++tail_idx;
|
||||||
|
new_tail[tail_idx] = r.get_tail(i);
|
||||||
|
new_tail_neg[tail_idx] = true;
|
||||||
|
}
|
||||||
|
for (unsigned i = r.get_uninterpreted_tail_size(),
|
||||||
|
sz = r.get_tail_size(); i < sz; ++i) {
|
||||||
|
++tail_idx;
|
||||||
|
new_tail[tail_idx] = r.get_tail(i);
|
||||||
|
new_tail_neg[tail_idx] = r.is_neg_tail(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app_ref mk_synchronize::product_application(ptr_vector<app> const &apps) {
|
||||||
|
unsigned args_num = 0;
|
||||||
|
string_buffer<> buffer;
|
||||||
|
|
||||||
|
// AG: factor out into mk_name
|
||||||
|
for (auto *app : apps) {
|
||||||
|
buffer << app->get_decl()->get_name() << "!!";
|
||||||
|
args_num += app->get_num_args();
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol name = symbol(buffer.c_str());
|
||||||
|
SASSERT(m_cache.contains(name));
|
||||||
|
func_decl * pred = m_cache[name];
|
||||||
|
|
||||||
|
ptr_vector<expr> args;
|
||||||
|
args.resize(args_num);
|
||||||
|
unsigned idx = 0;
|
||||||
|
for (auto *a : apps) {
|
||||||
|
for (unsigned i = 0, sz = a->get_num_args(); i < sz; ++i, ++idx)
|
||||||
|
args[idx] = a->get_arg(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return app_ref(m.mk_app(pred, args_num, args.c_ptr()), m);
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_ref mk_synchronize::product_rule(rule_ref_vector const & rules) {
|
||||||
|
unsigned n = rules.size();
|
||||||
|
|
||||||
|
string_buffer<> buffer;
|
||||||
|
bool first_rule = true;
|
||||||
|
for (auto it = rules.begin(); it != rules.end(); ++it, first_rule = false) {
|
||||||
|
if (!first_rule) {
|
||||||
|
buffer << "+";
|
||||||
|
}
|
||||||
|
buffer << (*it)->name();
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr_vector<app> heads;
|
||||||
|
heads.resize(n);
|
||||||
|
for (unsigned i = 0; i < n; ++i) {
|
||||||
|
heads[i] = rules[i]->get_head();
|
||||||
|
}
|
||||||
|
app_ref product_head = product_application(heads);
|
||||||
|
unsigned product_tail_length = 0;
|
||||||
|
bool has_recursion = false;
|
||||||
|
vector< ptr_vector<app> > recursive_calls;
|
||||||
|
recursive_calls.resize(n);
|
||||||
|
for (unsigned i = 0; i < n; ++i) {
|
||||||
|
rule& rule = *rules[i];
|
||||||
|
product_tail_length += rule.get_tail_size();
|
||||||
|
for (unsigned j = 0; j < rule.get_positive_tail_size(); ++j) {
|
||||||
|
app* tail = rule.get_tail(j);
|
||||||
|
if (is_recursive(rule, *tail)) {
|
||||||
|
has_recursion = true;
|
||||||
|
recursive_calls[i].push_back(tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (recursive_calls[i].empty()) {
|
||||||
|
recursive_calls[i].push_back(rule.get_head());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app_ref_vector new_tail(m);
|
||||||
|
svector<bool> new_tail_neg;
|
||||||
|
new_tail.resize(product_tail_length);
|
||||||
|
new_tail_neg.resize(product_tail_length);
|
||||||
|
unsigned tail_idx = -1;
|
||||||
|
if (has_recursion) {
|
||||||
|
add_rec_tail(recursive_calls, new_tail, new_tail_neg, tail_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (rule_vector::const_iterator it = rules.begin(); it != rules.end(); ++it) {
|
||||||
|
rule& rule = **it;
|
||||||
|
add_non_rec_tail(rule, new_tail, new_tail_neg, tail_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_ref new_rule(rm);
|
||||||
|
new_rule = rm.mk(product_head, tail_idx + 1,
|
||||||
|
new_tail.c_ptr(), new_tail_neg.c_ptr(), symbol(buffer.c_str()), false);
|
||||||
|
rm.fix_unbound_vars(new_rule, false);
|
||||||
|
return new_rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_synchronize::merge_rules(unsigned idx, rule_ref_vector & buf,
|
||||||
|
vector<rule_ref_vector> const & merged_rules,
|
||||||
|
rule_set & all_rules) {
|
||||||
|
if (idx >= merged_rules.size()) {
|
||||||
|
rule_ref product = product_rule(buf);
|
||||||
|
all_rules.add_rule(product.get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto *r : merged_rules[idx]) {
|
||||||
|
buf[idx] = r;
|
||||||
|
merge_rules(idx + 1, buf, merged_rules, all_rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_synchronize::merge_applications(rule & r, rule_set & rules) {
|
||||||
|
ptr_vector<app> non_recursive_preds;
|
||||||
|
obj_hashtable<app> apps;
|
||||||
|
for (unsigned i = 0; i < r.get_positive_tail_size(); ++i) {
|
||||||
|
app* t = r.get_tail(i);
|
||||||
|
if (!is_recursive(r, *t) && has_recursive_premise(t)) {
|
||||||
|
apps.insert(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (apps.size() < 2) return;
|
||||||
|
for (auto *a : apps) non_recursive_preds.push_back(a);
|
||||||
|
|
||||||
|
item_set_vector merged_decls = add_merged_decls(non_recursive_preds);
|
||||||
|
|
||||||
|
unsigned n = non_recursive_preds.size();
|
||||||
|
ptr_vector<func_decl> decls_buf;
|
||||||
|
decls_buf.resize(n);
|
||||||
|
bool was_added = false;
|
||||||
|
add_new_rel_symbols(0, merged_decls, decls_buf, was_added);
|
||||||
|
if (was_added){
|
||||||
|
rule_ref_vector rules_buf(rm);
|
||||||
|
rules_buf.resize(n);
|
||||||
|
vector<rule_ref_vector> renamed_rules = rename_bound_vars(merged_decls, rules);
|
||||||
|
merge_rules(0, rules_buf, renamed_rules, rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
replace_applications(r, rules, non_recursive_preds);
|
||||||
|
m_deps->populate(rules);
|
||||||
|
m_stratifier = alloc(rule_stratifier, *m_deps);
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_set * mk_synchronize::operator()(rule_set const & source) {
|
||||||
|
rule_set* rules = alloc(rule_set, m_ctx);
|
||||||
|
rules->inherit_predicates(source);
|
||||||
|
|
||||||
|
for (auto *r : source) { rules->add_rule(r); }
|
||||||
|
|
||||||
|
m_deps = alloc(rule_dependencies, m_ctx);
|
||||||
|
m_deps->populate(*rules);
|
||||||
|
m_stratifier = alloc(rule_stratifier, *m_deps);
|
||||||
|
|
||||||
|
unsigned current_rule = 0;
|
||||||
|
while (current_rule < rules->get_num_rules()) {
|
||||||
|
rule *r = rules->get_rule(current_rule);
|
||||||
|
merge_applications(*r, *rules);
|
||||||
|
++current_rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
134
src/muz/transforms/dl_mk_synchronize.h
Normal file
134
src/muz/transforms/dl_mk_synchronize.h
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2017-2018 Saint-Petersburg State University
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
dl_mk_synchronize.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Rule transformer that attempts to merge recursive iterations
|
||||||
|
relaxing the shape of the inductive invariant.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
Q(z) :- A(x), B(y), phi1(x,y,z).
|
||||||
|
A(x) :- A(x'), phi2(x,x').
|
||||||
|
A(x) :- phi3(x).
|
||||||
|
B(y) :- C(y'), phi4(y,y').
|
||||||
|
C(y) :- B(y'), phi5(y,y').
|
||||||
|
B(y) :- phi6(y).
|
||||||
|
|
||||||
|
Transformed clauses:
|
||||||
|
|
||||||
|
Q(z) :- AB(x,y), phi1(x,y,z).
|
||||||
|
AB(x,y) :- AC(x',y'), phi2(x,x'), phi4(y,y').
|
||||||
|
AC(x,y) :- AB(x',y'), phi2(x,x'), phi5(y,y').
|
||||||
|
AB(x,y) :- AC(x, y'), phi3(x), phi4(y,y').
|
||||||
|
AC(x,y) :- AB(x, y'), phi3(x), phi5(y,y').
|
||||||
|
AB(x,y) :- AB(x',y), phi2(x,x'), phi6(y).
|
||||||
|
AB(x,y) :- phi3(x), phi6(y).
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Dmitry Mordvinov (dvvrd) 2017-05-24
|
||||||
|
Lidiia Chernigovskaia (LChernigovskaya) 2017-10-20
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#ifndef DL_MK_SYNCHRONIZE_H_
|
||||||
|
#define DL_MK_SYNCHRONIZE_H_
|
||||||
|
|
||||||
|
#include"muz/base/dl_context.h"
|
||||||
|
#include"muz/base/dl_rule_set.h"
|
||||||
|
#include"util/uint_set.h"
|
||||||
|
#include"muz/base/dl_rule_transformer.h"
|
||||||
|
#include"muz/transforms/dl_mk_rule_inliner.h"
|
||||||
|
|
||||||
|
namespace datalog {
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Implements a synchronous product transformation.
|
||||||
|
*/
|
||||||
|
class mk_synchronize : public rule_transformer::plugin {
|
||||||
|
public:
|
||||||
|
typedef ptr_vector<rule_stratifier::item_set> item_set_vector;
|
||||||
|
private:
|
||||||
|
context& m_ctx;
|
||||||
|
ast_manager& m;
|
||||||
|
rule_manager& rm;
|
||||||
|
|
||||||
|
scoped_ptr<rule_dependencies> m_deps;
|
||||||
|
scoped_ptr<rule_stratifier> m_stratifier;
|
||||||
|
|
||||||
|
// symbol table that maps new predicate names to corresponding
|
||||||
|
// func_decl
|
||||||
|
map<symbol, func_decl*, symbol_hash_proc, symbol_eq_proc> m_cache;
|
||||||
|
|
||||||
|
/// returns true if decl is recursive in the given rule
|
||||||
|
/// requires that decl appears in the tail of r
|
||||||
|
bool is_recursive(rule &r, func_decl &decl) const;
|
||||||
|
bool is_recursive(rule &r, expr &e) const {
|
||||||
|
SASSERT(is_app(&e));
|
||||||
|
return is_app(&e) && is_recursive(r, *to_app(&e)->get_decl());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns true if the top-level predicate of app is recursive
|
||||||
|
bool has_recursive_premise(app * app) const;
|
||||||
|
|
||||||
|
item_set_vector add_merged_decls(ptr_vector<app> & apps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Compute Cartesian product of decls and create a new
|
||||||
|
predicate for each element. For example, if decls is
|
||||||
|
|
||||||
|
( (a, b), (c, d) ) )
|
||||||
|
|
||||||
|
create new predicates: a!!c, a!!d, b!!c, and b!!d
|
||||||
|
*/
|
||||||
|
void add_new_rel_symbols(unsigned idx, item_set_vector const & decls,
|
||||||
|
ptr_vector<func_decl> & buf, bool & was_added);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert vector of predicate apps into a single app. For example,
|
||||||
|
(Foo a) (Bar b) becomes (Foo!!Bar a b)
|
||||||
|
*/
|
||||||
|
app_ref product_application(ptr_vector<app> const & apps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Replace a given rule by a rule in which conjunction of
|
||||||
|
predicates is replaced by a single product predicate
|
||||||
|
*/
|
||||||
|
void replace_applications(rule & r, rule_set & rules,
|
||||||
|
ptr_vector<app> & apps);
|
||||||
|
|
||||||
|
rule_ref rename_bound_vars_in_rule(rule * r, unsigned & var_idx);
|
||||||
|
vector<rule_ref_vector> rename_bound_vars(item_set_vector const & heads,
|
||||||
|
rule_set & rules);
|
||||||
|
|
||||||
|
void add_rec_tail(vector< ptr_vector<app> > & recursive_calls,
|
||||||
|
app_ref_vector & new_tail,
|
||||||
|
svector<bool> & new_tail_neg, unsigned & tail_idx);
|
||||||
|
void add_non_rec_tail(rule & r, app_ref_vector & new_tail,
|
||||||
|
svector<bool> & new_tail_neg,
|
||||||
|
unsigned & tail_idx);
|
||||||
|
|
||||||
|
rule_ref product_rule(rule_ref_vector const & rules);
|
||||||
|
|
||||||
|
void merge_rules(unsigned idx, rule_ref_vector & buf,
|
||||||
|
vector<rule_ref_vector> const & merged_rules, rule_set & all_rules);
|
||||||
|
void merge_applications(rule & r, rule_set & rules);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
\brief Create synchronous product transformer.
|
||||||
|
*/
|
||||||
|
mk_synchronize(context & ctx, unsigned priority = 22500);
|
||||||
|
|
||||||
|
rule_set * operator()(rule_set const & source) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* DL_MK_SYNCHRONIZE_H_ */
|
|
@ -144,7 +144,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~maxres() {}
|
~maxres() override {}
|
||||||
|
|
||||||
bool is_literal(expr* l) {
|
bool is_literal(expr* l) {
|
||||||
return
|
return
|
||||||
|
@ -332,7 +332,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual lbool operator()() {
|
lbool operator()() override {
|
||||||
m_defs.reset();
|
m_defs.reset();
|
||||||
switch(m_st) {
|
switch(m_st) {
|
||||||
case s_primal:
|
case s_primal:
|
||||||
|
@ -343,7 +343,7 @@ public:
|
||||||
return l_undef;
|
return l_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void collect_statistics(statistics& st) const {
|
void collect_statistics(statistics& st) const override {
|
||||||
st.update("maxres-cores", m_stats.m_num_cores);
|
st.update("maxres-cores", m_stats.m_num_cores);
|
||||||
st.update("maxres-correction-sets", m_stats.m_num_cs);
|
st.update("maxres-correction-sets", m_stats.m_num_cs);
|
||||||
}
|
}
|
||||||
|
@ -781,7 +781,7 @@ public:
|
||||||
TRACE("opt", tout << "after remove: " << asms << "\n";);
|
TRACE("opt", tout << "after remove: " << asms << "\n";);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updt_params(params_ref& _p) {
|
void updt_params(params_ref& _p) override {
|
||||||
maxsmt_solver_base::updt_params(_p);
|
maxsmt_solver_base::updt_params(_p);
|
||||||
opt_params p(_p);
|
opt_params p(_p);
|
||||||
m_hill_climb = p.maxres_hill_climb();
|
m_hill_climb = p.maxres_hill_climb();
|
||||||
|
@ -816,7 +816,7 @@ public:
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void commit_assignment() {
|
void commit_assignment() override {
|
||||||
if (m_found_feasible_optimum) {
|
if (m_found_feasible_optimum) {
|
||||||
TRACE("opt", tout << "Committing feasible solution\n" << m_defs << " " << m_asms;);
|
TRACE("opt", tout << "Committing feasible solution\n" << m_defs << " " << m_asms;);
|
||||||
s().assert_expr(m_defs);
|
s().assert_expr(m_defs);
|
||||||
|
|
|
@ -56,33 +56,33 @@ public:
|
||||||
m_opt(opt)
|
m_opt(opt)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual ~assert_soft_cmd() {
|
~assert_soft_cmd() override {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void reset(cmd_context & ctx) {
|
void reset(cmd_context & ctx) override {
|
||||||
m_idx = 0;
|
m_idx = 0;
|
||||||
m_formula = nullptr;
|
m_formula = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual char const * get_usage() const { return "<formula> [:weight <rational-weight>] [:id <symbol>]"; }
|
char const * get_usage() const override { return "<formula> [:weight <rational-weight>] [:id <symbol>]"; }
|
||||||
virtual char const * get_main_descr() const { return "assert soft constraint with optional weight and identifier"; }
|
char const * get_main_descr() const override { return "assert soft constraint with optional weight and identifier"; }
|
||||||
|
|
||||||
// command invocation
|
// command invocation
|
||||||
virtual void prepare(cmd_context & ctx) {
|
void prepare(cmd_context & ctx) override {
|
||||||
reset(ctx);
|
reset(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
|
cmd_arg_kind next_arg_kind(cmd_context & ctx) const override {
|
||||||
if (m_idx == 0) return CPK_EXPR;
|
if (m_idx == 0) return CPK_EXPR;
|
||||||
return parametric_cmd::next_arg_kind(ctx);
|
return parametric_cmd::next_arg_kind(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void init_pdescrs(cmd_context & ctx, param_descrs & p) {
|
void init_pdescrs(cmd_context & ctx, param_descrs & p) override {
|
||||||
p.insert("weight", CPK_NUMERAL, "(default: 1) penalty of not satisfying constraint.");
|
p.insert("weight", CPK_NUMERAL, "(default: 1) penalty of not satisfying constraint.");
|
||||||
p.insert("id", CPK_SYMBOL, "(default: null) partition identifier for soft constraints.");
|
p.insert("id", CPK_SYMBOL, "(default: null) partition identifier for soft constraints.");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set_next_arg(cmd_context & ctx, expr * t) {
|
void set_next_arg(cmd_context & ctx, expr * t) override {
|
||||||
SASSERT(m_idx == 0);
|
SASSERT(m_idx == 0);
|
||||||
if (!ctx.m().is_bool(t)) {
|
if (!ctx.m().is_bool(t)) {
|
||||||
throw cmd_exception("Invalid type for expression. Expected Boolean type.");
|
throw cmd_exception("Invalid type for expression. Expected Boolean type.");
|
||||||
|
@ -91,11 +91,11 @@ public:
|
||||||
++m_idx;
|
++m_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void failure_cleanup(cmd_context & ctx) {
|
void failure_cleanup(cmd_context & ctx) override {
|
||||||
reset(ctx);
|
reset(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void execute(cmd_context & ctx) {
|
void execute(cmd_context & ctx) override {
|
||||||
if (!m_formula) {
|
if (!m_formula) {
|
||||||
throw cmd_exception("assert-soft requires a formulas as argument.");
|
throw cmd_exception("assert-soft requires a formulas as argument.");
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ public:
|
||||||
reset(ctx);
|
reset(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void finalize(cmd_context & ctx) {
|
void finalize(cmd_context & ctx) override {
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -123,14 +123,14 @@ public:
|
||||||
m_opt(opt)
|
m_opt(opt)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void reset(cmd_context & ctx) { }
|
void reset(cmd_context & ctx) override { }
|
||||||
virtual char const * get_usage() const { return "<term>"; }
|
char const * get_usage() const override { return "<term>"; }
|
||||||
virtual char const * get_descr(cmd_context & ctx) const { return "check sat modulo objective function";}
|
char const * get_descr(cmd_context & ctx) const override { return "check sat modulo objective function";}
|
||||||
virtual unsigned get_arity() const { return 1; }
|
unsigned get_arity() const override { return 1; }
|
||||||
virtual void prepare(cmd_context & ctx) {}
|
void prepare(cmd_context & ctx) override {}
|
||||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_EXPR; }
|
cmd_arg_kind next_arg_kind(cmd_context & ctx) const override { return CPK_EXPR; }
|
||||||
|
|
||||||
virtual void set_next_arg(cmd_context & ctx, expr * t) {
|
void set_next_arg(cmd_context & ctx, expr * t) override {
|
||||||
if (!is_app(t)) {
|
if (!is_app(t)) {
|
||||||
throw cmd_exception("malformed objective term: it cannot be a quantifier or bound variable");
|
throw cmd_exception("malformed objective term: it cannot be a quantifier or bound variable");
|
||||||
}
|
}
|
||||||
|
@ -138,11 +138,11 @@ public:
|
||||||
ctx.print_success();
|
ctx.print_success();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void failure_cleanup(cmd_context & ctx) {
|
void failure_cleanup(cmd_context & ctx) override {
|
||||||
reset(ctx);
|
reset(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void execute(cmd_context & ctx) {
|
void execute(cmd_context & ctx) override {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,18 +154,18 @@ public:
|
||||||
m_opt(opt)
|
m_opt(opt)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void reset(cmd_context & ctx) { }
|
void reset(cmd_context & ctx) override { }
|
||||||
virtual char const * get_usage() const { return "(get-objectives)"; }
|
char const * get_usage() const override { return "(get-objectives)"; }
|
||||||
virtual char const * get_descr(cmd_context & ctx) const { return "retrieve the objective values (after optimization)"; }
|
char const * get_descr(cmd_context & ctx) const override { return "retrieve the objective values (after optimization)"; }
|
||||||
virtual unsigned get_arity() const { return 0; }
|
unsigned get_arity() const override { return 0; }
|
||||||
virtual void prepare(cmd_context & ctx) {}
|
void prepare(cmd_context & ctx) override {}
|
||||||
|
|
||||||
|
|
||||||
virtual void failure_cleanup(cmd_context & ctx) {
|
void failure_cleanup(cmd_context & ctx) override {
|
||||||
reset(ctx);
|
reset(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void execute(cmd_context & ctx) {
|
void execute(cmd_context & ctx) override {
|
||||||
if (!ctx.ignore_check()) {
|
if (!ctx.ignore_check()) {
|
||||||
get_opt(ctx, m_opt).display_assignment(ctx.regular_stream());
|
get_opt(ctx, m_opt).display_assignment(ctx.regular_stream());
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,13 +79,13 @@ namespace opt {
|
||||||
m_hard.push_back(hard);
|
m_hard.push_back(hard);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool context::scoped_state::set(ptr_vector<expr> & hard) {
|
bool context::scoped_state::set(expr_ref_vector const & hard) {
|
||||||
bool eq = hard.size() == m_hard.size();
|
bool eq = hard.size() == m_hard.size();
|
||||||
for (unsigned i = 0; eq && i < hard.size(); ++i) {
|
for (unsigned i = 0; eq && i < hard.size(); ++i) {
|
||||||
eq = hard[i] == m_hard[i].get();
|
eq = hard.get(i) == m_hard.get(i);
|
||||||
}
|
}
|
||||||
m_hard.reset();
|
m_hard.reset();
|
||||||
m_hard.append(hard.size(), hard.c_ptr());
|
m_hard.append(hard);
|
||||||
return !eq;
|
return !eq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +130,7 @@ namespace opt {
|
||||||
m_fm(alloc(generic_model_converter, m, "opt")),
|
m_fm(alloc(generic_model_converter, m, "opt")),
|
||||||
m_model_fixed(),
|
m_model_fixed(),
|
||||||
m_objective_refs(m),
|
m_objective_refs(m),
|
||||||
|
m_core(m),
|
||||||
m_enable_sat(false),
|
m_enable_sat(false),
|
||||||
m_is_clausal(false),
|
m_is_clausal(false),
|
||||||
m_pp_neat(false),
|
m_pp_neat(false),
|
||||||
|
@ -173,11 +174,10 @@ namespace opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::get_unsat_core(expr_ref_vector & r) {
|
void context::get_unsat_core(expr_ref_vector & r) {
|
||||||
throw default_exception("Unsat cores are not supported with optimization");
|
r.append(m_core);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void context::set_hard_constraints(expr_ref_vector const& fmls) {
|
||||||
void context::set_hard_constraints(ptr_vector<expr>& fmls) {
|
|
||||||
if (m_scoped_state.set(fmls)) {
|
if (m_scoped_state.set(fmls)) {
|
||||||
clear_state();
|
clear_state();
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ namespace opt {
|
||||||
m_hard_constraints.append(s.m_hard);
|
m_hard_constraints.append(s.m_hard);
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool context::optimize() {
|
lbool context::optimize(expr_ref_vector const& asms) {
|
||||||
if (m_pareto) {
|
if (m_pareto) {
|
||||||
return execute_pareto();
|
return execute_pareto();
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,10 @@ namespace opt {
|
||||||
clear_state();
|
clear_state();
|
||||||
init_solver();
|
init_solver();
|
||||||
import_scoped_state();
|
import_scoped_state();
|
||||||
normalize();
|
normalize(asms);
|
||||||
|
if (m_hard_constraints.size() == 1 && m.is_false(m_hard_constraints.get(0))) {
|
||||||
|
return l_false;
|
||||||
|
}
|
||||||
internalize();
|
internalize();
|
||||||
update_solver();
|
update_solver();
|
||||||
if (contains_quantifiers()) {
|
if (contains_quantifiers()) {
|
||||||
|
@ -281,7 +284,7 @@ namespace opt {
|
||||||
symbol pri = optp.priority();
|
symbol pri = optp.priority();
|
||||||
|
|
||||||
IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n");
|
IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n");
|
||||||
lbool is_sat = s.check_sat(0,0);
|
lbool is_sat = s.check_sat(asms.size(),asms.c_ptr());
|
||||||
TRACE("opt", s.display(tout << "initial search result: " << is_sat << "\n"););
|
TRACE("opt", s.display(tout << "initial search result: " << is_sat << "\n"););
|
||||||
if (is_sat != l_false) {
|
if (is_sat != l_false) {
|
||||||
s.get_model(m_model);
|
s.get_model(m_model);
|
||||||
|
@ -289,7 +292,10 @@ namespace opt {
|
||||||
model_updated(m_model.get());
|
model_updated(m_model.get());
|
||||||
}
|
}
|
||||||
if (is_sat != l_true) {
|
if (is_sat != l_true) {
|
||||||
TRACE("opt", tout << m_hard_constraints << "\n";);
|
TRACE("opt", tout << m_hard_constraints << " " << asms << "\n";);
|
||||||
|
if (!asms.empty()) {
|
||||||
|
s.get_unsat_core(m_core);
|
||||||
|
}
|
||||||
return is_sat;
|
return is_sat;
|
||||||
}
|
}
|
||||||
IF_VERBOSE(1, verbose_stream() << "(optimize:sat)\n");
|
IF_VERBOSE(1, verbose_stream() << "(optimize:sat)\n");
|
||||||
|
@ -479,7 +485,6 @@ namespace opt {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
expr_ref context::mk_le(unsigned i, model_ref& mdl) {
|
expr_ref context::mk_le(unsigned i, model_ref& mdl) {
|
||||||
objective const& obj = m_objectives[i];
|
objective const& obj = m_objectives[i];
|
||||||
return mk_cmp(false, mdl, obj);
|
return mk_cmp(false, mdl, obj);
|
||||||
|
@ -490,7 +495,6 @@ namespace opt {
|
||||||
return mk_cmp(true, mdl, obj);
|
return mk_cmp(true, mdl, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
expr_ref context::mk_gt(unsigned i, model_ref& mdl) {
|
expr_ref context::mk_gt(unsigned i, model_ref& mdl) {
|
||||||
expr_ref result = mk_le(i, mdl);
|
expr_ref result = mk_le(i, mdl);
|
||||||
result = mk_not(m, result);
|
result = mk_not(m, result);
|
||||||
|
@ -751,22 +755,25 @@ namespace opt {
|
||||||
return m_arith.is_numeral(e, n) || m_bv.is_numeral(e, n, sz);
|
return m_arith.is_numeral(e, n) || m_bv.is_numeral(e, n, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::normalize() {
|
void context::normalize(expr_ref_vector const& asms) {
|
||||||
expr_ref_vector fmls(m);
|
expr_ref_vector fmls(m);
|
||||||
to_fmls(fmls);
|
to_fmls(fmls);
|
||||||
simplify_fmls(fmls);
|
simplify_fmls(fmls, asms);
|
||||||
from_fmls(fmls);
|
from_fmls(fmls);
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::simplify_fmls(expr_ref_vector& fmls) {
|
void context::simplify_fmls(expr_ref_vector& fmls, expr_ref_vector const& asms) {
|
||||||
if (m_is_clausal) {
|
if (m_is_clausal) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
goal_ref g(alloc(goal, m, true, false));
|
goal_ref g(alloc(goal, m, true, !asms.empty()));
|
||||||
for (expr* fml : fmls) {
|
for (expr* fml : fmls) {
|
||||||
g->assert_expr(fml);
|
g->assert_expr(fml);
|
||||||
}
|
}
|
||||||
|
for (expr * a : asms) {
|
||||||
|
g->assert_expr(a, a);
|
||||||
|
}
|
||||||
tactic_ref tac0 =
|
tactic_ref tac0 =
|
||||||
and_then(mk_simplify_tactic(m, m_params),
|
and_then(mk_simplify_tactic(m, m_params),
|
||||||
mk_propagate_values_tactic(m),
|
mk_propagate_values_tactic(m),
|
||||||
|
@ -788,6 +795,7 @@ namespace opt {
|
||||||
set_simplify(tac0.get());
|
set_simplify(tac0.get());
|
||||||
}
|
}
|
||||||
goal_ref_buffer result;
|
goal_ref_buffer result;
|
||||||
|
TRACE("opt", g->display(tout););
|
||||||
(*m_simplify)(g, result);
|
(*m_simplify)(g, result);
|
||||||
SASSERT(result.size() == 1);
|
SASSERT(result.size() == 1);
|
||||||
goal* r = result[0];
|
goal* r = result[0];
|
||||||
|
@ -795,7 +803,26 @@ namespace opt {
|
||||||
fmls.reset();
|
fmls.reset();
|
||||||
expr_ref tmp(m);
|
expr_ref tmp(m);
|
||||||
for (unsigned i = 0; i < r->size(); ++i) {
|
for (unsigned i = 0; i < r->size(); ++i) {
|
||||||
|
if (asms.empty()) {
|
||||||
fmls.push_back(r->form(i));
|
fmls.push_back(r->form(i));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr_vector<expr> deps;
|
||||||
|
expr_dependency_ref core(r->dep(i), m);
|
||||||
|
m.linearize(core, deps);
|
||||||
|
if (!deps.empty()) {
|
||||||
|
fmls.push_back(m.mk_implies(m.mk_and(deps.size(), deps.c_ptr()), r->form(i)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fmls.push_back(r->form(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r->inconsistent()) {
|
||||||
|
ptr_vector<expr> core_elems;
|
||||||
|
expr_dependency_ref core(r->dep(0), m);
|
||||||
|
m.linearize(core, core_elems);
|
||||||
|
m_core.append(core_elems.size(), core_elems.c_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1084,11 +1111,7 @@ namespace opt {
|
||||||
}
|
}
|
||||||
term = m_arith.mk_add(args.size(), args.c_ptr());
|
term = m_arith.mk_add(args.size(), args.c_ptr());
|
||||||
}
|
}
|
||||||
else if (m_arith.is_arith_expr(term) && !is_mul_const(term)) {
|
else if (m.is_ite(term) || !is_mul_const(term)) {
|
||||||
TRACE("opt", tout << "Purifying " << term << "\n";);
|
|
||||||
term = purify(fm, term);
|
|
||||||
}
|
|
||||||
else if (m.is_ite(term)) {
|
|
||||||
TRACE("opt", tout << "Purifying " << term << "\n";);
|
TRACE("opt", tout << "Purifying " << term << "\n";);
|
||||||
term = purify(fm, term);
|
term = purify(fm, term);
|
||||||
}
|
}
|
||||||
|
@ -1399,6 +1422,7 @@ namespace opt {
|
||||||
m_box_index = UINT_MAX;
|
m_box_index = UINT_MAX;
|
||||||
m_model.reset();
|
m_model.reset();
|
||||||
m_model_fixed.reset();
|
m_model_fixed.reset();
|
||||||
|
m_core.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::set_pareto(pareto_base* p) {
|
void context::set_pareto(pareto_base* p) {
|
||||||
|
|
|
@ -133,7 +133,7 @@ namespace opt {
|
||||||
void push();
|
void push();
|
||||||
void pop();
|
void pop();
|
||||||
void add(expr* hard);
|
void add(expr* hard);
|
||||||
bool set(ptr_vector<expr> & hard);
|
bool set(expr_ref_vector const& hard);
|
||||||
unsigned add(expr* soft, rational const& weight, symbol const& id);
|
unsigned add(expr* soft, rational const& weight, symbol const& id);
|
||||||
unsigned add(app* obj, bool is_max);
|
unsigned add(app* obj, bool is_max);
|
||||||
unsigned get_index(symbol const& id) { return m_indices[id]; }
|
unsigned get_index(symbol const& id) { return m_indices[id]; }
|
||||||
|
@ -164,6 +164,7 @@ namespace opt {
|
||||||
obj_map<func_decl, unsigned> m_objective_fns;
|
obj_map<func_decl, unsigned> m_objective_fns;
|
||||||
obj_map<func_decl, expr*> m_objective_orig;
|
obj_map<func_decl, expr*> m_objective_orig;
|
||||||
func_decl_ref_vector m_objective_refs;
|
func_decl_ref_vector m_objective_refs;
|
||||||
|
expr_ref_vector m_core;
|
||||||
tactic_ref m_simplify;
|
tactic_ref m_simplify;
|
||||||
bool m_enable_sat;
|
bool m_enable_sat;
|
||||||
bool m_enable_sls;
|
bool m_enable_sls;
|
||||||
|
@ -186,8 +187,8 @@ namespace opt {
|
||||||
void push() override;
|
void push() override;
|
||||||
void pop(unsigned n) override;
|
void pop(unsigned n) override;
|
||||||
bool empty() override { return m_scoped_state.m_objectives.empty(); }
|
bool empty() override { return m_scoped_state.m_objectives.empty(); }
|
||||||
void set_hard_constraints(ptr_vector<expr> & hard) override;
|
void set_hard_constraints(expr_ref_vector const& hard) override;
|
||||||
lbool optimize() override;
|
lbool optimize(expr_ref_vector const& asms) override;
|
||||||
void set_model(model_ref& _m) override { m_model = _m; }
|
void set_model(model_ref& _m) override { m_model = _m; }
|
||||||
void get_model_core(model_ref& _m) override;
|
void get_model_core(model_ref& _m) override;
|
||||||
void get_box_model(model_ref& _m, unsigned index) override;
|
void get_box_model(model_ref& _m, unsigned index) override;
|
||||||
|
@ -254,7 +255,7 @@ namespace opt {
|
||||||
|
|
||||||
void reset_maxsmts();
|
void reset_maxsmts();
|
||||||
void import_scoped_state();
|
void import_scoped_state();
|
||||||
void normalize();
|
void normalize(expr_ref_vector const& asms);
|
||||||
void internalize();
|
void internalize();
|
||||||
bool is_maximize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index);
|
bool is_maximize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index);
|
||||||
bool is_minimize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index);
|
bool is_minimize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index);
|
||||||
|
@ -270,7 +271,7 @@ namespace opt {
|
||||||
expr* mk_objective_fn(unsigned index, objective_t ty, unsigned sz, expr*const* args);
|
expr* mk_objective_fn(unsigned index, objective_t ty, unsigned sz, expr*const* args);
|
||||||
void to_fmls(expr_ref_vector& fmls);
|
void to_fmls(expr_ref_vector& fmls);
|
||||||
void from_fmls(expr_ref_vector const& fmls);
|
void from_fmls(expr_ref_vector const& fmls);
|
||||||
void simplify_fmls(expr_ref_vector& fmls);
|
void simplify_fmls(expr_ref_vector& fmls, expr_ref_vector const& asms);
|
||||||
void mk_atomic(expr_ref_vector& terms);
|
void mk_atomic(expr_ref_vector& terms);
|
||||||
|
|
||||||
void update_lower() { update_bound(true); }
|
void update_lower() { update_bound(true); }
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace opt {
|
||||||
fmls.push_back(mk_or(gt));
|
fmls.push_back(mk_or(gt));
|
||||||
fml = mk_and(fmls);
|
fml = mk_and(fmls);
|
||||||
IF_VERBOSE(10, verbose_stream() << "dominates: " << fml << "\n";);
|
IF_VERBOSE(10, verbose_stream() << "dominates: " << fml << "\n";);
|
||||||
TRACE("opt", tout << fml << "\n"; model_smt2_pp(tout, m, *m_model, 0););
|
TRACE("opt", model_smt2_pp(tout << fml << "\n", m, *m_model, 0););
|
||||||
m_solver->assert_expr(fml);
|
m_solver->assert_expr(fml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,9 @@ namespace opt {
|
||||||
sortmax(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft):
|
sortmax(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft):
|
||||||
maxsmt_solver_base(c, ws, soft), m_sort(*this), m_trail(m), m_fresh(m) {}
|
maxsmt_solver_base(c, ws, soft), m_sort(*this), m_trail(m), m_fresh(m) {}
|
||||||
|
|
||||||
virtual ~sortmax() {}
|
~sortmax() override {}
|
||||||
|
|
||||||
lbool operator()() {
|
lbool operator()() override {
|
||||||
obj_map<expr, rational> soft;
|
obj_map<expr, rational> soft;
|
||||||
if (!init()) {
|
if (!init()) {
|
||||||
return l_false;
|
return l_false;
|
||||||
|
|
|
@ -49,9 +49,9 @@ namespace opt {
|
||||||
m_trail(m),
|
m_trail(m),
|
||||||
m_defs(m) {}
|
m_defs(m) {}
|
||||||
|
|
||||||
virtual ~wmax() {}
|
~wmax() override {}
|
||||||
|
|
||||||
lbool operator()() {
|
lbool operator()() override {
|
||||||
TRACE("opt", tout << "weighted maxsat\n";);
|
TRACE("opt", tout << "weighted maxsat\n";);
|
||||||
scoped_ensure_theory wth(*this);
|
scoped_ensure_theory wth(*this);
|
||||||
obj_map<expr, rational> soft;
|
obj_map<expr, rational> soft;
|
||||||
|
|
|
@ -36,11 +36,12 @@ std::string marshal(expr_ref e, ast_manager &m) {
|
||||||
expr_ref unmarshal(std::istream &is, ast_manager &m) {
|
expr_ref unmarshal(std::istream &is, ast_manager &m) {
|
||||||
cmd_context ctx(false, &m);
|
cmd_context ctx(false, &m);
|
||||||
ctx.set_ignore_check(true);
|
ctx.set_ignore_check(true);
|
||||||
if (!parse_smt2_commands(ctx, is)) { return expr_ref(nullptr, m); }
|
if (!parse_smt2_commands(ctx, is)) {
|
||||||
|
return expr_ref(nullptr, m);
|
||||||
|
}
|
||||||
|
|
||||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
ptr_vector<expr>::const_iterator it = ctx.assertions().begin();
|
||||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
unsigned size = ctx.assertions().size();
|
||||||
unsigned size = static_cast<unsigned>(end - it);
|
|
||||||
return expr_ref(mk_and(m, size, it), m);
|
return expr_ref(mk_and(m, size, it), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2614,7 +2614,7 @@ namespace smt2 {
|
||||||
|
|
||||||
check_rparen("invalid get-value command, ')' expected");
|
check_rparen("invalid get-value command, ')' expected");
|
||||||
model_ref md;
|
model_ref md;
|
||||||
if (!m_ctx.is_model_available(md) || m_ctx.get_check_sat_result() == 0)
|
if (!m_ctx.is_model_available(md) || m_ctx.get_check_sat_result() == nullptr)
|
||||||
throw cmd_exception("model is not available");
|
throw cmd_exception("model is not available");
|
||||||
if (index != 0) {
|
if (index != 0) {
|
||||||
m_ctx.get_opt()->get_box_model(md, index);
|
m_ctx.get_opt()->get_box_model(md, index);
|
||||||
|
|
|
@ -394,7 +394,7 @@ namespace eq {
|
||||||
expr* const* args = &e;
|
expr* const* args = &e;
|
||||||
if (is_lambda(q)) {
|
if (is_lambda(q)) {
|
||||||
r = q;
|
r = q;
|
||||||
pr = 0;
|
pr = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
flatten_args(q, num_args, args);
|
flatten_args(q, num_args, args);
|
||||||
|
|
|
@ -156,7 +156,7 @@ namespace qe {
|
||||||
std::swap(e1, e2);
|
std::swap(e1, e2);
|
||||||
}
|
}
|
||||||
// y + -1*x == 0 --> y = x
|
// y + -1*x == 0 --> y = x
|
||||||
expr *a0 = 0, *a1 = 0, *x = 0;
|
expr *a0 = nullptr, *a1 = nullptr, *x = nullptr;
|
||||||
if (a.is_zero(e2) && a.is_add(e1, a0, a1)) {
|
if (a.is_zero(e2) && a.is_add(e1, a0, a1)) {
|
||||||
if (a.is_times_minus_one(a1, x)) {
|
if (a.is_times_minus_one(a1, x)) {
|
||||||
e1 = a0;
|
e1 = a0;
|
||||||
|
|
|
@ -1268,7 +1268,7 @@ namespace qe {
|
||||||
result.push_back(in.get());
|
result.push_back(in.get());
|
||||||
if (in->models_enabled()) {
|
if (in->models_enabled()) {
|
||||||
model_converter_ref mc;
|
model_converter_ref mc;
|
||||||
mc = model2model_converter(m_model.get());
|
mc = model2model_converter(m_model_save.get());
|
||||||
mc = concat(m_pred_abs.fmc(), mc.get());
|
mc = concat(m_pred_abs.fmc(), mc.get());
|
||||||
in->add(mc.get());
|
in->add(mc.get());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1862,8 +1862,9 @@ namespace sat {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
ba_solver::ba_solver(): m_solver(0), m_lookahead(0), m_unit_walk(0),
|
ba_solver::ba_solver()
|
||||||
m_allocator("ba"), m_constraint_id(0), m_ba(*this), m_sort(m_ba) {
|
: m_solver(nullptr), m_lookahead(nullptr), m_unit_walk(nullptr),
|
||||||
|
m_constraint_id(0), m_ba(*this), m_sort(m_ba) {
|
||||||
TRACE("ba", tout << this << "\n";);
|
TRACE("ba", tout << this << "\n";);
|
||||||
m_num_propagations_since_pop = 0;
|
m_num_propagations_since_pop = 0;
|
||||||
}
|
}
|
||||||
|
@ -3838,7 +3839,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
init_visited();
|
init_visited();
|
||||||
for (wliteral l : p1) {
|
for (wliteral l : p1) {
|
||||||
SASSERT(m_weights.get(l.second.index(), 0) == 0);
|
SASSERT(m_weights.size() <= l.second.index() || m_weights[l.second.index()] == 0);
|
||||||
m_weights.setx(l.second.index(), l.first, 0);
|
m_weights.setx(l.second.index(), l.first, 0);
|
||||||
mark_visited(l.second);
|
mark_visited(l.second);
|
||||||
}
|
}
|
||||||
|
@ -4394,6 +4395,12 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slack >= k) {
|
if (slack >= k) {
|
||||||
|
#if 0
|
||||||
|
return active2constraint();
|
||||||
|
active2pb(m_A);
|
||||||
|
std::cout << "not asserting\n";
|
||||||
|
display(std::cout, m_A, true);
|
||||||
|
#endif
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ namespace sat {
|
||||||
virtual void set_k(unsigned k) { VERIFY(k < 4000000000); m_k = k; }
|
virtual void set_k(unsigned k) { VERIFY(k < 4000000000); m_k = k; }
|
||||||
virtual unsigned get_coeff(unsigned i) const { UNREACHABLE(); return 0; }
|
virtual unsigned get_coeff(unsigned i) const { UNREACHABLE(); return 0; }
|
||||||
unsigned k() const { return m_k; }
|
unsigned k() const { return m_k; }
|
||||||
virtual bool well_formed() const;
|
bool well_formed() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class card : public pb_base {
|
class card : public pb_base {
|
||||||
|
@ -146,13 +146,13 @@ namespace sat {
|
||||||
literal& operator[](unsigned i) { return m_lits[i]; }
|
literal& operator[](unsigned i) { return m_lits[i]; }
|
||||||
literal const* begin() const { return m_lits; }
|
literal const* begin() const { return m_lits; }
|
||||||
literal const* end() const { return static_cast<literal const*>(m_lits) + m_size; }
|
literal const* end() const { return static_cast<literal const*>(m_lits) + m_size; }
|
||||||
virtual void negate();
|
void negate() override;
|
||||||
virtual void swap(unsigned i, unsigned j) { std::swap(m_lits[i], m_lits[j]); }
|
void swap(unsigned i, unsigned j) override { std::swap(m_lits[i], m_lits[j]); }
|
||||||
virtual literal_vector literals() const { return literal_vector(m_size, m_lits); }
|
literal_vector literals() const override { return literal_vector(m_size, m_lits); }
|
||||||
virtual bool is_watching(literal l) const;
|
bool is_watching(literal l) const override;
|
||||||
virtual literal get_lit(unsigned i) const { return m_lits[i]; }
|
literal get_lit(unsigned i) const override { return m_lits[i]; }
|
||||||
virtual void set_lit(unsigned i, literal l) { m_lits[i] = l; }
|
void set_lit(unsigned i, literal l) override { m_lits[i] = l; }
|
||||||
virtual unsigned get_coeff(unsigned i) const { return 1; }
|
unsigned get_coeff(unsigned i) const override { return 1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,14 +179,14 @@ namespace sat {
|
||||||
void update_max_sum();
|
void update_max_sum();
|
||||||
void set_num_watch(unsigned s) { m_num_watch = s; }
|
void set_num_watch(unsigned s) { m_num_watch = s; }
|
||||||
bool is_cardinality() const;
|
bool is_cardinality() const;
|
||||||
virtual void negate();
|
void negate() override;
|
||||||
virtual void set_k(unsigned k) { m_k = k; VERIFY(k < 4000000000); update_max_sum(); }
|
void set_k(unsigned k) override { m_k = k; VERIFY(k < 4000000000); update_max_sum(); }
|
||||||
virtual void swap(unsigned i, unsigned j) { std::swap(m_wlits[i], m_wlits[j]); }
|
void swap(unsigned i, unsigned j) override { std::swap(m_wlits[i], m_wlits[j]); }
|
||||||
virtual literal_vector literals() const { literal_vector lits; for (auto wl : *this) lits.push_back(wl.second); return lits; }
|
literal_vector literals() const override { literal_vector lits; for (auto wl : *this) lits.push_back(wl.second); return lits; }
|
||||||
virtual bool is_watching(literal l) const;
|
bool is_watching(literal l) const override;
|
||||||
virtual literal get_lit(unsigned i) const { return m_wlits[i].second; }
|
literal get_lit(unsigned i) const override { return m_wlits[i].second; }
|
||||||
virtual void set_lit(unsigned i, literal l) { m_wlits[i].second = l; }
|
void set_lit(unsigned i, literal l) override { m_wlits[i].second = l; }
|
||||||
virtual unsigned get_coeff(unsigned i) const { return m_wlits[i].first; }
|
unsigned get_coeff(unsigned i) const override { return m_wlits[i].first; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class xr : public constraint {
|
class xr : public constraint {
|
||||||
|
@ -197,13 +197,13 @@ namespace sat {
|
||||||
literal operator[](unsigned i) const { return m_lits[i]; }
|
literal operator[](unsigned i) const { return m_lits[i]; }
|
||||||
literal const* begin() const { return m_lits; }
|
literal const* begin() const { return m_lits; }
|
||||||
literal const* end() const { return begin() + m_size; }
|
literal const* end() const { return begin() + m_size; }
|
||||||
virtual void negate() { m_lits[0].neg(); }
|
void negate() override { m_lits[0].neg(); }
|
||||||
virtual void swap(unsigned i, unsigned j) { std::swap(m_lits[i], m_lits[j]); }
|
void swap(unsigned i, unsigned j) override { std::swap(m_lits[i], m_lits[j]); }
|
||||||
virtual bool is_watching(literal l) const;
|
bool is_watching(literal l) const override;
|
||||||
virtual literal_vector literals() const { return literal_vector(size(), begin()); }
|
literal_vector literals() const override { return literal_vector(size(), begin()); }
|
||||||
virtual literal get_lit(unsigned i) const { return m_lits[i]; }
|
literal get_lit(unsigned i) const override { return m_lits[i]; }
|
||||||
virtual void set_lit(unsigned i, literal l) { m_lits[i] = l; }
|
void set_lit(unsigned i, literal l) override { m_lits[i] = l; }
|
||||||
virtual bool well_formed() const;
|
bool well_formed() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -524,44 +524,44 @@ namespace sat {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ba_solver();
|
ba_solver();
|
||||||
virtual ~ba_solver();
|
~ba_solver() override;
|
||||||
virtual void set_solver(solver* s) { m_solver = s; }
|
void set_solver(solver* s) override { m_solver = s; }
|
||||||
virtual void set_lookahead(lookahead* l) { m_lookahead = l; }
|
void set_lookahead(lookahead* l) override { m_lookahead = l; }
|
||||||
virtual void set_unit_walk(unit_walk* u) { m_unit_walk = u; }
|
void set_unit_walk(unit_walk* u) override { m_unit_walk = u; }
|
||||||
void add_at_least(bool_var v, literal_vector const& lits, unsigned k);
|
void add_at_least(bool_var v, literal_vector const& lits, unsigned k);
|
||||||
void add_pb_ge(bool_var v, svector<wliteral> const& wlits, unsigned k);
|
void add_pb_ge(bool_var v, svector<wliteral> const& wlits, unsigned k);
|
||||||
void add_xr(literal_vector const& lits);
|
void add_xr(literal_vector const& lits);
|
||||||
|
|
||||||
virtual bool propagate(literal l, ext_constraint_idx idx);
|
bool propagate(literal l, ext_constraint_idx idx) override;
|
||||||
virtual lbool resolve_conflict();
|
lbool resolve_conflict() override;
|
||||||
virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r);
|
void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r) override;
|
||||||
virtual void asserted(literal l);
|
void asserted(literal l) override;
|
||||||
virtual check_result check();
|
check_result check() override;
|
||||||
virtual void push();
|
void push() override;
|
||||||
virtual void pop(unsigned n);
|
void pop(unsigned n) override;
|
||||||
virtual void simplify();
|
void simplify() override;
|
||||||
virtual void clauses_modifed();
|
void clauses_modifed() override;
|
||||||
virtual lbool get_phase(bool_var v);
|
lbool get_phase(bool_var v) override;
|
||||||
virtual bool set_root(literal l, literal r);
|
bool set_root(literal l, literal r) override;
|
||||||
virtual void flush_roots();
|
void flush_roots() override;
|
||||||
virtual std::ostream& display(std::ostream& out) const;
|
std::ostream& display(std::ostream& out) const override;
|
||||||
virtual std::ostream& display_justification(std::ostream& out, ext_justification_idx idx) const;
|
std::ostream& display_justification(std::ostream& out, ext_justification_idx idx) const override;
|
||||||
virtual void collect_statistics(statistics& st) const;
|
void collect_statistics(statistics& st) const override;
|
||||||
virtual extension* copy(solver* s);
|
extension* copy(solver* s) override;
|
||||||
virtual extension* copy(lookahead* s, bool learned);
|
extension* copy(lookahead* s, bool learned) override;
|
||||||
virtual void find_mutexes(literal_vector& lits, vector<literal_vector> & mutexes);
|
void find_mutexes(literal_vector& lits, vector<literal_vector> & mutexes) override;
|
||||||
virtual void pop_reinit();
|
void pop_reinit() override;
|
||||||
virtual void gc();
|
void gc() override;
|
||||||
virtual double get_reward(literal l, ext_justification_idx idx, literal_occs_fun& occs) const;
|
double get_reward(literal l, ext_justification_idx idx, literal_occs_fun& occs) const override;
|
||||||
virtual bool is_extended_binary(ext_justification_idx idx, literal_vector & r);
|
bool is_extended_binary(ext_justification_idx idx, literal_vector & r) override;
|
||||||
virtual void init_use_list(ext_use_list& ul);
|
void init_use_list(ext_use_list& ul) override;
|
||||||
virtual bool is_blocked(literal l, ext_constraint_idx idx);
|
bool is_blocked(literal l, ext_constraint_idx idx) override;
|
||||||
virtual bool check_model(model const& m) const;
|
bool check_model(model const& m) const override;
|
||||||
|
|
||||||
ptr_vector<constraint> const & constraints() const { return m_constraints; }
|
ptr_vector<constraint> const & constraints() const { return m_constraints; }
|
||||||
void display(std::ostream& out, constraint const& c, bool values) const;
|
void display(std::ostream& out, constraint const& c, bool values) const;
|
||||||
|
|
||||||
virtual bool validate();
|
bool validate() override;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -152,6 +152,8 @@ namespace sat {
|
||||||
m_gc_burst = p.gc_burst();
|
m_gc_burst = p.gc_burst();
|
||||||
m_gc_defrag = p.gc_defrag();
|
m_gc_defrag = p.gc_defrag();
|
||||||
|
|
||||||
|
m_force_cleanup = p.force_cleanup();
|
||||||
|
|
||||||
m_minimize_lemmas = p.minimize_lemmas();
|
m_minimize_lemmas = p.minimize_lemmas();
|
||||||
m_core_minimize = p.core_minimize();
|
m_core_minimize = p.core_minimize();
|
||||||
m_core_minimize_partial = p.core_minimize_partial();
|
m_core_minimize_partial = p.core_minimize_partial();
|
||||||
|
|
|
@ -146,6 +146,8 @@ namespace sat {
|
||||||
bool m_gc_burst;
|
bool m_gc_burst;
|
||||||
bool m_gc_defrag;
|
bool m_gc_defrag;
|
||||||
|
|
||||||
|
bool m_force_cleanup;
|
||||||
|
|
||||||
|
|
||||||
bool m_minimize_lemmas;
|
bool m_minimize_lemmas;
|
||||||
bool m_dyn_sub_res;
|
bool m_dyn_sub_res;
|
||||||
|
|
|
@ -26,7 +26,7 @@ Notes:
|
||||||
namespace sat {
|
namespace sat {
|
||||||
drat::drat(solver& s):
|
drat::drat(solver& s):
|
||||||
s(s),
|
s(s),
|
||||||
m_out(0),
|
m_out(nullptr),
|
||||||
m_inconsistent(false),
|
m_inconsistent(false),
|
||||||
m_check_unsat(false),
|
m_check_unsat(false),
|
||||||
m_check_sat(false),
|
m_check_sat(false),
|
||||||
|
|
|
@ -529,7 +529,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool local_search::check() {
|
lbool local_search::check() {
|
||||||
return check(0, 0);
|
return check(0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PROGRESS(tries, flips) \
|
#define PROGRESS(tries, flips) \
|
||||||
|
|
|
@ -277,7 +277,7 @@ namespace sat {
|
||||||
|
|
||||||
lbool check();
|
lbool check();
|
||||||
|
|
||||||
lbool check(unsigned sz, literal const* assumptions, parallel* p = 0);
|
lbool check(unsigned sz, literal const* assumptions, parallel* p = nullptr);
|
||||||
|
|
||||||
local_search_config& config() { return m_config; }
|
local_search_config& config() { return m_config; }
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ Author:
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
@ -31,7 +33,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
lookahead::scoped_ext::~scoped_ext() {
|
lookahead::scoped_ext::~scoped_ext() {
|
||||||
if (p.m_s.m_ext) p.m_s.m_ext->set_lookahead(0);
|
if (p.m_s.m_ext) p.m_s.m_ext->set_lookahead(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
lookahead::scoped_assumptions::scoped_assumptions(lookahead& p, literal_vector const& lits): p(p), lits(lits) {
|
lookahead::scoped_assumptions::scoped_assumptions(lookahead& p, literal_vector const& lits): p(p), lits(lits) {
|
||||||
|
@ -1215,7 +1217,7 @@ namespace sat {
|
||||||
lookahead& lh;
|
lookahead& lh;
|
||||||
public:
|
public:
|
||||||
lookahead_literal_occs_fun(lookahead& lh): lh(lh) {}
|
lookahead_literal_occs_fun(lookahead& lh): lh(lh) {}
|
||||||
double operator()(literal l) { return lh.literal_occs(l); }
|
double operator()(literal l) override { return lh.literal_occs(l); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ternary clause managagement:
|
// Ternary clause managagement:
|
||||||
|
@ -2055,6 +2057,15 @@ namespace sat {
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lookahead::should_cutoff(unsigned depth) {
|
||||||
|
return depth > 0 &&
|
||||||
|
((m_config.m_cube_cutoff == depth_cutoff && depth == m_config.m_cube_depth) ||
|
||||||
|
(m_config.m_cube_cutoff == freevars_cutoff && m_freevars.size() <= m_init_freevars * m_config.m_cube_freevars) ||
|
||||||
|
(m_config.m_cube_cutoff == psat_cutoff && psat_heur() >= m_config.m_cube_psat_trigger) ||
|
||||||
|
(m_config.m_cube_cutoff == adaptive_freevars_cutoff && m_freevars.size() < m_cube_state.m_freevars_threshold) ||
|
||||||
|
(m_config.m_cube_cutoff == adaptive_psat_cutoff && psat_heur() >= m_cube_state.m_psat_threshold));
|
||||||
|
}
|
||||||
|
|
||||||
lbool lookahead::cube(bool_var_vector& vars, literal_vector& lits, unsigned backtrack_level) {
|
lbool lookahead::cube(bool_var_vector& vars, literal_vector& lits, unsigned backtrack_level) {
|
||||||
scoped_ext _scoped_ext(*this);
|
scoped_ext _scoped_ext(*this);
|
||||||
lits.reset();
|
lits.reset();
|
||||||
|
@ -2100,22 +2111,13 @@ namespace sat {
|
||||||
}
|
}
|
||||||
backtrack_level = UINT_MAX;
|
backtrack_level = UINT_MAX;
|
||||||
depth = m_cube_state.m_cube.size();
|
depth = m_cube_state.m_cube.size();
|
||||||
if ((m_config.m_cube_cutoff == depth_cutoff && depth == m_config.m_cube_depth) ||
|
if (should_cutoff(depth)) {
|
||||||
(m_config.m_cube_cutoff == freevars_cutoff && m_freevars.size() <= m_init_freevars * m_config.m_cube_freevars) ||
|
|
||||||
(m_config.m_cube_cutoff == psat_cutoff && psat_heur() >= m_config.m_cube_psat_trigger) ||
|
|
||||||
(m_config.m_cube_cutoff == adaptive_freevars_cutoff && m_freevars.size() < m_cube_state.m_freevars_threshold) ||
|
|
||||||
(m_config.m_cube_cutoff == adaptive_psat_cutoff && psat_heur() >= m_cube_state.m_psat_threshold)) {
|
|
||||||
double dec = (1.0 - pow(m_config.m_cube_fraction, depth));
|
double dec = (1.0 - pow(m_config.m_cube_fraction, depth));
|
||||||
m_cube_state.m_freevars_threshold *= dec;
|
m_cube_state.m_freevars_threshold *= dec;
|
||||||
m_cube_state.m_psat_threshold *= 2.0 - dec;
|
m_cube_state.m_psat_threshold *= 2.0 - dec;
|
||||||
set_conflict();
|
set_conflict();
|
||||||
m_cube_state.inc_cutoff();
|
m_cube_state.inc_cutoff();
|
||||||
#if 0
|
|
||||||
// return cube of all literals, not just the ones in the main cube
|
|
||||||
lits.append(m_trail.size() - init_trail, m_trail.c_ptr() + init_trail);
|
|
||||||
#else
|
|
||||||
lits.append(m_cube_state.m_cube);
|
lits.append(m_cube_state.m_cube);
|
||||||
#endif
|
|
||||||
vars.reset();
|
vars.reset();
|
||||||
for (auto v : m_freevars) if (in_reduced_clause(v)) vars.push_back(v);
|
for (auto v : m_freevars) if (in_reduced_clause(v)) vars.push_back(v);
|
||||||
backtrack(m_cube_state.m_cube, m_cube_state.m_is_decision);
|
backtrack(m_cube_state.m_cube, m_cube_state.m_is_decision);
|
||||||
|
@ -2135,6 +2137,8 @@ namespace sat {
|
||||||
if (lit == null_literal) {
|
if (lit == null_literal) {
|
||||||
vars.reset();
|
vars.reset();
|
||||||
for (auto v : m_freevars) if (in_reduced_clause(v)) vars.push_back(v);
|
for (auto v : m_freevars) if (in_reduced_clause(v)) vars.push_back(v);
|
||||||
|
m_model.reset();
|
||||||
|
init_model();
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
TRACE("sat", tout << "choose: " << lit << " cube: " << m_cube_state.m_cube << "\n";);
|
TRACE("sat", tout << "choose: " << lit << " cube: " << m_cube_state.m_cube << "\n";);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue