What is the "official" version of the PDR engine in Z3? - z3

I was trying out the PDR engine in Z3 and I'm not sure which version of Z3 to use.
The "official" master branch from git seems to work but is dated Nov 2012. I'm sure there have been improvements since then. The unstable branch, on the other hand, "may contain unstable and/or untested code", which seems to be true.
What would be the most recent "stable" version of the engine?
For example
(declare-rel R (Real Real))
(declare-var x Real)
(declare-var y Real)
(rule
(=> (and (= x 0) (= y 0)) (R x y))
)
(rule
(=> (R x y) (R (+ x 1) (+ y 1)))
)
(query
(and (R x y) (not (= x y)))
)
Above works in master, returning unsat, but in the unstable branch the engine wanders off not solving the problem. Same holds for the example from a recent CAV paper.

This is somewhat of a regression and thanks for pointing this out.
The older version of PDR used predicates from the query when checking for inductiveness. The updated version omits this feature and diverges even though the property is very easily seen as inductive.
Using predicates from the query isn't very general and I have tried to replace this with other means. For example you can do a "magic-set" transformation that should push opportune predicates down.

Related

Best Z3 tactics for elementary algebra of fields

I want to use Z3 to proof validity of statements like this:
∀ a b: ℤ, ~ b = 0 -> (a / b) ^ 2. = (a * a) / (b * b)
Or in SMT-LIB format:
(declare-fun b () Int)
(declare-fun a () Int)
(assert (=> (= b 0) false))
(assert (let ((a!1 (= (^ (/ (to_real a) (to_real b)) 2.0)
(/ (to_real (* a a)) (to_real (* b b))))))
(not a!1)))
(check-sat)
But I get timeout with the default tactic. I guess Z3 is wasting its time trying to instantiate numbers in order to find a solution. But I'm only interested in unsat output since the problem is generalized and a sat output doesn't mean anything. What combination of tactics I should use to find validity of simple algebraic statements like this?
When I run your script, I get unsat pretty quickly:
$ time z3 a.smt2
unsat
z3 a.smt2 0.17s user 0.01s system 97% cpu 0.191 total
Perhaps your z3 is too old? Here's the version I have:
$ z3 --version
Z3 version 4.12.0 - 64 bit
Try upgrading, I think the latest released version is 4.12.1.
If the issue persists and you have the latest z3, you should report this as a regression at https://github.com/Z3Prover/z3/issues

Tactics for z3 sequence problems

Are there specific tactics I should consider for quantifier-free sequence problems? I am getting unknown satisfiability solving problems like the one below (find a sequence containing one value but not another).
I am using version 4.8.5.0 of z3.
(declare-const l (Seq Int))
(declare-const x Int)
(declare-const y Int)
(assert (not (seq.contains l (seq.unit y))))
(assert (seq.contains l (seq.unit x)))
(check-sat)
[result is unknown]
Sequence logic recently went through a bunch of changes. When I try your benchmark with a fresh build of z3 from their github sources, it successfully reports sat. See here: https://github.com/Z3Prover/z3
Before reaching out for new tactics, would be great if you can use the github version.

Get fractional part of real in QF_UFNRA

