Simple byte array in Z3 (SMT) - z3

I try make a simple example for checking bytes in fixed array. I read also Z3 tutorials but i can't get it working. Here is may scenario:
I have fixed byte array with length of 16: T(16)
I have these conditions to check:
A = (T(16) + 1) And 0x0F
T(A) = 0x76
0x01 <= A <= 0x7F
It mean take byte from T(16) add 1, make AND with 0x0F, and assign result number to variable A.
Now check if in array T on position A T(A) is number 0x76. Also A can be between values 0x01 and 0x7F.
These conditions are repeating for more positions in array, but I need get it working just for first case. The goal of this is: find right order of known bytes in fixed array based on given equations.
I try it with this script but doesn't work.
Error: operator is applied to arguments of the wrong sort.
(declare-const t (Array Int Int))
(declare-const a Int)
; A = (t(16) + 1) And 0x0F
(assert (= a (bvand (+ (select t 16) 1) #x0F)))
; t(A) = 0x76
(assert (= (select t a) #x76))
(check-sat)
;(get-model)
Example:
on T(16) is value 0x14, + 1 = 0x15, AND 0x0F = 0x05, on T(0x05) should be value 0x76.
Thank you.

You can't mix integers and bitvectors like that and there is no need. Use bitvectors of size 8 in all cases. Don't use Int.
Besides that this will work.
You might find that not using arrays but only bitvectors is faster. This is something to experiment with.

Related

Rounded floating-point number comparison issue

Working on an analyzer based on Z3 (this analyzer should detect overflows when doubles converted to long/ulong in .net), I came across a strange thing related to floating-point numbers.
Finally, I've created a small sample that shows the issue:
Both:
(assert (= ((_ fp.to_sbv 64) roundTowardZero (fp #b0 #b10000111110 #x0000000000000)) #x8000000000000000))
(check-sat)
and:
(assert (not (= ((_ fp.to_sbv 64) roundTowardZero (fp #b0 #b10000111110 #x0000000000000)) #x8000000000000000)))
(check-sat)
give me sat.
How could it happen that a rounded floating-point number may be equal to some value, and at the same time it may not be equal?
The floating point constant evaluates to
(-1)^0 * 2^(1086 - 1023) * (1 + 0) = 2^63
A Signed Bit-Vector of size e can hold values in the range [-2^(e-1), 2^(e-1) - 1]. Thus, the range of a Signed Bit-Vector of size 64 is [-2^63, 2^63 - 1].
Because 2^63 is outside that range, the conversion of 2^63 to a Signed Bit-Vector of size 64 is undefined:
In addition, fp.to_ubv and fp.to_sbv are unspecified for finite number inputs that are out of range (which includes all negative numbers for fp.to_ubv).
(source: SMT-LIB docs)
Since the conversion is undefined, the following expression
((_ fp.to_sbv 64) roundTowardZero (fp #b0 #b10000111110 #x0000000000000))
may have an arbitrary, unconstrained, 64-bit Bit-Vector value.
This explains why the equality can be found to be both true and false.
I assume you made those assertions separately of another, i.e. you asked Z3 if P is satisfiable, and (separately) if ¬P is satisfiable. This is different from asking if P ∧ ¬P is satisfiable. As an example, assume P is n = 0, for some integer n. Clearly, n could be 1, in which case ¬(n = 0) is satisfied, and n could be 0, in which case n = 0 is satisfied.

Can you limit a real variable between two bounds?

Can you limit a real variable between two bounds?
s = Solver()
input = Reals('input')
s.add(input >= -2, input <= 2)
This example return unsat for me.
In cases like this, the sexpr method of the Solver class is your friend!
You're tripping up because of the extremely weakly typed nature of the z3py bindings. The call Reals returns multiple results, which you are assigning to a single element. That is, your input variable is now a list containing one variable. This, in turn, makes the whole program meaningless, as you can observe yourself:
from z3 import *
s = Solver()
input = Reals('input')
s.add(input >= -2, input <= 2)
print s.sexpr()
This prints:
(assert true)
(assert false)
Why? Because your variable input is a list, and the bizarre rules of type promotion decided that a list is greater than or equal to -2 but less than 2. (This is totally meaningless, just the way the bindings work. There's no rhyme or reason it should be this way. One can argue it should do more type-checking and give you a proper error. But I digress.)
To solve, simply change your call of Reals to Real:
from z3 import *
s = Solver()
input = Real('input')
s.add(input >= -2, input <= 2)
print s.sexpr()
print s.check()
print s.model()
This prints:
(declare-fun input () Real)
(assert (>= input (- 2.0)))
(assert (<= input 2.0))
sat
[input = 0]
which is exactly what you wanted to say.

Z3,C++ API, How to convert bool sort to int sort

I am using Z3 in C++, and I have some bool-sort exprs.
What I want to do is to count the number of true-value exprs.
A very simple way is to convert those expr into int-sort and then add them up.
However I don't know how to convert bool to int.
Thanks!
SOLUTION:
As the cpp example file shows(function ite_example2()):
expr b = c.bool_const("x");
expr x = c.int_val(1);
expr y = c.int_val(0);
expr conj = ite(b,x,y);
Pseudo-boolean functions
For counting booleans, and asserting how many are true etc. (mutex like conditions), pseudo-boolean functions are your friends:
https://github.com/Z3Prover/z3/blob/master/src/api/c%2B%2B/z3%2B%2B.h#L949-L953
These functions allow you to assert constraints that let you create cardinality conditions, which is what I suspect you are trying to do in the first place. These functions generate much better code for z3 to solve, compared to any other indirect encoding. Here's a discussion on it, based on the python interface: K-out-of-N constraint in Z3Py
Direct counting
You can also do a direct count of course, but you should prefer the above functions if they suit your need. If you really do want to get an integer, you'll have to use:
int_val: create a number expression
ite: if-then-else
sum: create a sum
Essentially creating the expression (pseudo-code):
z = int_val(0);
o = int_val(1);
sum(ite(b1, o, z), ite(b2, o, z), ...)
But you should really stick to pseudo-booleans if at all possible.
#include <iostream>
using namespace std;
int main() {
int a = 6;
a += (int)true;
cout << a << "\n";
}
It's been a long time I used Z3, but I think you should be able to define a function that will effectively project true=>1 and false=>0 (or the other way).
Assuming that you are doing it the script it would look similar to
(declare-fun boolToIntDirect (Bool) Int)
(assert (= (boolToIntDirect false) 0))
(assert (= (boolToIntDirect true) 1))
(declare-fun boolToIntNegated (Bool) Int)
(assert (= (boolToIntNegated false) 1))
(assert (= (boolToIntNegated true) 0))
Then, if you construct an expression using that function, it will do the conversion, and will also report any problems like i.e. getting non-bool argument.
There are built-in functions in Z3 for counting "k amongst N" and other variants.
They should usually be preferred as they offer better performance due to dedicated strategies.
((_ at-most k) x y z)
this means at most k of the Booleans x, y, z... are true.
See this other question for more details, and the comment by Nikolaj Bjorner on the answer for the SMT syntax of the variants.
K-out-of-N constraint in Z3Py

Z3: How to best encode a "switch statement"?

I want to create an expression that selects one of a given set of expressions. Given an array of expressions
Expr[] availableExprs = ...;
with statically known length, I want Z3 to select any one of these (like a switch statement). In case the problem is SAT I need a way to find out which of these was selected in the model (its index in the array).
What is the fastest way to encode this?
I considered these approaches so far:
Have an integer restricted to [0, arrayLength) and use ITE to select one of those expressions. The model allows me to extract this integer. Unfortunately, this introduces the integer theory to the model (which previously did not use integers at all).
Have one boolean for each possible choice. Use ITE to select an expression. Assert that exactly one of those booleans is true. This strategy does not need any special theory (I think) but the encoding might be too verbose.
Store the expressions into an array expression and read from that array using an integer. This saves the ITE chain but introduces the array theory.
Clearly, all of these work, but they all seem to have drawbacks. What is the best strategy?
If all you want is to encode is that an element v is in a finite set {e1, ..., en} (with sort U), you can do this using smtlib2 as follows:
(declare-fun v () U)
(declare-fun p1 () Bool)
...
(assert (= p1 (= v e1)))
(assert (= p2 (= v e2)))
...
(assert (= pn (= v en)))
(assert (or p1 ... pn))
The variable v will be equal to one of the elements in "the array" of {e1 ... en}. And pi must be true if the selection variable v is equal to ei. This is basically a restatement of Nikolaj's suggestion, but recast for arbitrary sorts.
Note that multiple pi may be set to true as there is no guarantee ei != ej. If you need to ensure no two elements are both selected, you will need to figure out what semantics you want. If the {e1... en} are already entailed to be distinct, you don't need to add anything. If the "array" elements must be distinct but are not yet entailed to be distinct, you can assert
(assert (distinct e1 ... en))
(This will probably be internally expanded to something quadratic in n.)
You can instead say that no 2 p variables can be true as once. Note that this is a weaker statement. To see this, suppose v = e1 = 1 and e2 = e3 = 0. Then p1 = true and p2 = p3 = false. The obvious encoding for these constraints is quadratic:
(assert (or (not pi) (not pj))) ; for all i < j
If you need a better encoding for this, try taking a look at how to encode "p1+ ... + pn <= 1" in Translating Pseudo-Boolean Constraints into SAT section 5.3. I would only try this if the obvious encoding fails though.
I think you want to make sure that each expression is quantifier free and uses only functions and predicates already present in the formula. If this is not the case then introduce a fresh propositional variable p_i for each index and assert ctx.MkIff(p_i, availableExprs[i]) to the solver.
When Z3 produces a model, use model.Eval(p_i) and check if the result is the expression "True".

Performance issue with unsatisfiable models

I'm using Z3 to construct a bounded model-checker. I'm running into a strange performance problem when trying to implement a completeness test. The completeness test has to make sure that all states that every path contains each state at most once. If there are still paths which fulfill this property, Z3 is quick with an answer, however in the case where all paths have been considered, Z3 seems to be exponentially slow.
I've reduced my test-case to the following:
; Set the problem size (length of path)
(define-fun sz () Int 5)
; Used to define valid states
(define-fun limit ((s Int)) Bool
(and (>= s 0)
(<= s sz)))
; Constructs a path of a given length
(define-fun path-of-len ((path (Array Int Int)) (len Int)) Bool
(forall ((i Int))
(=> (and (>= i 0)
(< i len))
(limit (select path i)))))
; Asserts that a given path only contains unique states
(define-fun loop-free ((path (Array Int Int)) (len Int)) Bool
(forall ((i Int) (j Int))
(=> (and (>= i 0)
(>= j 0)
(< i len)
(< j len)
(not (= i j)))
(not (= (select path i) (select path j))))))
; Construct a unique path of a given length
(define-fun path ((path (Array Int Int)) (len Int)) Bool
(and (path-of-len path len)
(loop-free path len)))
; Declare a concrete path
(declare-const tpath (Array Int Int))
; Assert that the path is loop free
(assert (path tpath (+ sz 2)))
(check-sat)
On my computer this results in the following running times (depending on path length):
3: 0.057s
4: 0.561s
5: 42.602s
6: >15m (aborted)
If I switch from Int to bitvectors of size 64, the performance gets a little better, but still seems exponential:
3: 0.035s
4: 0.053s
5: 0.061s
6: 0.106s
7: 0.467s
8: 1.809s
9: 2m49.074s
Strangely enough, for a length of 10 it only takes 2m34.197s.
If I switch to bitvectors of smaller size, the performance gets a little better, but is still exponential.
So my question is: Is this to be expected? Is there a better way to formulate this "loop-free" constraint?
Your formula is essentially encoding the “pigeon-hole” problem.
You have sz+1 holes (the values 0, 1, …, sz) and sz+2 pigeons (the array cells (select tpath 0), …, (select tpath (+ sz 1))).
You first quantifier is stating that each pigeon should be put in one of the holes.
The second is stating that two different pigeons should not be in the same hole.
There is no polynomial size resolution proof for the “pigeon-hole” problem.
So, the exponential growth in run time is expected.
Note that any SAT solver based on resolution, DPLL, or CDCL will perform badly on the pigeon-hole problem..
You get better performance when using bit-vectors because Z3 reduces them to propositional logic and case analysis is much more efficient at that level.
BTW, you are using quantifiers for encoding parametric problems.
That is an elegant solution, but it is not the most efficient approach for Z3.
For Z3, in general, it is better to assert the 'expanded' quantifier free problem.
However, for the problem described in your question, it will not make a big difference, since you will still experience the exponential growth.
Just like what Leonardo said, since the pigeon-hole problem is exponential in nature, the performance will go bad eventually whatsoever. The only thing you could probably do is to postpone the time the performance goes bad. Since you have tried bit-vector, my suggestions are try converting the problem into quantifier-free problem as suggested by Leonardo, given that the problem size is pre-defined, and try using some tactics.

Resources