how to eliminate bitvector arithmetic in Z3 - z3

I am trying to use the z3 to eliminate the expression
not ((not x) add y)
which equals to
x sub y
by this code:
(declare-const x (_ BitVec 32))
(declare-const y (_ BitVec 32))
(assert (= (bvnot (bvadd (bvnot x) y)) (bvsub x y)))
(check-sat)
(simplify (bvnot (bvadd (bvnot x) y)))
I want to get the result like:
sat
(bvsub x y)
However, the result is:
sat
(bvnot (bvadd (bvnot x) y))
Would some one help me out?

We can prove that (bvnot (bvadd (bvnot x) y)) is equivalent to (bvsub x y) using the following script.
(declare-const x (_ BitVec 32))
(declare-const y (_ BitVec 32))
(assert (not (= (bvnot (bvadd (bvnot x) y)) (bvsub x y))))
(check-sat)
In this script, we used Z3 to show that (not (= (bvnot (bvadd (bvnot x) y)) (bvsub x y))) is unsatisfiable. That is, it is not possible to find values for x and y such that the value of (bvnot (bvadd (bvnot x) y)) is different from the value of (bvsub x y).
In Z3, the simplify command just applies rewriting rules, and it ignores the set of asserted expressions. The simplify command is much faster than checking satisfiability using check-sat. Moreover, given two equivalent expressions F and G, there is not guarantee that the result of (simplify F) will be equal to (simplify G). For example, in Z3 v4.3.1, the simplify command produces different results for (= (bvnot (bvadd (bvnot x) y) and (bvsub x y), although they are equivalent expressions. On the other hand, it produces the same result for (= (bvneg (bvadd (bvneg x) y) and (bvsub x y).
(simplify (bvnot (bvadd (bvnot x) y)))
(simplify (bvneg (bvadd (bvneg x) y)))
(simplify (bvsub x y))
Here is the full script for the examples above.
BTW, these examples are much more readable if we use the Z3 Python interface.
x, y = BitVecs('x y', 32)
prove(~(~x + y) == x - y)
print simplify(x - y)
print simplify(~(~x + y))
print simplify(-(-x + y))
Finally, Z3 has more complex simplification procedures. They are available as Tactics. The tutorials in Python and SMT 2.0 format provide additional information.
Another possibility is to modify the Z3 simplier/rewriter. As you pointed out, not x is equivalent to -x -1. We can easily add this rewrite rule: not x --> -x - 1 to the Z3 rewriter.
As an example, in this commit, I added a new option called "bvnot2arith" that enables this rule.
The actual implementation is very small (5 lines of code).

Related

Decidable sqrt function in Z3

Since disabling unsound simplification of root objects, Z3 will now fail on this simple model involving a square root:
(define-fun sqrt ((x Real)) Real (^ x 0.5))
(declare-fun y () Real)
(declare-fun x () Real)
(assert (= y (sqrt x)))
(check-sat)
This returns sat with Z3 4.4.1, but unknown with master.
If I change the problem definition to use is_sqrt as defined by Nikolaj in this question, then Z3 master will return sat. The approach using is_sqrt shows that all real roots can be pushed into QF_NRA by introducing auxiliary variables, so I think Z3 should be able to solve all problems involving roots over the reals.
How can I define a square-root function in the reals that will result in a decidable theory, assuming the rest of the model is in QF_NRA?
There is a subtle difference between (assert (= y (^ x 0.5))) and (assert (and (= x (* y y)) (> y 0.0))). The difference comes from the requirement that all functions in Z3 (and SMT-LIB) are total. This means, for example, that y=1/x, x=0 is considered satisfiable. Given that ^ is total in Z3, (assert (and (= y (^ x 0.5)) (< x 0.0))) is considered satisfiable. We can't convert (= y (^ x 0.5)) to (and (= x (* y y)) (> y 0.0)), because if x < 0 then the former is considered satisfiable but the latter is unsatisfiable. Similarly, any sqrt function defined within SMT-LIB would also be total, so we cannot define a sqrt function by any other means such that (assert (= y (sqrt x))) is equivalent to (assert (and (= x (* y y)) (> y 0.0))). In addition to the above difference as to whether or not y = sqrt(x), x < 0 (pseudocode) is considered satisfiable, it is also the case that (assert (and (= x (* y y)) (> y 0.0))) is decidable (it is in QF_NRA), while (assert (= y (^ x 0.5))) is not.
The solution for my purpose is to not use a Z3 or SMT-LIB function definition for the square-root. Instead, I will use statements of the form (assert (and (= x (* y y)) (> y 0.0))) to indicate that y is the square-root of x. Such assertions are within QF_NRA, so models built in this way will be decidable. Furthermore, this has the advantage that y = sqrt(x), x < 0 (pseudocode) will return unsat if it is represented in SMT-LIB via the statements (assert (and (= x (* y y)) (> y 0.0))) and (assert (< x 0.0)). To return unsat for this example is more in-line with my use case.

Bitvector arithmetics on Z3

I'm trying to use Z3 to solve arithmetic equations using bitvector arithmetic. I was wondering if there is a way to handle also Real numbers. For example if I can specify a constant different from #x1 and use real number instead.
(set-option :pp.bv-literals false)
(declare-const x (_ BitVec 4))
(declare-const y (_ BitVec 4))
(assert (= (bvadd x y) #x1))
(check-sat)
(get-model)
Yes, both SMT-Lib (and Z3) fully support real numbers: http://smtlib.cs.uiowa.edu/theories-Reals.shtml
You can simply write your example as follows:
(declare-const x Real)
(declare-const y Real)
(assert (= (+ x y) 1))
(check-sat)
(get-model)
You can also mix/match Int/Real/Bitvector, so long as everything is properly typed. Here's an example showing how to use Ints and Reals together:
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(declare-const d Real)
(declare-const e Real)
(assert (> e (+ (to_real (+ a b)) 2.0)))
(assert (= d (+ (to_real c) 0.5)))
(assert (> a b))
(check-sat)
(get-model)
However, note that conversion from bit-vectors to integers is usually uninterpreted. See here for a discussion: Z3 int2bv operation

z3: What might be the reason for timeout (rise4fun)

The problem is: timeout when I try it in rise4fun:
I already tried not to use "forall", but it doesn't work too.
(declare-const x Real)
(declare-const y Real)
(declare-const t Real)
(declare-const u Real)
(declare-const v Real)
(declare-const w Real)
(declare-fun f (Real) Real)
(assert (forall ((x Real) (y Real)) (<= (+ (f x) (f y)) (* 2 (f (/ (+ x y) 2))))))
(assert (<= (+ 2 (f (* 2 (+ t u))) (f (* 2 (+ v w))) (f (+ t u v w))) (+ 2 (* 3 (f (+ t u v w))))))
(check-sat)
(get-model)
Can anybody help?
The example uses both non-linear arithmetic, functions and quantifiers.
Z3 does not handle this combination in any particular way.
The latest version of Z3 does terminate quickly in default mode without the quantifier, but mainly by being lucky as opposed to using a
decision procedure, in this case. With the quantifier, however, tZ3 enters
a search space where it is unable to solve for the function f.

Z3 timeout after replacement of uninterpreted sort to Int

For formula with uninterpreted sort B Z3 prints unsat but when I replace sort B to Int it prints timeout(second script). I would like to understand the reason for it.
first:
(declare-sort A)
(declare-sort B)
(declare-fun f (B) A)
(declare-fun f-inv (A) B)
(declare-const b0 B)
(declare-const b1 B)
(assert (forall ((x B)) (= (f-inv (f x)) x)))
(assert (not (= (f b0) (f b1))))
(check-sat)
second:
(declare-sort A)
(declare-fun f (Int) A)
(declare-fun f-inv (A) Int)
(assert (forall ((x Int)) (= (f-inv (f x)) x)))
(assert (not (= (f 0) (f 1))))
(check-sat)
The reason is that Z3 is not able to decide neither "first" and "second".
For "first" I am obtaining : "sat".
For "first" when the line
(assert (not (= (f b0) (f b1))))
is replaced by
(assert (= (f b0) (f b1)))
the result is "sat". In other words Z3 is not able to decide "first". The effective result from Z3 is "timeout" for "first" and "second".
Z3 has problems with combinations of uninterpreted functions.
Do you agree?
Both versions are now sat when tried online on Compsys tools.

How to introduce the infinity in the Tropical Arithmetic using Z3

The following code introduces the basic properties of the Tropical Arithmetic using Z3 with SMT-LIB:
; This example illustrates basic tropical arithmetic
(define-fun tropadd ((a Real)(b Real)) Real (if (> a b)
b
a))
(define-fun tropmul ((a Real)(b Real)) Real (+ a b))
(declare-fun x () Real)
(declare-fun y () Real)
(declare-fun z () Real)
(push)
(assert(not(= (tropadd x y) (tropadd y x))))
(check-sat)
(pop)
(push)
(assert(not(= (tropmul x y) (tropmul y x))))
(check-sat)
(pop)
(push)
(assert(not(= (tropmul x (tropmul y z)) (tropmul (tropmul x y) z))))
(check-sat)
(pop)
(push)
(assert(not(= (tropadd x (tropadd y z)) (tropadd (tropadd x y) z))))
(check-sat)
(pop)
(push)
(assert(not(= (tropmul x (tropadd y z)) (tropadd (tropmul x y) (tropmul x z)))))
(check-sat)
(pop)
(push)
(assert(not(= (tropmul x 0) x)))
(check-sat)
(pop)
(push)
(assert (= (tropmul x 2) 3))
(check-sat)
(get-model)
(pop)
(push)
(assert (= (tropadd x 2) 1))
(check-sat)
(get-model)
The output is:
unsat
unsat
unsat
unsat
unsat
unsat
sat
(model (define-fun x () Real 1.0)
sat
(model (define-fun x () Real 1.0) )
Please run this code online here
This code introduces the tropical addition and the tropical multiplication. Then is proved that these operations satisfy: commutative, associate, distributive; and modulative for the tropical multiplication.
With the aim to satisfy the modulative for the tropical addition is necessary to introduce
the infinity, it is to say a new symbol such: infinity + a = a for all a.
Please, can you teach me how to introduce such infinity in the tropical code. Many thanks.
You'd have to define a new type, some sort of a discriminating union to include the infinity; and extend your operations to cover this new type. The standard way to do this in SMT-Lib is to introduce an uninterpreted sort, and then assert the definitions of mul/add etc., as appropriate axioms over it. How well the underlying solver will handle such axioms really will depend on how well it handles quantifiers and what sort of problems you throw at it, since those axioms will no doubt involve quantifiers.
An alternative is to use a higher-level approach, such as advocated by Z3Py or SBV (Haskell bindings to Z3 and other SMT solvers), where you can hide most of the machinery in the high-level structure as afforded by those languages. That's what I would try first, as SMT-Lib can get quite verbose and error-prone when you deal with a lot of uninterpreted sorts, axioms, etc.

Resources