In this paper (Section 3.2), it says that z3 applies rewriting/simplification of formulas before it does any other steps.
Suppose I have a formula in QF_UF, that consists of multiple assert statements. Is there any rewriting rule that would somehow "break the barrier" between different assert statements? Or, asking the other way round: Can I be sure that rewrite rules are only applied locally, "within" one assert statement?
For example, consider the following formula:
(set-logic QF_UF)
(set-option :auto-config false)
(set-option :PROOF_MODE 2)
(declare-fun a () Bool)
(assert a)
(assert (not a))
(check-sat)
(get-proof)
Can I be sure that the proof will contain a resolution step to prove False, or is it possible that False will be concluded by a rewrite/simplification step?
The reason I am asking is that for my application, every assert statement has a special semantics. Rewriting/Simplification across several assert statements would render the resulting proof of unsatisfiability unusable (or at least: very hard to use) for me.
Z3 3.2 applies several preprocessing steps. Using (set-option :auto-config false) will disable most of them. You should also include the following two options:
(set-option :propagate-booleans false)
(set-option :propagate-values false)
Related
I am experimenting with z3. I am surprised that, when setting the logic to LIA, z3 can return real numbers. For example, the following:
from z3 import *
sol = SolverFor("LIA")
vB = Real('vB')
sol.add(vB < 3)
sol.add(vB > 2)
sol.check()
print(sol.model())
returns:
[vB = 5/2]
Can someone please explain how it can be the case?
Strictly speaking, this is a "bug" in z3. Here's the equivalent SMT script:
(set-logic LIA)
(declare-fun vB () Real)
(assert (< vB 3.0))
(assert (> vB 2.0))
(check-sat)
(get-model)
If you run this with cvc4/cvc5, you get:
(error "Parse Error: a.smt2:2.23: Symbol 'Real' not declared as a type
(declare-fun vB () Real)
^
")
And Yices says:
(error "at line 2, column 20: undefined sort: Real")
CVC and Yices are correct here, since you restricted the logic to "LIA", the name "Real" is no longer defined. Z3, however, is playing loose here, and allowing reals by default. (It internally uses logics to pick which algorithms to run, but it's not always consistent in making sure the logic restricts the names available.)
You can report this at the z3 issue tracker here: https://github.com/Z3Prover/z3/issues. I suspect they're already aware of this, but would be good to have it recorded.
I have switched from using Int to Bit Vectors in SMT. However, the logic QF_BV does not allow the use of any quantifiers in your script, and I need to define FOL rules.
I know how to eliminate existential quantifiers, but universal quantifiers? How to do that?
Imagine a code like that:
(set-logic QF_AUFBV)
(define-sort Index () (_ BitVec 3))
(declare-fun P (Index) Bool)
(assert (forall ((i Index)) (= (P (bvadd i #b001)) (not (P i)) ) ) )
Strictly speaking, you're out-of-luck. According to http://smtlib.cs.uiowa.edu/logics.shtml, there's no logic that contains quantifiers and bit-vectors at the same time.
Having said that, most solvers will allow non-standard combinations. Simply leave out the set-logic command, and you might get lucky. For instance, Z3 takes your query just fine without the set-logic part; I just tried..
I am experimenting with Z3, and more specifically with muZ, however some queries fail, and I don't understand why.
For example this definition of implication
(declare-rel imp (Bool Bool))
(declare-var post Bool)
(rule (imp false post))
(rule (=> (imp true post) post))
(query (imp true false) :print-certificate true)
gives the error (error "query failed: Illegal head. The head predicate needs to be uninterpreted and registered (as recursive) (= (:var 0) true)")
Much larger examples, with many parameters defined with the same structure work as expected. Furthermore by removing the second rule I get the error ERROR: certificates are not supported for datalog which makes me suspect that for some reason this problem is being incorrectly interpreted as datalog, and the larger problems are being interpreted as fixedpoints.
What makes this query fail?
The format form rules generally assumes that rules have uninterpreted predicates in the head. The second rule has a bound variable in the head.
If you add non-propositional features to the datalog rules, such as arithmetic,
the fixedpoint engine will seek to dispatch an engine that understands such features. You can control the engine by specifying (set-option :fixedpoint.engine 'engine-name'), where 'engine-name' is datalog/duality/pdr, etc. Support for certificates and answers vary among the engines.
I tried to use bit vectors to get randomized results in model values like suggested by de Moura here but then with Z3Py instead of SMTLIB. I translated his example to:
from z3 import *
s = Solver()
x = BitVec('x', 16)
set_option('auto_config', False)
set_option('smt.phase_selection',5)
s.add(ULT(x,100))
s.check()
s.model()
s.check()
s.model()
However, the result seems to always be the same, i.e.
- repetitive checking with s.check() does not alter the result.
- even after a restart of the python interactive shell the result of the execution will be the same
Adding a change of the random seed did not alter the results: set_option('smt.random_seed', 123)
Does anyone have an idea why is not working as desired?
Thanks in advance!
Carsten
This case is simply too simple. It's essentially solved by the preprocessor and never gets to a point where it needs to select a phase, so random phase selection has no effect. Leo's answer to the cited post is now a little bit out of date and Z3 has changed, so it doesn't immediately replicate using the latest unstable version because Z3 chooses to use a different solver. We can still get the random behavior if we force it to use the incremental solver by adding a (push) command though; here's an updated example that is seed dependent:
(set-option :auto_config false)
(set-option :smt.phase_selection 5)
(set-option :smt.random_seed 456)
(declare-const x (_ BitVec 16))
(assert (bvult x (_ bv100 16)))
(push)
(check-sat)
(get-model)
;; try again to get a different model
(check-sat)
(get-model)
;; try again to get a different model
(check-sat)
(get-model)
I just upgraded z3 from 4.1 to 4.3.1, and it seems that the smtlib2 input has changed :
now, a function/constant declaration is not deleted by a pop statement.
Here is the SMTlib2 input that works fine with z3 4.1 (and other SMT solvers...), but return with an error with z3 4.3.1 : (error "line 19 column 25: invalid declaration, constant 'bs_2' (whith the given signature) already declared")
(set-option :produce-models true)
(set-option :produce-unsat-cores true)
(set-option :interactive-mode true)
(set-option :print-success false)
(push 1)
(declare-fun bs_1 () Bool)
(push 1)
(declare-fun bs_2 () Bool)
(assert (and bs_1 (not bs_2)))
(check-sat)
(pop 1)
(push 1)
(declare-fun bs_2 () Bool)
(assert (and bs_1 (not bs_2)))
(check-sat)
(pop 1)
(pop 1)
(exit)
Removing the last bs_2 declaration works fine with z3 4.3.1, but not for z3 4.1.
Am I using the push/pop wrong ?
In Z3 4.3.1, we tried to relax some of the SMT-LIB 2.0 restrictions to make Z3 more convenient to use. For example, we can now write (+ x 2) instead of (+ x 2.0) when x is Real. Declarations are global instead of scoped like in Z3 4.1. The motivation was to allow users to encode problems more succinctly. We can use the following option to enable scoped declarations like in Z3 4.1
(set-option :global-decls false)
That being said, I understand this change is very confusing and counter-intuitive for users that are used to other SMT solvers, or read a manual describing the SMT-LIB standard. Thus, we will change the default back to (set-option :global-decls false).