Z3 gives a NaN value for my floating point constraint - z3

Given the following floating point constraint, Z3 produces a abnormal model, in which z is NaN. Obviously, it is not a right solution. Is it a bug?
BTW. the version of z3 is 4.5.0
(declare-const x (_ FP 11 53))
(declare-const y (_ FP 11 53))
(declare-const z (_ FP 11 53))
(assert
(and
(not (fp.lt x (_ +zero 11 53)))
(not (fp.lt y (_ +zero 11 53)))
(not (fp.lt z (_ +zero 11 53)))
(not (fp.leq (fp.add roundNearestTiesToEven x y) z))
)
)
(check-sat)
(get-model)

This is not a bug, these are the correct semantics for the operators involved (according to SMT-LIB and according to IEEE-754 as well). The model I get is this:
(model
(define-fun z () (_ FloatingPoint 11 53)
(_ NaN 11 53))
(define-fun y () (_ FloatingPoint 11 53)
(fp #b0 #b00000000000 #x0000000004000))
(define-fun x () (_ FloatingPoint 11 53)
(_ +zero 11 53))
)
and indeed (not (fp.leq (fp.add roundNearestTiesToEven x y) z)) is satisfied, i.e., x + y is not less than NaN, because nothing is less than NaN (all predicates are false for NaN inputs).
If this behavior is not desired, we can of course add another constraint to make sure z is not a NaN:
(assert (not (= z (_ NaN 11 53))))
and Z3 will then find a model where y (and thus x+y) is NaN.

Related

Which nonlinear assert is complete in smt/z3 optimize?

I list some assert about Quadratic function:
(declare-fun H () Int)
(assert (>= H 8000))
(assert (<= H 12000))
(minimize (- (^ H 2) H))
(check-sat)
but the answer is "unknown" and the reason for unknown is (incomplete (theory arithmetic)); I can't understand which is the lost one
In general z3 cannot deal with non-linear terms. (A term is non-linear if you multiply two variables together. In your case, that'd be (^ H 2).
This is especially true of the optimization engine: Nonlinear constraints over integers is most likely going to be beyond reach. But you're in luck: Your formula is rather simple so it can handle it fine. Rewrite it using multiplication:
(declare-fun H () Int)
(assert (>= H 8000))
(assert (<= H 12000))
(minimize (- (* H H) H))
(check-sat)
(get-model)
This prints:
sat
(model
(define-fun H () Int
8000)
)

Is there a way to specify the domain of a variable when defining it using an array?

My program reads the constraints from a smt2 file, and all the variables are defined as an array. For example
(declare-fun x () (Array (_ BitVec 32) (_ BitVec 8) ) )
(declare-fun y () (Array (_ BitVec 32) (_ BitVec 8) ) )
(assert (bvslt (concat (select x (_ bv3 32) ) (concat (select x (_ bv2 32) ) (concat (select x (_ bv1 32) ) (select x (_ bv0 32) ) ) ) ) (concat (select y (_ bv3 32) ) (concat (select y (_ bv2 32) ) (concat (select y (_ bv1 32) ) (select y (_ bv0 32) ) ) ) ) ) )
(check-sat)
(exit)
Some other constraints are omitted. Sometimes the solver gives a value of x as:
(store (store (store ((as const (Array (_ BitVec 32) (_ BitVec 8))) #xfe)
#x00000002
#x00)
#x00000001
#xff)
#x00000003
#x80)
According to the definition, each element of the array is a hex value, so the value should be 0x8000fffe. This value is beyond the upper bounds of integer in C++. When I covert it back to int, it is a negative value. So I guess Z3 treats all variables defined by an array as unsigned int.
For example, if the constraint is x > y, the solver may give
x = 0x8000fffe
and
y = 0x00000001. The values satisfy the constraint in unsigned comparison, but when conducting a signed comparison, x is negative and y is positive so it is wrong. I am wondering if there is a way to tell the solver that the numbers are signed when defining them as an array?
Added 22:26:43 09/14/2019
I got two smt2 files, one is
(set-logic QF_AUFBV )
(declare-fun x () (Array (_ BitVec 32) (_ BitVec 8) ) )
(declare-fun y () (Array (_ BitVec 32) (_ BitVec 8) ) )
(assert (bvslt (concat (select x (_ bv3 32) ) (concat (select x (_ bv2 32) ) (concat (select x (_ bv1 32) ) (select x (_ bv0 32) ) ) ) ) (concat (select y (_ bv3 32) ) (concat (select y (_ bv2 32) ) (concat (select y (_ bv1 32) ) (select y (_ bv0 32) ) ) ) ) ) )
(check-sat)
(exit)
The constraint is simply x < y.
The other one is
(set-logic QF_AUFBV )
(declare-fun x () (Array (_ BitVec 32) (_ BitVec 8) ) )
(declare-fun y () (Array (_ BitVec 32) (_ BitVec 8) ) )
(assert (let ( (?B1 (concat (select y (_ bv3 32) ) (concat (select y (_ bv2 32) ) (concat (select y (_ bv1 32) ) (select y (_ bv0 32) ) ) ) ) ) (?B2 (concat (select x (_ bv3 32) ) (concat (select x (_ bv2 32) ) (concat (select x (_ bv1 32) ) (select x (_ bv0 32) ) ) ) ) ) ) (let ( (?B3 (bvsub ?B1 ?B2 ) ) ) (and (and (and (and (and (= false (= (_ bv0 32) ?B2 ) ) (= false (= (_ bv0 32) ?B1 ) ) ) (= false (bvslt ?B1 ?B2 ) ) ) (= false (= (_ bv0 32) ?B3 ) ) ) (= false (bvslt ?B3 ?B2 ) ) ) (= (_ bv0 32) (bvsub ?B3 ?B2 ) ) ) ) ) )
(check-sat)
(exit)
which is
[(! (0 == x)),
(! (0 == y)),
(! ( y < x)),
(! (0 ==( y - x))),
(! (( y - x) < x)),
(0 ==(( y - x) - x)) ]
These smt2 files are generated by Klee.The solver gives
x = (store (store (store ((as const (Array (_ BitVec 32) (_ BitVec 8))) #xfe)
#x00000002
#x00)
#x00000001
#xff)
#x00000003
#x80)
y = before minimize: (store (store (store ((as const (Array (_ BitVec 32) (_ BitVec 8))) #xfc)
#x00000002
#x01)
#x00000001
#xff)
#x00000003
#x00)
so x=0x8000fffe, and y=0x0001fffc. Converted to decimal, we have x=2147549180, and y=131068. So y-x-x is-4294967296, not decimal 0. The solver thinks it is satisfied bacause 4294967296 is
1 00000000 00000000 00000000 00000000
in binary, where the "1" is the 33rd bit, and will be removed. So -4294967296 is considered 0x00 in the memory. This is the reason I asked this question. X and y should be integers, so 0x8000fffe is -0x0000fffe, aka -65534. And y is 131068. And y-x-x is apparently not 0. So in terms of integer, the values don't satisfy the constraints. The expression y - x - x seems to be computed in unsigned rules.
Bit-vectors have no signs
There's no notion of signed or unsigned bit-vector in SMTLib. A bit-vector is simply a sequence of bits, without any attached semantics as to how to treat it as a number.
It is the operations, however, that distinguish signedness. This is why you have bvslt and bvult; for signed and unsigned less-than comparison, for instance. You might want to read the logic description here: http://smtlib.cs.uiowa.edu/theories-FixedSizeBitVectors.shtml
Long story short, all the solver is telling you is that the result contains these bits; how you interpret that as an unsigned word or a signed 2's complement number is totally up to you. Note that this perfectly matches how machine arithmetic is done in hardware, where you simply have registers that contain bit-sequences. It's the instructions that treat the values according to whatever convention they might choose to do so.
I hope that's clear; feel free to ask about a specific case; posting full programs is always helpful as well, so long as they abstract away from details and describe what you're trying to do.
Also see this earlier question that goes into a bit more detail: How to model signed integer with BitVector?
Avoiding overflow/underflow
You can ask z3 to avoid overflow/underflow during bit-vector arithmetic. However, this will require adding extra assertions for each operation you want to perform, so it can get rather messy. (Also, looks like you want to use Klee; I'm not sure if Klee allows you to do this to start with.) The technique is explained in detail in this paper: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/z3prefix.pdf
In particular, you want to read through Section 5.1: Authors describe how to "annotate" each arithmetic operation and assert that it does not overflow explicitly. For instance, if you want to make sure addition doesn't overflow; you first zero-extend your bit-vectors from 32-bits to 33-bits; do the addition, and check if the 33-bit of the result is 1. To avoid overflow, you simply write an assertion saying that bit cannot be 1. Here's an example:
; Two 32-bit variables
(declare-fun x () (_ BitVec 32))
(declare-fun y () (_ BitVec 32))
; Zero-Extend them to 33-bits
(define-fun x33 () (_ BitVec 33) (concat #b0 x))
(define-fun y33 () (_ BitVec 33) (concat #b0 y))
; Add them
(define-fun extendedAdd () (_ BitVec 33) (bvadd x33 y33))
; Get the sign bit
(define-fun signBit () (_ BitVec 1) ((_ extract 32 32) extendedAdd))
; Assert that the addition won't overflow:
(assert (= signBit #b0))
; Regular addition result:
(define-fun addResult () (_ BitVec 32) ((_ extract 31 0) extendedAdd))
; Now you can use addResult as the result of x+y; and you'll
; be assured that this addition will never overflow
(check-sat)
(get-model)
You'd also have to check for underflow at each operation. Further adding complexity.
As you can see, this can get very hairy and the rules for multiplication are actually quite tricky. To simplify this z3 actually provides built-in primitives for multiplication overflow-checking, called:
bvsmul_noovfl: True only if signed multiplication doesn't overflow
bvsmul_noudfl: True only if signed multiplication doesn't underflow
bvumul_noovfl: True only if unsigned multiplication doesn't overflow
There is no predicate for checking if an unsigned multiplication can underflow because that cannot happen. But the point remains: You have to annotate each operation and explicitly assert the relevant conditions. This is best done by a higher-level API during code generation, and some z3 bindings do support such operations. (For instance, see http://hackage.haskell.org/package/sbv-8.4/docs/Data-SBV-Tools-Overflow.html for how the Haskell layer on top of SMT-solvers handles this.) If you'll do this at scale, you probably want to build some mechanism that automatically generates for you as doing it manually would be extremely error-prone.
Or you can switch and use Int type, which never overflows! But then, of course, you're no longer modeling an actual running program but reasoning about actual integer values; which might be acceptable depending on your problem domain.

Combining elements of a given set of items in z3

The following z3 code picks elements from {x1..x6} in order to maximize the total weight, while satisfying total length less than 10.
(declare-datatypes () ((Item (mk-item (size Int) (weight Int)))))
(define-fun ee () Item (mk-item 0 0)); empty item
(define-fun i1 () Item (mk-item 4 2))
(define-fun i2 () Item (mk-item 4 2))
(define-fun i3 () Item (mk-item 1 4))
(define-fun i4 () Item (mk-item 5 5))
(define-fun i5 () Item (mk-item 3 2))
(define-fun i6 () Item (mk-item 1 9))
(define-fun x_props ((x Bool) (i Item)) Item (ite x i ee))
; each x defines whether an item is selected or not
(declare-const x1 Bool)
(declare-const x2 Bool)
(declare-const x3 Bool)
(declare-const x4 Bool)
(declare-const x5 Bool)
(declare-const x6 Bool)
(define-fun total_size () Int
(+
(size (x_props x1 i1))
(size (x_props x2 i2))
(size (x_props x3 i3))
(size (x_props x4 i4))
(size (x_props x5 i5))
(size (x_props x6 i6))
))
(define-fun total_weight () Int
(+
(weight (x_props x1 i1))
(weight (x_props x2 i2))
(weight (x_props x3 i3))
(weight (x_props x4 i4))
(weight (x_props x5 i5))
(weight (x_props x6 i6))
))
(assert (< total_size 10))
(maximize total_weight)
(check-sat)
(get-model)
However, I can imagine this scaling very bad as the number of item properties explode, and the number of items as well.
Would there be a different, more concise approach? In particular, can you think of a way to factorize the total_size and total_weight functions, as there is a lot of repetition there?
There's really nothing wrong with your encoding. Since you need to sum through a number of elements, the only way to do that is either being explicit about them, or use a recursive function. While SMT-Lib and Z3 both support recursive-functions, the implementation isn't quite strong yet, and you'd better stick to the explicit style.
The issue here is really trying to use SMT-Lib as a programming language, which it was not really intended for. I'd recommend looking into high-level language interfaces instead, such as those from Python, Scala, or Haskell; which would take care of the repetitive coding. Here's a good site for describing how to do model such things in Python: https://ericpony.github.io/z3py-tutorial/guide-examples.htm and here's an example of a similar problem in Haskell: https://hackage.haskell.org/package/sbv-7.4/docs/src/Data.SBV.Examples.Optimization.VM.html

Understanding z3 bvsmod behavior with SSA

I am trying to learn using z3. So this question might be silly.
Why do I get a unexpected values for x___0 from Z3 when I use bvsmod as compared to bvadd in the following code. I'm using SSA to implement execution flow here.
Z3 instructions:
(set-option :pp.bv-literals false)
;
; The code
; x %= 5
; x * 2 == 8
; Implement SSA
; x1 = x0 % 5
; x1 * 2 == 8
;
(push)
(set-info :status unknown)
(declare-const x___0 (_ BitVec 32))
(declare-const x___1 (_ BitVec 32))
(assert (= x___1 (bvsmod x___0 (_ bv5 32))))
(assert (= (bvmul x___1 (_ bv2 32)) (_ bv8 32)))
(check-sat)
(get-model)
(pop)
;
; The code
; x += 1
; x * 2 == 8
; Implement SSA
; x1 = x0 + 1
; x1 * 2 == 8
;
(push)
(declare-const x___0 (_ BitVec 32))
(declare-const x___1 (_ BitVec 32))
(assert (= x___1 (bvadd x___0 (_ bv1 32))))
(assert (= (bvmul x___1 (_ bv2 32)) (_ bv8 32)))
(check-sat)
(get-model)
(pop)
Results:
sat
(model
(define-fun x___1 () (_ BitVec 32)
(_ bv4 32))
(define-fun x___0 () (_ BitVec 32)
(_ bv3720040335 32))
)
sat
(model
(define-fun x___1 () (_ BitVec 32)
(_ bv4 32))
(define-fun x___0 () (_ BitVec 32)
(_ bv3 32))
)
In case of equation where I use bvadd x___0 get a value 3, which makes sense.
Why do I get a value 3720040335 in case of bvsmod, which is no where near the expected value i.e. some value ending with 4?
There's nothing wrong with the value you are getting. Your encoding is just fine.
Notice that you are using 32-bit signed integers (implicitly implied by the call to bvsmod.) The model returned gives you the value 32-bit bit-vector value whose decimal equivalent is 3720040335. When interpreted as a signed-value, this is actually -574926961, and you can verify (-574926961) % 5 indeed equals 4 as you requested.
Note that the solver is free to give you any model that satisfies your constraints. If you want a more specific value, you'll need to add additional constraints to encode what "simple" should formally mean.
If you want to write the formula like that, you need quantifiers.
I suggest you use SMT expressions instead; sharing will happen for free.
write e.g.:
(assert (= (bvmul (bvadd x___0 (_ bv1 32)) (_ bv2 32)) (_ bv8 32)))
If you need the intermediate values, you can always later do an (eval ...)

Use Z3 and SMT-LIB to get a maximum of two values

How do I get the maximum of a formula using smt-lib2?
I want something like this:
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(assert (= x 2))
(assert (= y 4))
(assert (= z (max x y))
(check-sat)
(get-model)
(exit)
Of course, 'max' is unknown to smtlibv2.
So, how can this be done?
In Z3, you can easily define a macro max and use it for getting maximum of two values:
(define-fun max ((x Int) (y Int)) Int
(ite (< x y) y x))
There is another trick to model max using uninterpreted functions, which will be helpful to use with Z3 API:
(declare-fun max (Int Int) Int)
(assert (forall ((x Int) (y Int))
(= (max x y) (ite (< x y) y x))))
Note that you have to set (set-option :macro-finder true), so Z3 is able to replace universal quantifiers with body of the function when checking satisfiability.
You've got abs, and per basic math max(a,b) = (a+b+abs(a-b))/2

Resources