unsat core function in z3 - z3

Suppose I read the SMTLIB formula using the API:
context ctx;
...
expr F = to_expr(ctx, Z3_parse_smtlib2_file(ctx,argv[1],0,0,0,0,0,0));
The expression F is a conjunction of assertions of the form:
(and (< (+ x y) 3)
(> (- x1 x2) 0)
(< (- x1 x2) 4)
(not (= (- x1 x2) 1))
(not (= (- x1 x2) 2))
(not (= (- x1 x2) 3)))
I'd like to extract each individual assertion from this conjunction using the following code fragment from post: How to use z3 split clauses of unsat cores & try to find out unsat core again
F = F.simplify();
for (unsigned i = 0; i < F.num_args(); i++) {
expr Ai = F.arg(i);
// ... Do something with Ai, just printing in this example.
std::cout << Ai << "\n";
}
After utilizing the F.arg(i), the original clause (< (+ x y) 3) has been changed into (not (<= 3 (+ x y))). Here is my
a) question : How can I place the clause (not (<= 3 (+ x y))) to (< (+ x y) 3) ?
b) question : I consider the symbol <= mean to imply in this case, not mean to less than. Am I right?
c) question : Because the clause (not (<= 3 (+ x y))) model is true or false, how can I get arithmetic values such as x = 1, y = -1?
It's very grateful for any suggestion.
Thank you very much.

The expression (< (+ x y) 3) is transformed into (not (<= 3 (+ x y))) when F = F.simplify().
In the code fragment you used, the method simplify() is used to "flat" nested "and"s. That is, a formula (and (and A B) (and C (and D E))) is flattened into (and A B C D E). Then, all conjuncts can be easily traversed using the for-loop. However, the simplify() will also perform other transformations in the input formula. Keep in mind, that all transformation preserve equivalence. That is, the input and output formula are logically equivalent. If the transformations applied by simplify() are not desirable, I suggest you avoid this method. If you still want to traverse nested "and"s, you can use an auxiliary todo vector. Here is an example:
expr_vector todo(c);
todo.push_back(F);
while (!todo.empty()) {
expr current = todo.back();
todo.pop_back();
if (current.decl().decl_kind() == Z3_OP_AND) {
// it is an AND, then put children into the todo list
for (unsigned i = 0; i < current.num_args(); i++) {
todo.push_back(current.arg(i));
}
}
else {
// do something with current
std::cout << current << "\n";
}
}

Related

Negation in z3 datalog for expressing optimality

