Simplifying z3 expression using C++ API - z3

I have such an expression
z3::expr expr = (exists ((flag Bool))
(exists ((w Int))
(exists ((i Int))
(exists ((counter Int))
(and (= i (+ x y z))
flag
(not (= i 0))
(= i counter)
(not (= w counter))
(>= i 1)
(= w 0)))))))
I use C++ API to do quantifier elimination and simplification.
z3::goal g(ctx);
g.add(expr);
z3::apply_result result = (qe & simplify & propagate_ineqs)(g);
I have defined the tactics.
I want to get such result:
(or (>= (+ x y z) 1 )
(<= (+ x y z) -1 ))
but I get this output which is appropriate for my application:
(let ((a!1 (or (<= (+ (* (- 1) x)
(* (- 1) y)
(* (- 1) z))
(- 1))
(<= (+ x y z) (- 1)))))
(and (or (<= (+ x y z) (- 1))
(>= (+ x y z) 1))
a!1
(>= (+ x y z) 1)))
what tactics should I use to make it work as I want?

I solved the issue by setting these options in the context, before defining the goal:
ctx.set(":pp-min-alias-size", 1000000);
ctx.set(":pp-max-depth", 1000000);
it didn't simplify as I wanted, but removed the "let"s and that's better than nothing!

Related

solving equation and quantifier elimination

I want to use z3 to find the result of the following expression after quantifier elimination. What is the correct syntax?
(declare-fun n () Int)
(declare-fun X () Int)
(declare-fun X_1_ () Int)
(declare-fun X_0_ () Int)
(assert (exists ((R__0 Int) (R__1 Int)(R_0_0 Int) (R_1_0 Int)) (and (>= n 3)
(= X n)
(=(+ X_0_ X_1_) X)
(>= X_0_ 0)
(<= R_0_0 X_0_)
(>= R_0_0 0)
(<= R_0_0 R__0)
(>= X_1_ 0)
(<= R_1_0 X_1_)
(>= R_1_0 0)
(<= R_1_0 R__0)
(<= R__0 X)
(<= R__1 X)
(= (+ R_1_0 R_0_0) R__0)
(> (* 3 R__0) (* 2 n))
(>= R_0_0 R_1_0)
(<= (* 3 R_0_0) (* 2 n))
(<= (* 3 R__1) (* 2 n)))))
(apply (using-params qe :qe-nonlinear true))
Use the qe_rec tactic. Changing your last line to:
(apply qe_rec)
produces:
(goals
(goal
(>= X_1_ 0)
(>= X_0_ 0)
(= (+ X_0_ X_1_) X)
(= X n)
(>= n 3)
(<= (+ (* (- 2) n) (* 3 X_1_)) 0)
(>= (* 9 X_1_) 7)
(<= (+ (* 2 n) (* (- 6) X_0_)) (- 1))
:precision precise :depth 1)
)

function with quantifier in Z3

