I am currently working with arrays and in some cases Z3 returns lambda functions for them in the produced model.
An example of my code:
(set-option :random-seed 0)
(set-option :produce-models true)
(set-option :produce-unsat-cores true)
;
(set-info :status sat)
(declare-fun tmp_bv3 () (_ BitVec 4))
(declare-fun tmp_array2 () (Array (_ BitVec 4) Bool))
(declare-fun tmp_bool3 () Bool)
(declare-fun tmp_bool0 () Bool)
(assert
(let ((?x564 (store tmp_array2 tmp_bv3 tmp_bool3)))
(let (($x33 (bvult tmp_bv3 tmp_bv3)))
(let ((?x237 (bvurem tmp_bv3 tmp_bv3)))
(let ((?x24 (store tmp_array2 tmp_bv3 tmp_bool0)))
(= (store ?x24 ?x237 $x33) ?x564))))))
(check-sat)
(get-value (tmp_array2 tmp_bv3 tmp_bool0 tmp_bool3 ))
(get-info :reason-unknown)
For this example Z3 version 4.8.6 returned the following model:
((tmp_array2 ((as const (Array (_ BitVec 4) Bool)) false))
(tmp_bv3 #x0)
(tmp_bool0 false)
(tmp_bool3 false))
And the current version (4.8.12) returns:
((tmp_array2 (lambda ((x!1 (_ BitVec 4))) (= x!1 #x0)))
(tmp_bv3 #x0)
(tmp_bool0 false)
(tmp_bool3 false))
For my use case of the results returned by Z3, I would prefer the format returned by version 4.8.6.
And therefore I was wondering if an option exists to disable lambda functions in the model?
z3's model printing around arrays have been in flux recently; and different versions do print the models in different ways. (For instance, see https://github.com/Z3Prover/z3/issues/5604)
If I try your program using the latest z3 from GitHub master, then it prints:
sat
((tmp_array2 ((as const (Array (_ BitVec 4) Bool)) false))
(tmp_bv3 #x1)
(tmp_bool0 false)
(tmp_bool3 false))
(:reason-unknown "")
So, it appears this behavior is indeed currently restored in the repo. But you are correct that you might get a lambda-output depending on which version you're using.
So far as I know there's no explicit option you can use to control this behavior. If you can compile from the master (https://github.com/Z3Prover/z3) that'll solve your problem. If not, I'm afraid you're out of luck. You could of course report this as an issue in their tracker, but since the latest master does the right thing, I guess the answer you'll get will be "upgrade."
Related
I was wondering if there are is any way to represent an smtlib2 formula as a template. For instance:
(declare-fun b () (_ BitVec 16))
(declare-fun a () (_ BitVec 8))
(declare-fun c () (_ BitVec 32))
(assert (= c (bvor ((_ zero_extend 24) a) ((_ zero_extend 16) b))))
can be represented as (say using jinja2-style templating)
((declare-fun {{B_VAR}} () (_ BitVec {{B_VAR_SIZE}}))
(declare-fun {{A_VAR}} () (_ BitVec {{A_VAR_SIZE}}))
(declare-fun {{C_VAR}} () (_ BitVec {{C_VAR_SIZE}}))
(assert (= {{C_VAR}} (bvor ((_ zero_extend 24) {{A_VAR}}) ((_ zero_extend {{B_VAR_SIZE}}) {{B_VAR}}))))
And then the template can be rendered to represent an actual smtlib formula:
(declare-fun P () (_ BitVec 16))
(declare-fun Q () (_ BitVec 8))
(declare-fun R () (_ BitVec 32))
(assert (= R (bvor ((_ zero_extend 24) Q) ((_ zero_extend 16) P))))
Is there any natural way to do this other than use something like jinja2 and create my own template for every formula?
Alternatively, considering that I already have a z3::expr_vector that represents an SMT formula, is there a way to "templatize" it? My eventual goal is that I would like to "invoke" the templatized version with unique bitvector names for each invocation. Does the z3 C++ API have any methods which naturally allows one to achieve this?
There isn't anything in the z3 C++/Java API's to do this. However, if you're programming in C++ or Java, simply write a function that produces this expression. You're saying that you already have a z3::expr_vector; you should instead write a function that takes the relevant parts (i.e., variable names and sizes), and then constructs this final expression; i.e., regular programming using the z3 AST.
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.
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.
I'm playing around with Z3's QBVF solver, and wondering if it's possible to extract values from an existential assertion. To wit, let's say I have the following:
(assert (exists ((x (_ BitVec 16))) (forall ((y (_ BitVec 16))) (bvuge y x))))
This basically says that there is a "least" 16-bit unsigned value. Then, I can say:
(check-sat)
(get-model)
And Z3-3.0 happily responds:
sat
(model (define-fun x!0 () (_ BitVec 16)
#x0000)
)
Which is really cool. But what I want to do is to be able to extract pieces of that model via get-value. Unsurprisingly, none of the following seem to work
(get-value (x))
(get-value (x!0))
In each case Z3 rightly complains there's no such constant. Clearly Z3 has that information as evidenced by the response to the (check-sat) call. Is there any way to access the existential value automatically via get-value, or some other mechanism?
Thanks..
In Z3, get-value only allows the user to reference “global” declarations.
The existential variable x is a local declaration. Thus, it can’t be accessed using get-value.
By default, Z3 eliminates existential variables using a process called “skolemization”.
The idea is to replace existential variables with fresh constants and function symbols.
For example, the formula
exists x. forall y. exists z. P(x, y, z)
is converted into
forall y. P(x!1, y, z!1(y))
Note that z becomes a function because the choice of z may depend on y.
Wikipedia has an entry on skolem normal form
That being said, I never found a satisfactory solution for the problem you described.
For example, a formula may have many different existential variables with the same name.
So, it is not clear how to reference each instance in the get-value command in a non-ambiguous way.
A possible workaround for this limitation is to apply the skolemization step “by hand”, or at least for the variables you want to know the value.
For example,
(assert (exists ((x (_ BitVec 16))) (forall ((y (_ BitVec 16))) (bvuge y x))))
is written as:
(declare-const x (_ BitVec 16))
(assert (forall ((y (_ BitVec 16))) (bvuge y x)))
(check-sat)
(get-value x)
If the existential variable is nested in a universal quantifier such as:
(assert (forall ((y (_ BitVec 16))) (exists ((x (_ BitVec 16))) (bvuge y x))))
(check-sat)
(get-model)
A fresh skolem function can be used to obtain the value of x for each y.
The example above becomes:
(declare-fun sx ((_ BitVec 16)) (_ BitVec 16))
(assert (forall ((y (_ BitVec 16))) (bvuge y (sx y))))
(check-sat)
(get-model)
In this example, sx is the fresh function. The model, produced by Z3, will assign an interpretation for sx. In version 3.0, the interpretation is the identity function. This function can be used to obtain the value of x for each y.