I'm trying to check a simple Timed Automata for reachability using Z3's fixed-point engine.
The TA I'm modeling is:
-->(x = 0 & 0 <= c <= 5) --[c > 2]-->(x = 1)
I want to verify that the state x = 1 & c = 3 is reachable. To do that I input the following into Z3:
(declare-rel T (Int Real Int Real))
(declare-rel REACH (Int Real))
(declare-var x Int)
(declare-var c Real)
(declare-var nx Int)
(declare-var nc Real)
(declare-var delay Real)
(rule (! (=> (and (= x 0) (> c 2.0)) (T x c 1 c)) :named stepint))
(rule (! (=> (and (REACH x c) (T x c nx nc)) (REACH nx nc)) :named tstep))
(rule (! (=> (and (= c 0.0) (= x 0)) (REACH x c)) :named initialstates))
(rule (! (let ((a!1 (and (>= delay 0.0) (= nc (+ c delay)) (or (not (= x 0)) (< nc 5.0)))))
(=> a!1 (T x c x nc))) :named TICK))
(query (and (REACH x c) (= x 1) (= c 3.0))
:print-certificate true)
When I run the above in Z3 on rise4fun I get back:
formula false in model: (= REACH_1_0 3.0)
formula false in model: (= REACH_0_0 1)
formula false in model: (= query!0_0_n 1)
formula false in model: (= query!0_1_n 3.0)
sat
(REACH 1 3.0)
Which indicates that x= 1 & c = 3 is reachable. What does "formula false in model mean"? Is this simply informational or is Z3 warning me about potentially poorly formed input?
The bugs appear fixed in the "opt" branch. I have not ported the fixes to the unstable branch yet. It will happen, but if impatient, use the "opt" branch.
Sorry.
Related
I am using Z3 and the extended SMT-LIB2 syntax to solve my horn clauses.
I know that head of a horn clause should be an uninterpreted predicate; but, I wonder how I should rewrite the following clauses to be a set of horn clauses.
(declare-rel inv (Int Int ))
(declare-var k Int)
(declare-var k_p Int)
(declare-var a Int)
(declare-var a_p Int)
(rule (=> (and (= a 0) (= k 0)) (inv a k)))
(rule (=> (and (inv a k) (= a_p (+ a 1))(= k_p (+ k 1))) (inv a_p k_p)))
(rule (=> (and (inv a k) (> k 0) ) (> a 0)))
(query inv )
Z3 complains that (> a 0) cannot be head of a horn clause.
I can rewrite the last clause as the following:
(rule (=> (and (inv a k) (> k 0) ) (gtz a)))
(rule (=> (> a 0) (gtz a)))
But, then the clauses become so weak that I don't get the intended model for the invariant inv. I wonder if there is a better way to do this.
Maybe you want to say
(declare-rel inv (Int Int ))
(declare-rel q ())
(declare-var k Int)
(declare-var k_p Int)
(declare-var a Int)
(declare-var a_p Int)
(rule (=> (and (= a 0) (= k 0)) (inv a k)))
(rule (=> (and (inv a k) (= a_p (+ a 1))(= k_p (+ k 1))) (inv a_p k_p)))
(rule (=> (and (inv a k) (> k 0) (not (> a 0))) q))
(query q )
I am having trouble attempting to prove this fairly simple Z3 query.
(set-option :smt.auto-config false) ; disable automatic self configuration
(set-option :smt.mbqi false) ; disable model-based quantifier instantiation
(declare-fun sum (Int) Int)
(declare-fun list () (Array Int Int))
(declare-fun i0 () Int)
(declare-fun s0 () Int)
(declare-fun i1 () Int)
(declare-fun s1 () Int)
(assert (forall ((n Int))
(! (or (not (<= n 0)) (= (sum n) 0))
:pattern ((sum n)))))
(assert (forall ((n Int))
(! (let ((a1 (= (sum n)
(+ (select list (- n 1))
(sum (- n 1))))))
(or (<= n 0) a1))
:pattern ((sum n)))))
(assert (>= i0 0))
(assert (= s0 (sum i0)))
(assert (= i1 (+ 1 i0)))
(assert (= s1 (+ 1 s0 (select list i0))))
(assert (not (= s1 (sum i1))))
(check-sat)
Seems to me that the final assertion should instantiate the second quantified statement for i1 while the assert involving s0 should instantiate the quantifiers for i0. These two should should easily lead to UNSAT.
However, Z3 returns unknown. What am I missing?
Never mind, there was an silly error in my query.
This code:
(assert (= s1 (+ 1 s0 (select list i0))))
should have been:
(assert (= s1 (+ s0 (select list i0))))
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.
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.
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!