3-SAT formulas as an SMT-LIB - z3

I try to find whether there are such values of A-F that make the Boolean expression TRUE.
I use online z3 solver (https://jfmc.github.io/z3-play/)
It gives error
Error: (error "line 11 column 12: Wrong number of arguments (4) passed to function (declare-fun A () Bool)")
sat
This is my code:
(set-logic QF_LIA)
(declare-const A Bool)
(declare-const B Bool)
(declare-const C Bool)
(declare-const D Bool)
(declare-const E Bool)
(declare-const F Bool)
(assert
(and
(A or B or C)
(D or E or F)
))
(check-sat)
(get-model)
(exit)

In SMTLib, functions are written in prefix-notation. So, instead of:
(assert
(and
(A or B or C)
(D or E or F)
))
you should use:
(assert (and (or A B C)
(or D E F)
)
)
This is similar to languages like Lisp/Scheme, where prefix-notation makes the syntax simple to parse/manipulate by programs.

Related

is there a way to express "if and only if" in SMTLIB?

Is it the same as define in SMTLIB? Or is the only way to define a function on my own? If z3 has a way to do that via its python binding that would work for me also.
In SMTLib, iff is simply = over booleans:
(declare-fun a () Bool)
(declare-fun b () Bool)
(assert (= a b))
In z3py, you can use the regular equality comparison:
from z3 import *
a, b = Bools('a b')
s = Solver()
s.add(a == b)

Converting Z3 QBF formula directly to pcnf

I'm using Z3 theorem prover (using Z3Py: the Z3 API in Python) to create QBF (Quantified Boolean formula).
Is there any way in Z3 to directly convert your qbf formula into Prenex normal form ?
I don't think there's a tactic to convert to Prenex, but you can surely apply the quantifier-elimination tactic and further process your formulas. Note that the transformed formulas will not really look like the originals, as they are mechanically generated.
Here's an example:
from z3 import *
f = Function('f', IntSort(), IntSort(), IntSort())
x, y = Ints('x y')
p = ForAll(x, Or(x == 2, Exists(y, f (x, y) == 0)))
print Tactic('qe')(p)
Here qe is the quantifier elimination tactic. This produces:
[[Not(Exists(x!0,
Not(Or(x!0 == 2,
Exists(x!1,
And(f(x!0, x!1) <= 0,
f(x!0, x!1) >= 0))))))]]
For a nice tutorial on tactics, see here: http://ericpony.github.io/z3py-tutorial/strategies-examples.htm
You could use the skolemize tactic (snf) which will by definition be in prenex form. However it will also eliminate existential quantifiers which is not what you want. Here's an example.
(declare-fun a (Int) Bool)
(declare-fun b (Int) Bool)
(declare-fun c (Int) Bool)
(assert
(forall ((x Int))
(or
(exists ((y Int))
(a y)
)
(exists ((z Int))
(=>
(b z)
(c x)
)
)
)
)
)
(apply
(and-then
; mode (symbol) NNF translation mode: skolem (skolem normal form), quantifiers (skolem normal form + quantifiers in NNF), full (default: skolem)
(using-params snf :mode skolem)
)
:print_benchmark true
:print false
)
When Z3 is given the above it will responds with something like
(declare-fun c (Int) Bool)
(declare-fun b (Int) Bool)
(declare-fun a (Int) Bool)
(assert (forall ((x Int))
(or (exists ((y Int)) (a y)) (exists ((z Int)) (=> (b z) (c x))))))
(check-sat)
You can see the available tactics by running
echo "(help-tactic)" | ./z3 -in | less
from a bash shell.
Unfortunately I can't see one that states it does conversion to prenex.

Implicit vs explicit existential quantification in SMT formulas

Given the following code:
from z3 import *
a,b,c = BitVecs('a b c', 32)
f1 = Exists([a, b, c], And(a + b == c, a < b, c == 1337))
f2 = And(a + b == c, a < b, c == 1337)
prove(f1 == f2)
I would assume that z3 implicitly existential quantifies a, b and c, in this example. Why aren't the two formulas equal, what is the difference?
The way you formulated your query doesn't really check whether f1 equals f2. Your query is essentially asking the solver to find a, b, c such that the following fails to hold:
Exists([a, b, c], And(a + b == c, a < b, c == 1337))
=
And(a + b == c, a < b, c == 1337))
And indeed, you can instantiate the outer a, b, and c such that the right hand-side is false; but the left hand side is an existential which is true; thus failing the equivalence you asked for.
It might be easier to see this with a simpler example; with just one boolean variable. You're essentially asking:
x == (Exists [x], x)
You see that those xs are actually different, so we can rename the inner one to (say) y; we get:
x == (Exist [y]. y)
Now, the right-hand-side is clearly true since there is a y that makes (Exist [y]. y) true. So, you are essentially asking the prover to establish that no matter what x you pick, it is true. Which is definitely not the case when you pick x to be false.
Indeed, you can ask Z3 to give you the formula it's trying to prove, and this is what it returns for your original query:
(set-info :status unknown)
(declare-fun c () (_ BitVec 32))
(declare-fun b () (_ BitVec 32))
(declare-fun a () (_ BitVec 32))
(assert
(let (($x24 (exists ((a (_ BitVec 32))
(b (_ BitVec 32))
(c (_ BitVec 32)) )
(and (= (bvadd a b) c) (bvslt a b) (= c (_ bv1337 32))))))
(let (($x57 (= $x24 (and (= (bvadd a b) c) (bvslt a b) (= c (_ bv1337 32))))))
(and $x57))))
(check-sat)
Which is clearly satisfiable, by the above reasoning.
(See Z3: convert Z3py expression to SMT-LIB2 from Solver object for the code that converts a z3-python query to smt-lib.)