Using smtlib I would like to make something like modulo using QF_UFNRA. This disables me from using mod, to_int, to_real an such things.
In the end I want to get the fractional part of z in the following code:
(set-logic QF_UFNRA)
(declare-fun z () Real)
(declare-fun z1 () Real)
(define-fun zval_1 ((x Real)) Real
x
)
(declare-fun zval (Real) Real)
(assert (= z 1.5));
(assert (=> (and (<= 0.0 z) (< z 1.0)) (= (zval z) (zval_1 z))))
(assert (=> (>= z 1.0) (= (zval z) (zval (- z 1.0)))))
(assert (= z1 (zval z)))
Of course, as I am asking this question here, implies, that it didn't work out.
Has anybody got an idea how to get the fractional part of z into z1 using logic QF_UFNRA?
This is a great question. Unfortunately, what you want to do is not possible in general if you restrict yourself to QF_UFNRA.
If you could encode such functionality, then you can decide arbitrary Diophantine equations. You would simply cast a given Diophantine equation over reals, compute the "fraction" of the real solution with this alleged method, and assert that the fraction is 0. Since reals are decidable, this would give you a decision procedure for Diophantine equations, accomplishing the impossible. (This is known as Hilbert's 10th problem.)
So, as innocent as the task looks, it is actually not doable. But that doesn't mean you cannot encode this with some extensions, and possibly have the solver successfully decide instances of it.
If you allow quantifiers and recursive functions
If you allow yourself quantifiers and recursive-functions, then you can write:
(set-logic UFNRA)
(define-fun-rec frac ((x Real)) Real (ite (< x 1) x (frac (- x 1))))
(declare-fun res () Real)
(assert (= (frac 1.5) res))
(check-sat)
(get-value (res))
To which z3 responds:
sat
((res (/ 1.0 2.0)))
Note that we used the UFNRA logic allowing quantification, which is required here implicitly due to the use of the define-fun-rec construct. (See the SMTLib manual for details.) This is essentially what you tried to encode in your question, but instead using the recursive-function-definition facilities instead of implicit encoding. There are several caveats in using recursive functions in SMTLib however: In particular, you can write functions that render your system inconsistent rather easily. See Section 4.2.3 of http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.5-draft.pdf for details.
If you can use QF_UFNIRA
If you move to QF_UFNIRA, i.e., allow mixing reals and integers, the encoding is easy:
(set-logic QF_UFNIRA)
(declare-fun z () Real)
(declare-fun zF () Real)
(declare-fun zI () Int)
(assert (= z (+ zF zI)))
(assert (<= 0 zF))
(assert (< zF 1))
(assert (= z 1.5))
(check-sat)
(get-value (zF zI))
z3 responds:
sat
((zF (/ 1.0 2.0))
(zI 1))
(You might have to be careful about the computation of zI when z < 0, but the idea is the same.)
Note that just because the encoding is easy doesn't mean z3 will always be able to answer the query successfully. Due to mixing of Real's and Integer's, the problem remains undecidable as discussed before. If you have other constraints on z, z3 might very well respond unknown to this encoding. In this particular case, it happens to be simple enough so z3 is able to find a model.
If you have sin and pi:
This is more of a thought experiment than a real alternative. If SMTLib allowed for sin and pi, then you can check whether sin (zI * pi) is 0, for a suitably constrained zI. Any satisfying model to this query would ensure that zI is integer. You can then use this value to extract the fractional part by subtracting zI from z.
But this is futile as SMTLib neither allows for sin nor pi. And for good reason: Decidability would be lost. Having said that, maybe some brave soul can design a logic that supported sin, pi, etc., and successfully answered your query correctly, while returning unknown when the problem becomes too hard for the solver. This is already the case for nonlinear arithmetic and the QF_UFNIRA fragment: The solver may give up in general, but the heuristics it employs might solve problems of practical interest.
Restriction to Rationals
As a theoretical aside, it turns out that if you restrict yourself to rationals only (instead of actual reals) then you can indeed write a first-order formula to recognize integers. The encoding is not for the faint of heart, however: http://math.mit.edu/~poonen/papers/ae.pdf. Furthermore, since the encoding involves quantifiers, it's probably quite unlikely that SMT solvers will do well with a formulation based on this idea.
[Incidentally, I should extend thanks to my work colleagues; this question made for a great lunch-time conversation!]

Symmetry breaking for Z3 -- in the context of the UFBV logic (new version)

(This is my second try to get help. If the question/approach do not make sense or not clear, please just let me know. I would also be pleased about any small hint or reference, which can help me to understand the behaviour of Z3 with my SBAs)
I am working on bounded verification of relational specification using the UFBV Z3 logic. The current problem I am investigating, needs the falsification of all possible models (because of a negative use of a reachability predicate), which kills the solver performance in higher bounds.
Because only a part of the possible models are indeed interesting (not isomorphic to others), I am trying to introduce symmetry breaking techniques (known in the SAT area).
However the use of what I call symmetry breaking axioms can improve the performance of Z3 in some cases, but the general, behaviour of the solver becomes instable.
One of my approaches (I think the most promising one), bases on breaking the symmetry on relations w.r.t. their domains. It introduces of each domains D of a relation R and each atom a \in D axioms, which enforce an order on the binary representation of R^{M} and R^{M[a+1/a]}, where M is a model for the specification. For homogeneous relations the axioms are relaxed.
Let be R \subset AxA a relation. My relaxed symmetry breaking axioms for R look like this:
;; SBA(R, A)_upToDiag
(assert
(forall ( (ai A) (aj A) )
(=>
(bvult ai aj)
(=>
(forall ((x A))
(=>
(bvult x aj)
(= (R ai x) (R (bvadd ai (_ bv1 n)) x))
)
)
(=>
(R ai aj)
(R (bvadd ai (_ bv1 n)) aj)
)))))
;; SBA(R, A)_diag
(assert
(forall ( (ai A) )
(=>
(forall ((x A))
(=>
(bvult x ai)
(= (R ai x) (R (bvadd ai (_ bv1 n)) x))
)
)
(=>
(R ai ai)
(R (bvadd ai (_ bv1 n)) (bvadd ai (_ bv1 n)))
))))
My problem is, that the effect of using this SBAs is not stable/consistent. It differs from bound to bound and form specification to another. Also the use of all or only one of the SBAs affects the performance.
In the SAT context the success of the so-called symmetry breaking predicate (SBP) approach bases on the backtracking capability of the SAT solver, which (somehow) guaranty, that if the solver back track, it will then prune the search space using, amongst others, the SBPs.
What is the differences (if any) in the context of Z3?
How can I enforce the solve to use these axioms to prune the search space (when it back track)?
Would the use of (quantifier) patterns for my SBAs helps?
Regards,
Aboubakr Achraf El Ghazi
In Z3 3.2, there are two main engines for handling quantified formulas: E-matching and MBQI (model based quantifier instantiation). E-matching is only effective in unsatisfiable formulas. Z3 will not be able to show that a formula is satisfiable using this engine. MBQI is more expensive, but it can show that several classes of formulas (containing quantifiers) are satisfiable. The Z3 guide describes these two engines (and other options). To use Z3 effectively on nontrivial problems, it is very useful to understand how these two engines work.
Symmetry breaking is usually very effective way to reduce the search space. It is hard to pinpoint exactly what is going on in your problem. I can see the following explanations for the non stable behavior:
MBQI is having a hard time creating a model that satisfies the SBAs. Although the SBAs prune the search space, if the problem is satisfiable, Z3 will try to build an interpretation (model) that satisfies them. So, in this case, the SBA is just overhead. This is particularly true, if the input formula is very easy to satisfy, but becomes hard when you add the SBAs. You can confirm this hypothesis by using the option MBQI_TRACE=true. Z3 will display messages such as: [mbqi] failed k!18. Where k![line-number] is the quantifier id. You can assign your own ids using the tag :qid. Here is an example:
(assert (forall ((x T) (y T)) (! (=> (and (subtype x y)
(subtype y x))
(= x y))
:qid antisymmetry)))
BTW, you can disable the MBQI module using MBQI=false.
In future versions of Z3, we are planning to add an option to disable MBQI for some quantified formulas. This feature may be useful for SBAs.
Another explanation is that E-matching is creating too many instances of the SBAs. You can confirm that using the option QI_PROFILE=true. Z3 will dump information such as:
[quantifier_instances] antisymmetry : 12 : 1 : 2.00
The first number is the number of generated instances. If that is the source of the problem, one solution is to assign restrictive patterns for the SBAs that are generating too many instances. For example, Z3 will use (R ai aj) as a pattern for SBA(R, A)_upToDiag. This kind of pattern may create a quadratic number of instances. Another experiment consists in disabling E-matching. Example, the option
AUTO_CONFIG=false EMATCHING=false MBQI=true
You may also try to disable relevancy propagation in the configuration above, option: RELEVANCY=0.
Finally, another option is to generate the instances of the SBAs that you believe are useful, and remove the quantified formulas.

Display quantified-out formula

how do I display the result of quantifier elimination ?
z3 seems to be happy with the following input
(set-option :elim-quantifiers true)
(declare-fun y () Real)
(simplify (exists ((x Real)) (>= x y)))
but it returns it the same as output.
Thanks
Z3 3.x has a new front-end for the SMT-LIB 2.0 input format.
In the new front-end, the command simplify is not an “umbrella” for all simplifications and pre-processing steps available in Z3.
The “do-all” approach used in Z3 2.x had several problems.
So, in Z3 3.x, we started using a fine-grain approach where the user can specify tactics/strategies for solving and/or simplifying formulas.
For example, one can write:
(declare-const x Int)
(assert (not (or (<= x 0) (<= x 2))))
(apply (and-then simplify propagate-bounds))
This new infrastructure is working in progress.
For example, Z3 3.2 does not have commands/tactics for eliminating quantifiers in the new front-end.
The commands/tactics for quantifier elimination will be available in Z3 3.3.
In the meantime, you can use the old SMT-LIB front-end for eliminating quantifiers.
You must provide the command line option -smtc to force Z3 to use the old front-end.
Moreover, the old front-end is not fully compliant with SMT-LIB 2.0. So, you must write:
(set-option ELIM_QUANTIFIERS true)
(declare-fun y () Real)
(simplify (exists ((x Real)) (>= x y)))

Resources