Supposed I have a BoolExpr in the form of
a & (a | b) or a | (a & b)
and I want to simplify it to
a
by calling simplify(). It doesn't work.
Also, for a constraint like
(a | b) & (b | a)
simplify() can not turn it into the simplest form
(a|b) or (b|a).
Is there a workaround way?
#Nikolaj Bjorner: Thanks for your help and I have one more question:
Here is my original constraint:
Goal: (goal
(or (> (type o) 2) (= (type o) 1))
(or (= (type o) 1) (> (type o) 2)))
Here is the simplified version(by ctx-solver-simplify):
(or (= (type o) 1) (not (<= (type o) 2)))
The actual constraint I am expecting is:
(or (= (type o) 1) (> (type o) 2))
and I don't want to introduce any negation. What should I do?
The default simplifier seeks only rewrites that are cheap.
There is a different simplifier that you can invoke as a tactic.
It simplifies the goals you describe.
For example:
(declare-const a Bool)
(declare-const b Bool)
(assert (or a (and a b)))
(apply ctx-solver-simplify)
It may return several subgoal that need to be re-assembled to a formula.
The Z3 tutorial on rise4fun.com describes tactics.
The ctx-solver-simplify does limited context-dependent rewriting. It is still incomplete.
It does not produce canonical normal forms (two formulas that are equivalent may simplify to
two different formulas).
Related
What I need is pretty straight-forward, I'm looking for a tool/library that gets several
constraints in a format like this:
{"vars": {a=2, b=1, c=3}, "eval": "False"}
{"vars": {a=1, b=1, c=2}, "eval": "True"}
{"vars": {a=1, b=2, c=1}, "eval": "True"}
And then synthesize a boolean expression for me based on predefined symbols:
Symbols: ["between variables": ['<=', '>=', '<', '>', '==', '!='], "between expressions": ['and', 'or']]
I need only one solution for this system; for instance, one can be
a == b or b == c or a == c
I've been looking into Z3 library features but couldn't find anything useful. Please do inform me if you know about an appropriate tool.
Program synthesis is a very active area of research; and the quality of the programs you'll get really depends on what sort of program templates you want to use. An SMT solver will most likely not give you the kind of programs that you're looking for out-of-the-box, although they will work.
Here's how I'd code your current problem: I'd use an uninterpreted function and add the "test-cases" as constraints. Like this:
(declare-fun f (Int Int Int) Bool)
(assert (not (f 2 1 3)))
(assert (f 1 1 2))
(assert (f 1 2 1))
(check-sat)
(get-model)
When I run this, z3 says:
sat
(
(define-fun f ((x!0 Int) (x!1 Int) (x!2 Int)) Bool
(ite (and (= x!0 2) (= x!1 1) (= x!2 3)) false
true))
)
If you read the output, you'll see that it essentially synthesized the following program:
if (a == 2) && (b == 1) && (c == 3)
then False
else True
Is this correct? Absolutely. Is this really what you wanted it to do? Most likely not. But out-of-the box you'll not get anything better from an SMT solver.
For synthesizing cool programs using SMT based technologies, see, for instance, Emina Torlak's research. Here's a good paper to start with: http://synapse.uwplse.org
I was working with z3 with the following example.
f=Function('f',IntSort(),IntSort())
n=Int('n')
c=Int('c')
s=Solver()
s.add(c>=0)
s.add(f(0)==0)
s.add(ForAll([n],Implies(n>=0, f(n+1)==f(n)+10/(n-c))))
The last equation is inconsistent (since n=c would make it indeterminate). But, Z3 cannot detect this kind of inconsistencies. Is there any way in which Z3 can be made to detect it, or any other tool that can detect it?
As far as I can tell, your assertion that the last equation is inconsistent does not match the documentation of the SMT-LIB standard. The page Theories: Reals says:
Since in SMT-LIB logic all function symbols are interpreted
as total functions, terms of the form (/ t 0) are meaningful in
every instance of Reals. However, the declaration imposes no
constraints on their value. This means in particular that
for every instance theory T and
for every value v (as defined in the :values attribute) and
closed term t of sort Real,
there is a model of T that satisfies (= v (/ t 0)).
Similarly, the page Theories: Ints says:
See note in the Reals theory declaration about terms of the form
(/ t 0).
The same observation applies here to terms of the form (div t 0) and
(mod t 0).
Therefore, it stands to reason to believe that no SMT-LIB compliant tool would ever print unsat for the given formula.
Z3 does not check for division by zero because, as Patrick Trentin mentioned, the semantics of division by zero according to SMT-LIB are that it returns an unknown value.
You can manually ask Z3 to check for division by zero, to ensure that you never depend division by zero. (This is important, for example, if you are modeling a language where division by zero has a different semantics from SMT-LIB.)
For your example, this would look as follows:
(declare-fun f (Int) Int)
(declare-const c Int)
(assert (>= c 0))
(assert (= (f 0) 0))
; check for division by zero
(push)
(declare-const n Int)
(assert (>= n 0))
(assert (= (- n c) 0))
(check-sat) ; reports sat, meaning division by zero is possible
(get-model) ; an example model where division by zero would occur
(pop)
;; Supposing the check had passed (returned unsat) instead, we could
;; continue, safely knowing that division by zero could not happen in
;; the following.
(assert (forall ((n Int))
(=> (>= n 0)
(= (f (+ n 1))
(+ (f n) (/ 10 (- n c)))))))
As we know Z3 has limitations with recurrences. Is there any way get the result for the following program? what will additional equation help z3 get the result?
from z3 import *
ackermann=Function('ackermann',IntSort(),IntSort(),IntSort())
m=Int('m')
n=Int('n')
s=Solver()
s.add(ForAll([n,m],Implies(And(n>=0,m>=0),ackermann(m,n) == If(m!=0,If(n!=0,ackermann(m - 1,ackermann(m,n - 1)),If(n==0,ackermann(m - 1,1),If(m==0,n + 1,0))),If(m==0,n + 1,0)))))
s.add(n>=0)
s.add(m>=0)
s.add(Not(Implies(ackermann(m,n)>=0,ackermann(m+1,0)>=0)))
s.check()
With a nested recursive definition like Ackermann's function, I don't think there's much you can do to convince Z3 (or any other SMT solver) to actually do any interesting proofs. Such properties will require clever inductive arguments, and an SMT solver is just not the right tool for this sort of verification. A theorem prover like Isabelle, HOL, Coq, ... is the better choice here.
Having said that, the basic approach to establishing recursive function properties in SMT is to literally code up the inductive hypothesis as a quantified axiom, and arrange for the property you want proven to precisely line up with that axiom when the e-matching engine kicks in so it can instantiate the quantifiers "correctly." I'm putting the word correctly in quotes here, because the matching engine will go ahead and keep instantiating the axiom in unproductive ways especially for a function like Ackermann's. Theorem provers, on the other hand, precisely give you control over the proof structure so you can explicitly guide the prover through the proof-search space.
Here's an example you can look at: list concat in z3 which is doing an inductive proof of a much simpler inductive property than you are targeting, using the SMT-Lib interface. While it won't be easy to extend it to handle your particular example, it might provide some insight into how to go about it.
In the particular case of Z3, you can also utilize its fixed-point reasoning engine using the PDR algorithm to answer queries about certain recursive functions. See http://rise4fun.com/z3/tutorialcontent/fixedpoints#h22 for an example that shows how to model McCarthy's famous 91 function as an interesting case study.
Z3 will not try to do anything by induction for you, but (as Levent Erkok mentioned) you can give it the induction hypothesis and have it check that the result follows.
This works on your example as follows.
(declare-fun ackermann (Int Int) Int)
(assert (forall ((m Int) (n Int))
(= (ackermann m n)
(ite (= m 0) (+ n 1)
(ite (= n 0) (ackermann (- m 1) 1)
(ackermann (- m 1) (ackermann m (- n 1))))))))
(declare-const m Int)
(declare-const n Int)
(assert (>= m 0))
(assert (>= n 0))
; Here's the induction hypothesis
(assert (forall ((ihm Int) (ihn Int))
(=> (and (<= 0 ihm) (<= 0 ihn)
(or (< ihm m) (and (= ihm m) (< ihn n))))
(>= (ackermann ihm ihn) 0))))
(assert (not (>= (ackermann m n) 0)))
(check-sat) ; reports unsat as desired
Does
(=> (f g))
always mean the same thing as
(or (not f) g))
?
The two expressions behave differently in my model. While using => gives me UNSAT, using the other variant does not yield any result (timeout). I would be content just having a list of operators and their meanings. I am aware of the SMTLIB standard, but the documents don't explicitly talk about the meanings of operators. Specifically '=>' seems to double as an alias for the 'ite' (if_then_else) operator if used in a ternary expression and I'm quite confused about that.
I set the AUFLIA logic, if that's relevant.
I'm looking for a simple yes or no answer first. And a proper documentation about SMT2 (maybe a book) second.
I have this rather large model generated from Daniel Jackson's marksweep model for alloy4 of those of you who are willing to see for yourself.
Your expressions are incorrect/unwellformed.
=> indeed means 'implies'. In other words, (=> f g) is equivalent to (or (not f) g).
If in doubt, you could prove it using Z3. The below query is unsat:
(declare-const p Bool)
(declare-const q Bool)
(define-fun conjecture () Bool
(= (=> p q)
(or (not p) q)))
(assert (not conjecture))
(check-sat)
In the following example, I tried to use uninterpreted Boolean function like "(declare-const p (Int) Bool)" rather than single Boolean constant for each assumption. But it does not work (it gives compilation error).
(set-option :produce-unsat-cores true)
(set-option :produce-models true)
(declare-fun p (Int) Bool)
;(declare-const p1 Bool)
;(declare-const p2 Bool)
; (declare-const p3 Bool)
;; We assert (=> p C) to track C using p
(declare-const x Int)
(declare-const y Int)
(assert (=> (p 1) (> x 10)))
;; An Boolean constant may track more than one formula
(assert (=> (p 1) (> y x)))
(assert (=> (p 2) (< y 5)))
(assert (=> (p 3) (> y 0)))
(check-sat (p 1) (p 2) (p 3))
(get-unsat-core)
Output
Z3(18, 16): ERROR: invalid check-sat command, 'not' expected, assumptions must be Boolean literals
Z3(19, 19): ERROR: unsat core is not available
I understand that it is not possible (unsupported) to use Boolean function. Is there any reason behind that? Is there different way to do that?
We have this restriction because Z3 applies many simplifications before it solves a problem. Some of them will rewrite formulas and terms. The problem that is actually solved by Z3 is very often quite different from the input problem. We would have trace back the simplified assumptions to the original assumptions, or introduce auxiliary variables. Restricting to Boolean literals avoids this issue, and makes the interface very clean. Note that this restriction does not limit the expressiveness. If you think it is too annoying to declare many Boolean variables to track different assertions. I suggest you take a look at the new Python front-end for Z3 called Z3Py. It is much more convenient to use than SMT 2.0. Here is your example in Z3Py: http://rise4fun.com/Z3Py/cL
In this example, instead of creating an uninterpreted predicate p, a "vector" (actually, it is a Python list) o Boolean constants is created.
The Z3Py online tutorial contains many examples.
It is also possible to implement in Z3Py the approach that creates auxiliary variables.
Here is the script that does the trick. I defined a function check_ext that does all the plumbing. http://rise4fun.com/Z3Py/B4