I have a problem with quantifier.
Let a(0) = 0, and a(n+1) would be either a(n)+1 or a(n)+2 based on the value of x(n). We may expect that for any kind of x(.) and for all n, a(n) <= n*2.
Here is the code for Z3:
(declare-fun a (Int) Int)
(declare-fun x (Int) Int)
(declare-fun N () Int)
(assert (forall
((n Int))
(=> (>= n 0)
(= (a (+ n 1))
(ite (> (x n) 0)
(+ (a n) 1)
(+ (a n) 2)
)
)
)
))
(assert (= (a 0) 0))
(assert (> (a N) (+ N N)))
(check-sat)
(get-model)
I hope Z3 could return "unsat", while it always "timeout".
I wonder if Z3 could handle this kind of quantifier, and if somebody could give some advice.
Thanks.
The formula is SAT, for N < 0, the graph of a is underspecified.
But the default quantifier instantiation engine can't determine this. You can take advantage of that you are defining a recursive function to enforce a different engine.
;(declare-fun a (Int) Int)
(declare-fun x (Int) Int)
(declare-fun y (Int) Int)
(declare-fun N () Int)
(define-fun-rec a ((n Int)) Int
(if (> n 0) (if (> (x (- n 1)) 0) (+ (a (- n 1)) 1) (+ (a (- n 1)) 2)) (y n)))
(assert (= (a 0) 0))
(assert (> (a N) (+ N N)))
(check-sat)
(get-model)
As Malte writes, there is no support for induction on such formulas so don't expect Z3 to produce induction proofs. It does find inductive invariants on a class of Horn clause formulas, but it requires a transformation to cast arbitrary formulas into this format.
Thanks, Malte and Nikolaj.
The variable N should be bounded:
(assert (> N 0))
(assert (< N 10000))
I replace
(assert (> (a N) (+ N N)))
with
(assert (and
(not (> (a N) (+ N N)))
(> (a (+ N 1)) (+ (+ N 1) (+ N 1)))
))
and it works for both definition of a(n).
Does this a kind of inductive proof as you mentioned?
Here are the two blocks of code, and both of them return "unsat":
(declare-fun a (Int) Int)
(declare-fun x (Int) Int)
(declare-fun N () Int)
(assert (forall
((n Int))
(=> (>= n 0)
(= (a (+ n 1))
(ite (> (x n) 0)
(+ (a n) 1)
(+ (a n) 2)
)
))
))
(assert (= (a 0) 0))
(assert (> N 0))
(assert (< N 10000))
;(assert (> (a N) (+ N N)))
(assert (and
(not (> (a N) (+ N N)))
(> (a (+ N 1)) (+ (+ N 1) (+ N 1)))
))
(check-sat)
;(get-model)
and
(declare-fun x (Int) Int)
(declare-fun y (Int) Int)
(declare-fun N () Int)
(define-fun-rec a ((n Int)) Int
(if (> n 0)
(if (> (x (- n 1)) 0) (+ (a (- n 1)) 1) (+ (a (- n 1)) 2)) (y n)))
(assert (= (a 0) 0))
(assert (> N 0))
(assert (< N 10000))
;(assert (> (a N) (+ N N)))
(assert (and
(not (> (a N) (+ N N)))
(> (a (+ N 1)) (+ (+ N 1) (+ N 1)))
))
(check-sat)
;(get-model)

Why result of Z3 online and Z3PY are different?

Following code I have tried in Online and Offline Z3
(set-option :smt.mbqi true)
(declare-var X Int)
(declare-var X_ Int)
(declare-var a_ Int)
(declare-var su_ Int)
(declare-var t_ Int)
(declare-var N1 Int)
(assert (>= X 0))
(assert (forall ((n1 Int)) (=> (< n1 N1) (>= X (* (+ n1 1) (+ n1 1))))))
(assert (= X_ X))
(assert (= a_ N1))
(assert (= su_ (* (+ N1 1) (+ N1 1))))
(assert (= t_ (* (+ N1 1) 2)))
(assert (< X (* (+ N1 1) (+ N1 1))))
(assert (not (< X (* (+ a_ 1) (+ a_ 1)))))
(check-sat)
Result unsat
Following code I have tried in Z3PY
set_option('smt.mbqi', True)
s=Solver()
s.add(X>=0)
s.add(ForAll(n1,Implies(n1 < N1,((n1+1)**2)<=X)))
s.add(((N1+1)**2)>X)
s.add(X_==X)
s.add(a_==N1)
s.add(su_==((N1+1)**2))
s.add(t_==(2*(N1+1)))
s.add(Not(((a_+1)**2)>X))
result- unknown
Is processing power different?
The reason for the difference in results is because the input is not the same. For instance, the expression
(N1+1)**2
is semantically the same as
(* (+ N1 1) (+ N1 1))
but because of the syntactic difference, Z3 will not simplify the formula to something that it can solve easily. The syntactically equivalent problem in Python is
s.add(X>=0)
s.add(ForAll(n1,Implies(n1 < N1,((n1+1)**2)<=X)))
s.add(((N1+1)*(N1+1)) > X)
s.add(X_==X)
s.add(a_==N1)
s.add(su_==((N1+1)*(N1+1)))
s.add(t_==(2*(N1+1)))
s.add(Not(((a_+1)*(a_+1))>X))
which yields the desired result.
Are the constraints the same?
I don't see the python variant of:
(assert (< X (* (+ N1 1) (+ N1 1))))

