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)
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 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!
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).
I want to transform the bitvector theory into int theory in Z3, and when encounter the "bvnot" operation, I relpace it with "not", here is a simple example:
(assert (= (bvnot (ite (bvsle t0 #x0a) #b1 #b0)) #b1))
and after transformation :
(assert (= (not (ite (< t0 10) 1 0)) 1))
However, Z3 reported error with this assertion:
invalid function application for not, sort mismatch on argument at position 1, expected Bool but given Int
How can I convert int sort to boolean sort?
Tanhks!
Jin
You already have everything in place, but the constants 1 and 0 are not Boolean values; the corresponding values are true and false, i.e., this should work:
(assert (= (not (ite (< t0 10) true false)) true))
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.