Satisfiability of Presburger Formulas with z3 - z3

I'm using z3 (v4.3.2 32bit on Linux) to decide satisfiability of Presburger Arithmetic formulas, but I have a problem with the following formula :
(assert (forall ((x1 Int) (x2 Int) (x3 Int))
(=> (and (= x3 1) (= x1 (- x2)))
(forall ((x4 Int) (x5 Int) (x6 Int))
(=> (= x6 x2)
(exists ((y Int))
(=> (= x5 (+ x6 (- x4)))
(and (= (+ x1 x4) y)
(= x5 (- y))
(= (+ x1 x4) (- x5))
)
)
)
)
)
)
)
)
(check-sat)
I'm quite sure that this formula is satisfiable, but z3 answers "unsat".
In fact, if I try to change a bit the formula, z3 answers "sat", like with the following formula
(assert (forall ((x3 Int) (x1 Int) (x2 Int))
(=> (and (= x3 1) (= x1 (- x2)))
(forall ((x4 Int) (x5 Int) (x6 Int))
(=> (= x6 x2)
(exists ((y Int))
(=> (= x5 (+ x6 (- x4)))
(and (= (+ x1 x4) y)
(= x5 (- y))
(= (+ x1 x4) (- x5))
)
)
)
)
)
)
)
)
(check-sat)
where I've just switched the quantification on x3 in top of the list of the first forall quantification. If I also remove the x3 variable, which is in fact useless, z3 also answers "sat".
Is there something I don't understand or is this a bug ?

Thanks for pointing this out.
This is a bug in the quantifier elimination modules that affects cases of nested quantifiers.
It is now fixed in the unstable branch.

Related

Guiding z3's proof search

I'm trying to get z3 to work (most of the time) for very simple non-linear integer arithmetic problems. Unfortunately, I've hit a bit of a wall with exponentiation. I want to be able handle problems like x^{a+b+2} = (x * x * x^{a} * x{b}). I only need to handle non-negative exponents.
I tried redefining exponentiation as a recursive function (so that it's just allowed to return 1 for any non-positive exponent) and using a pattern to facilitate z3 inferring that x^{a+b} = x^{a} * x^{b}, but it doesn't seem to work - I'm still timing out.
(define-fun-rec pow ((x!1 Int) (x!2 Int)) Int
(if (<= x!2 0) 1 (* x!1 (pow x!1 (- x!2 1)))))
; split +
(assert (forall ((a Int) (b Int) (c Int))
(! (=>
(and (>= b 0) (>= c 0))
(= (pow a (+ b c)) (* (pow a c) (pow a b))))
:pattern ((pow a (+ b c))))))
; small cases
(assert (forall ((a Int)) (= 1 (pow a 0))))
(assert (forall ((a Int)) (= a (pow a 1))))
(assert (forall ((a Int)) (= (* a a) (pow a 2))))
(assert (forall ((a Int)) (= (* a a a) (pow a 3))))
; Our problem
(declare-const x Int)
(declare-const i Int)
(assert (>= i 0))
; This should be provably unsat, by splitting and the small case for 2
(assert (not (= (* (* x x) (pow x i)) (pow x (+ i 2)))))
(check-sat) ;times out
Am I using patterns incorrectly, is there a way to give stronger hints to the proof search, or an easier way to do achieve what I want?
Pattern (also called triggers) may only contain uninterpreted functions. Since + is an interpreted function, you essentially provide an invalid pattern, in which case virtually anything can happen.
As a first step, I disabled Z3's auto-configuration feature and also MBQI-based quantifier instantiation:
(set-option :auto_config false)
(set-option :smt.mbqi false)
Next, I introduced an uninterpreted plus function and replaced each application of + by plus. That sufficed to make your assertion verify (i.e. yield unsat). You can of course also axiomatise plus in terms of +, i.e.
(declare-fun plus (Int Int) Int)
(assert (forall ((a Int) (b Int))
(! (= (plus a b) (+ a b))
:pattern ((plus a b)))))
but your assertion already verifies without the definitional axioms for plus.

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)

Can options change `sat` into `unsat`?

Another question from a Z3 newbie. Can options change the behavior of Z3? I might expect them to affect termination, or change sat or unsat into unknown but not sat into unsat or vice versa.
This example:
(set-option :smt.macro-finder true)
(declare-datatypes () ((Option (none) (some (Data Int)))))
(define-sort Set () (Array Option Option))
(declare-fun filter1 (Option) Option)
(declare-fun filter2 (Option) Option)
(declare-var s1 Set)
(declare-var s2 Set)
(declare-var x1 Option)
(declare-var x2 Option)
(declare-var x3 Option)
(declare-var x4 Option)
(assert (not (= x1 none)))
(assert (not (= x2 none)))
(assert (not (= x3 none)))
(assert (not (= x4 none)))
(assert (= (select s1 x1) x2))
(assert (= (select s2 x3) x4))
(assert (forall ((x Option)) (= (filter1 x) (ite (or (= none x) (= (Data x) 1)) x none))))
(assert (forall ((x Option)) (= (filter2 x) (ite (or (= none x) (= (Data x) 2)) x none))))
(assert (= ((_ map filter1) s1) s2))
(assert (= ((_ map filter2) s1) s2))
(check-sat)
(get-model)
returns sat with the first line and unsat without it.
Is this a bug or am I missing something fundamental?
This is a bug. The two quantifiers are essentially providing "definitions" for filter1 and filter2.
The option smt.macro-finder is used to eliminate functions symbols by expanding these definitions. It is essentially performing "macro expansion". However, there is a bug in the macro expander. It does not expand the occurrences of filter1 and filter2 in the map constructs: (_ map filter1) and (_ map filter2).
This bug will be fixed.
In the meantime, we should not use the map construct and smt.macro-finder option simultaneously.

Resources