Getting the domain of an Int with z3 - 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.

Related

Having assertions inside definitions in SMT

I want to capture the assertion inside fac.
int f( x )
{
if( x == 1) return 1;
else{
assert( x > 0 );
return 2;
}
}
int g (x)
{ assert( x > 5 );
return f(x-1) + f(x-2);
}
I want an smt2 code for this.
I can do this by striping the argument and making it global with unique name (also rename inside f), then do this 3 times each with a different name for function. Like below :
( declare-const x1 Int )
(define-fun f1 () Int
( ite ( x1 > 0) 1 2 )
)
(assert (> x1 0))
( declare-const x2 Int )
(define-fun f2 () Int
( ite ( x2 > 0) 1 2 )
)
(assert (> x2 0))
( declare-const x3 Int )
(define-fun g1 () Int
( + f1 f2 )
)
(assert (> x3 5))
I don't want to this. Is there any other way to do this without repeating ?
EDIT
My purpose is to find values violating the asserts.
As far as I know, it is not possible to embed assertions within function definitions.
What I would try to do is to separate the expected behavior, the input assumptions and the output guarantees (if any).
Example:
(define-fun f ((x Int)) Int
(ite (= x 1) 1 2)
)
(define-fun f-helper ((x Int)) Bool
(< 0 x)
)
(define-fun g ((x Int)) Int
(+ (f (- x 1)) (f (- x 2)))
)
(define-fun g-helper ((x Int)) Bool
(and (< 5 x)
(f-helper (- x 1))
(f-helper (- x 2))
)
)
(declare-const x Int)
(declare-const y Int)
(assert (and (= y (g x))
(g-helper x)
))
(check-sat)
(get-model)
In this example we use f to model the behavior of the original function f, and f-helper to model the assumptions of f. The output, using the online Z3 tool, is as follows:
sat
(model
(define-fun x () Int
6)
(define-fun y () Int
4)
)
I would conclude saying that this approach could become tricky as soon as f and g are used inside both positive and negative contexts.. in this case one should pay extra attention that the polarity of the assertions is correct wrt. the expected result.

trying an example from rise4fun / z3 / tutorial / strategies

some example from the rise4fun-site:
(declare-const x Int)
(declare-const y Int)
(declare-const z Int)
(declare-const a Int) ; this is added
(assert (= a 3 )) ; this is added: a := 3
(assert (< 0 x 10)) ; rewritten, but same constraint
(assert (< 0 y 10))
(assert (< 0 z 10))
(assert (= (+ (* 3 y) (* 2 x)) z)) ; plain function from rise4fun
;(assert (= (+ (* a y) (* 2 x)) z)) ; here literal 3 is replaced by a
(check-sat-using (then (using-params simplify :arith-lhs true :som true)
normalize-bounds
lia2pb
pb2bv
bit-blast
sat))
(get-model)
(get-info :version)
when i comment the plain function from rise4fun and uncomment my function, the solver will fail to produce a result and respond with 'unknown' (tried with 4.8.0). Isn't the solver or some preprocessor smart enough to see that 'a' is just a constant with fixed value 3?
That's right, the simplify tactic is not smart enough to propagate values because it would be too expensive in general. However, ctx-simplify or propagate-values do the job. For instance:
(check-sat-using (then (using-params simplify :arith-lhs true :som true)
propagate-values
normalize-bounds
lia2pb
pb2bv
bit-blast
sat))

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.

Distinct in z3 SMT and python

My question is that Does "Distinct" works in z3 python?. I've compared the following code and it seem not giving the same results:
(declare-const x Int)
(declare-const y Int)
(assert (distinct x y))
(check-sat)
(get-model)
The result was:
sat
(model
(define-fun y () Int
0)
(define-fun x () Int
1)
)
I've added negative assertion just to test and the result was unsat which is correct:
(assert (= x y))
unsat
Z3(6, 10): ERROR: model is not available
But when I use z3 in python it give me always sat as follows:
x = Int('x')
y = Int('y')
Distinct(x, y)
s = Solver
s = Solver()
s.check()
when I add the following assertion It should give me unsat but It returns sat:
s.add(x == y)
[y = 0, x = 0]
Is this means that I used wrong syntax ?
The `Distinct' function only creates a term, it doesn't add itself to the solver. Here's an example that works for me:
x = Int('x')
y = Int('y')
d = Distinct(x, y)
s = Solver()
s.add(d) # SAT without this one, UNSAT with
s.add(x == y)
print s
print s.check()

unsat core function in 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";
}
}

Resources