Acessing elements of a sort w/ multiple fields

I'm having some trouble using sorts in the SMTlib2 format. For example, I define an Interval as:
(declare-sort Pair 2)
(define-sort Interval () (Pair Int Int))
Now how can I return a new Interval from a function? e.g.:
(define-fun getInterval ((a Int) (b Int)) Interval
(Interval a b))
This doesn't work.
My question is: how can I construct and instantiate objects of a given sort, and how can I access their fields?
Right now I'm using 2 UFs that I created as field getters, but I still don't know how to have a constructor:
(declare-fun L (Interval) Int)
(declare-fun H (Interval) Int)
Thanks,
Nuno
You should look into Record subsection, Datatypes section in Z3 SMT guide. Basically, you can create a record type with a constructor mk-pair and two selectors first and second for accessing its fields.
Here is an examplerise4fun link:
(set-option :macro-finder true)
(declare-datatypes (T1 T2) ((Pair (mk-pair (first T1) (second T2)))))
(define-sort Interval () (Pair Int Int))
(define-fun getInterval ((a Int) (b Int)) Interval
(mk-pair a b))
(declare-const p1 Interval)
(declare-const p2 Interval)
;construct objects of a give sort
(assert (= p1 (getInterval 2 2)))
;accessing their fields
(assert (= (first p1) (second p2)))
(check-sat)
(get-model)

Can I use declare-const to eliminate the forall universal quantifier?

I have some confusion of using universal quantifier and declare-const without using forall
(set-option :mbqi true)
(declare-fun f (Int Int) Int)
(declare-const a Int)
(declare-const b Int)
(assert (forall ((x Int)) (>= (f x x) (+ x a))))
I can write like this:
(declare-const x Int)
(assert (>= (f x x) (+ x a))))
with Z3 will explore all the possible values of type Int in this two cases. So what's the difference?
Can I really use the declare-const to eliminate the forall quantifier?
No, the statements are different. Constants in Z3 are nullary (0 arity) functions, so (declare-const a Int) is just syntactic sugar for (declare-fun a () Int), so these two statements are identical. Your second statement (assert (>= (f x x) (+ x a)))) implicitly asserts existence of x, instead of for all x as in your first statement (assert (forall ((x Int)) (>= (f x x) (+ x a)))). To be clear, note that in your second statement, only a single assignment for x needs to satisfy the assertion, not all possible assignments (also note the difference in the function f, and see this Z3#rise script: http://rise4fun.com/Z3/4cif ).
Here's the text of that script:
(set-option :mbqi true)
(declare-fun f (Int Int) Int)
(declare-const a Int)
(declare-fun af () Int)
(declare-const b Int)
(declare-fun bf () Int)
(push)
(declare-const x Int)
(assert (>= (f x x) (+ x a)))
(check-sat) ; note the explicit model value for x: this only checks a single value of x, not all of them
(get-model)
(pop)
(push)
(assert (forall ((x Int)) (>= (f x x) (+ x a))))
(check-sat)
(get-model) ; no model for x since any model must satisfy assertion
(pop)
Also, here's an example from the Z3 SMT guide ( http://rise4fun.com/z3/tutorial/guide from under the section "Uninterpreted functions and constants"):
(declare-fun f (Int) Int)
(declare-fun a () Int) ; a is a constant
(declare-const b Int) ; syntax sugar for (declare-fun b () Int)
(assert (> a 20))
(assert (> b a))
(assert (= (f 10) 1))
(check-sat)
(get-model)
You can eliminate a top-level exists with a declare-const. Maybe this is the source of your confusion? The following two are equivalent:
(assert (exists ((x Int)) (> x 0)))
(check-sat)
and
(declare-fun x () Int)
(assert (> x 0))
(check-sat)
Note that this only applies to top-level existential quantifiers. If you have nested quantification of both universals (forall) and existentials (exists), then you can do skolemization to float the existentials to the top level. This process is more involved but rather straightforward from a logical point of view.
There is no general way of floating universal quantifiers to the top-level in this way, at least not in classical logic as embodied by SMT-Lib.

Resources