Prove() method of Z3? - z3

Z3 has a prove() method, that can prove the equivalence of two formulas.
However, I cannot find technical documentation of this prove() method. What is the definition of "equivalence" that prove() is using behind the scene ? Is that the "partial equivalence" (proposed in the "Regression Verification" paper), or something more powerful ?
A reminder, the "partial equivalence" guarantees that two formulas are equivalent if given the same input, they produce the same output.

In "Regression Verification", we are checking whether a newer version of a program produces the same output as the earlier one. That is, it is an approach for checking program equivalence.
In this approach, theorem provers (SMT solvers) such as Z3 are used. That being said, we should not confuse program equivalence with formula equivalence in first-order logic. Z3 processes first-order logic formulas. First-order logic has well defined semantics. A key concept is satisfiability. For example, the formula p or q is satisfiable, because we can make it true by assigning p or q to true. On the other hand, p and (not p) is unsatisfiable. We can find additional information in this section of the Z3 tutorial.
The Z3 API provides procedures for checking the satisfiability of first-order formulas. The Z3 Python interface has a prove procedure. It shows that a formula is valid by showing that its negation is unsatisfiable. This is a simple function built on top of the Z3 API. Here is a link to its documentation.The documentation was automatically generated from the PyDoc annotations in the code.
Note that, prove(F) is checking whether a formula F is valid or not. Thus, we can use prove(F == G) to try to prove that two first-order formulas F and G are equivalent. That is, we are essentially showing that F iff G is a valid formula.

Related

Z3 times out on (presumably) decidable logic