I use Z3 with :fixedpoint.engine set to datalog.
I have an enumerated filter relation (f pos min max). Let us say that we have (f #x10 #x100000 #x200000), (f #x20 #x150000 #x200000) and (f #x20 #x300000 #x500000).
For a given x, I search the greatest pos such that (f pos min max) and min <= x <= max (Here I use intervals but filters can be arbitrarily complex). Priority (sort t) and values (sort s) are BitVectors but x, min and max are on a rather large space (eg. 24 bits).
; configuration
(set-option :fixedpoint.engine datalog)
; sorts
(define-sort s () (_ BitVec 24))
(define-sort t () (_ BitVec 8))
; Relations
(declare-rel f (t s s))
(declare-rel match (t s))
(declare-rel better (t s))
(declare-rel best (t s))
(declare-rel a (t))
(declare-rel b ())
(declare-rel c ())
(declare-var x s)
(declare-var xmin s)
(declare-var xmax s)
(declare-var p t)
(declare-var q t)
; Facts (EDB)
(rule (f #x10 #x100000 #x200000))
(rule (f #x20 #x150000 #x200000))
(rule (f #x20 #x300000 #x500000))
; Rules
(rule (=> (and (f p xmin xmax) (bvule xmin x) (bvule x xmax))
(match p x)))
(rule (=> (and (match q x) (bvugt q p))
(better p x)))
(rule (=> (and (match p x) (not (better p x)))
(best p x)))
; Queries
(rule (=> (match p #x170000) (a p)))
(rule (=> (better #x10 #x170000) b))
(rule (=> (best #x10 #x170000) c))
; output: sat
; (or (= (:var 0) #x20) (= (:var 0) #x10))
(query (a p) :print-answer true)
; output: sat
(query b)
; Output 'WARNING: creating large table of size 16777216 for relation better' and fails
(query c)
(match p x) codes the fact that a filter at priority p filters x.
(better p x) if a rule with a better priority than p filters x.
(best p x) codes that the best filter matching x has priority p.
If I query (match p #x170000), I quickly get #x10 and #x20. If I ask (better #x10 #x170000) I quickly get
an answer same for priority #20. But the query on (best p #x170000) fails to execute in reasonable time and reasonable space.
It seems that (not (better p x)) is computed independently of (match p x) and so is represented by a very large table (the possible values of x are not forwarded). In some cases I can restrict x by some tricks in better (sometimes I know that I am only interested by x that explicitly appear in other relations) so that the space is reduced but this is not a real generic solutions and sometimes I am stuck.
How should I rephrase the problem or which options should I use to avoid this problem ?
Z3's default Datalog tables are over concrete values, so if you use large bit-vectors, Z3 may end-up creating huge tables.
You can try a simpler table data-structure, that supports fewer operations but it's sparse (uses "don't care" bits).
You can try it out with: z3 fixedpoint.engine=datalog fixedpoint.datalog.default_relation=doc file.smt2

Getting the domain of an Int with z3

Is there any way of get the specific domain of an Integer variable with z3 (assuming the variable belong to a finite domain)?
I have the following set of constraints:
1 <= X <= 5
2 <= Y <= 8
X + Y == T
and I would like to obtain:
3 <= T <= 13
Or even a simpler case:
1 <= X <= 10
5 <= X <= 15
I want to get:
5 <= X <= 10
This seems to be pretty trivial, but I didn't find a way to obtain such an answer with z3.
You can use Z3's optimization routines to solve these sorts of constraints. Your first problem can be coded as:
(declare-const X Int)
(declare-const Y Int)
(declare-const T Int)
(assert (<= 1 X 5))
(assert (<= 2 Y 8))
(assert (= (+ X Y) T))
(push)
(minimize T)
(check-sat)
(pop)
(maximize T)
(check-sat)
To which z3 responds:
sat
(objectives
(T 3)
)
sat
(objectives
(T 13)
)
Which, if you squint right, is saying 3 <= T <= 13; as you were trying to find out.
You can also use the Python interface to do the same. Your second example can be coded in z3py as follows:
from z3 import *
X = Int('X')
s = Optimize()
s.add(1 <= X); s.add(X <= 10)
s.add(5 <= X); s.add(X <= 15)
s.push()
s.minimize(X)
s.check()
print s.model()
s.pop()
s.maximize(X)
s.check()
print s.model()
which produces:
[X = 5]
[X = 10]
indicating 5 <= X <= 10.
Getting min/max with one call
If you want to avoid two calls to the solver, then you can use the box parameter to optimization, which optimizes the objectives independently:
(declare-const X Int)
(declare-const Y Int)
(declare-const T Int)
(assert (<= 1 X 5))
(assert (<= 2 Y 8))
(assert (= (+ X Y) T))
(minimize T)
(maximize T)
(set-option:opt.priority box)
(check-sat)
Now, z3 responds:
sat
(objectives
(T 3)
(T 13)
)
which contains the results in the order given, i.e, 3 for minimize and 13 for maximize.

How to model variable swap in SMT (Z3)?

I have a program that sorts variables, and I'm trying to check its validity with Z3, but I have one code segment where the variables are being swapped and I don't know how to model it in SMT syntax. Here is the original code segment:
if (x > y) {
temp = x;
x = y;
y = temp;
}
And regarding the SMT I have written an assertion, but I guess it is not exactly the correct thing:
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun temp () Int)
(assert (=> (> s1 s2) (and (= tmp s1) (= s1 s2) (= s2 tmp))))
Any ideas how to do variable assignment in SMT?
You should look into Single Static Assignment [1]. In this way you can rewrite your original code as follows.
if (x0 > y0) {
temp0 = x0;
x1 = y0;
y1 = temp0;
}
It thus becomes clear that you have two different instances of x and y. The first (x0, y0) is the one you are comparing in the if condition. The second (x1, y1) is the result of the operation.
This introduces an implicit notion of time that makes it also easier to write properties about your code. E.g.,
((x1 = x0) & (y1 = y0)) | ((x1 = y0) | (y1 = x0))
Of course, this might require adjusting other parts of your code, so that you are using the right variables.
[1] https://en.wikipedia.org/wiki/Static_single_assignment_form
We can rewrite what you want using a single expression as a tuple:
(result1, result2) = x > y ? (x, y) : (y, x)
Z3 supports tuples but I'm less experienced with that. It's probably easier to blast this into parts:
result1 = x > y ? x : y
result2 = x > y ? y : x
And the ?: operator maps to ITE in Z3.
You don't even need "temp variables" for this (but clearly you can).
(assert (=> (> s1 s2) (and (= tmp s1) (= s1 s2) (= s2 tmp))))
I think this is revealing that you don't understand that Z3 "variables" are actually constants and you cannot actually swap them. In each model they take on a single value only. There is no temporal component to constants. = means "is equal?" and not "make it equal!".

Z3 to show that if a^3=x*y*z then 3a <= x+y+z

I'm a total newbie with Z3 (started today). So far liking it a lot. Great tool. Unfortunately the syntax confuses me a bit.
I want to prove that if:
a^3 = xyz = m ( with a, x, y, z, m (0..1) )
then:
3a <= (x+y+z)
I do so by trying to find a model satisfying that:
3a > (x+y+z)
Here is the Z3 code:
(declare-const a Real)
(declare-const x Real)
(declare-const y Real)
(declare-const z Real)
(declare-const m Real)
(assert (> a 0))
(assert (< a 1))
(assert (> x 0))
(assert (< x 1))
(assert (> y 0))
(assert (< y 1))
(assert (> z 0))
(assert (< z 1))
(assert (> m 0))
(assert (< m 1))
(assert (= (* (* a a) a) m))
(assert (= (* (* x y) z) m))
(assert (> (* 3.0 a) (+ (+ z y) x) ))
(check-sat)
The model is unsatisfied.
Have I successfully proved what I wanted? As I said, the syntax confuses me since I'm a total newbie.
Your solution is correct.
Explanation: What you wrote is equivalent to:
0 < x < 1
0 < y < 1
0 < z < 1
0 < m < 1
a * a * a = m
x * y * z = m
3 * a > x + y + z
Z3 says this is unsatisfiable. Thus, if
a^3 = xyz = m ( with a, x, y, z, m (0..1) )
then it cannot be the case that:
3a > (x+y+z)
because, if this did occur, then the SMT problem you posed would be satisfiable, which would be a contradiction with the claim by Z3 that the SMT problem is unsatisfiable. If it cannot be the case that 3a > (x+y+z), then it must be the case that 3a <= (x+y+z), which is the statement you originally wanted to prove.
I think that your solution is correct. Let me explain a bit about using Z3 to prove validity of a statement A. The key idea is that, in the classical logic, e.g., propositional logic and predicate logic:
A is Valid iff negation(A) is Unsatisfiable.
This is a pretty well-known result. You can find it in many textbooks and materials, for example, in page 4 of this slide. So, validity of P -> Q can be proved via checking for unsatisfiability of its negation: P /\ negation(Q).
In particular, for your example,
(a^3 = x*y*z = m) -> (3a <= x+y+z) is Valid,
iff
(a^3 = m) /\ (x*y*z = m) /\ (3a > x+y+z) is Unsatifiable.

How much nonlinearity could z3 handle in practice?

My apologies if this question is ill-phrased but I'm trying to use z3 (in python with the language binding) to solve some nonlinear equations, but unfortunately neither the qfnra-nlsat nor the general solver could solve the following system unless a, b and c are all given:
y == 0.001 * (a ** 2.07) * (b ** 0.9) * (c ** 0.7) + 0.002
y > 0.0
I tried with the following tactic:
t = z3.Then('simplify', 'qfnra-nlsat')
and I also tried substituting the nonlinear parts with some intermediate names and add the exponential parts back in later with incremental solver using push(). But z3 basically gets stuck (longer than 1 hour as far as I tried) in both cases.
I'm a newbie to CSP and the theoretical background involved, sorry if this is a dumb question but I'm wondering if such nonlinearity is beyond (empirically) solvable by z3 or I'm not using it correctly? Thanks!
Edit:
Here's the python code that fails on my machine:
import z3
a = z3.Real('a')
b = z3.Real('b')
c = z3.Real('c')
y = z3.Real('y')
eq = [
y == 0.001 * (a ** 2.07) * (b ** 0.9) * (c ** 0.7) + 0.002,
y >= 0.0
]
t = z3.Then('simplify', 'qfnra-nlsat')
s = t.solver()
s.add(eq)
r = s.check()
print r
m = s.model()
print m
Here's the output:
unknown
[y = 1/500 ]
Edit:
It seems that the latest code from z3 git repo is kinda broken. I tried with 4.4.1 release and it all worked out.
A follow up question though, if I just add one more constraint below:
a == 16.0
And z3 gets stuck, which I could not understand...It seems that the additional constraint above is pretty trivial, an initial guess of b and c being both 1s should solve the system, but I guess that's not how z3 works? Any idea on how to solve the system with this new constraint?
Presuming I didn't make some translation mistake, I tried this out in the pure SMT-LIB interface and it seems to work fine.
If you still have some problems after looking at this, please encode your entire example that is failing, as maybe you have some constraints that you didn't include that is causing it to fail. Or, possibly the overloaded Python operators (e.g., **) are not being interpreted properly (although that does seem to be the right usage for power), so you may want to use the Z3 Python API's functions for various expressions.
I included this x variable that's extra just to double check I was using ^ correctly as power, and it seems right (rise4fun link: http://rise4fun.com/Z3/plLQJ ):
(declare-const x Real)
(declare-const y Real)
(declare-const a Real)
(declare-const b Real)
(declare-const c Real)
; y == 0.001 * (a ** 2.07) * (b ** 0.9) * (c ** 0.7) + 0.002
(assert (= y (+ (* 0.001 (^ a 2.07) (^ b 0.9) (^ c 0.7)) 0.002)))
(assert (> y 0.0))
(check-sat-using qfnra-nlsat)
(get-model)
(assert (> x 1.0))
(assert (= x (^ 5.0 2.5))) ; check ^ means pow
(check-sat-using qfnra-nlsat)
(get-model)
This yields:
sat
(model
(define-fun a () Real
(- 1.0))
(define-fun b () Real
(- 1.0))
(define-fun c () Real
(- 1.0))
(define-fun y () Real
(+ (/ 1.0 500.0)
(* (- (/ 69617318994479297159441705182250977318952641791835914067365099344218850343780027694073822279020999411953209540560859156221731465694293028234177768119402105034869871366755227547291324996387.0
4000.0))
(^ (/ 1.0 8.0) 207.0))))
)
sat
(model
(define-fun a () Real
(- 1.0))
(define-fun b () Real
(- 1.0))
(define-fun c () Real
(- 1.0))
(define-fun x () Real
(root-obj (+ (^ x 2) (- 3125)) 2))
(define-fun y () Real
(+ (/ 1.0 500.0)
(* (- (/ 69617318994479297159441705182250977318952641791835914067365099344218850343780027694073822279020999411953209540560859156221731465694293028234177768119402105034869871366755227547291324996387.0
4000.0))
(^ (/ 1.0 8.0) 207.0))))
)

Resources