mirror of
https://github.com/Z3Prover/z3
synced 2025-04-06 17:44:08 +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")
|
||||
endif()
|
||||
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")
|
||||
elseif ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
|
||||
message(STATUS "Platform: FreeBSD")
|
||||
|
@ -380,9 +380,17 @@ endif()
|
|||
################################################################################
|
||||
# FIXME: Support ARM "-mfpu=vfp -mfloat-abi=hard"
|
||||
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")
|
||||
# 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")
|
||||
set(SSE_FLAGS "/arch:SSE2")
|
||||
else()
|
||||
|
|
|
@ -12,8 +12,8 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z
|
|||
|
||||
## 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)
|
||||
|
||||
[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
|
||||
``PREFIX/lib``, and include files at ``PREFIX/include``, where ``PREFIX``
|
||||
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:
|
||||
|
||||
```bash
|
||||
|
|
|
@ -21,7 +21,7 @@ Version 4.8.0
|
|||
extracting models from apply_result have been replaced.
|
||||
- An optional mode handles xor constraints using a custom xor propagator.
|
||||
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
|
||||
(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
|
||||
|
@ -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).
|
||||
|
||||
- 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
|
||||
===========
|
||||
|
|
|
@ -5,6 +5,6 @@ in the build directory.
|
|||
|
||||
This command will create the executable cpp_example.
|
||||
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
|
||||
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.
|
||||
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
|
||||
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
|
||||
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
|
||||
|
|
|
@ -5,8 +5,8 @@ in the build directory.
|
|||
|
||||
This command will create the executable maxsat.
|
||||
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
|
||||
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.
|
||||
|
|
|
@ -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
|
||||
(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 "")
|
||||
| Some (m) ->
|
||||
Printf.printf "Solver says: %s\n" (string_of_status q) ;
|
||||
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))
|
||||
Printf.printf "Model: \n%s\n" (Model.to_string m)
|
||||
)
|
||||
|
||||
(**
|
||||
|
@ -330,12 +329,14 @@ let _ =
|
|||
let ss = (Symbol.mk_string ctx "mySymbol") in
|
||||
let bs = (Boolean.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 "string symbol: %s\n" (Symbol.to_string ss);
|
||||
Printf.printf "bool sort: %s\n" (Sort.to_string bs);
|
||||
Printf.printf "int sort: %s\n" (Sort.to_string ints);
|
||||
Printf.printf "real sort: %s\n" (Sort.to_string rs);
|
||||
Printf.printf "integer: %s\n" (Expr.to_string v);
|
||||
basic_tests ctx ;
|
||||
quantifier_example1 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
|
||||
# python example.py
|
||||
|
||||
# Running this example on OSX:
|
||||
# Running this example on macOS:
|
||||
# export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:MYZ3/bin
|
||||
# export PYTHONPATH=MYZ3/bin/python
|
||||
# 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.
|
||||
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
|
||||
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
|
||||
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
|
||||
def init_project_def():
|
||||
set_version(4, 8, 0, 0)
|
||||
add_lib('util', [])
|
||||
add_lib('util', [], includes2install = ['z3_version.h'])
|
||||
add_lib('polynomial', ['util'], 'math/polynomial')
|
||||
add_lib('sat', ['util'])
|
||||
add_lib('nlsat', ['polynomial', 'sat'])
|
||||
|
|
|
@ -396,7 +396,7 @@ def check_java():
|
|||
libdirs = m.group(1).split(',')
|
||||
for libdir in libdirs:
|
||||
q = os.path.dirname(libdir)
|
||||
if cdirs.count(q) == 0:
|
||||
if cdirs.count(q) == 0 and len(q) > 0:
|
||||
cdirs.append(q)
|
||||
t.close()
|
||||
|
||||
|
@ -1668,9 +1668,6 @@ class DotNetDLLComponent(Component):
|
|||
'/noconfig',
|
||||
'/nostdlib+',
|
||||
'/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
|
||||
def mk_version_dot_h(major, minor, build, revision):
|
||||
c = get_component(UTIL_COMPONENT)
|
||||
version_template = os.path.join(c.src_dir, 'version.h.in')
|
||||
version_header_output = os.path.join(c.src_dir, 'version.h')
|
||||
version_template = os.path.join(c.src_dir, 'z3_version.h.in')
|
||||
version_header_output = os.path.join(c.src_dir, 'z3_version.h')
|
||||
# Note the substitution names are what is used by the CMake
|
||||
# builds system. If you change these you should change them
|
||||
# in the CMake build too
|
||||
|
|
|
@ -166,6 +166,8 @@ foreach (header ${libz3_public_headers})
|
|||
set_property(TARGET libz3 APPEND PROPERTY
|
||||
PUBLIC_HEADER "${CMAKE_SOURCE_DIR}/src/api/${header}")
|
||||
endforeach()
|
||||
set_property(TARGET libz3 APPEND PROPERTY
|
||||
PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/util/z3_version.h")
|
||||
|
||||
install(TARGETS libz3
|
||||
EXPORT Z3_EXPORTED_TARGETS
|
||||
|
|
|
@ -468,7 +468,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_decl_symbol_parameter(c, d, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
return nullptr;
|
||||
|
@ -486,7 +486,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_decl_sort_parameter(c, d, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
|
@ -504,7 +504,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_decl_ast_parameter(c, d, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
|
@ -522,7 +522,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_decl_func_decl_parameter(c, d, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (idx >= to_func_decl(d)->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
|
@ -596,7 +596,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_domain(c, d, i);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(d, 0);
|
||||
CHECK_VALID_AST(d, nullptr);
|
||||
if (i >= to_func_decl(d)->get_arity()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
--*/
|
||||
#include<typeinfo>
|
||||
#include "api/api_context.h"
|
||||
#include "util/version.h"
|
||||
#include "util/z3_version.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "api/api_log_macros.h"
|
||||
|
|
|
@ -379,10 +379,8 @@ extern "C" {
|
|||
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]);
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
to_fixedpoint_ref(d)->ctx().assert_expr(*it);
|
||||
for (expr * e : ctx.assertions()) {
|
||||
to_fixedpoint_ref(d)->ctx().assert_expr(e);
|
||||
}
|
||||
|
||||
return of_ast_vector(v);
|
||||
|
@ -717,5 +715,4 @@ extern "C" {
|
|||
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())
|
||||
(*to_goal_ref(g)->mc())(m_ref->m_model);
|
||||
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) {
|
||||
|
|
|
@ -19,7 +19,7 @@ Revision History:
|
|||
#include "api/z3.h"
|
||||
#include "api/api_log_macros.h"
|
||||
#include "util/util.h"
|
||||
#include "util/version.h"
|
||||
#include "util/z3_version.h"
|
||||
|
||||
std::ostream * g_z3_log = nullptr;
|
||||
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;
|
||||
LOG_Z3_optimize_check(c, o);
|
||||
LOG_Z3_optimize_check(c, o, num_assumptions, assumptions);
|
||||
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;
|
||||
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());
|
||||
|
@ -137,7 +143,9 @@ extern "C" {
|
|||
scoped_timer timer(timeout, &eh);
|
||||
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
|
||||
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) {
|
||||
if (!mk_c(c)->m().canceled()) {
|
||||
|
@ -157,6 +165,22 @@ extern "C" {
|
|||
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_TRY;
|
||||
LOG_Z3_optimize_to_string(c, o);
|
||||
|
@ -330,10 +354,8 @@ extern "C" {
|
|||
return;
|
||||
}
|
||||
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
to_optimize_ptr(opt)->add_hard_constraint(*it);
|
||||
for (expr * e : ctx->assertions()) {
|
||||
to_optimize_ptr(opt)->add_hard_constraint(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,10 +71,8 @@ extern "C" {
|
|||
SET_ERROR_CODE(Z3_PARSER_ERROR, errstrm.str().c_str());
|
||||
return of_ast_vector(v);
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
v->m_ast_vector.push_back(*it);
|
||||
for (expr * e : ctx->assertions()) {
|
||||
v->m_ast_vector.push_back(e);
|
||||
}
|
||||
return of_ast_vector(v);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*++
|
||||
Copyright (c) 2018 Microsoft Corporation
|
||||
Copyright (c) Microsoft Corporation, Arie Gurfinkel 2017
|
||||
|
||||
Module Name:
|
||||
|
||||
|
@ -70,39 +70,39 @@ extern "C"
|
|||
}
|
||||
|
||||
Z3_ast Z3_API Z3_qe_model_project_skolem (Z3_context c,
|
||||
Z3_model m,
|
||||
Z3_model mdl,
|
||||
unsigned num_bounds,
|
||||
Z3_app const bound[],
|
||||
Z3_ast body,
|
||||
Z3_ast_map map)
|
||||
{
|
||||
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();
|
||||
|
||||
ast_manager& man = mk_c(c)->m ();
|
||||
app_ref_vector vars(man);
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
app_ref_vector vars(m);
|
||||
if (!to_apps(num_bounds, bound, vars)) {
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
|
||||
expr_ref result (mk_c(c)->m ());
|
||||
expr_ref result (m);
|
||||
result = to_expr (body);
|
||||
model_ref model (to_model_ref (m));
|
||||
expr_map emap (man);
|
||||
model_ref model (to_model_ref (mdl));
|
||||
expr_map emap (m);
|
||||
|
||||
spacer::qe_project (mk_c(c)->m (), vars, result, model, emap);
|
||||
mk_c(c)->save_ast_trail (result.get ());
|
||||
spacer::qe_project(m, vars, result, model, emap);
|
||||
mk_c(c)->save_ast_trail(result);
|
||||
|
||||
obj_map<ast, ast*> &map_z3 = to_ast_map_ref(map);
|
||||
|
||||
for (expr_map::iterator it = emap.begin(), end = emap.end(); it != end; ++it){
|
||||
man.inc_ref(&(it->get_key()));
|
||||
man.inc_ref(it->get_value());
|
||||
map_z3.insert(&(it->get_key()), it->get_value());
|
||||
for (auto& kv : emap) {
|
||||
m.inc_ref(kv.m_key);
|
||||
m.inc_ref(kv.m_value);
|
||||
map_z3.insert(kv.m_key, kv.m_value);
|
||||
}
|
||||
|
||||
return of_expr (result.get ());
|
||||
return of_expr (result);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
@ -124,9 +124,9 @@ extern "C"
|
|||
|
||||
expr_ref result (mk_c(c)->m ());
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -138,8 +138,8 @@ extern "C"
|
|||
ast_ref_vector &vVars = to_ast_vector_ref (vars);
|
||||
|
||||
app_ref_vector vApps (mk_c(c)->m());
|
||||
for (unsigned i = 0; i < vVars.size (); ++i) {
|
||||
app *a = to_app (vVars.get (i));
|
||||
for (ast* v : vVars) {
|
||||
app * a = to_app(v);
|
||||
if (a->get_kind () != AST_APP) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, 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);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ extern "C" {
|
|||
expr_ref result(mk_c(c)->m());
|
||||
if (num_decls == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE, nullptr);
|
||||
RETURN_Z3(0);
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
|
||||
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));
|
||||
mk_c(c)->save_ast_trail(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,
|
||||
|
@ -178,7 +178,7 @@ extern "C" {
|
|||
RESET_ERROR_CODE();
|
||||
if (num_decls == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE, nullptr);
|
||||
RETURN_Z3(0);
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
|
||||
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);
|
||||
mk_c(c)->save_ast_trail(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;
|
||||
if (!initialized)
|
||||
init_solver(c, s);
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
to_solver_ref(s)->assert_expr(*it);
|
||||
for (expr * e : ctx->assertions()) {
|
||||
to_solver_ref(s)->assert_expr(e);
|
||||
}
|
||||
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);
|
||||
char const* ext = get_extension(file_name);
|
||||
std::ifstream is(file_name);
|
||||
init_solver(c, s);
|
||||
if (!is) {
|
||||
SET_ERROR_CODE(Z3_FILE_ACCESS_ERROR, nullptr);
|
||||
}
|
||||
|
@ -368,7 +367,22 @@ extern "C" {
|
|||
v->m_ast_vector.push_back(f);
|
||||
}
|
||||
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[]) {
|
||||
|
@ -615,7 +629,7 @@ extern "C" {
|
|||
}
|
||||
catch (z3_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());
|
||||
|
@ -628,7 +642,7 @@ extern "C" {
|
|||
to_ast_vector_ref(vs).push_back(a);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -127,6 +127,14 @@ namespace z3 {
|
|||
unsat, sat, unknown
|
||||
};
|
||||
|
||||
enum rounding_mode {
|
||||
RNA,
|
||||
RNE,
|
||||
RTP,
|
||||
RTN,
|
||||
RTZ
|
||||
};
|
||||
|
||||
inline check_result to_check_result(Z3_lbool l) {
|
||||
if (l == Z3_L_TRUE) return sat;
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
class context {
|
||||
private:
|
||||
bool m_enable_exceptions;
|
||||
rounding_mode m_rounding_mode;
|
||||
Z3_context m_ctx;
|
||||
void init(config & c) {
|
||||
m_ctx = Z3_mk_context_rc(c);
|
||||
m_enable_exceptions = true;
|
||||
m_rounding_mode = RNA;
|
||||
Z3_set_error_handler(m_ctx, 0);
|
||||
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||
}
|
||||
|
@ -171,7 +184,7 @@ namespace z3 {
|
|||
}
|
||||
|
||||
/**
|
||||
\brief The C++ API uses by defaults exceptions on errors.
|
||||
\brief The C++ API uses by defaults exceptions on errors.
|
||||
For applications that don't work well with exceptions (there should be only few)
|
||||
you have the ability to turn off exceptions. The tradeoffs are that applications
|
||||
have to be very careful about using check_error() after calls that may result in an
|
||||
|
@ -247,6 +260,26 @@ namespace z3 {
|
|||
*/
|
||||
sort array_sort(sort 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].
|
||||
\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 real_const(char const * name);
|
||||
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);
|
||||
|
||||
|
@ -307,6 +344,9 @@ namespace z3 {
|
|||
expr bv_val(char const * n, unsigned sz);
|
||||
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(std::string const& s);
|
||||
|
||||
|
@ -465,6 +505,7 @@ namespace z3 {
|
|||
public:
|
||||
sort(context & c):ast(c) {}
|
||||
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) {}
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
|
@ -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 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.
|
||||
|
||||
|
@ -634,7 +682,7 @@ namespace z3 {
|
|||
\brief Return true if this is a regular expression.
|
||||
*/
|
||||
bool is_re() const { return get_sort().is_re(); }
|
||||
|
||||
|
||||
/**
|
||||
\brief Return true if this is a Finite-domain expression.
|
||||
|
||||
|
@ -644,6 +692,10 @@ namespace z3 {
|
|||
|
||||
*/
|
||||
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.
|
||||
|
@ -696,29 +748,29 @@ namespace z3 {
|
|||
\brief Return true if this expression is well sorted (aka type correct).
|
||||
*/
|
||||
bool is_well_sorted() const { bool r = Z3_is_well_sorted(ctx(), m_ast) != 0; check_error(); return r; }
|
||||
|
||||
|
||||
/**
|
||||
\brief Return string representation of numeral or algebraic number
|
||||
This method assumes the expression is numeral or algebraic
|
||||
|
||||
|
||||
\pre is_numeral() || is_algebraic()
|
||||
*/
|
||||
std::string get_decimal_string(int precision) const {
|
||||
assert(is_numeral() || is_algebraic());
|
||||
return std::string(Z3_get_numeral_decimal_string(ctx(), m_ast, precision));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return int value of numeral, throw if result cannot fit in
|
||||
machine int
|
||||
|
||||
It only makes sense to use this function if the caller can ensure that
|
||||
the result is an integer or if exceptions are enabled.
|
||||
the result is an integer or if exceptions are enabled.
|
||||
If exceptions are disabled, then use the is_numeral_i function.
|
||||
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
int get_numeral_int() const {
|
||||
int get_numeral_int() const {
|
||||
int result = 0;
|
||||
if (!is_numeral_i(result)) {
|
||||
assert(ctx().enable_exceptions());
|
||||
|
@ -727,13 +779,13 @@ namespace z3 {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return uint value of numeral, throw if result cannot fit in
|
||||
machine uint
|
||||
|
||||
It only makes sense to use this function if the caller can ensure that
|
||||
the result is an integer or if exceptions are enabled.
|
||||
the result is an integer or if exceptions are enabled.
|
||||
If exceptions are disabled, then use the is_numeral_u function.
|
||||
\pre is_numeral()
|
||||
*/
|
||||
|
@ -747,11 +799,11 @@ namespace z3 {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return \c int64_t value of numeral, throw if result cannot fit in
|
||||
\c int64_t.
|
||||
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
int64_t get_numeral_int64() const {
|
||||
|
@ -764,11 +816,11 @@ namespace z3 {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return \c uint64_t value of numeral, throw if result cannot fit in
|
||||
\c uint64_t.
|
||||
|
||||
|
||||
\pre is_numeral()
|
||||
*/
|
||||
uint64_t get_numeral_uint64() const {
|
||||
|
@ -786,7 +838,7 @@ namespace z3 {
|
|||
return Z3_get_bool_value(ctx(), m_ast);
|
||||
}
|
||||
|
||||
expr numerator() const {
|
||||
expr numerator() const {
|
||||
assert(is_numeral());
|
||||
Z3_ast r = Z3_get_numerator(ctx(), m_ast);
|
||||
check_error();
|
||||
|
@ -794,7 +846,7 @@ namespace z3 {
|
|||
}
|
||||
|
||||
|
||||
expr denominator() const {
|
||||
expr denominator() const {
|
||||
assert(is_numeral());
|
||||
Z3_ast r = Z3_get_denominator(ctx(), m_ast);
|
||||
check_error();
|
||||
|
@ -803,6 +855,17 @@ namespace z3 {
|
|||
|
||||
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.
|
||||
This method assumes the expression is an application.
|
||||
|
@ -905,7 +968,7 @@ namespace z3 {
|
|||
bool is_implies() const { return is_app() && Z3_OP_IMPLIES == decl().decl_kind(); }
|
||||
bool is_eq() const { return is_app() && Z3_OP_EQ == decl().decl_kind(); }
|
||||
bool is_ite() const { return is_app() && Z3_OP_ITE == decl().decl_kind(); }
|
||||
|
||||
|
||||
friend expr distinct(expr_vector const& args);
|
||||
friend expr concat(expr const& a, expr const& b);
|
||||
friend expr concat(expr_vector const& args);
|
||||
|
@ -992,23 +1055,34 @@ namespace z3 {
|
|||
friend expr nor(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_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); }
|
||||
|
||||
friend expr abs(expr const & a);
|
||||
friend expr sqrt(expr const & a, expr const & rm);
|
||||
|
||||
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 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.
|
||||
+ is overloaded as sequence concatenation and regular expression union.
|
||||
concat is overloaded to handle sequences and regular expressions
|
||||
*/
|
||||
expr extract(expr const& offset, expr const& length) const {
|
||||
expr extract(expr const& offset, expr const& length) const {
|
||||
check_context(*this, offset); check_context(offset, length);
|
||||
Z3_ast r = Z3_mk_seq_extract(ctx(), *this, offset, length); check_error(); return expr(ctx(), r);
|
||||
Z3_ast r = Z3_mk_seq_extract(ctx(), *this, offset, length); check_error(); return expr(ctx(), r);
|
||||
}
|
||||
expr replace(expr const& src, expr const& dst) const {
|
||||
check_context(*this, src); check_context(src, dst);
|
||||
|
@ -1049,19 +1123,19 @@ namespace z3 {
|
|||
return expr(ctx(), r);
|
||||
}
|
||||
|
||||
friend expr range(expr const& lo, expr const& hi);
|
||||
friend expr range(expr const& lo, expr const& hi);
|
||||
/**
|
||||
\brief create a looping regular expression.
|
||||
*/
|
||||
expr loop(unsigned lo) {
|
||||
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, 0);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, 0);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
expr loop(unsigned lo, unsigned hi) {
|
||||
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, hi);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, hi);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1094,7 +1168,7 @@ namespace z3 {
|
|||
|
||||
|
||||
inline expr implies(expr const & a, expr const & b) {
|
||||
assert(a.is_bool() && b.is_bool());
|
||||
assert(a.is_bool() && b.is_bool());
|
||||
_Z3_MK_BIN_(a, b, Z3_mk_implies);
|
||||
}
|
||||
inline expr implies(expr const & a, bool b) { return implies(a, a.ctx().bool_val(b)); }
|
||||
|
@ -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(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(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();
|
||||
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==(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==(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() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) == b; }
|
||||
|
||||
inline expr operator!=(expr const & a, expr const & b) {
|
||||
check_context(a, b);
|
||||
|
@ -1168,8 +1248,8 @@ namespace z3 {
|
|||
a.check_error();
|
||||
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!=(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!=(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() || b.is_fpa()); return b.ctx().num_val(a, b.get_sort()) != b; }
|
||||
|
||||
inline expr operator+(expr const & a, expr const & b) {
|
||||
check_context(a, b);
|
||||
|
@ -1188,6 +1268,9 @@ namespace z3 {
|
|||
Z3_ast _args[2] = { a, b };
|
||||
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 {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1208,6 +1291,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
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 {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1245,6 +1331,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
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 {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1263,6 +1352,9 @@ namespace z3 {
|
|||
else if (a.is_bv()) {
|
||||
r = Z3_mk_bvneg(a.ctx(), a);
|
||||
}
|
||||
else if (a.is_fpa()) {
|
||||
r = Z3_mk_fpa_neg(a.ctx(), a);
|
||||
}
|
||||
else {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1281,6 +1373,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
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 {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1300,6 +1395,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
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 {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1322,6 +1420,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
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 {
|
||||
// operator is not supported by given arguments.
|
||||
assert(false);
|
||||
|
@ -1341,6 +1442,9 @@ namespace z3 {
|
|||
else if (a.is_bv() && b.is_bv()) {
|
||||
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 {
|
||||
// operator is not supported by given arguments.
|
||||
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 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 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 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>
|
||||
|
||||
\pre c.is_bool()
|
||||
*/
|
||||
|
||||
inline expr ite(expr const & c, expr const & t, expr const & e) {
|
||||
check_context(c, t); check_context(c, e);
|
||||
assert(c.is_bool());
|
||||
|
@ -1453,45 +1570,45 @@ namespace z3 {
|
|||
inline expr smod(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvsmod(a.ctx(), a, b)); }
|
||||
inline expr smod(expr const & a, int b) { return smod(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr smod(int a, expr const & b) { return smod(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief unsigned reminder operator for bitvectors
|
||||
*/
|
||||
inline expr urem(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvurem(a.ctx(), a, b)); }
|
||||
inline expr urem(expr const & a, int b) { return urem(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr urem(int a, expr const & b) { return urem(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief shift left operator for bitvectors
|
||||
*/
|
||||
inline expr shl(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvshl(a.ctx(), a, b)); }
|
||||
inline expr shl(expr const & a, int b) { return shl(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr shl(int a, expr const & b) { return shl(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief logic shift right operator for bitvectors
|
||||
*/
|
||||
inline expr lshr(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvlshr(a.ctx(), a, b)); }
|
||||
inline expr lshr(expr const & a, int b) { return lshr(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr lshr(int a, expr const & b) { return lshr(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief arithmetic shift right operator for bitvectors
|
||||
*/
|
||||
inline expr ashr(expr const & a, expr const & b) { return to_expr(a.ctx(), Z3_mk_bvashr(a.ctx(), a, b)); }
|
||||
inline expr ashr(expr const & a, int b) { return ashr(a, a.ctx().num_val(b, a.get_sort())); }
|
||||
inline expr ashr(int a, expr const & b) { return ashr(b.ctx().num_val(a, b.get_sort()), b); }
|
||||
|
||||
|
||||
/**
|
||||
\brief Extend the given bit-vector with zeros to the (unsigned) equivalent bitvector of size m+i, where m is the size of the given bit-vector.
|
||||
*/
|
||||
inline expr zext(expr const & a, unsigned i) { return to_expr(a.ctx(), Z3_mk_zero_ext(a.ctx(), i, a)); }
|
||||
|
||||
|
||||
/**
|
||||
\brief Sign-extend of the given bit-vector to the (signed) equivalent bitvector of size m+i, where m is the size of the given bit-vector.
|
||||
*/
|
||||
inline expr sext(expr const & a, unsigned i) { return to_expr(a.ctx(), Z3_mk_sign_ext(a.ctx(), i, a)); }
|
||||
|
||||
|
||||
template<typename T> class cast_ast;
|
||||
|
||||
template<> class cast_ast<ast> {
|
||||
|
@ -1563,7 +1680,7 @@ namespace z3 {
|
|||
unsigned m_index;
|
||||
public:
|
||||
iterator(ast_vector_tpl const* v, unsigned i): m_vector(v), m_index(i) {}
|
||||
iterator(iterator& other): m_vector(other.m_vector), m_index(other.m_index) {}
|
||||
iterator(iterator& other): m_vector(other.m_vector), m_index(other.m_index) {}
|
||||
iterator operator=(iterator const& other) { m_vector = other.m_vector; m_index = other.m_index; return *this; }
|
||||
|
||||
bool operator==(iterator const& other) {
|
||||
|
@ -1773,7 +1890,7 @@ namespace z3 {
|
|||
return expr(ctx, r);
|
||||
}
|
||||
|
||||
inline expr mk_or(expr_vector const& args) {
|
||||
inline expr mk_or(expr_vector const& args) {
|
||||
array<Z3_ast> _args(args);
|
||||
Z3_ast r = Z3_mk_or(args.ctx(), _args.size(), _args.ptr());
|
||||
args.check_error();
|
||||
|
@ -1852,7 +1969,7 @@ namespace z3 {
|
|||
model(context & c):object(c) { init(Z3_mk_model(c)); }
|
||||
model(context & c, Z3_model m):object(c) { init(m); }
|
||||
model(model const & s):object(s) { init(s.m_model); }
|
||||
model(model& src, context& dst, translate) : object(dst) { init(Z3_model_translate(src.ctx(), src, dst)); }
|
||||
model(model& src, context& dst, translate) : object(dst) { init(Z3_model_translate(src.ctx(), src, dst)); }
|
||||
~model() { Z3_model_dec_ref(ctx(), m_model); }
|
||||
operator Z3_model() const { return m_model; }
|
||||
model & operator=(model const & s) {
|
||||
|
@ -1884,7 +2001,7 @@ namespace z3 {
|
|||
}
|
||||
|
||||
// returns interpretation of constant declaration c.
|
||||
// If c is not assigned any value in the model it returns
|
||||
// If c is not assigned any value in the model it returns
|
||||
// an expression with a null ast reference.
|
||||
expr get_const_interp(func_decl c) const {
|
||||
check_context(*this, c);
|
||||
|
@ -1898,7 +2015,7 @@ namespace z3 {
|
|||
check_error();
|
||||
return func_interp(ctx(), r);
|
||||
}
|
||||
|
||||
|
||||
// returns true iff the model contains an interpretation
|
||||
// for function f.
|
||||
bool has_interp(func_decl f) const {
|
||||
|
@ -1945,7 +2062,7 @@ namespace z3 {
|
|||
bool is_uint(unsigned i) const { Z3_bool r = Z3_stats_is_uint(ctx(), m_stats, i); check_error(); return r != 0; }
|
||||
bool is_double(unsigned i) const { Z3_bool r = Z3_stats_is_double(ctx(), m_stats, i); check_error(); return r != 0; }
|
||||
unsigned uint_value(unsigned i) const { unsigned r = Z3_stats_get_uint_value(ctx(), m_stats, i); check_error(); return r; }
|
||||
double double_value(unsigned i) const { double r = Z3_stats_get_double_value(ctx(), m_stats, i); check_error(); return r; }
|
||||
double double_value(unsigned i) const { double r = Z3_stats_get_double_value(ctx(), m_stats, i); check_error(); return r; }
|
||||
friend std::ostream & operator<<(std::ostream & out, stats const & s);
|
||||
};
|
||||
inline std::ostream & operator<<(std::ostream & out, stats const & s) { out << Z3_stats_to_string(s.ctx(), s); return out; }
|
||||
|
@ -2001,7 +2118,7 @@ namespace z3 {
|
|||
void add(expr const & e, char const * p) {
|
||||
add(e, ctx().bool_const(p));
|
||||
}
|
||||
// fails for some compilers:
|
||||
// fails for some compilers:
|
||||
// void add(expr_vector const& v) { check_context(*this, v); for (expr e : v) add(e); }
|
||||
void from_file(char const* file) { Z3_solver_from_file(ctx(), m_solver, file); ctx().check_parser_error(); }
|
||||
void from_string(char const* s) { Z3_solver_from_string(ctx(), m_solver, s); ctx().check_parser_error(); }
|
||||
|
@ -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); }
|
||||
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 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); }
|
||||
friend std::ostream & operator<<(std::ostream & out, solver const & s);
|
||||
|
||||
|
@ -2064,11 +2183,11 @@ namespace z3 {
|
|||
param_descrs get_param_descrs() { return param_descrs(ctx(), Z3_solver_get_param_descrs(ctx(), m_solver)); }
|
||||
|
||||
|
||||
expr_vector cube(expr_vector& vars, unsigned cutoff) {
|
||||
Z3_ast_vector r = Z3_solver_cube(ctx(), m_solver, vars, cutoff);
|
||||
check_error();
|
||||
return expr_vector(ctx(), r);
|
||||
}
|
||||
expr_vector cube(expr_vector& vars, unsigned cutoff) {
|
||||
Z3_ast_vector r = Z3_solver_cube(ctx(), m_solver, vars, cutoff);
|
||||
check_error();
|
||||
return expr_vector(ctx(), r);
|
||||
}
|
||||
|
||||
class cube_iterator {
|
||||
solver& m_solver;
|
||||
|
@ -2116,7 +2235,7 @@ namespace z3 {
|
|||
cube_iterator operator++(int) { assert(false); return *this; }
|
||||
expr_vector const * operator->() const { return &(operator*()); }
|
||||
expr_vector const& operator*() const { return m_cube; }
|
||||
|
||||
|
||||
bool operator==(cube_iterator const& other) {
|
||||
return other.m_end == m_end;
|
||||
};
|
||||
|
@ -2405,7 +2524,7 @@ namespace z3 {
|
|||
|
||||
class optimize : public object {
|
||||
Z3_optimize m_opt;
|
||||
|
||||
|
||||
public:
|
||||
class handle {
|
||||
unsigned m_h;
|
||||
|
@ -2453,8 +2572,20 @@ namespace z3 {
|
|||
void pop() {
|
||||
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); }
|
||||
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(); }
|
||||
expr lower(handle const& h) {
|
||||
Z3_ast r = Z3_optimize_get_lower(ctx(), m_opt, h.h());
|
||||
|
@ -2481,25 +2612,25 @@ namespace z3 {
|
|||
public:
|
||||
fixedpoint(context& c):object(c) { m_fp = Z3_mk_fixedpoint(c); Z3_fixedpoint_inc_ref(c, m_fp); }
|
||||
~fixedpoint() { Z3_fixedpoint_dec_ref(ctx(), m_fp); }
|
||||
operator Z3_fixedpoint() const { return m_fp; }
|
||||
operator Z3_fixedpoint() const { return m_fp; }
|
||||
void from_string(char const* s) { Z3_fixedpoint_from_string(ctx(), m_fp, s); check_error(); }
|
||||
void from_file(char const* s) { Z3_fixedpoint_from_file(ctx(), m_fp, s); check_error(); }
|
||||
void add_rule(expr& rule, symbol const& name) { Z3_fixedpoint_add_rule(ctx(), m_fp, rule, name); check_error(); }
|
||||
void add_fact(func_decl& f, unsigned * args) { Z3_fixedpoint_add_fact(ctx(), m_fp, f, f.arity(), args); check_error(); }
|
||||
check_result query(expr& q) { Z3_lbool r = Z3_fixedpoint_query(ctx(), m_fp, q); check_error(); return to_check_result(r); }
|
||||
check_result query(func_decl_vector& relations) {
|
||||
check_result query(func_decl_vector& relations) {
|
||||
array<Z3_func_decl> rs(relations);
|
||||
Z3_lbool r = Z3_fixedpoint_query_relations(ctx(), m_fp, rs.size(), rs.ptr());
|
||||
check_error();
|
||||
return to_check_result(r);
|
||||
Z3_lbool r = Z3_fixedpoint_query_relations(ctx(), m_fp, rs.size(), rs.ptr());
|
||||
check_error();
|
||||
return to_check_result(r);
|
||||
}
|
||||
expr get_answer() { Z3_ast r = Z3_fixedpoint_get_answer(ctx(), m_fp); check_error(); return expr(ctx(), r); }
|
||||
std::string reason_unknown() { return Z3_fixedpoint_get_reason_unknown(ctx(), m_fp); }
|
||||
void update_rule(expr& rule, symbol const& name) { Z3_fixedpoint_update_rule(ctx(), m_fp, rule, name); check_error(); }
|
||||
unsigned get_num_levels(func_decl& p) { unsigned r = Z3_fixedpoint_get_num_levels(ctx(), m_fp, p); check_error(); return r; }
|
||||
expr get_cover_delta(int level, func_decl& p) {
|
||||
Z3_ast r = Z3_fixedpoint_get_cover_delta(ctx(), m_fp, level, p);
|
||||
check_error();
|
||||
expr get_cover_delta(int level, func_decl& p) {
|
||||
Z3_ast r = Z3_fixedpoint_get_cover_delta(ctx(), m_fp, level, p);
|
||||
check_error();
|
||||
return expr(ctx(), r);
|
||||
}
|
||||
void add_cover(int level, func_decl& p, expr& property) { Z3_fixedpoint_add_cover(ctx(), m_fp, level, p, property); check_error(); }
|
||||
|
@ -2513,7 +2644,7 @@ namespace z3 {
|
|||
std::string to_string() { return Z3_fixedpoint_to_string(ctx(), m_fp, 0, 0); }
|
||||
std::string to_string(expr_vector const& queries) {
|
||||
array<Z3_ast> qs(queries);
|
||||
return Z3_fixedpoint_to_string(ctx(), m_fp, qs.size(), qs.ptr());
|
||||
return Z3_fixedpoint_to_string(ctx(), m_fp, qs.size(), qs.ptr());
|
||||
}
|
||||
void push() { Z3_fixedpoint_push(ctx(), m_fp); check_error(); }
|
||||
void pop() { Z3_fixedpoint_pop(ctx(), m_fp); check_error(); }
|
||||
|
@ -2548,11 +2679,37 @@ 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::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::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_vector const& d, sort r) {
|
||||
array<Z3_sort> dom(d);
|
||||
Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s);
|
||||
Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s);
|
||||
}
|
||||
inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
|
||||
array<Z3_symbol> _enum_names(n);
|
||||
|
@ -2667,6 +2824,10 @@ namespace z3 {
|
|||
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::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)); }
|
||||
|
||||
|
@ -2688,12 +2849,15 @@ namespace z3 {
|
|||
inline expr context::bv_val(int64_t n, unsigned sz) { sort s = bv_sort(sz); Z3_ast r = Z3_mk_int64(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||
inline expr context::bv_val(uint64_t n, unsigned sz) { sort s = bv_sort(sz); Z3_ast r = Z3_mk_unsigned_int64(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||
inline expr context::bv_val(char const * n, unsigned sz) { sort s = bv_sort(sz); Z3_ast r = Z3_mk_numeral(m_ctx, n, s); check_error(); return expr(*this, r); }
|
||||
inline expr context::bv_val(unsigned n, bool const* bits) {
|
||||
inline expr context::bv_val(unsigned n, bool const* bits) {
|
||||
array<Z3_bool> _bits(n);
|
||||
for (unsigned i = 0; i < n; ++i) _bits[i] = bits[i] ? 1 : 0;
|
||||
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(std::string const& s) { Z3_ast r = Z3_mk_string(m_ctx, s.c_str()); check_error(); return expr(*this, r); }
|
||||
|
||||
|
@ -2817,8 +2981,8 @@ namespace z3 {
|
|||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
inline expr select(expr const & a, int i) {
|
||||
return select(a, a.ctx().num_val(i, a.get_sort().array_domain()));
|
||||
inline expr select(expr const & a, int i) {
|
||||
return select(a, a.ctx().num_val(i, a.get_sort().array_domain()));
|
||||
}
|
||||
inline expr select(expr const & a, expr_vector const & i) {
|
||||
check_context(a, i);
|
||||
|
@ -2848,10 +3012,10 @@ namespace z3 {
|
|||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr as_array(func_decl & f) {
|
||||
Z3_ast r = Z3_mk_as_array(f.ctx(), f);
|
||||
f.check_error();
|
||||
return expr(f.ctx(), r);
|
||||
inline expr as_array(func_decl & f) {
|
||||
Z3_ast r = Z3_mk_as_array(f.ctx(), f);
|
||||
f.check_error();
|
||||
return expr(f.ctx(), r);
|
||||
}
|
||||
|
||||
#define MK_EXPR1(_fn, _arg) \
|
||||
|
@ -2883,21 +3047,21 @@ namespace z3 {
|
|||
|
||||
inline expr set_del(expr const& s, expr const& e) {
|
||||
MK_EXPR2(Z3_mk_set_del, s, e);
|
||||
}
|
||||
}
|
||||
|
||||
inline expr set_union(expr const& a, expr const& b) {
|
||||
check_context(a, b);
|
||||
check_context(a, b);
|
||||
Z3_ast es[2] = { a, b };
|
||||
Z3_ast r = Z3_mk_set_union(a.ctx(), 2, es);
|
||||
a.check_error();
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr set_intersect(expr const& a, expr const& b) {
|
||||
check_context(a, b);
|
||||
check_context(a, b);
|
||||
Z3_ast es[2] = { a, b };
|
||||
Z3_ast r = Z3_mk_set_intersect(a.ctx(), 2, es);
|
||||
a.check_error();
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
|
@ -2981,10 +3145,10 @@ namespace z3 {
|
|||
MK_EXPR1(Z3_mk_re_complement, a);
|
||||
}
|
||||
inline expr range(expr const& lo, expr const& hi) {
|
||||
check_context(lo, hi);
|
||||
Z3_ast r = Z3_mk_re_range(lo.ctx(), lo, hi);
|
||||
lo.check_error();
|
||||
return expr(lo.ctx(), r);
|
||||
check_context(lo, hi);
|
||||
Z3_ast r = Z3_mk_re_range(lo.ctx(), lo, hi);
|
||||
lo.check_error();
|
||||
return expr(lo.ctx(), r);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2995,7 +3159,7 @@ namespace z3 {
|
|||
Z3_ast_vector r = Z3_parse_smtlib2_string(*this, s, 0, 0, 0, 0, 0, 0);
|
||||
check_error();
|
||||
return expr_vector(*this, r);
|
||||
|
||||
|
||||
}
|
||||
inline expr_vector context::parse_file(char const* s) {
|
||||
Z3_ast_vector r = Z3_parse_smtlib2_file(*this, s, 0, 0, 0, 0, 0, 0);
|
||||
|
|
|
@ -147,11 +147,6 @@ if (DOTNET_TOOLCHAIN_IS_WINDOWS)
|
|||
"/nostdlib+"
|
||||
"/reference:mscorlib.dll"
|
||||
)
|
||||
# FIXME: This flag only works when the working directory of csc.exe is
|
||||
# the directory containing the ``libz3`` target. I can't get this to work
|
||||
# correctly with multi-configuration generators (i.e. Visual Studio) so
|
||||
# just don't set the flag for now.
|
||||
#list(APPEND CSC_FLAGS "/linkresource:$<TARGET_FILE_NAME:libz3>")
|
||||
elseif (DOTNET_TOOLCHAIN_IS_MONO)
|
||||
# We need to give the assembly a strong name so that it can be installed
|
||||
# into the GAC.
|
||||
|
|
|
@ -183,9 +183,9 @@ namespace Microsoft.Z3
|
|||
/// don't use strict inequalities) meets the objectives.
|
||||
/// </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)
|
||||
{
|
||||
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>
|
||||
/// Declare an arithmetical maximization objective.
|
||||
/// Return a handle to the objective. The handle is used as
|
||||
|
|
|
@ -1976,6 +1976,22 @@ public class Context implements AutoCloseable {
|
|||
{
|
||||
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.
|
||||
|
|
|
@ -161,9 +161,23 @@ public class Optimize extends Z3Object {
|
|||
* Produce a model that (when the objectives are bounded and
|
||||
* 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) {
|
||||
case Z3_L_TRUE:
|
||||
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.
|
||||
* Return a handle to the objective. The handle is used as
|
||||
|
|
|
@ -43,6 +43,14 @@ let mk_list f n =
|
|||
in
|
||||
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 cfg = Z3native.mk_config () 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_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_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 compare (a:expr) (b:expr) = AST.compare a b
|
||||
end
|
||||
|
@ -1036,7 +1044,7 @@ struct
|
|||
let mk_mod = Z3native.mk_mod
|
||||
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_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_int2bv = Z3native.mk_int2bv
|
||||
end
|
||||
|
@ -1061,11 +1069,13 @@ struct
|
|||
let mk_numeral_nd (ctx:context) (num:int) (den:int) =
|
||||
if den = 0 then
|
||||
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
|
||||
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_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_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 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 mk_const (ctx:context) (name:Symbol.symbol) (size:int) =
|
||||
Expr.mk_const ctx name (mk_sort ctx size)
|
||||
|
@ -1810,8 +1815,10 @@ struct
|
|||
| _ -> UNKNOWN
|
||||
|
||||
let get_model x =
|
||||
let q = Z3native.solver_get_model (gc x) x in
|
||||
if Z3native.is_null_model q then None else Some q
|
||||
try
|
||||
let q = Z3native.solver_get_model (gc x) x in
|
||||
if Z3native.is_null_model q then None else Some q
|
||||
with | _ -> None
|
||||
|
||||
let get_proof x =
|
||||
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 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
|
||||
| L_TRUE -> Solver.SATISFIABLE
|
||||
| L_FALSE -> Solver.UNSATISFIABLE
|
||||
| _ -> Solver.UNKNOWN
|
||||
|
||||
let get_model (x:optimize) =
|
||||
let q = Z3native.optimize_get_model (gc x) x in
|
||||
if Z3native.is_null_model q then None else Some q
|
||||
try
|
||||
let q = Z3native.optimize_get_model (gc x) x in
|
||||
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_upper (x:handle) = Z3native.optimize_get_upper (gc x.opt) x.opt x.h
|
||||
|
|
|
@ -1152,9 +1152,6 @@ sig
|
|||
(** Create a new integer 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 *)
|
||||
val get_big_int : Expr.expr -> Big_int.big_int
|
||||
|
||||
|
@ -1543,9 +1540,6 @@ sig
|
|||
(** The size of a bit-vector sort. *)
|
||||
val get_size : Sort.sort -> int
|
||||
|
||||
(** Retrieve the int value. *)
|
||||
val get_int : Expr.expr -> int
|
||||
|
||||
(** Returns a string representation of a numeral. *)
|
||||
val numeral_to_string : Expr.expr -> string
|
||||
|
||||
|
@ -3413,10 +3407,10 @@ sig
|
|||
(** 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. *)
|
||||
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. *)
|
||||
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
|
||||
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ If you are using a 64-bit Python interpreter, you should use
|
|||
msbuild /p:configuration=external /p:platform=x64
|
||||
|
||||
|
||||
On Linux and OSX, you must install Z3Py, before trying example.py.
|
||||
To install Z3Py on Linux and OSX, you should execute the following
|
||||
On Linux and macOS, you must install Z3Py, before trying example.py.
|
||||
To install Z3Py on Linux and macOS, you should execute the following
|
||||
command in the Z3 root directory
|
||||
|
||||
sudo make install-z3py
|
||||
|
|
|
@ -73,7 +73,7 @@ def _build_z3():
|
|||
if subprocess.call(['nmake'], env=build_env,
|
||||
cwd=BUILD_DIR) != 0:
|
||||
raise LibError("Unable to build Z3.")
|
||||
else: # linux and osx
|
||||
else: # linux and macOS
|
||||
if subprocess.call(['make', '-j', str(multiprocessing.cpu_count())],
|
||||
env=build_env, cwd=BUILD_DIR) != 0:
|
||||
raise LibError("Unable to build Z3.")
|
||||
|
|
|
@ -1258,6 +1258,11 @@ def Consts(names, sort):
|
|||
names = names.split(" ")
|
||||
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):
|
||||
"""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())
|
||||
|
||||
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)
|
||||
|
||||
def is_forall(self):
|
||||
|
@ -2176,6 +2183,8 @@ class ArithRef(ExprRef):
|
|||
>>> (x * y).sort()
|
||||
Real
|
||||
"""
|
||||
if isinstance(other, BoolRef):
|
||||
return If(other, self, 0)
|
||||
a, b = _coerce_exprs(self, other)
|
||||
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.")
|
||||
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.
|
||||
|
||||
>>> A = ArraySort(IntSort(), BoolSort())
|
||||
|
@ -4292,12 +4301,23 @@ def ArraySort(d, r):
|
|||
>>> AA
|
||||
Array(Int, Array(Int, Bool))
|
||||
"""
|
||||
sig = _get_args(sig)
|
||||
if __debug__:
|
||||
_z3_assert(is_sort(d), "Z3 sort expected")
|
||||
_z3_assert(is_sort(r), "Z3 sort expected")
|
||||
_z3_assert(d.ctx == r.ctx, "Context mismatch")
|
||||
_z3_assert(len(sig) > 1, "At least two arguments expected")
|
||||
arity = len(sig) - 1
|
||||
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
|
||||
return ArraySortRef(Z3_mk_array_sort(ctx.ref(), d.ast, r.ast), ctx)
|
||||
if len(sig) == 2:
|
||||
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):
|
||||
"""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)
|
||||
|
||||
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)
|
||||
if vars is not None:
|
||||
for v in vars:
|
||||
|
@ -6619,19 +6644,15 @@ class Solver(Z3PPObject):
|
|||
return
|
||||
|
||||
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
|
||||
|
||||
def proof(self):
|
||||
"""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)
|
||||
|
||||
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):
|
||||
"""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)
|
||||
|
||||
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):
|
||||
"""Return statistics for the last `check()`.
|
||||
|
||||
|
@ -7285,10 +7311,15 @@ class Optimize(Z3PPObject):
|
|||
"""restore to previously created backtracking point"""
|
||||
Z3_optimize_pop(self.ctx.ref(), self.optimize)
|
||||
|
||||
def check(self):
|
||||
def check(self, *assumptions):
|
||||
"""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):
|
||||
"""Return a string that describes why the last `check()` returned `unknown`."""
|
||||
return Z3_optimize_get_reason_unknown(self.ctx.ref(), self.optimize)
|
||||
|
@ -7300,6 +7331,9 @@ class Optimize(Z3PPObject):
|
|||
except Z3Exception:
|
||||
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):
|
||||
if not isinstance(obj, OptimizeObjective):
|
||||
raise Z3Exception("Expecting objective handle returned by maximize/minimize")
|
||||
|
@ -8040,7 +8074,7 @@ def substitute(t, *m):
|
|||
"""
|
||||
if isinstance(m, tuple):
|
||||
m1 = _get_args(m)
|
||||
if isinstance(m1, list):
|
||||
if isinstance(m1, list) and all(isinstance(p, tuple) for p in m1):
|
||||
m = m1
|
||||
if __debug__:
|
||||
_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);
|
||||
|
||||
|
||||
/**
|
||||
\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.
|
||||
|
||||
|
|
|
@ -117,10 +117,12 @@ extern "C" {
|
|||
\brief Check consistency and produce optimal values.
|
||||
\param c - 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);
|
||||
|
||||
/**
|
||||
\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.
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ Revision History:
|
|||
#include "math/polynomial/algebraic_numbers.h"
|
||||
#include "util/id_gen.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "util/gparams.h"
|
||||
|
||||
struct arith_decl_plugin::algebraic_numbers_wrapper {
|
||||
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()) {
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -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()) {
|
||||
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));
|
||||
}
|
||||
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_DIV));
|
||||
op_names.push_back(builtin_name("div",OP_IDIV));
|
||||
// clashes with user-defined functions
|
||||
// op_names.push_back(builtin_name("divides",OP_IDIVIDES));
|
||||
if (gparams::get_value("smtlib2_compliant") == "true") {
|
||||
op_names.push_back(builtin_name("divisible",OP_IDIVIDES));
|
||||
}
|
||||
op_names.push_back(builtin_name("rem",OP_REM));
|
||||
op_names.push_back(builtin_name("mod",OP_MOD));
|
||||
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();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1656,6 +1656,12 @@ bool ast_manager::are_distinct(expr* a, expr* b) const {
|
|||
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) {
|
||||
SASSERT(m_plugins.get(id, 0) == 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_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; }
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ bool smt_renaming::all_is_legal(char const* s) {
|
|||
}
|
||||
|
||||
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]);
|
||||
m_translate.insert(s, sym_b(s, false));
|
||||
m_rev_translate.insert(s, s);
|
||||
|
|
|
@ -152,21 +152,13 @@ namespace format_ns {
|
|||
|
||||
format * mk_int(ast_manager & m, int i) {
|
||||
char buffer[128];
|
||||
#ifdef _WINDOWS
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%d", i);
|
||||
#else
|
||||
sprintf(buffer, "%d", i);
|
||||
#endif
|
||||
SPRINTF_D(buffer, i);
|
||||
return mk_string(m, buffer);
|
||||
}
|
||||
|
||||
format * mk_unsigned(ast_manager & m, unsigned u) {
|
||||
char buffer[128];
|
||||
#ifdef _WINDOWS
|
||||
sprintf_s(buffer, ARRAYSIZE(buffer), "%u", u);
|
||||
#else
|
||||
sprintf(buffer, "%u", u);
|
||||
#endif
|
||||
SPRINTF_U(buffer, u);
|
||||
return mk_string(m, buffer);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ Notes:
|
|||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/well_sorted.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/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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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-2, 0, bv_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;
|
||||
}
|
||||
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);
|
||||
flt_app = m_util.mk_bv2rm(bv_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;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -220,6 +220,8 @@ private:
|
|||
|
||||
func_decl * mk_bv_uf(func_decl * f, sort * const * domain, sort * range);
|
||||
expr_ref nan_wrap(expr * n);
|
||||
|
||||
expr_ref extra_quantify(expr * e);
|
||||
};
|
||||
|
||||
#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_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 {
|
||||
new_decl_sorts.push_back(s);
|
||||
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(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
|
||||
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)));
|
||||
}
|
||||
array_util autil(m);
|
||||
func_decl * f = 0;
|
||||
func_decl * f = nullptr;
|
||||
if (autil.is_as_array(n2, f)) {
|
||||
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;
|
||||
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 {
|
||||
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));
|
||||
ctx.set_print_success(ps);
|
||||
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
compile(*it);
|
||||
for (expr * e : ctx.assertions()) {
|
||||
compile(e);
|
||||
}
|
||||
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) {
|
||||
char buffer[128];
|
||||
#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
|
||||
sprintf(buffer, "proof_lemma_%d.smt2", m_proof_lemma_id);
|
||||
#endif
|
||||
|
|
|
@ -458,7 +458,7 @@ struct pb2bv_rewriter::imp {
|
|||
result = m.mk_true();
|
||||
expr_ref_vector carry(m), new_carry(m);
|
||||
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 d_i = (bound % b_i).get_unsigned();
|
||||
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) {
|
||||
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_info(m_family_id, OP_STRING_CONST, 1, ¶m));
|
||||
return m_manager->mk_const(f);
|
||||
|
|
|
@ -17,7 +17,7 @@ Notes:
|
|||
--*/
|
||||
#include "util/gparams.h"
|
||||
#include "util/env_params.h"
|
||||
#include "util/version.h"
|
||||
#include "util/z3_version.h"
|
||||
#include "ast/ast_smt_pp.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/ast_pp_dot.h"
|
||||
|
|
|
@ -1315,7 +1315,7 @@ void cmd_context::assert_expr(expr * t) {
|
|||
m().inc_ref(t);
|
||||
m_assertions.push_back(t);
|
||||
if (produce_unsat_cores())
|
||||
m_assertion_names.push_back(0);
|
||||
m_assertion_names.push_back(nullptr);
|
||||
if (m_solver)
|
||||
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_timer timer(timeout, &eh);
|
||||
scoped_rlimit _rlimit(m().limit(), rlimit);
|
||||
expr_ref_vector asms(m());
|
||||
asms.append(num_assumptions, assumptions);
|
||||
if (!m_processing_pareto) {
|
||||
ptr_vector<expr> cnstr(m_assertions);
|
||||
cnstr.append(num_assumptions, assumptions);
|
||||
get_opt()->set_hard_constraints(cnstr);
|
||||
expr_ref_vector assertions(m());
|
||||
unsigned sz = m_assertions.size();
|
||||
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 {
|
||||
r = get_opt()->optimize();
|
||||
r = get_opt()->optimize(asms);
|
||||
if (r == l_true && get_opt()->is_pareto()) {
|
||||
m_processing_pareto = true;
|
||||
}
|
||||
|
@ -1805,11 +1816,8 @@ void cmd_context::validate_model() {
|
|||
cancel_eh<reslimit> eh(m().limit());
|
||||
expr_ref r(m());
|
||||
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;
|
||||
for (; it != end; ++it) {
|
||||
expr * a = *it;
|
||||
for (expr * a : assertions()) {
|
||||
if (is_ground(a)) {
|
||||
r = nullptr;
|
||||
evaluator(a, r);
|
||||
|
|
|
@ -148,8 +148,8 @@ public:
|
|||
virtual bool empty() = 0;
|
||||
virtual void push() = 0;
|
||||
virtual void pop(unsigned n) = 0;
|
||||
virtual lbool optimize() = 0;
|
||||
virtual void set_hard_constraints(ptr_vector<expr> & hard) = 0;
|
||||
virtual lbool optimize(expr_ref_vector const& asms) = 0;
|
||||
virtual void set_hard_constraints(expr_ref_vector const & hard) = 0;
|
||||
virtual void display_assignment(std::ostream& out) = 0;
|
||||
virtual bool is_pareto() = 0;
|
||||
virtual void set_logic(symbol const& s) = 0;
|
||||
|
@ -452,11 +452,8 @@ public:
|
|||
|
||||
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_iterator end_assertions() const { return m_assertions.end(); }
|
||||
|
||||
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(); }
|
||||
ptr_vector<expr> const& assertions() const { return m_assertions; }
|
||||
ptr_vector<expr> const& assertion_names() const { return m_assertion_names; }
|
||||
|
||||
/**
|
||||
\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();
|
||||
bool proofs_enabled = t.proofs_enabled();
|
||||
if (ctx.produce_unsat_cores()) {
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
ptr_vector<expr>::const_iterator it2 = ctx.begin_assertion_names();
|
||||
SASSERT(end - it == ctx.end_assertion_names() - it2);
|
||||
ptr_vector<expr>::const_iterator it = ctx.assertions().begin();
|
||||
ptr_vector<expr>::const_iterator end = ctx.assertions().end();
|
||||
ptr_vector<expr>::const_iterator it2 = ctx.assertion_names().begin();
|
||||
SASSERT(ctx.assertions().size() == ctx.assertion_names().size());
|
||||
for (; it != end; ++it, ++it2) {
|
||||
t.assert_expr(*it, proofs_enabled ? m.mk_asserted(*it) : nullptr, m.mk_leaf(*it2));
|
||||
}
|
||||
}
|
||||
else {
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
t.assert_expr(*it, proofs_enabled ? m.mk_asserted(*it) : nullptr, nullptr);
|
||||
for (expr * e : ctx.assertions()) {
|
||||
t.assert_expr(e, proofs_enabled ? m.mk_asserted(e) : 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;
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace polynomial {
|
|||
|
||||
struct lt_var {
|
||||
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
|
||||
// two items at the same index instead of comparing
|
||||
// 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) {
|
||||
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";);
|
||||
|
||||
|
@ -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* v = get_const_interp(f);
|
||||
if (!v) return expr_ref(0, m);
|
||||
if (!v) return expr_ref(nullptr, m);
|
||||
top_sort st(m);
|
||||
expr_ref result1(v, m);
|
||||
expr_ref result2 = cleanup_expr(st, v, UINT_MAX);
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace datalog {
|
|||
rule_dependencies::rule_dependencies(const rule_dependencies & o, bool reversed):
|
||||
m_context(o.m_context) {
|
||||
if (reversed) {
|
||||
for (auto & kv : o) {
|
||||
for (auto & kv : o) {
|
||||
func_decl * pred = kv.m_key;
|
||||
item_set & orig_items = *kv.get_value();
|
||||
|
||||
|
@ -114,8 +114,8 @@ namespace datalog {
|
|||
app* a = to_app(e);
|
||||
d = a->get_decl();
|
||||
if (m_context.is_predicate(d)) {
|
||||
// insert d and ensure the invariant
|
||||
// that every predicate is present as
|
||||
// insert d and ensure the invariant
|
||||
// that every predicate is present as
|
||||
// a key in m_data
|
||||
s.insert(d);
|
||||
ensure_key(d);
|
||||
|
@ -148,7 +148,7 @@ namespace datalog {
|
|||
item_set& itms = *kv.get_value();
|
||||
set_intersection(itms, allowed);
|
||||
}
|
||||
for (func_decl* f : to_remove)
|
||||
for (func_decl* f : to_remove)
|
||||
remove_m_data_entry(f);
|
||||
}
|
||||
|
||||
|
@ -253,18 +253,18 @@ namespace datalog {
|
|||
//
|
||||
// -----------------------------------
|
||||
|
||||
rule_set::rule_set(context & ctx)
|
||||
: m_context(ctx),
|
||||
m_rule_manager(ctx.get_rule_manager()),
|
||||
m_rules(m_rule_manager),
|
||||
rule_set::rule_set(context & ctx)
|
||||
: m_context(ctx),
|
||||
m_rule_manager(ctx.get_rule_manager()),
|
||||
m_rules(m_rule_manager),
|
||||
m_deps(ctx),
|
||||
m_stratifier(nullptr),
|
||||
m_refs(ctx.get_manager()) {
|
||||
}
|
||||
|
||||
rule_set::rule_set(const rule_set & other)
|
||||
: m_context(other.m_context),
|
||||
m_rule_manager(other.m_rule_manager),
|
||||
rule_set::rule_set(const rule_set & other)
|
||||
: m_context(other.m_context),
|
||||
m_rule_manager(other.m_rule_manager),
|
||||
m_rules(m_rule_manager),
|
||||
m_deps(other.m_context),
|
||||
m_stratifier(nullptr),
|
||||
|
@ -353,10 +353,27 @@ namespace datalog {
|
|||
break; \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
DEL_VECTOR(*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() {
|
||||
if (!is_closed()) {
|
||||
|
@ -365,7 +382,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
bool rule_set::close() {
|
||||
SASSERT(!is_closed()); //the rule_set is not already closed
|
||||
SASSERT(!is_closed()); //the rule_set is not already closed
|
||||
m_deps.populate(*this);
|
||||
m_stratifier = alloc(rule_stratifier, m_deps);
|
||||
if (!stratified_negation()) {
|
||||
|
@ -426,7 +443,7 @@ namespace datalog {
|
|||
inherit_predicates(src);
|
||||
}
|
||||
|
||||
const rule_vector & rule_set::get_predicate_rules(func_decl * pred) const {
|
||||
const rule_vector & rule_set::get_predicate_rules(func_decl * pred) const {
|
||||
decl2rules::obj_map_entry * e = m_head2rules.find_core(pred);
|
||||
if (!e) {
|
||||
return m_empty_rule_vector;
|
||||
|
@ -519,7 +536,7 @@ namespace datalog {
|
|||
out << "\n";
|
||||
non_empty = false;
|
||||
}
|
||||
|
||||
|
||||
for (func_decl * first : *strat) {
|
||||
const func_decl_set & deps = m_deps.get_deps(first);
|
||||
for (func_decl * dep : deps) {
|
||||
|
@ -545,8 +562,8 @@ namespace datalog {
|
|||
unsigned rule_stratifier::get_predicate_strat(func_decl * pred) const {
|
||||
unsigned num;
|
||||
if (!m_pred_strat_nums.find(pred, num)) {
|
||||
//the number of the predicate is not stored, therefore it did not appear
|
||||
//in the algorithm and therefore it does not depend on anything and nothing
|
||||
//the number of the predicate is not stored, therefore it did not appear
|
||||
//in the algorithm and therefore it does not depend on anything and nothing
|
||||
//depends on it. So it is safe to assign zero strate to it, although it is
|
||||
//not strictly true.
|
||||
num = 0;
|
||||
|
@ -641,7 +658,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
|
||||
// We put components whose indegree is zero to m_strats and assign its
|
||||
// We put components whose indegree is zero to m_strats and assign its
|
||||
// m_components entry to zero.
|
||||
unsigned comp_cnt = m_components.size();
|
||||
for (unsigned i = 0; i < comp_cnt; i++) {
|
||||
|
@ -680,7 +697,7 @@ namespace datalog {
|
|||
strats_index++;
|
||||
}
|
||||
//we have managed to topologicaly order all the components
|
||||
SASSERT(std::find_if(m_components.begin(), m_components.end(),
|
||||
SASSERT(std::find_if(m_components.begin(), m_components.end(),
|
||||
std::bind1st(std::not_equal_to<item_set*>(), (item_set*)0)) == m_components.end());
|
||||
|
||||
//reverse the strats array, so that the only the later components would depend on earlier ones
|
||||
|
@ -713,7 +730,7 @@ namespace datalog {
|
|||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace datalog {
|
|||
\brief Number of predicates that depend on \c f.
|
||||
*/
|
||||
unsigned out_degree(func_decl * f) const;
|
||||
|
||||
|
||||
/**
|
||||
\brief If the rependency graph is acyclic, put all elements into \c res
|
||||
ordered so that elements can depend only on elements that are before them.
|
||||
|
@ -131,7 +131,7 @@ namespace datalog {
|
|||
it must exist for the whole lifetime of the \c stratifier object.
|
||||
*/
|
||||
rule_stratifier(const rule_dependencies & deps)
|
||||
: m_deps(deps), m_next_preorder(0)
|
||||
: m_deps(deps), m_next_preorder(0)
|
||||
{
|
||||
process();
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ namespace datalog {
|
|||
const comp_vector & get_strats() const { return m_strats; }
|
||||
|
||||
unsigned get_predicate_strat(func_decl * pred) const;
|
||||
|
||||
|
||||
void display( std::ostream & out ) const;
|
||||
};
|
||||
|
||||
|
@ -203,6 +203,10 @@ namespace datalog {
|
|||
\brief Remove rule \c r from the rule set.
|
||||
*/
|
||||
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.
|
||||
|
@ -276,8 +280,7 @@ namespace datalog {
|
|||
inline std::ostream& operator<<(std::ostream& out, rule_set const& r) { r.display(out); return out; }
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* DL_RULE_SET_H_ */
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ namespace datalog {
|
|||
}
|
||||
unsigned n = container.size();
|
||||
unsigned ofs = 1;
|
||||
int r_i = 1;
|
||||
unsigned r_i = 1;
|
||||
for(unsigned i=removed_cols[0]+1; i<n; i++) {
|
||||
if(r_i!=removed_col_cnt && removed_cols[r_i]==i) {
|
||||
r_i++;
|
||||
|
|
|
@ -177,5 +177,6 @@ def_module_params('fp',
|
|||
('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.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:
|
||||
void set_background(cmd_context& ctx) {
|
||||
datalog::context& dlctx = m_dl_ctx->dlctx();
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
dlctx.assert_expr(*it);
|
||||
for (expr * e : ctx.assertions()) {
|
||||
dlctx.assert_expr(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -493,7 +493,8 @@ lemma::lemma (ast_manager &manager, expr * body, unsigned lvl) :
|
|||
m_pob(nullptr), m_ctp(nullptr),
|
||||
m_lvl(lvl), m_init_lvl(m_lvl),
|
||||
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);
|
||||
normalize(m_body, m_body);
|
||||
}
|
||||
|
@ -505,7 +506,8 @@ lemma::lemma(pob_ref const &p) :
|
|||
m_pob(p), m_ctp(nullptr),
|
||||
m_lvl(p->level()), m_init_lvl(m_lvl),
|
||||
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);
|
||||
m_pob->get_skolems(m_zks);
|
||||
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_lvl(p->level()), m_init_lvl(m_lvl),
|
||||
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) {
|
||||
m_pob->get_skolems(m_zks);
|
||||
add_binding(m_pob->get_binding());
|
||||
|
@ -921,10 +923,10 @@ void pred_transformer::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);
|
||||
m_frames.get_frame_geq_lemmas (level, res);
|
||||
m_frames.get_frame_geq_lemmas (level, res, bg);
|
||||
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
|
||||
void pred_transformer::add_lemma_core(lemma* lemma, bool ground_only)
|
||||
{
|
||||
SASSERT(!lemma->is_background());
|
||||
unsigned lvl = lemma->level();
|
||||
expr* l = lemma->get_expr();
|
||||
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); }
|
||||
}
|
||||
|
||||
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);
|
||||
lem->set_background(bg);
|
||||
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.
|
||||
expr_ref result(property, m), v(m), c(m);
|
||||
expr_substitution sub(m);
|
||||
proof_ref pr(m);
|
||||
pr = m.mk_asserted(m.mk_true());
|
||||
for (unsigned i = 0; i < sig_size(); ++i) {
|
||||
c = m.mk_const(pm.o2n(sig(i), 0));
|
||||
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);
|
||||
rep->set_substitution(&sub);
|
||||
|
@ -1236,13 +1243,38 @@ void pred_transformer::add_cover(unsigned level, expr* property)
|
|||
expr_ref_vector lemmas(m);
|
||||
flatten_and(result, lemmas);
|
||||
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)
|
||||
{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
|
||||
|
@ -1293,7 +1325,7 @@ bool pred_transformer::is_qblocked (pob &n) {
|
|||
|
||||
// assert cti
|
||||
s->assert_expr(n.post());
|
||||
lbool res = s->check_sat(0, 0);
|
||||
lbool res = s->check_sat(0, nullptr);
|
||||
|
||||
// if (res == l_false) {
|
||||
// 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);
|
||||
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
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
|
@ -1482,8 +1522,8 @@ bool pred_transformer::is_invariant(unsigned level, lemma* lem,
|
|||
lemma_expr = gnd_lemma.get();
|
||||
}
|
||||
|
||||
conj.push_back(mk_not(m, lemma_expr));
|
||||
flatten_and (conj);
|
||||
cand.push_back(mk_not(m, lemma_expr));
|
||||
flatten_and (cand);
|
||||
|
||||
prop_solver::scoped_level _sl(*m_solver, level);
|
||||
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;}
|
||||
m_solver->set_core(core);
|
||||
m_solver->set_model(mdl_ref_ptr);
|
||||
expr * bg = m_extend_lit.get ();
|
||||
lbool r = m_solver->check_assumptions (conj, aux, m_transition_clause,
|
||||
1, &bg, 1);
|
||||
|
||||
conj.push_back(m_extend_lit);
|
||||
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) {
|
||||
solver_level = m_solver->uses_level ();
|
||||
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_model (nullptr);
|
||||
expr_ref_vector aux (m);
|
||||
if (ctx.use_bg_invs()) get_pred_bg_invs(conj);
|
||||
conj.push_back (m_extend_lit);
|
||||
lbool res = m_solver->check_assumptions (state, aux,
|
||||
m_transition_clause,
|
||||
|
@ -1941,14 +1985,27 @@ void pred_transformer::update_solver_with_rfs(prop_solver *solver,
|
|||
}
|
||||
|
||||
/// pred_transformer::frames
|
||||
|
||||
|
||||
bool pred_transformer::frames::add_lemma(lemma *new_lemma)
|
||||
{
|
||||
TRACE("spacer", tout << "add-lemma: " << pp_level(new_lemma->level()) << " "
|
||||
<< m_pt.head()->get_name() << " "
|
||||
<< 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;
|
||||
for (auto *old_lemma : m_lemmas) {
|
||||
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_restart_initial_threshold = m_params.spacer_restart_initial_threshold();
|
||||
m_pdr_bfs = m_params.spacer_gpdr_bfs();
|
||||
m_use_bg_invs = m_params.spacer_use_bg_invs();
|
||||
|
||||
if (m_use_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)) {
|
||||
return pt->get_cover_delta(p_orig, level);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (!m_rels.find(p, pt)) {
|
||||
pt = alloc(pred_transformer, *this, get_manager(), p);
|
||||
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);
|
||||
pt->add_cover(lvl, property);
|
||||
pt->add_cover(lvl, property, bg);
|
||||
}
|
||||
|
||||
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;
|
||||
if (!m_rels.find(p, pt))
|
||||
{ return expr_ref(m.mk_false(), m); }
|
||||
return pt->get_reachable();
|
||||
}
|
||||
|
||||
bool context::validate()
|
||||
{
|
||||
bool context::validate() {
|
||||
if (!m_validate_result) { return true; }
|
||||
|
||||
std::stringstream msg;
|
||||
|
@ -2483,7 +2543,7 @@ bool context::validate()
|
|||
model_ref model;
|
||||
vector<relation_info> rs;
|
||||
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);
|
||||
ex.to_model(model);
|
||||
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,
|
||||
vector<relation_info>& rs) const {
|
||||
vector<relation_info>& rs, bool with_bg) const {
|
||||
for (auto const& kv : m_rels) {
|
||||
pred_transformer* r = kv.m_value;
|
||||
if (r->head() == m_query_pred) {
|
||||
continue;
|
||||
}
|
||||
expr_ref conj = r->get_formulas(lvl);
|
||||
expr_ref conj = r->get_formulas(lvl, with_bg);
|
||||
m_pm.formula_n2o(0, false, conj);
|
||||
res.push_back(conj);
|
||||
ptr_vector<func_decl> sig(r->head()->get_arity(), r->sig());
|
||||
|
@ -2662,7 +2722,7 @@ lbool context::solve(unsigned from_lvl)
|
|||
IF_VERBOSE(1, {
|
||||
expr_ref_vector refs(m);
|
||||
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;
|
||||
inductive_property ex(m, mc, rs);
|
||||
verbose_stream() << ex.to_string();
|
||||
|
@ -2844,7 +2904,7 @@ model_ref context::get_model()
|
|||
model_ref model;
|
||||
expr_ref_vector refs(m);
|
||||
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);
|
||||
ex.to_model (model);
|
||||
return model;
|
||||
|
@ -2877,7 +2937,7 @@ expr_ref context::mk_unsat_answer() const
|
|||
{
|
||||
expr_ref_vector refs(m);
|
||||
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);
|
||||
return ex.to_expr();
|
||||
}
|
||||
|
|
|
@ -128,8 +128,9 @@ class lemma {
|
|||
unsigned m_init_lvl; // level at which lemma was created
|
||||
unsigned m_bumped:16;
|
||||
unsigned m_weakness:16;
|
||||
unsigned m_external:1;
|
||||
unsigned m_blocked:1;
|
||||
unsigned m_external:1; // external lemma from another solver
|
||||
unsigned m_blocked:1; // blocked by CTP
|
||||
unsigned m_background:1; // background assumed fact
|
||||
|
||||
void mk_expr_core();
|
||||
void mk_cube_core();
|
||||
|
@ -163,6 +164,9 @@ public:
|
|||
void set_external(bool ext){m_external = ext;}
|
||||
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;}
|
||||
void set_blocked(bool v) {m_blocked=v;}
|
||||
|
||||
|
@ -222,6 +226,7 @@ class pred_transformer {
|
|||
pred_transformer &m_pt; // parent pred_transformer
|
||||
lemma_ref_vector m_pinned_lemmas; // all created lemmas
|
||||
lemma_ref_vector m_lemmas; // active lemmas
|
||||
lemma_ref_vector m_bg_invs; // background (assumed) invariants
|
||||
unsigned m_size; // num of frames
|
||||
|
||||
bool m_sorted; // true if m_lemmas is sorted by m_lt
|
||||
|
@ -230,7 +235,8 @@ class pred_transformer {
|
|||
void sort ();
|
||||
|
||||
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() {}
|
||||
void simplify_formulas ();
|
||||
|
||||
|
@ -245,17 +251,25 @@ 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) {
|
||||
if (lemma->level() >= level) {
|
||||
out.push_back(lemma->get_expr());
|
||||
}
|
||||
}
|
||||
if (with_bg) {
|
||||
for (auto &lemma : m_bg_invs)
|
||||
out.push_back(lemma->get_expr());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned size () const {return m_size;}
|
||||
unsigned lemma_size () const {return m_lemmas.size ();}
|
||||
void add_frame () {m_size++;}
|
||||
const lemma_ref_vector& get_bg_invs() const {return m_bg_invs;}
|
||||
unsigned size() const {return m_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 inherit_frames (frames &other) {
|
||||
for (auto &other_lemma : other.m_lemmas) {
|
||||
lemma_ref new_lemma = alloc(lemma, m_pt.get_ast_manager(),
|
||||
|
@ -265,6 +279,7 @@ class pred_transformer {
|
|||
add_lemma(new_lemma.get());
|
||||
}
|
||||
m_sorted = false;
|
||||
m_bg_invs.append(other.m_bg_invs);
|
||||
}
|
||||
|
||||
bool add_lemma (lemma *new_lemma);
|
||||
|
@ -418,6 +433,11 @@ class pred_transformer {
|
|||
|
||||
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:
|
||||
pred_transformer(context& ctx, manager& pm, func_decl* head);
|
||||
~pred_transformer() {}
|
||||
|
@ -448,7 +468,7 @@ public:
|
|||
}
|
||||
unsigned get_num_levels() const {return m_frames.size ();}
|
||||
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();
|
||||
|
||||
std::ostream& display(std::ostream& strm) const;
|
||||
|
@ -484,7 +504,7 @@ public:
|
|||
bool propagate_to_next_level(unsigned level);
|
||||
void propagate_to_infinity(unsigned level);
|
||||
/// \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);}
|
||||
expr* get_reach_case_var (unsigned idx) const;
|
||||
bool has_rfs () const { return !m_reach_facts.empty () ;}
|
||||
|
@ -527,7 +547,7 @@ public:
|
|||
bool check_inductive(unsigned level, expr_ref_vector& state,
|
||||
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();
|
||||
|
||||
|
@ -958,6 +978,7 @@ class context {
|
|||
bool m_simplify_formulas_pre;
|
||||
bool m_simplify_formulas_post;
|
||||
bool m_pdr_bfs;
|
||||
bool m_use_bg_invs;
|
||||
unsigned m_push_pob_max_depth;
|
||||
unsigned m_max_level;
|
||||
unsigned m_restart_initial_threshold;
|
||||
|
@ -992,7 +1013,8 @@ class context {
|
|||
|
||||
// Generate inductive property
|
||||
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
|
||||
|
@ -1027,18 +1049,20 @@ public:
|
|||
|
||||
|
||||
const fp_params &get_params() const { return m_params; }
|
||||
bool use_native_mbp () {return m_use_native_mbp;}
|
||||
bool use_ground_pob () {return m_ground_pob;}
|
||||
bool use_instantiate () {return m_instantiate;}
|
||||
bool weak_abs() {return m_weak_abs;}
|
||||
bool use_qlemmas () {return m_use_qlemmas;}
|
||||
bool use_euf_gen() {return m_use_euf_gen;}
|
||||
bool simplify_pob() {return m_simplify_pob;}
|
||||
bool use_ctp() {return m_use_ctp;}
|
||||
bool use_inc_clause() {return m_use_inc_clause;}
|
||||
unsigned blast_term_ite_inflation() {return m_blast_term_ite_inflation;}
|
||||
bool elim_aux() {return m_elim_aux;}
|
||||
bool reach_dnf() {return m_reach_dnf;}
|
||||
bool use_eq_prop() const {return m_use_eq_prop;}
|
||||
bool use_native_mbp() const {return m_use_native_mbp;}
|
||||
bool use_ground_pob() const {return m_ground_pob;}
|
||||
bool use_instantiate() const {return m_instantiate;}
|
||||
bool weak_abs() const {return m_weak_abs;}
|
||||
bool use_qlemmas() const {return m_use_qlemmas;}
|
||||
bool use_euf_gen() const {return m_use_euf_gen;}
|
||||
bool simplify_pob() const {return m_simplify_pob;}
|
||||
bool use_ctp() const {return m_use_ctp;}
|
||||
bool use_inc_clause() const {return m_use_inc_clause;}
|
||||
unsigned blast_term_ite_inflation() const {return m_blast_term_ite_inflation;}
|
||||
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;}
|
||||
manager& get_manager() {return m_pm;}
|
||||
|
@ -1081,7 +1105,7 @@ public:
|
|||
unsigned get_num_levels(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);
|
||||
void add_invariant (func_decl *pred, expr* property);
|
||||
model_ref get_model();
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace{
|
|||
contains_array_op_proc(ast_manager &manager) :
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -117,11 +117,11 @@ class lemma_quantifier_generalizer : public lemma_generalizer {
|
|||
int m_offset;
|
||||
public:
|
||||
lemma_quantifier_generalizer(context &ctx, bool normalize_cube = true);
|
||||
virtual ~lemma_quantifier_generalizer() {}
|
||||
virtual void operator()(lemma_ref &lemma);
|
||||
~lemma_quantifier_generalizer() override {}
|
||||
void operator()(lemma_ref &lemma) override;
|
||||
|
||||
virtual void collect_statistics(statistics& st) const;
|
||||
virtual void reset_statistics() {m_st.reset();}
|
||||
void collect_statistics(statistics& st) const override;
|
||||
void reset_statistics() override {m_st.reset();}
|
||||
private:
|
||||
bool generalize(lemma_ref &lemma, app *term);
|
||||
|
||||
|
|
|
@ -600,7 +600,7 @@ namespace spacer {
|
|||
proof* hypothesis_reducer::reduce_core(proof* pf) {
|
||||
SASSERT(m.is_false(m.get_fact(pf)));
|
||||
|
||||
proof *res = NULL;
|
||||
proof *res = nullptr;
|
||||
|
||||
ptr_vector<proof> todo;
|
||||
todo.push_back(pf);
|
||||
|
|
|
@ -94,6 +94,7 @@ void prop_solver::add_level()
|
|||
|
||||
void prop_solver::ensure_level(unsigned lvl)
|
||||
{
|
||||
if (is_infty_level(lvl)) return;
|
||||
while (lvl >= level_cnt()) {
|
||||
add_level();
|
||||
}
|
||||
|
|
|
@ -48,7 +48,8 @@ namespace spacer {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -25,6 +25,7 @@ z3_add_component(transforms
|
|||
dl_mk_array_eq_rewrite.cpp
|
||||
dl_mk_array_instantiation.cpp
|
||||
dl_mk_elim_term_ite.cpp
|
||||
dl_mk_synchronize.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
dataflow
|
||||
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) {
|
||||
return
|
||||
|
@ -332,7 +332,7 @@ public:
|
|||
}
|
||||
|
||||
|
||||
virtual lbool operator()() {
|
||||
lbool operator()() override {
|
||||
m_defs.reset();
|
||||
switch(m_st) {
|
||||
case s_primal:
|
||||
|
@ -343,7 +343,7 @@ public:
|
|||
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-correction-sets", m_stats.m_num_cs);
|
||||
}
|
||||
|
@ -781,7 +781,7 @@ public:
|
|||
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);
|
||||
opt_params p(_p);
|
||||
m_hill_climb = p.maxres_hill_climb();
|
||||
|
@ -816,7 +816,7 @@ public:
|
|||
return l_true;
|
||||
}
|
||||
|
||||
virtual void commit_assignment() {
|
||||
void commit_assignment() override {
|
||||
if (m_found_feasible_optimum) {
|
||||
TRACE("opt", tout << "Committing feasible solution\n" << m_defs << " " << m_asms;);
|
||||
s().assert_expr(m_defs);
|
||||
|
|
|
@ -56,33 +56,33 @@ public:
|
|||
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_formula = nullptr;
|
||||
}
|
||||
|
||||
virtual char const * get_usage() const { 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_usage() const override { return "<formula> [:weight <rational-weight>] [:id <symbol>]"; }
|
||||
char const * get_main_descr() const override { return "assert soft constraint with optional weight and identifier"; }
|
||||
|
||||
// command invocation
|
||||
virtual void prepare(cmd_context & ctx) {
|
||||
void prepare(cmd_context & ctx) override {
|
||||
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;
|
||||
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("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);
|
||||
if (!ctx.m().is_bool(t)) {
|
||||
throw cmd_exception("Invalid type for expression. Expected Boolean type.");
|
||||
|
@ -91,11 +91,11 @@ public:
|
|||
++m_idx;
|
||||
}
|
||||
|
||||
virtual void failure_cleanup(cmd_context & ctx) {
|
||||
void failure_cleanup(cmd_context & ctx) override {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
void execute(cmd_context & ctx) override {
|
||||
if (!m_formula) {
|
||||
throw cmd_exception("assert-soft requires a formulas as argument.");
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public:
|
|||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void finalize(cmd_context & ctx) {
|
||||
void finalize(cmd_context & ctx) override {
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -123,14 +123,14 @@ public:
|
|||
m_opt(opt)
|
||||
{}
|
||||
|
||||
virtual void reset(cmd_context & ctx) { }
|
||||
virtual char const * get_usage() const { return "<term>"; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "check sat modulo objective function";}
|
||||
virtual unsigned get_arity() const { return 1; }
|
||||
virtual void prepare(cmd_context & ctx) {}
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_EXPR; }
|
||||
void reset(cmd_context & ctx) override { }
|
||||
char const * get_usage() const override { return "<term>"; }
|
||||
char const * get_descr(cmd_context & ctx) const override { return "check sat modulo objective function";}
|
||||
unsigned get_arity() const override { return 1; }
|
||||
void prepare(cmd_context & ctx) override {}
|
||||
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)) {
|
||||
throw cmd_exception("malformed objective term: it cannot be a quantifier or bound variable");
|
||||
}
|
||||
|
@ -138,11 +138,11 @@ public:
|
|||
ctx.print_success();
|
||||
}
|
||||
|
||||
virtual void failure_cleanup(cmd_context & ctx) {
|
||||
void failure_cleanup(cmd_context & ctx) override {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
void execute(cmd_context & ctx) override {
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -154,18 +154,18 @@ public:
|
|||
m_opt(opt)
|
||||
{}
|
||||
|
||||
virtual void reset(cmd_context & ctx) { }
|
||||
virtual char const * get_usage() const { return "(get-objectives)"; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "retrieve the objective values (after optimization)"; }
|
||||
virtual unsigned get_arity() const { return 0; }
|
||||
virtual void prepare(cmd_context & ctx) {}
|
||||
void reset(cmd_context & ctx) override { }
|
||||
char const * get_usage() const override { return "(get-objectives)"; }
|
||||
char const * get_descr(cmd_context & ctx) const override { return "retrieve the objective values (after optimization)"; }
|
||||
unsigned get_arity() const override { return 0; }
|
||||
void prepare(cmd_context & ctx) override {}
|
||||
|
||||
|
||||
virtual void failure_cleanup(cmd_context & ctx) {
|
||||
void failure_cleanup(cmd_context & ctx) override {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
void execute(cmd_context & ctx) override {
|
||||
if (!ctx.ignore_check()) {
|
||||
get_opt(ctx, m_opt).display_assignment(ctx.regular_stream());
|
||||
}
|
||||
|
|
|
@ -79,13 +79,13 @@ namespace opt {
|
|||
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();
|
||||
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.append(hard.size(), hard.c_ptr());
|
||||
m_hard.append(hard);
|
||||
return !eq;
|
||||
}
|
||||
|
||||
|
@ -130,6 +130,7 @@ namespace opt {
|
|||
m_fm(alloc(generic_model_converter, m, "opt")),
|
||||
m_model_fixed(),
|
||||
m_objective_refs(m),
|
||||
m_core(m),
|
||||
m_enable_sat(false),
|
||||
m_is_clausal(false),
|
||||
m_pp_neat(false),
|
||||
|
@ -173,11 +174,10 @@ namespace opt {
|
|||
}
|
||||
|
||||
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(ptr_vector<expr>& fmls) {
|
||||
void context::set_hard_constraints(expr_ref_vector const& fmls) {
|
||||
if (m_scoped_state.set(fmls)) {
|
||||
clear_state();
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ namespace opt {
|
|||
m_hard_constraints.append(s.m_hard);
|
||||
}
|
||||
|
||||
lbool context::optimize() {
|
||||
lbool context::optimize(expr_ref_vector const& asms) {
|
||||
if (m_pareto) {
|
||||
return execute_pareto();
|
||||
}
|
||||
|
@ -263,7 +263,10 @@ namespace opt {
|
|||
clear_state();
|
||||
init_solver();
|
||||
import_scoped_state();
|
||||
normalize();
|
||||
normalize(asms);
|
||||
if (m_hard_constraints.size() == 1 && m.is_false(m_hard_constraints.get(0))) {
|
||||
return l_false;
|
||||
}
|
||||
internalize();
|
||||
update_solver();
|
||||
if (contains_quantifiers()) {
|
||||
|
@ -281,7 +284,7 @@ namespace opt {
|
|||
symbol pri = optp.priority();
|
||||
|
||||
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"););
|
||||
if (is_sat != l_false) {
|
||||
s.get_model(m_model);
|
||||
|
@ -289,7 +292,10 @@ namespace opt {
|
|||
model_updated(m_model.get());
|
||||
}
|
||||
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;
|
||||
}
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:sat)\n");
|
||||
|
@ -479,7 +485,6 @@ namespace opt {
|
|||
return r;
|
||||
}
|
||||
|
||||
|
||||
expr_ref context::mk_le(unsigned i, model_ref& mdl) {
|
||||
objective const& obj = m_objectives[i];
|
||||
return mk_cmp(false, mdl, obj);
|
||||
|
@ -489,8 +494,7 @@ namespace opt {
|
|||
objective const& obj = m_objectives[i];
|
||||
return mk_cmp(true, mdl, obj);
|
||||
}
|
||||
|
||||
|
||||
|
||||
expr_ref context::mk_gt(unsigned i, model_ref& mdl) {
|
||||
expr_ref result = mk_le(i, mdl);
|
||||
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);
|
||||
}
|
||||
|
||||
void context::normalize() {
|
||||
void context::normalize(expr_ref_vector const& asms) {
|
||||
expr_ref_vector fmls(m);
|
||||
to_fmls(fmls);
|
||||
simplify_fmls(fmls);
|
||||
simplify_fmls(fmls, asms);
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
goal_ref g(alloc(goal, m, true, false));
|
||||
goal_ref g(alloc(goal, m, true, !asms.empty()));
|
||||
for (expr* fml : fmls) {
|
||||
g->assert_expr(fml);
|
||||
}
|
||||
for (expr * a : asms) {
|
||||
g->assert_expr(a, a);
|
||||
}
|
||||
tactic_ref tac0 =
|
||||
and_then(mk_simplify_tactic(m, m_params),
|
||||
mk_propagate_values_tactic(m),
|
||||
|
@ -788,6 +795,7 @@ namespace opt {
|
|||
set_simplify(tac0.get());
|
||||
}
|
||||
goal_ref_buffer result;
|
||||
TRACE("opt", g->display(tout););
|
||||
(*m_simplify)(g, result);
|
||||
SASSERT(result.size() == 1);
|
||||
goal* r = result[0];
|
||||
|
@ -795,8 +803,27 @@ namespace opt {
|
|||
fmls.reset();
|
||||
expr_ref tmp(m);
|
||||
for (unsigned i = 0; i < r->size(); ++i) {
|
||||
fmls.push_back(r->form(i));
|
||||
if (asms.empty()) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
bool context::is_maximize(expr* fml, app_ref& term, expr_ref& orig_term, unsigned& index) {
|
||||
|
@ -1084,11 +1111,7 @@ namespace opt {
|
|||
}
|
||||
term = m_arith.mk_add(args.size(), args.c_ptr());
|
||||
}
|
||||
else if (m_arith.is_arith_expr(term) && !is_mul_const(term)) {
|
||||
TRACE("opt", tout << "Purifying " << term << "\n";);
|
||||
term = purify(fm, term);
|
||||
}
|
||||
else if (m.is_ite(term)) {
|
||||
else if (m.is_ite(term) || !is_mul_const(term)) {
|
||||
TRACE("opt", tout << "Purifying " << term << "\n";);
|
||||
term = purify(fm, term);
|
||||
}
|
||||
|
@ -1399,6 +1422,7 @@ namespace opt {
|
|||
m_box_index = UINT_MAX;
|
||||
m_model.reset();
|
||||
m_model_fixed.reset();
|
||||
m_core.reset();
|
||||
}
|
||||
|
||||
void context::set_pareto(pareto_base* p) {
|
||||
|
|
|
@ -133,7 +133,7 @@ namespace opt {
|
|||
void push();
|
||||
void pop();
|
||||
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(app* obj, bool is_max);
|
||||
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, expr*> m_objective_orig;
|
||||
func_decl_ref_vector m_objective_refs;
|
||||
expr_ref_vector m_core;
|
||||
tactic_ref m_simplify;
|
||||
bool m_enable_sat;
|
||||
bool m_enable_sls;
|
||||
|
@ -186,8 +187,8 @@ namespace opt {
|
|||
void push() override;
|
||||
void pop(unsigned n) override;
|
||||
bool empty() override { return m_scoped_state.m_objectives.empty(); }
|
||||
void set_hard_constraints(ptr_vector<expr> & hard) override;
|
||||
lbool optimize() override;
|
||||
void set_hard_constraints(expr_ref_vector const& hard) override;
|
||||
lbool optimize(expr_ref_vector const& asms) override;
|
||||
void set_model(model_ref& _m) override { m_model = _m; }
|
||||
void get_model_core(model_ref& _m) override;
|
||||
void get_box_model(model_ref& _m, unsigned index) override;
|
||||
|
@ -254,7 +255,7 @@ namespace opt {
|
|||
|
||||
void reset_maxsmts();
|
||||
void import_scoped_state();
|
||||
void normalize();
|
||||
void normalize(expr_ref_vector const& asms);
|
||||
void internalize();
|
||||
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);
|
||||
|
@ -270,7 +271,7 @@ namespace opt {
|
|||
expr* mk_objective_fn(unsigned index, objective_t ty, unsigned sz, expr*const* args);
|
||||
void to_fmls(expr_ref_vector& 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 update_lower() { update_bound(true); }
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace opt {
|
|||
fmls.push_back(mk_or(gt));
|
||||
fml = mk_and(fmls);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ namespace opt {
|
|||
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) {}
|
||||
|
||||
virtual ~sortmax() {}
|
||||
~sortmax() override {}
|
||||
|
||||
lbool operator()() {
|
||||
lbool operator()() override {
|
||||
obj_map<expr, rational> soft;
|
||||
if (!init()) {
|
||||
return l_false;
|
||||
|
|
|
@ -49,9 +49,9 @@ namespace opt {
|
|||
m_trail(m),
|
||||
m_defs(m) {}
|
||||
|
||||
virtual ~wmax() {}
|
||||
~wmax() override {}
|
||||
|
||||
lbool operator()() {
|
||||
lbool operator()() override {
|
||||
TRACE("opt", tout << "weighted maxsat\n";);
|
||||
scoped_ensure_theory wth(*this);
|
||||
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) {
|
||||
cmd_context ctx(false, &m);
|
||||
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 end = ctx.end_assertions();
|
||||
unsigned size = static_cast<unsigned>(end - it);
|
||||
ptr_vector<expr>::const_iterator it = ctx.assertions().begin();
|
||||
unsigned size = ctx.assertions().size();
|
||||
return expr_ref(mk_and(m, size, it), m);
|
||||
}
|
||||
|
||||
|
|
|
@ -2614,7 +2614,7 @@ namespace smt2 {
|
|||
|
||||
check_rparen("invalid get-value command, ')' expected");
|
||||
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");
|
||||
if (index != 0) {
|
||||
m_ctx.get_opt()->get_box_model(md, index);
|
||||
|
|
|
@ -394,7 +394,7 @@ namespace eq {
|
|||
expr* const* args = &e;
|
||||
if (is_lambda(q)) {
|
||||
r = q;
|
||||
pr = 0;
|
||||
pr = nullptr;
|
||||
return;
|
||||
}
|
||||
flatten_args(q, num_args, args);
|
||||
|
|
|
@ -156,7 +156,7 @@ namespace qe {
|
|||
std::swap(e1, e2);
|
||||
}
|
||||
// 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_times_minus_one(a1, x)) {
|
||||
e1 = a0;
|
||||
|
|
|
@ -1266,9 +1266,9 @@ namespace qe {
|
|||
in->reset();
|
||||
in->inc_depth();
|
||||
result.push_back(in.get());
|
||||
if (in->models_enabled()) {
|
||||
if (in->models_enabled()) {
|
||||
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());
|
||||
in->add(mc.get());
|
||||
}
|
||||
|
|
|
@ -1862,8 +1862,9 @@ namespace sat {
|
|||
return p;
|
||||
}
|
||||
|
||||
ba_solver::ba_solver(): m_solver(0), m_lookahead(0), m_unit_walk(0),
|
||||
m_allocator("ba"), m_constraint_id(0), m_ba(*this), m_sort(m_ba) {
|
||||
ba_solver::ba_solver()
|
||||
: 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";);
|
||||
m_num_propagations_since_pop = 0;
|
||||
}
|
||||
|
@ -3838,7 +3839,7 @@ namespace sat {
|
|||
}
|
||||
init_visited();
|
||||
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);
|
||||
mark_visited(l.second);
|
||||
}
|
||||
|
@ -4394,6 +4395,12 @@ namespace sat {
|
|||
}
|
||||
|
||||
if (slack >= k) {
|
||||
#if 0
|
||||
return active2constraint();
|
||||
active2pb(m_A);
|
||||
std::cout << "not asserting\n";
|
||||
display(std::cout, m_A, true);
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ namespace sat {
|
|||
virtual void set_k(unsigned k) { VERIFY(k < 4000000000); m_k = k; }
|
||||
virtual unsigned get_coeff(unsigned i) const { UNREACHABLE(); return 0; }
|
||||
unsigned k() const { return m_k; }
|
||||
virtual bool well_formed() const;
|
||||
bool well_formed() const override;
|
||||
};
|
||||
|
||||
class card : public pb_base {
|
||||
|
@ -146,13 +146,13 @@ namespace sat {
|
|||
literal& operator[](unsigned i) { return m_lits[i]; }
|
||||
literal const* begin() const { return m_lits; }
|
||||
literal const* end() const { return static_cast<literal const*>(m_lits) + m_size; }
|
||||
virtual void negate();
|
||||
virtual void swap(unsigned i, unsigned j) { std::swap(m_lits[i], m_lits[j]); }
|
||||
virtual literal_vector literals() const { return literal_vector(m_size, m_lits); }
|
||||
virtual bool is_watching(literal l) const;
|
||||
virtual literal get_lit(unsigned i) const { return m_lits[i]; }
|
||||
virtual void set_lit(unsigned i, literal l) { m_lits[i] = l; }
|
||||
virtual unsigned get_coeff(unsigned i) const { return 1; }
|
||||
void negate() override;
|
||||
void swap(unsigned i, unsigned j) override { std::swap(m_lits[i], m_lits[j]); }
|
||||
literal_vector literals() const override { return literal_vector(m_size, m_lits); }
|
||||
bool is_watching(literal l) const override;
|
||||
literal get_lit(unsigned i) const override { return m_lits[i]; }
|
||||
void set_lit(unsigned i, literal l) override { m_lits[i] = l; }
|
||||
unsigned get_coeff(unsigned i) const override { return 1; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -179,14 +179,14 @@ namespace sat {
|
|||
void update_max_sum();
|
||||
void set_num_watch(unsigned s) { m_num_watch = s; }
|
||||
bool is_cardinality() const;
|
||||
virtual void negate();
|
||||
virtual void set_k(unsigned k) { m_k = k; VERIFY(k < 4000000000); update_max_sum(); }
|
||||
virtual void swap(unsigned i, unsigned j) { 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; }
|
||||
virtual bool is_watching(literal l) const;
|
||||
virtual literal get_lit(unsigned i) const { return m_wlits[i].second; }
|
||||
virtual void set_lit(unsigned i, literal l) { m_wlits[i].second = l; }
|
||||
virtual unsigned get_coeff(unsigned i) const { return m_wlits[i].first; }
|
||||
void negate() override;
|
||||
void set_k(unsigned k) override { m_k = k; VERIFY(k < 4000000000); update_max_sum(); }
|
||||
void swap(unsigned i, unsigned j) override { std::swap(m_wlits[i], m_wlits[j]); }
|
||||
literal_vector literals() const override { literal_vector lits; for (auto wl : *this) lits.push_back(wl.second); return lits; }
|
||||
bool is_watching(literal l) const override;
|
||||
literal get_lit(unsigned i) const override { return m_wlits[i].second; }
|
||||
void set_lit(unsigned i, literal l) override { m_wlits[i].second = l; }
|
||||
unsigned get_coeff(unsigned i) const override { return m_wlits[i].first; }
|
||||
};
|
||||
|
||||
class xr : public constraint {
|
||||
|
@ -197,13 +197,13 @@ namespace sat {
|
|||
literal operator[](unsigned i) const { return m_lits[i]; }
|
||||
literal const* begin() const { return m_lits; }
|
||||
literal const* end() const { return begin() + m_size; }
|
||||
virtual void negate() { m_lits[0].neg(); }
|
||||
virtual void swap(unsigned i, unsigned j) { std::swap(m_lits[i], m_lits[j]); }
|
||||
virtual bool is_watching(literal l) const;
|
||||
virtual literal_vector literals() const { return literal_vector(size(), begin()); }
|
||||
virtual literal get_lit(unsigned i) const { return m_lits[i]; }
|
||||
virtual void set_lit(unsigned i, literal l) { m_lits[i] = l; }
|
||||
virtual bool well_formed() const;
|
||||
void negate() override { m_lits[0].neg(); }
|
||||
void swap(unsigned i, unsigned j) override { std::swap(m_lits[i], m_lits[j]); }
|
||||
bool is_watching(literal l) const override;
|
||||
literal_vector literals() const override { return literal_vector(size(), begin()); }
|
||||
literal get_lit(unsigned i) const override { return m_lits[i]; }
|
||||
void set_lit(unsigned i, literal l) override { m_lits[i] = l; }
|
||||
bool well_formed() const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -524,44 +524,44 @@ namespace sat {
|
|||
|
||||
public:
|
||||
ba_solver();
|
||||
virtual ~ba_solver();
|
||||
virtual void set_solver(solver* s) { m_solver = s; }
|
||||
virtual void set_lookahead(lookahead* l) { m_lookahead = l; }
|
||||
virtual void set_unit_walk(unit_walk* u) { m_unit_walk = u; }
|
||||
~ba_solver() override;
|
||||
void set_solver(solver* s) override { m_solver = s; }
|
||||
void set_lookahead(lookahead* l) override { m_lookahead = l; }
|
||||
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_pb_ge(bool_var v, svector<wliteral> const& wlits, unsigned k);
|
||||
void add_xr(literal_vector const& lits);
|
||||
|
||||
virtual bool propagate(literal l, ext_constraint_idx idx);
|
||||
virtual lbool resolve_conflict();
|
||||
virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r);
|
||||
virtual void asserted(literal l);
|
||||
virtual check_result check();
|
||||
virtual void push();
|
||||
virtual void pop(unsigned n);
|
||||
virtual void simplify();
|
||||
virtual void clauses_modifed();
|
||||
virtual lbool get_phase(bool_var v);
|
||||
virtual bool set_root(literal l, literal r);
|
||||
virtual void flush_roots();
|
||||
virtual std::ostream& display(std::ostream& out) const;
|
||||
virtual std::ostream& display_justification(std::ostream& out, ext_justification_idx idx) const;
|
||||
virtual void collect_statistics(statistics& st) const;
|
||||
virtual extension* copy(solver* s);
|
||||
virtual extension* copy(lookahead* s, bool learned);
|
||||
virtual void find_mutexes(literal_vector& lits, vector<literal_vector> & mutexes);
|
||||
virtual void pop_reinit();
|
||||
virtual void gc();
|
||||
virtual double get_reward(literal l, ext_justification_idx idx, literal_occs_fun& occs) const;
|
||||
virtual bool is_extended_binary(ext_justification_idx idx, literal_vector & r);
|
||||
virtual void init_use_list(ext_use_list& ul);
|
||||
virtual bool is_blocked(literal l, ext_constraint_idx idx);
|
||||
virtual bool check_model(model const& m) const;
|
||||
bool propagate(literal l, ext_constraint_idx idx) override;
|
||||
lbool resolve_conflict() override;
|
||||
void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r) override;
|
||||
void asserted(literal l) override;
|
||||
check_result check() override;
|
||||
void push() override;
|
||||
void pop(unsigned n) override;
|
||||
void simplify() override;
|
||||
void clauses_modifed() override;
|
||||
lbool get_phase(bool_var v) override;
|
||||
bool set_root(literal l, literal r) override;
|
||||
void flush_roots() override;
|
||||
std::ostream& display(std::ostream& out) const override;
|
||||
std::ostream& display_justification(std::ostream& out, ext_justification_idx idx) const override;
|
||||
void collect_statistics(statistics& st) const override;
|
||||
extension* copy(solver* s) override;
|
||||
extension* copy(lookahead* s, bool learned) override;
|
||||
void find_mutexes(literal_vector& lits, vector<literal_vector> & mutexes) override;
|
||||
void pop_reinit() override;
|
||||
void gc() override;
|
||||
double get_reward(literal l, ext_justification_idx idx, literal_occs_fun& occs) const override;
|
||||
bool is_extended_binary(ext_justification_idx idx, literal_vector & r) override;
|
||||
void init_use_list(ext_use_list& ul) override;
|
||||
bool is_blocked(literal l, ext_constraint_idx idx) override;
|
||||
bool check_model(model const& m) const override;
|
||||
|
||||
ptr_vector<constraint> const & constraints() const { return m_constraints; }
|
||||
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_defrag = p.gc_defrag();
|
||||
|
||||
m_force_cleanup = p.force_cleanup();
|
||||
|
||||
m_minimize_lemmas = p.minimize_lemmas();
|
||||
m_core_minimize = p.core_minimize();
|
||||
m_core_minimize_partial = p.core_minimize_partial();
|
||||
|
|
|
@ -146,6 +146,8 @@ namespace sat {
|
|||
bool m_gc_burst;
|
||||
bool m_gc_defrag;
|
||||
|
||||
bool m_force_cleanup;
|
||||
|
||||
|
||||
bool m_minimize_lemmas;
|
||||
bool m_dyn_sub_res;
|
||||
|
|
|
@ -26,7 +26,7 @@ Notes:
|
|||
namespace sat {
|
||||
drat::drat(solver& s):
|
||||
s(s),
|
||||
m_out(0),
|
||||
m_out(nullptr),
|
||||
m_inconsistent(false),
|
||||
m_check_unsat(false),
|
||||
m_check_sat(false),
|
||||
|
|
|
@ -529,7 +529,7 @@ namespace sat {
|
|||
}
|
||||
|
||||
lbool local_search::check() {
|
||||
return check(0, 0);
|
||||
return check(0, nullptr);
|
||||
}
|
||||
|
||||
#define PROGRESS(tries, flips) \
|
||||
|
|
|
@ -277,7 +277,7 @@ namespace sat {
|
|||
|
||||
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; }
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ Author:
|
|||
|
||||
Notes:
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include <cmath>
|
||||
|
@ -31,7 +33,7 @@ namespace sat {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -1215,7 +1217,7 @@ namespace sat {
|
|||
lookahead& lh;
|
||||
public:
|
||||
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:
|
||||
|
@ -2055,6 +2057,15 @@ namespace sat {
|
|||
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) {
|
||||
scoped_ext _scoped_ext(*this);
|
||||
lits.reset();
|
||||
|
@ -2100,22 +2111,13 @@ namespace sat {
|
|||
}
|
||||
backtrack_level = UINT_MAX;
|
||||
depth = m_cube_state.m_cube.size();
|
||||
if ((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)) {
|
||||
if (should_cutoff(depth)) {
|
||||
double dec = (1.0 - pow(m_config.m_cube_fraction, depth));
|
||||
m_cube_state.m_freevars_threshold *= dec;
|
||||
m_cube_state.m_psat_threshold *= 2.0 - dec;
|
||||
set_conflict();
|
||||
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);
|
||||
#endif
|
||||
vars.reset();
|
||||
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);
|
||||
|
@ -2135,6 +2137,8 @@ namespace sat {
|
|||
if (lit == null_literal) {
|
||||
vars.reset();
|
||||
for (auto v : m_freevars) if (in_reduced_clause(v)) vars.push_back(v);
|
||||
m_model.reset();
|
||||
init_model();
|
||||
return l_true;
|
||||
}
|
||||
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