I'm trying to learn a little about z3 and the bit vector theory.
My intention is to make a function to get the nibble from a position of the bitvector
This code returns the nibble:
(define-fun g_nibble(
(l ( _ BitVec 12))
(idx (Int))
) ( _ BitVec 4)
(ite
(= idx 1) ((_ extract 11 8) l)
(ite
(= idx 2) ((_ extract 7 4) l)
(ite
(= idx 3) ((_ extract 3 0) l)
(_ bv0 4)
)
)
))
the problem is that i want avoid the multiples ite calls.
I tried to replace ((_ extract 3 0) l) for somthing like ((_ extract (+ 4 idx) idx l) but it doesn't work.
Thanks
P.S: The idea is use z3 from command line (without using any library).
The extract function only takes numerals as arguments, not arbitrary expressions. However, we can shift the expression to one direction and then extract the first or last four bits, e.g. along the lines of
((_ extract 11 8) (bvshl l (bvmul idx four)))
(where idx and four are bit-vector expressions of size 12).
Related
So I'm trying to check whether all values in an array is unique with the following Z3 code.
(declare-const A (Array Int Int))
(declare-const n Int)
(assert (forall ((i Int) (j Int)) (and (and (and (>= i 0) (< i n)) (and (>= j 0) (< j n)))
(implies (= (select A i) (select A j)) (= i j)))))
(check-sat)
I'm quite new to Z3 so I don't quite understand the grammar and stuff, but can anyone tell me whether this code is right, and if not, where's the problem?
The problem as you wrote is unsat, because it says whenever 0 <= i < n and 0 <= j < n, if A[i] = A[j], then i = j. There is no array and a particular n you can pick to satisfy this constraint.
What you really want to write is the following instead:
(declare-const A (Array Int Int))
(declare-const n Int)
(assert (forall ((i Int) (j Int)) (implies (and (>= i 0) (< i n)
(>= j 0) (< j n)
(= (select A i) (select A j)))
(= i j))))
(check-sat)
(get-model)
The above says If it's the case that i and j are within bounds, and array elements are the same, then i must equal j. And this variant would be satisifiable for any n; and indeed here's what z3 reports:
sat
(
(define-fun n () Int
0)
(define-fun A () (Array Int Int)
((as const (Array Int Int)) 0))
)
But note that z3 simply picked n = 0, which made it easy to satisfy the formula. Let's make sure we get a more interesting model, by adding:
(assert (> n 2))
Now we get:
sat
(
(define-fun n () Int
3)
(define-fun A () (Array Int Int)
(lambda ((x!1 Int))
(let ((a!1 (ite (and (<= 1 x!1) (not (<= 2 x!1))) 7 8)))
(ite (<= 1 x!1) (ite (and (<= 1 x!1) (<= 2 x!1)) 6 a!1) 5))))
)
and we see that z3 picked the array to have 3 elements with distinct values at positions we care about.
Note that this sort of reasoning with quantifiers is a soft-spot for SMT solvers; while z3 is able to find models for these cases, if you keep adding quantified axioms you'll likely get unknown as the answer, or z3 (or any other SMT solver for that matter) will take longer and longer time to respond.
I want to define a function that takes in a bitvector and returns true if bits at certain position satisfy some values.
Eg: I need to return true if bitvector is 1x00x01x where x denotes don't care.
My current implemntation is:
(define-fun function_i ((i (_ BitVec 8))) Bool
(and true
(= #b1 ((_ extract 1 1) i))
(= #b0 ((_ extract 2 2) i))
(= #b0 ((_ extract 4 4) i))
(= #b0 ((_ extract 5 5) i))
(= #b1 ((_ extract 7 7) i))
)
)
This is for one variable and there could be many variables with 32 sized bitvectors. I am worried this kind of implementation slows down z3. Would the extract function slow down the solver? Is there a better way to implement this?
That's fine. A more compact way is (i & 1101) == 1000 (force first bit 1, 2nd 0 and last 0, 3rd bit can be 0 or 1)
I know that both bv2int and int2bv are handled as uninterpreted functions in Z3. Still, I am looking for a best practice in solving the following problem: given a "small" (< 10 bits) bitvector index,
how to efficiently cast it to Int, and use in queries like this one:
(declare-const s String)
(declare-const someInt Int)
(declare-const someBitVec10 (_ BitVec 10))
(assert (= s "74g\x00!!#2#$$"))
;(assert (str.in.re (str.at s someBitVec10) (re.range "a" "z")))
( assert (str.in.re (str.at s someInt ) (re.range "1" "3")))
(check-sat)
(get-value (s someInt))
Output:
sat
((s "74g\x00!!#2#$$")
(someInt 7))
Thanks!
Given the following code:
from z3 import *
a,b,c = BitVecs('a b c', 32)
f1 = Exists([a, b, c], And(a + b == c, a < b, c == 1337))
f2 = And(a + b == c, a < b, c == 1337)
prove(f1 == f2)
I would assume that z3 implicitly existential quantifies a, b and c, in this example. Why aren't the two formulas equal, what is the difference?
The way you formulated your query doesn't really check whether f1 equals f2. Your query is essentially asking the solver to find a, b, c such that the following fails to hold:
Exists([a, b, c], And(a + b == c, a < b, c == 1337))
=
And(a + b == c, a < b, c == 1337))
And indeed, you can instantiate the outer a, b, and c such that the right hand-side is false; but the left hand side is an existential which is true; thus failing the equivalence you asked for.
It might be easier to see this with a simpler example; with just one boolean variable. You're essentially asking:
x == (Exists [x], x)
You see that those xs are actually different, so we can rename the inner one to (say) y; we get:
x == (Exist [y]. y)
Now, the right-hand-side is clearly true since there is a y that makes (Exist [y]. y) true. So, you are essentially asking the prover to establish that no matter what x you pick, it is true. Which is definitely not the case when you pick x to be false.
Indeed, you can ask Z3 to give you the formula it's trying to prove, and this is what it returns for your original query:
(set-info :status unknown)
(declare-fun c () (_ BitVec 32))
(declare-fun b () (_ BitVec 32))
(declare-fun a () (_ BitVec 32))
(assert
(let (($x24 (exists ((a (_ BitVec 32))
(b (_ BitVec 32))
(c (_ BitVec 32)) )
(and (= (bvadd a b) c) (bvslt a b) (= c (_ bv1337 32))))))
(let (($x57 (= $x24 (and (= (bvadd a b) c) (bvslt a b) (= c (_ bv1337 32))))))
(and $x57))))
(check-sat)
Which is clearly satisfiable, by the above reasoning.
(See Z3: convert Z3py expression to SMT-LIB2 from Solver object for the code that converts a z3-python query to smt-lib.)
I am trying to use the function Z3_benchmark_to_smtlib_string(). Here are the arguments I am using:
Z3_benchmark_to_smtlib_string(
ctx, /* this one is valid */
"test", /* this one is random, I don't understand it */
"QF_UFBV", /* I got this name from the smtlib website, valid ? */
"sat", /* not sure about this one either */
NULL, /* not sure about this one either */
nb_assumptions, /* should be ok */
assumptions, /* should be ok too */
NULL); /* not sure about this one, is this mandatory ? */
Any help would be welcome.
In parallel, I am using displaying my assumptions on the fly, using:
Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB2_COMPLIANT);
en get strange characters like : ?x21, ?x24, ?x37, (see below). Any hint to solve this issue ?
Thanks in advance,
A.G.
(let ((?x21 (bvand (_ bv582 32) (ite (= ((_ sign_extend 24) (_ bv98 8)) ((_ sign_extend 24) |Mem5[8]|)) (_ bv64 32) (_ bv0 32)))))
(let ((?x24 (bvand ?x21 (ite (bvsgt ((_ sign_extend 24) (_ bv98 8)) ((_ sign_extend 24) |Mem5[8]|)) (_ bv128 32) (_ bv0 32)))))
(let ((?x37 (bvand ?x24 (ite (= ((_ sign_extend 24) (_ bv97 8)) ((_ sign_extend 24) |Mem6[8]|)) (_ bv64 32) (_ bv0 32)))))
(bvand ?x37 (ite (bvsgt ((_ sign_extend 24) (_ bv97 8)) ((_ sign_extend 24) |Mem6[8]|)) (_ bv128 32) (_ bv0 32))))))
This function is quite old. It was created when SMT 2.0 didn't exist. A SMT 1.0 benchmark looks like that:
(benchmark example
:status sat
:logic QF_LIA
:extrafuns ((x1 Int) (x2 Int) (x3 Int) (x4 Int) (x5 Int))
:assumption (>= (- x1 x2) 1)
:assumption (>= (- x1 x2) 3)
:assumption (= x3 x5)
:formula (= x2 (* 6 x4))
)
The function you are using was meant for producing a benchmark in this format. That is why we have parameters such as name, logic, status, etc. They correspond to the annotations in the example above. Moreover, a SMT 1.0 problem consists of 0 or more assumptions and 1 formula.
When SMT 2.0 was introduced, this method was extended to print benchmarks in SMT 2.0 format when we have
Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB2_COMPLIANT);
The strange characters are just auxiliary let declarations used to avoid an exponential blowup when printing formulas. Note that, Z3 ASTs are DAGs and not trees. It is very easy to create a DAG using the C API that has a lot of sharing. Example:
a_1 = Z3_mk_bvadd(b, c)
a_2 = Z3_mk_bvmul(a1, a1)
a_3 = Z3_mk_bvadd(a2, a2)
a_4 = Z3_mk_bvmul(a3, a3)
...
The AST a_100 is a very compact object in memory. If we try to print it as a tree without using the auxiliary let declarations, the output will be very huge.
Note that the output produced by this function was never meant to be consumed by humans. It is mainly used to generate benchmarks for the SMT-LIB repository.