I'm writing a proofchecker for a novel program logic, dealing with weak memory. Z3 does the heavy lifting: I translate all my checks into ASTs and throw them at Z3 using the ML binding. (But, see below, I've checked that Z3 online, via rise4fun, gives the same answer). Here's the implication I would like to check, pretty-printed so I can understand the operator nesting, with the names slightly simplified so it's easy to see what they are:
r1=1
=> y=1
/\ x=1
/\ xnew=x
/\ ynew=2
=> xnew=x
/\ ynew=y
\/ Exists(r1)
r1=1
=> y=1
/\ x=1
/\ xnew=x
/\ ynew=2
This translates into ASTs nicely (type declarations not shown, but see below for actual Z3 input):
(let ((a1 (and (=> (= r1 1) (and (= y 1) (= x 1)))
(= xnew x)
(= ynew 2)))
(a2 (exists ((r1 Int))
(and (=> (= r1 1) (and (= y 1) (= x 1)))
(= xnew x)
(= ynew 2)))))
(=> a1 (or
(and (= xnew x) (= ynew y)) a2)))
So that's all fine. But Z3 says 'unknown'. Oddly, this is the only one of many thousands of queries in all my tests which gives this result. So I investigated with the online version of Z3, via the rise4fun tutorial, which accepted this input
(declare-const r1 Int)
(declare-const y Int)
(declare-const x Int)
(declare-const xnew Int)
(declare-const ynew Int)
(define-fun a1 () Bool
(and (=> (= r1 1) (and (= y 1) (= x 1)))
(= xnew x)
(= ynew 2))
)
(define-fun a2 () Bool
(exists ((r1 Int))
(and (=> (= r1 1) (and (= y 1) (= x 1)))
(= xnew x)
(= ynew 2)))
)
(define-fun conjecture () Bool
(=> a1 (or (and (= xnew x) (= ynew y)) a2))
)
(assert (not conjecture))
(check-sat)
and said 'unknown'.
Am I making a simple error, or is this a bug, or what?
This seems to be a bug in the master branch and in the executable used online.
The behavior does not reproduce in the latest unstable branch.
Related
Is there a way to simplify the following expression to "6 < var"?
According to Z3, these expressions are equivalent but simplification does not produce the latter.
I have tried the three parameters since they seem to be related to if-then-else but this also did not help.
(declare-fun var () Int)
(simplify
(exists ((bx Int))
(and
(exists ((byX Int))
(ite (> bx 5) (= byX 0) (&& (> bx 2) (= byX (+ byX 4)))))
(= bx (+ var 1))
(> var 6)
)
)
:push_ite_arith true
:pull_cheap_ite true
:ite_extra_rules true
)
(assert
(not
(iff
(exists ((bx Int))
(and
(exists ((by Int))
(ite (> bx 5) (= by 0) (&& (> bx 2) (= by (+ by 4)))))
(= bx (+ var 1))
(> var 6)
)
)
(< 6 var)
)
)
)
(check-sat)
Not in general, no.
Z3's simplifications and what you would consider "simple" are typically not the same, and it works more or less as a black-box. It won't produce output like what you would get from a symbolic math package or alike: The simplifications are more geared towards making the input "simpler" for further solving; not for "presenting it back to the user" purpose.
You can find many similar questions on stack-overflow, see: https://stackoverflow.com/search?q=%5Bz3%5D+simplify and in particular this answer from Leo: simplification in Z3
In SMT: check uniqueness and totality of function I gave a function axiomatization and asked Z3 for a model. However because solving something with quantifiers in it is undecidable in general, Z3 times out.
Here is a modified version in which the "int" case is modelled as a single value:
(declare-datatypes () ((ABC int error none)))
(declare-fun f (ABC ABC) ABC)
(assert (forall ((x ABC)) (=> (or (= x int) (= x error) (= x none)) (= (f none x) none))))
(assert (forall ((x ABC)) (=> (or (= x int) (= x error) (= x none)) (= (f x none) none))))
(assert (forall ((x ABC)) (=> (or (= x int) (= x error)) (= (f error x) error))))
(assert (forall ((x ABC)) (=> (or (= x int) (= x error)) (= (f x error) error))))
(assert (forall ((x ABC) (y ABC)) (=> (and (= x int) (= y int)) (= (f x y) int))))
(check-sat)
(get-model)
Because there now are finitely many cases, Z3 gives an answer quickly:
sat
(model
(define-fun k!26 ((x!0 ABC)) ABC
(ite (= x!0 error) error
(ite (= x!0 int) int
none)))
(define-fun f!28 ((x!0 ABC) (x!1 ABC)) ABC
(ite (and (= x!0 error) (= x!1 int)) error
(ite (and (= x!0 int) (= x!1 error)) error
(ite (and (= x!0 error) (= x!1 error)) error
(ite (and (= x!0 int) (= x!1 int)) int
none)))))
(define-fun k!27 ((x!0 ABC)) ABC
(ite (= x!0 error) error
(ite (= x!0 int) int
none)))
(define-fun f ((x!0 ABC) (x!1 ABC)) ABC
(f!28 (k!27 x!0) (k!26 x!1)))
)
Both k!26 and k!27 actually just return their input (this is easily seen by checking all three cases). Is it possible to simplify the model by eliminating these two functions automatically?
Optimally I would like to have something like the following, although I see that might not be possible:
(define-fun f ((x!0 ABC) (x!1 ABC)) ABC
(ite (or (= x!0 none) (= x!1 none)) none
(ite (or (= x!0 error) (= x!1 error)) error
int)))
I'm using Z3Py, but both general Z3-specific and Z3Py-specific answers are welcome.
I don't think there's much you can do to guide Z3 to provide a "simpler" answer here; as the model generated depends on how the proof was done and even simple changes to the problem can have unpredictable results. In particular, the model you get can change with the next version of Z3.
Having said that, a common trick is to eval terms in the model. Since your current problem only involves a finite domain, you can enumerate it. If you add the following lines at the end of your script:
(eval (f int int))
(eval (f int error))
(eval (f int none))
(eval (f error int))
(eval (f error error))
(eval (f error none))
(eval (f none int))
(eval (f none error))
(eval (f none none))
Then Z3 will print:
int
error
none
error
error
none
none
none
none
Perhaps you can use that output to construct a "simpler" model yourself. Of course, this only works if the domain is finite; but you can use the same trick to evaluate "interesting" parts of the input domain, depending on your problem.
(set-option :smt.mbqi true)
(declare-fun R(Int) Int)
(declare-const a Int)
(assert (= (R 0) 0))
(assert (forall ((n Int)) (=> (> n 0) (= (R n ) (+ (R (- n 1)) 1)))))
(assert (not (= a 5)))
(assert (not (= (R a) 5)))
(check-sat)
I have tried the above code in Z3,But Z3 unable to answer.Can you please guide me where i have made the mistake ?
As a general pattern don't expect MBQI to produce models
involving functions that
only have an infinite range of different values.
If you really must, then you can use the define-fun-rec construct to define
a recursive function. Z3 currently trusts that the definition
is well-formed (e.g., that the equation corresponding to the function
definition is satisfiable).
(set-option :smt.mbqi true)
(declare-fun F (Int) Int)
(define-fun-rec R ((n Int)) Int
(if (= n 0) 0
(if (> n 0) (+ (R (- n 1)) 1)
(F n))))
(declare-const a Int)
(assert (not (= a 5)))
(assert (not (= (R a) 5)))
(check-sat)
(get-model)
Z3 uses recursively defined functions passively during search: whenever
there is a candidate model for the ground portion of the constraints, it
checks that the function graph is adequately defined on the values of the candidate model. If it isn't, then the function definition is instantiated on the selected values until it is well defined on the values that are relevant
to the ground constraints.
I originally posted the question as shown below the dotted line, but since then I have an even simpler example:
(declare-fun f (Int) Int)
(assert (= (f 10) 1))
(check-sat)
(get-model)
produces an interpretation for f as expected. However change the constant to anything but 10, and Z3 just spins the arrowhead a couple of times but then prints nothing!
--------------------------------------- original question -----------------------------
I tried Z3 on the following input and the arrowhead turns a few times and stops but Z3 prints or says nothing. Why?
(declare-fun f (Int Int) Int)
(assert (>= (f 1 1) 1))
(assert (>= (f 1 2) 2))
(assert (>= (f 2 1) 2))
(assert (>= (f 2 2) 2))
(assert (= (f 1 1) 1))
(assert (= (f 2 2) 2))
(assert (or (= (f 1 2) 1) (= (f 1 2) 2)))
(assert (or (= (f 2 1) 1) (= (f 2 1) 2)))
(check-sat)
(get-model)
I feel like I'm missing something really obvious..
I am obtaining (using iZ3, Z3 unstable branch)
sat
(model
(define-fun f ((x!1 Int) (x!2 Int)) Int
(ite (and (= x!1 1) (= x!2 1)) 1
(ite (and (= x!1 2) (= x!2 2)) 2
(ite (and (= x!1 1) (= x!2 2)) 2
(ite (and (= x!1 2) (= x!2 1)) 2 2)))))
)
Run this example online here
I presume you're using Z3 on rise4fun? The version running there may be a little out of date. We have to manually update the binary there. If it doesn't reply, it's either because it times out, or because there was some other problem (e.g., segfault). It's quite possible that the version on rise4fun exhibits some bug that's already been fixed in other version of Z3 (e.g., unstable, iZ3, etc).
I have 3 variables a, b and c. I need to calculate c = absolute(b-a).
I encode this statement in Z3 as
(assert (>= c 0))
(assert (or (= c (- a b) (= c (- b a))))
I was thinking, is there a more efficient way of writing it in Z3?
Does Z3 have internal support for calculating absolute value?
Also, I hope there won't be any performance penalty for writing code like this, rather than using some other way.
Your encoding is correct. However, users usually encode the absolute value function using
(define-fun absolute ((x Int)) Int
(ite (>= x 0) x (- x)))
Then, they can write constraints such as:
(assert (= c (absolute (- a b))))
Here is the complete example (also available online at rise4fun):
(define-fun absolute ((x Int)) Int
(ite (>= x 0) x (- x)))
(declare-const a Int)
(declare-const b Int)
(declare-const c Int)
(assert (= a 3))
(assert (= b 4))
(assert (= c (absolute (- a b))))
(check-sat)
(get-model)