We are experimenting with a relational logic for functional program verification. Our logic is equipped with relations over algebraic datatypes along with equality and subset-inclusion predicates over relations. Our verification procedure performs inductive program analysis (structural induction) and generates verification conditions (VCs) with sufficiently strong inductive hypotheses. VCs generated by our verification procedure adhere to the following format:
bindings <var-type bindings> in <antecedent-predicate> => <consequent-predicate> end
Here is an example VC generated by our procedure : http://pastebin.com/exncPHDA
We encode VCs thus generated in SMT2 language using following rules:
Each concrete type (eg: 'a list) translates to an uninterpreted sort.
Relations are encoded as uninterpreted n-ary functions from uninterpreted sorts to bool.
Relational assertions (eg: R = R1 U R2, R = R1 X R2) are encoded as prenex-quantified assertions over uninterpreted functions.
The result of above encoding is (presumably) a formula in effectively propositional (EPR) first-order logic. With help of Z3, we were able to assert validity (unsatisfiability of negation) of many VCs. However, in some cases when VC is invalid (negation is SAT), Z3 loops. The example given above (http://pastebin.com/exncPHDA) is one such VC, whose SMT2 encoding is given here : http://pastebin.com/s8ezha7D . Z3 doesn't seem to terminate while asserting this formula.
Given that deciding quantified boolean formulas is NEXPTIME hard, non-termination of decision procedure is not very surprising. Nonetheless, we would like to know if there are any optimizations that we can do while encoding the formula in Z3 so as to make non-termination least likely -
Our current encoding creates many empty sets (i.e., one assertion of form forall x:T, f(x)=false) and many instances of same singleton sets (i.e., forall x:T, (f(x) = true) <=> (x = v)). Does reducing such duplication help?
Due to program elaboration, we currently have many variables and transitive equalities. Does reduction in number of variables help?
Also, how likely is it that Z3 loops while deciding an unsatisfiable quantified boolean formula?
In Z3, we say a quantifier of the form forall X, f(X) = T[X], where X is vector of variables, f is an uninterpreted function, and T is a term/formula that does not contain f, is a macro. Z3 can eliminate these quantifiers in a preprocessing step by simply replacing all occurrences of f. The option :macro-finder turns on this feature.
(set-option :macro-finder true)
If we apply this preprocessing step, the example can be solved instantaneously.
Here is a link with the updated script: http://rise4fun.com/Z3/z2UJ
Remark: in the work-in-progress (unstable) branch at http://z3.codeplex.com, this option is called :smt.macro-finder.

Z3 patterns and injectivity

In the Z3 tutorial, section 13.2.3, there is a nice example on how to reduce the number of patterns that have to be instantiated when dealing with the axiomatisation of injectivity. In the example, the function f that has to be stated injective, takes an object of type A as input and return an object of type B. As far as I understand the sorts A and B are disjunct.
I have an SMT problem (FOL+EUF) on which Z3 seems not to terminate, and I am trying to isolate the cause. I have a function f:A->A that I assert being injective. Could the problem be that the domain and codomain of f coincide?
Thanks in advance for any suggestion.
Z3 does not terminate because it keeps trying to build an interpretation for the problem.
Satisfiable problems containing injectivity axiom are usually hard for Z3.
They usually fall in a class of problems that can't be decided by Z3
The Z3 guide describes most of the classes that can be decided by Z3.
Moreover, Z3 can produce models for infinite domains such as integers and reals. However, in most cases, the functions produced by Z3 have finite ranges. For example, the quantifier forall x, y: x <= y implies f(x) <= f(y) can be satisfied by assigning f to a function that has a finite range. More information can be found in this article. Unfortunately, injectivity usually requires a range that is as "big" as the domain. Moreover, it is very easy to write axioms that can only be satisfied by an infinite universe. For example, the formula
(assert
(forall ((d1 Value)(d2 Value)(d3 Value)(d4 Value))
(! (=>
(and (= (ENC d1 d2) (ENC d3 d4)))
(and (= d1 d3) (= d2 d4))
)
:pattern ((ENC d1 d2) (ENC d3 d4)))
)
)
can only be satisfied if the universe of Value has one element or is infinite.
Another problem is combining the injectivity axiom for a function f with axioms of the form forall x: f(x) != a. If f is a function from A to A, then the formula can only be satisfied if A has an infinite universe.
That being said, we can prevent the non-termination by reducing the amount of "resources" used by the Z3 model finder for quantified formulas. The options
(set-option :auto-config false)
(set-option :mbqi-max-iterations 10)
If we use these options, Z3 will terminate in your example, but will return unknown. It also returns a "candidate" model. It is not really a model since it does not satisfy all universal quantifiers in the problem. The option
(set-option :mbqi-trace true)
will instruct Z3 to display which quantifiers were not satisfied.
Regarding the example in section 13.2.3, the function may use the same input and return types. Using the trick described in this section will only help unsatisfiable instances. Z3 will also not terminate (for satisfiable formulas) if you re-encode the injectivity axioms using this trick.
Note that the tutorial you cited is very old, and contains outdated information.

Model-based Quantifier Instantiation and the St1 fragment of many-sorted logic

This is a follow-up to my previous question on Z3's Model-based
Quantifier Instantiation (MBQI) and the stratified sorts fragment (thanks
again to Leonardo de Moura for the quick answer).
In their paper on decidable fragments of many-sorted logic [Abadi et
al., Decidable fragments of many-sorted logic, LPAR 2007], the authors
describe a fragment St1 of many-sorted logic that is decidable with a
finite model property.
This fragment requires the sorts to be stratified and the formula F to be in (skolemized) prenex normal form as described in the Z3
documentation, but allows an additional atomic formula
y in Im[f]
to occur in F, which is a "shorthand" for
exists x1 : A1, ..., xn : An . y = f(x1,...,xn)
where f is a function with a signature f : A1 x ... x An -> B, and f must be the only function with range B. Thus, the St1 fragment allows (in a very restricted way) to violate the stratification, e.g., in order to assert that f is surjective.
I am not sure if this could be an open research question:
Does someone know whether the MBQI decision procedure for Z3 is complete
for the St1 fragment? Will Z3 produce (theoretically) either SAT or
UNSAT for F after a finite time?
First, one clarification, in principle, MBQI can decide the stratified multi-sorted fragment. The justification is given in Section 4.1 of http://research.microsoft.com/en-us/um/people/leonardo/ci.pdf (*). However, Z3 4.0 does not support implement the additional rules suggested in Section 4.1. So, Z3 4.0, may fail (return unknown) on formulas that are in this fragment. I just want to make clear a distinction between the algorithm and the actual implementation using the current Z3.
Regarding your question, yes MBQI framework can decide the stratified formulas containing the expanded predicate y in Im[f]. I'm assuming this predicate occurs only positively.
That is, we do not have not y in Im[f] which is equivalent to
forall x1:A1, ...,xn:An. y != f(x1, ... xn)
If y in Im[f] occurs only positively, then it can be expanded, and after skolemization we have a ground formula of the form y = f(k1, ..., kn).
MBQI is still a decision procedure because the set F* defined in (*) will still be finite. F* may become infinite only if the stratification is broken inside of a universal formula.

Model-based Quantifier Instantiation and the Stratified Sorts Fragment

the documentation of Z3 says for the Model-based Quantifier Instantiation (MBQI):
Stratified Sorts Fragment
The statified sorts fragment is another decidable fragment of many
sorted first-order logic formulas. It corresponds to formulas which,
when written in prenex normal form, there is a function level from
sorts to naturals, and for every function
(declare-fun f (S_1 ... S_n) R)
level(R) < level(S_i).
Does Z3 support any formula that is in prenex normal form, or only universal ones where all existential quantifiers have been removed by skolemization?
This would make the fragment more restrictive, wouldn't it (as the skolem functions might break the stratification)?
( At least in the paper on MBQI [Complete instantiation for quantified SMT formulas, Yeting Ge and Leonardo de Moura, CAV 2009] it seems to me that only universal formulas were covered. )
You are correct. The condition level(R) < level(S_i) must be satisfied after all existential quantifiers have been removed by skolemization. Skolemization may introduce new uninterpreted function symbols, and they also need to satisfy the condition above.

Quantifier Elimination - More questions

Many thanks Josh and Leonardo for answering the previous question.
I have few more questions.
<1> Consider another example.
(exists k) i * k > = 4 and k > 1.
This has a simple solution i > 0. (both for Int and Real case)
However, when I tried following,
(declare-const i Int)
(assert (exists ((k Int)) (and (>= (* i k) 4) (> k 1))))
(apply (using-params qe :qe-nonlinear true))
Z3 Could not eliminate quantifier here.
However, it could eliminate for a Real case. (when i and k are both reals)
Is Quantifier Elimination more difficult for integers?
<2> I am using Z3 C API in my system. I am adding some non-linear constraints on Integers with quantifiers in my system.
Z3 currently checks for satisfiability and gives me a correct model when the system is satisfiable.
I know that after quantifier elimination, these constraints get reduced to linear constraints.
I thought that z3 does quantifier elimination automatically before checking satisfiability. But since, it couldn't do that in case 1 above, I now think, that it usually finds a model without Quantifier Elimination. Am I correct?
Currently z3 can solve the constraints in my system. But it may fail on complex systems.
In such case, is it a good idea to do quantifier elimination by some other method without z3 and add constraints to z3 later?
<3> I can think of adding Real non-linear constraints instead of Integer non-linear constraints in my system. In that case, how can I enforce z3 to do Quantifier Elimination using C-API ?
<4> Finally, is this a good idea to enforce z3 to do Quantifier Elimination? Or it usually finds a model more intelligently without doing Quantifier Elimination?
Thanks.
<1> The theory of nonlinear integer arithmetic does not admit quantifier elimination (qe).
Moreover, the decision problem for nonlinear integer arithmetic is undecidable.
Recall that, Z3 has limited support for quantifier elimination of nonlinear real arithmetic formulas. The current procedure is based on virtual term substitution. Future versions, may have full support for nonlinear real arithmetic.
<2> Quantifier elimination is not enabled by default. The user must request it.
Z3 may find models for satisfiable formulas even when quantifier elimination is not enabled.
It uses a technique called model-based quantifier instantiation (MBQI). The Z3 online tutorial has several examples describing capabilities and limitations of this technique.
<3> You have to enable it when you create the Z3_context object.
Any option that is set in the command line, can be provided during Z3_context object creation. Here is an example, that enables model construction and quantifier elimination:
Z3_config cfg = Z3_mk_config();
Z3_context ctx;
Z3_set_param_value(cfg, "MODEL", "true");
Z3_set_param_value(cfg, "ELIM_QUANTIFIERS", "true");
Z3_set_param_value(cfg, "ELIM_NLARITH_QUANTIFIERS", "true");
ctx = mk_context_custom(cfg, throw_z3_error);
Z3_del_config(cfg);
After that, ctx is pointing to a Z3 context object that supports model construction and quantifier elimination.
<4> The MBQI module is not complete even for the linear arithmetic fragment.
The Z3 online tutorial describes the fragments it is complete. MBQI module is a good option for problems that contain uninterpreted functions. If your problems only use arithmetic, then quantifier elimination is usually better and more efficient. That being said, several problems can be quickly solved using MBQI.

Resources