I wrote z3 query in SMT2 format using QF_FPABV logic (quantifier-free floating-point arithmetic and bit-vector logic??).
The query is shown as follows:
(set-logic QF_FPABV)
(set-option :produce-models true)
(declare-fun f0 () (_ FP 8 24))
(declare-fun f1 () (_ FP 8 24))
(declare-fun f2 () (_ FP 8 24))
(assert (= f2 (* roundNearestTiesToEven f0 f1)))
(assert (>= f2 ((_ asFloat 8 24) roundNearestTiesToEven 3.0 0)))
(check-sat)
; (check-sat-using (then simplify solve-eqs bit-blast smt))
(get-model)
With
(check-sat),
I acquired the result and the model as:
sat
(model
(define-fun f2 () (_ FP 8 24)
(as +1.44919359683990478515625p127 (_ FP 8 24)))
(define-fun f1 () (_ FP 8 24)
(as +1.476345062255859375p0 (_ FP 8 24)))
(define-fun f0 () (_ FP 8 24)
(as +1.9632179737091064453125p126 (_ FP 8 24)))
)
This is what I expect.
However, if I use
(check-sat-using (then simplify solve-eqs bit-blast smt))
instead, I acquired:
sat
(model
;; universe for RoundingMode:
;; RoundingMode!val!0
;; -----------
;; definitions for universe elements:
(declare-fun RoundingMode!val!0 () RoundingMode)
;; cardinality constraint:
(forall ((x RoundingMode)) (= x RoundingMode!val!0))
;; -----------
;; universe for (_ FP 8 24):
;; FP!val!0 FP!val!1 FP!val!2 FP!val!3
;; -----------
;; definitions for universe elements:
(declare-fun FP!val!0 () (_ FP 8 24))
(declare-fun FP!val!1 () (_ FP 8 24))
(declare-fun FP!val!2 () (_ FP 8 24))
(declare-fun FP!val!3 () (_ FP 8 24))
;; cardinality constraint:
(forall ((x (_ FP 8 24)))
(or (= x FP!val!0) (= x FP!val!1) (= x FP!val!2) (= x FP!val!3)))
;; -----------
(define-fun f1 () (_ FP 8 24)
FP!val!2)
(define-fun f0 () (_ FP 8 24)
FP!val!1)
(define-fun f2 () (_ FP 8 24)
(* roundNearestTiesToEven FP!val!1 FP!val!2))
)
This model is not trivial to interpret...
For this simple example, I can just use (check-sat) to acquire human-readable results.
For some complex examples which contains non-linear operations,
I need to use (check-sat-using (then simplify solve-eqs bit-blast smt))
to avoid getting "Unknown" from z3...
Is there any document which can teach me to interpret such non-human-readable model?
The problem here is that the floating-point theory is not fully integrated with the SMT kernel of Z3 yet (I'm working on that in a separate branch). Because of that, the kernel treats all floating-point sorts as uninterpreted and therefore the model contains definitions of those sorts (the universes). At the moment, the best way to get around that is to call the fpa2bv tactic directly, e.g., change
(check-sat-using (then simplify solve-eqs bit-blast smt))
to
(check-sat-using (then simplify fpa2bv simplify solve-eqs bit-blast smt))
It is necessary to call the simplify tactic before calling fpa2bv and it is also necessary to call the simplifier before the bit-blast tactic, because those tactics rely on the simplifier to eliminate some particular expressions.
I think this is an issue with the model-completion code in Z3. There was a similar bug quite a while ago: Z3 FP logic: produces unexpected model
I thought the issue was already addressed and the code sample in that ticket now works correctly with z3 4.3.2, but apparently the code fragment you presented here triggers a similar problem that's not quite addressed yet.
Related
I have a simple example in nonlinear integer arithmetic, namely a search for Pythagorean triples. Based on what I read in related questions (see below), I'd expect Z3 to find a solution to this problem, but it returns 'unknown'. Here is the example in SMT-LIB v2:
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(declare-fun xSquared () Int)
(declare-fun ySquared () Int)
(declare-fun zSquared () Int)
(declare-fun xSquaredPlusYSquared () Int)
(assert (= xSquared (* x x)))
(assert (= ySquared (* y y)))
(assert (= zSquared (* z z)))
(assert (= xSquaredPlusYSquared (+ xSquared ySquared)))
(assert (and (> x 0) (> y 0) (> z 0) (= xSquaredPlusYSquared zSquared)))
(check-sat)
(exit)
There are a few related questions, most notably:
How does Z3 handle non-linear integer arithmetic?
Need help understanding the equation
Combining nonlinear Real with linear Int
Z3 support for nonlinear arithmetic
z3 limitations in handling nonlinear real arithmetics
It seems that Z3 won't attempt finding a solution by bit-blasting unless variables have a finite range. Replacing (check-sat) with the following command will find the solution:
(check-sat-using (then (using-params add-bounds :add-bound-lower -100 :add-bound-upper 100) smt))
Alternatively, one can add assert statements forcing each variable to have some finite range.
I am using the inbuilt interpolation feature on the latest (unstable branch) version of Z3. It works fine with SMT2 formulas containing integers. It does however, throw a iz3proof_itp::proof_error and a subsequent iz3translate::unsupported error (See Below) for the following SMT2 program -
(set-option :produce-models true)
(set-logic QF_AUFBV)
(declare-fun a () (_ BitVec 32))
(declare-fun b () (_ BitVec 32))
(declare-fun x1 () (_ BitVec 32))
(declare-fun x2 () (_ BitVec 32))
(declare-fun x3 () (_ BitVec 32))
(declare-fun y1 () (_ BitVec 32))
(declare-fun y2 () (_ BitVec 32))
(compute-interpolant
(= a (_ bv0 32))
(= b (bvneg (_ bv2 32)))
(= x1 (_ bv1 32))
(= y1 (_ bv0 32))
(= x2 (bvadd x1 a))
(= x3 (bvadd x2 b))
(= y2 (bvadd y1 a))
(bvsge x3 (_ bv0 32))
)
I tried it on the online version on rise4fun, and it worked fine. So after a bit of debugging, I found that the error is thrown from inside the function find_congruence_position in file iz3proof_itp.cpp.
So I made the following simple (maybe dangerous) change to the function to take care of the proof_error atleast for now -
Changing if(x == arg(arg(con,0),i) && (y == arg(arg(con,1),i)) at line 2431
to if((x == arg(arg(con,0),i) && (y == arg(arg(con,1),i))) || (y == arg(arg(con,0),i) && (x == arg(arg(con,1),i))))
I simply or'd the condition with its copy where x and y are interchanged - I had found that x and y sometimes have their values interchanged, maybe due to some proof techniques.
This did take care of the problem, I found that using equality and non-equality, along with bvadd or bvneg with BitVecs while computing interpolants worked. For example the following file worked -
(set-option :produce-models true)
(set-logic QF_AUFBV)
(declare-fun a () (_ BitVec 32))
(declare-fun b () (_ BitVec 32))
(compute-interpolant
(= a (_ bv0 32))
(= b (bvadd a (_ bv1 32)))
(= b (_ bv0 32))
)
But then I tried using relational operators, like bvsgt or bvsge, and it threw a new error -
terminate called after throwing an instance of 'iz3translation::unsupported'
I looked more into it, found out that the expression causing the problem was -
(not ((_ bit2bool 2) x2)) - it was assigned a PR_TH_LEMMA type and the UNKNOWN_THEORY kind. It seems that there is no support for such operations.
Since the online version is working, I'd like to know if it's possible to obtain that version. I read the previous questions and answers on StackOverflow, and I'm a bit confused. Some say BitVec theory is not supported (Although these posts are old), but then how is the online version working? Or am I doing something wrong? Any help is highly appreciated.
Actually, interpolation for bit vector arithmetic is not supported. It's interesting that it works on the web version. That version is quite old, however, and I think it predates the source-available version of Z3. I can think of two possible reasons why it works:
1) That version of interpolating Z3 used the "foci" prover as a backup. Whenever it encountered a part of the proof it didn't understand, it would package that part up as a lemma and reprove it using foci. The current version does not use foci (which is a third-party tool not available in source) and relies entirely on the proof generated by Z3.
2) The older version might have been doing bit-blasting in a different way. If all the non-local proof steps are purely propositional (using just the resolution rule) then it is easy to compute an interpolant.
As far as I understand it, however, computing interpolants from an efficient bit-vector solver (using all the known pre-processing tricks) is an open problem.
How does one use the 'repeat' and 'rotate_left' bitvector operations?
More generally, where can I find detailed documentation of bitvector operations in the SMT2 scripting format used by Z3?
Everything I find seems to just go to tutorials, or broken links:
https://github.com/Z3Prover/z3/wiki/Documentation
http://research.microsoft.com/en-us/um/redmond/projects/z3/old/documentation.html
Trying to understand "repeat", "rotate_left", and "rotate_right" by guessing has been frustating. I cannot figure out how to use them. For example
(display (repeat #b01))
(display (repeat #b01 3))
(display (repeat 3))
(display (rotate_left #b0001 2))
gives
"repeat expects one non-zero integer parameter"
"repeat expects one argument"
"operator is applied to arguments of the wrong sort"
"rotate left expects one argument"
Where is the documentation? Hoping they didn't explain because all of this is standard, I also looked at smt-lib.org but that doesn't list these details either. So frustrating.
In addition to dejvuth's answer:
The SMT language is well documented (see smt-lib.org), for this particular issue the FixedSizeBitVectors theory and the QF_BV logic definition are relevant. The latter contains the definition for repeat:
((_ repeat i) (_ BitVec m) (_ BitVec i*m))
- ((_ repeat i) x) means concatenate i copies of x
Apart from those, David Cok wrote an excellent SMT2 tutorial.
The names of functions in the Z3 API is the same as in SMT2 where syntax permits, in this case prefixed with Z3_mk_ to indicate that they are functions that construct Z3 expressions.
For your example, you should write something like this
(declare-const a (_ BitVec 2))
(declare-const b (_ BitVec 6))
(assert (= a #b01))
(assert (= b ((_ repeat 3) a)))
(declare-const c (_ BitVec 4))
(declare-const d (_ BitVec 4))
(assert (= c #b0001))
(assert (= d ((_ rotate_left 2) c)))
(check-sat)
(get-model)
You will get
sat
(model
(define-fun d () (_ BitVec 4)
#x4)
(define-fun c () (_ BitVec 4)
#x1)
(define-fun b () (_ BitVec 6)
#b010101)
(define-fun a () (_ BitVec 2)
#b01)
)
A good document that I usually use is its API.
Browsing Z3 source code, I came across a bunch of files referring to QF_FPA, which seems to stand for quantifier-free, floating-point-arithmetic. However, I don't seem to be able to locate any documentation regarding its state, or how it can be used via various front-ends (in particular SMT-Lib2). Is this an encoding of IEEE-754 FP? If so, which precisions/operations are supported? Any documentation would be most helpful..
Yes, Z3 supports floating point arithmetic as proposed by Ruemmer and Wahl in a recent SMT-workshop paper. At the current stage, there is no official FPA theory, and Z3's support is very basic (only a bit-blaster). We're not actively advertising this yet, but it can be used exactly as proposed in the paper by Ruemmer/Wahl (setting logics QF_FPA and QF_FPABV). At the moment, we are working on a new decision procedure for FPA, but it will be some time until that is available.
Here's a brief example of what an FPA SMT2 formula could look like:
(set-logic QF_FPA)
(declare-const x (_ FP 11 53))
(declare-const y (_ FP 11 53))
(declare-const r (_ FP 11 53))
(assert (and
(= x ((_ asFloat 11 53) roundTowardZero 0.5 0))
(= y ((_ asFloat 11 53) roundTowardZero 0.5 0))
(= r (+ roundTowardZero x y))
))
(check-sat)
The floating point logics are named QF_FP and QF_FPBV in v4.4.2. The link to the description of the theory in RELEASE_NOTES is broken. The correct page is http://smtlib.cs.uiowa.edu/theories-FloatingPoint.shtml. The proposed example above should be
(set-logic QF_FP)
(declare-const x (_ FloatingPoint 11 53))
(declare-const y (_ FloatingPoint 11 53))
(declare-const r (_ FloatingPoint 11 53))
(assert (and
(= x (fp #b0 #b00000000010 #b0000000000000000000000000000000000000000000000000010))
(= y (fp #b0 #b00000000010 #b0000000000000000000000000000000000000000000000000010))
(= r (fp.add roundTowardZero x y))
))
(check-sat)
I'm using the latest Z3 version 3.2. I get an unexpected response from the "get-value" command. Here is the little script that I run in SMT-LIB2 compliant mode:
(set-option :produce-models true)
(declare-datatypes () ((Object o0 null)))
(declare-fun IF (Object) Int)
(declare-fun i2 () Int)
(assert (= (IF o0) i2))
(assert (= (IF null) 0))
(check-sat)
(get-value (i2))
The response is:
((i2 (IF o0)))
I expect to get just "0" back. Is there any way to ask Z3 to evaluate the returned term to a universe constant?
Here is the full model:
(model
;; universe for Object:
;; Object!val!0
;; -----------
;; definitions for universe elements:
(declare-fun Object!val!0 () Object)
;; cardinality constraint:
(forall ((x Object)) (= x Object!val!0))
;; -----------
(define-fun i2 () Int
(IF o0))
(define-fun IF ((x!1 Object)) Int
(ite (= x!1 Object!val!0) 0
0))
)
I'm also puzzled why o0 is not defined in the model.
This has been fixed in Z3 4.0.
Z3 4.0 will be released soon. In the meantime, you can use it online: http://rise4fun.com/Z3/75y
This link can be used to execute your example. Z3 4.0 produces the expected result.
Regarding the bug, the main problem is that Z3 is treating Object as an uninterpreted sort.
In Z3 3.2, you can workaround this bug by including
(set-option :auto-config false)
in the beginning of your script.