z3 and z3PY giving different results

When I tried following in z3, I got result timeout
(set-option :smt.mbqi true)
(declare-fun R(Int) Int)
(declare-fun Q(Int) Int)
(declare-var X Int)
(declare-var Y Int)
(declare-const k Int)
(assert (>= X 0))
(assert (> Y 0))
(assert (forall ((n Int)) (=> (= n 0) (= (Q n) 0))))
(assert (forall ((n Int)) (=> (= n 0) (= (R n) X))))
(assert (forall ((n Int)) (=> (> n 0) (= (R (+ n 1) ) (+ (R n) (* 2 Y))))))
(assert (forall ((n Int)) (=> (> n 0) (= (Q (+ n 1) ) (- (Q n) 2)))))
(assert (forall ((n Int)) (=> (> n 0) (= X (+ (* (Q n) Y) (R n))))))
(assert (forall ((n Int)) (= X (+ (* (Q n) Y) (R n)))))
(assert (= X (+ (* (Q k) Y) (R k))))
(assert (not (= (* X 2) (+ (* (Q (+ k 1)) Y) (R (+ k 1))))))
(check-sat)
Same when I tried in z3py using following code, I got result unsat which is wrong
from z3 import *
x=Int('x')
y=Int('y')
k=Int('k')
n1=Int('n1')
r=Function('r',IntSort(),IntSort())
q=Function('q',IntSort(),IntSort())
s=Solver()
s.add(x>=0)
s.add(y>0)
s.add(ForAll(n1,Implies(n1==0,r(0)==x)))
s.add(ForAll(n1,Implies(n1==0,q(0)==0)))
s.add(ForAll(n1,Implies(n1>0,r(n1+1)==r(n1)-(2*y))))
s.add(ForAll(n1,Implies(n1>0,q(n1+1)==q(n1)+(2))))
s.add(x==q(k)*y+r(k))
s.add(not(2*x==q(k+1)*y+r(k+1)))
if sat==s.check():
print s.check()
print s.model()
else :
print s.check()
Looking forward to Suggestions.
My suggestion is to use replace the built-in not operator by the Z3 function called Not, e.g.
not(2*x==q(k+1)*y+r(k+1))
is simplified to False by Python before Z3 gets to see it, while
Not(2*x==q(k+1)*y+r(k+1))
has the desired meaning.

z3 times out in case of a formula with quantifiers

I am getting timeout on the following example.
http://rise4fun.com/Z3/zbOcW
Is there any trick to make this work (eg.by reformulating the problem or using triggers)?
For this example, the macro finder will be useful (I think often with forall quantifiers with implications), you can enable it with:
(set-option :macro-finder true)
Here's your updated example that gets sat quickly (rise4fun link: http://rise4fun.com/Z3/Ux7gN ):
(set-option :macro-finder true)
(declare-const a (Array Int Bool))
(declare-const sz Int)
(declare-const n Int)
(declare-const d Int)
(declare-const r Bool)
(declare-const x Int)
(declare-const y Int)
;;ttff
(declare-fun ttff (Int Int Int) Bool)
(assert
(forall ((x1 Int) (y1 Int) (n1 Int))
(= (ttff x1 y1 n1)
(and
(forall ((i Int))
(=> (and (<= x1 i) (< i y1))
(= (select a i) true)))
(forall ((i Int))
(=> (and (<= y1 i) (< i n1))
(= (select a i) false)))))))
;; A1
(assert (and (<= 0 n) (<= n sz)))
;; A2
(assert (< 0 d))
;; A3
(assert (and (and (<= 0 x) (<= x y)) (<= y n)))
;; A4
(assert (ttff x y n))
;; A6
(assert
(=> (< 0 y)
(= (select a (- y 1)) true)))
;; A7
(assert
(=> (< 0 x)
(= (select a (- x 1)) false)))
;;G
(assert
(not
(iff
(and (<= (* 2 d) (+ n 1)) (ttff (- (+ n 1) (* 2 d)) (- (+ n 1) d) (+ n 1)))
(and (= (- (+ n 1) y) d) (<= d (- y x))))))
(check-sat)
(get-model)

Resources