Z3 patterns and injectivity - z3

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.

Related

Limit scope of defined sort

I am trying to limit the scope of a newly defined sort via SMT-LIB. Doing so would simplify my script by reducing the amount of necessary assertions.
For this I played with define-sort and forall.
(define-sort R () Real)
(assert (forall ((x R)) (< 0 x)))
(declare-const r R)
(check-sat)
But z3 always returns unsat no matter what. So I guess this is not possible. Is it?
Unfortunately, this is not possible in SMTLib. See this answer for details: Is there an UnsignedIntSort in Z3?
As Christoph pointed out your query is unsat because the quantified assertion is false; which puts the solver in the unsat state, regardless of what other constraints you might have.
In my experience, the best way to deal with these scenarios is to not use SMTLib directly; but instead a higher-level API and use the programmatic features afforded by those environments to spit out all the > 0 constraints as you need them. It's hairy and ugly, but it is the only way to deal with these in SMTLib as it stands today. The only solver that supported this sort of "predicate subtyping" was Yices v1.0 with its own input language, which is no longer supported.

Complexity of finding a solution to SMT system with quantifier

I need to find a solution to a problem by generating by using z3py. The formulas are generated depending on input of the user. During the generation of the formulas temporary SMT variables are created that can take on only a limited amount of values, eg is its an integer only even values are allowed. For this case let the temporary variables be a and b and their relation with global variables x and y are defined by the predicate P(a,b,x,y).
An example generated using SMT-LIB like syntax:
(set-info :status unknown)
(declare-fun y () Int)
(declare-fun x () Int)
(assert
(forall (
(a Int) (b Int) (z Int) )
(let
(($x22 (exists ((z Int))(and (< x z) (> z y)))))
(=>
P(a, b, x, y)
$x22))))
(check-sat)
where
z is a variable of which all possible values must be considered
a and b represent variables who's allowed values are restricted by the predicate P
the variable 'x' and 'y' need to be computed for which the formula is satisfied.
Questions:
Does the predicate P reduce the time needed by z3 to find a solution?
Alternatively: viewing that z3 perform search over all possible values for z and a will the predicate P reduce the size of the search space?
Note: The question was updated after remarks from Levent Erkok.
The SMTLib example you gave (generated or hand-written) doesn't make much sense to me. You have universal quantification over x and z, and inside of that you existentially quantify z again, and the whole formula seems meaningless. But perhaps that's not your point and this is just a toy. So, I'll simply ignore that.
Typically, "redundant equations" (as you put it), should not impact performance. (By redundant, I assume you mean things that are derivable from other facts you presented?) Aside: a=z in your above formula is not redundant at all.
This should be true as long as you remain in the decidable subset of the logics; which typically means linear and quantifier-free.
The issue here is that you have quantifier and in particular you have nested quantifiers. SMT-solvers do not deal well with them. (Search stack-overflow for many questions regarding quantifiers and z3.) So, if you have performance issues, the best strategy is to see if you really need them. Just by looking at the example you posted, it is impossible to tell as it doesn't seem to be stating a legitimate fact. So, see if you can express your property without quantifiers.
If you have to have quantifiers, then you are at the mercy of the e-matcher and the heuristics, and all bets are off. I've seen wild performance characteristics in that case. And if reasoning with quantifiers is your goal, then I'd argue that SMT solvers are just not the right tool for you, and you should instead use theorem provers like HOL/Isabelle/Coq etc., that have built-in support for quantifiers and higher-order logic.
If you were to post an actual example of what you're trying to have z3 prove for you, we might be able to see if there's another way to formulate it that might make it easier for z3 to handle. Without a specific goal and an example, it's impossible to opine any further on performance.

Using functions, reals, and quantifiers in Z3

I'm trying to pose queries to Z3 that involve uninterpreted functions (always with domain int), reals, and quantifiers. I know that adding quantifiers will often lead to unknown results, but I was surprised at how quickly this happened:
(declare-fun $in1 (Int) Real)
(declare-fun $in2 (Int) Real)
(assert (< ($in1 0) ($in2 0)))
(assert (forall (($$out Real))
(not (and (< ($in1 0) $$out) (< $$out ($in2 0))))))
(check-sat)
This query should result in unsat but instead times out with unknown. Is there a flag or option I could set which might lead Z3 to solve this query? I'd hate to have to go through and flatten all my uninterpreted functions into scalars, but that is something I could do.
Yes, it looks like this is a hard instance for Z3. E-matching fails to prove unsatisfiability and after that MBQI essentially starts to enumerate real numbers, which will not lead to the goal here.
If you just want a quick result but don't care about unknowns, simply set smt.mbqi.max_iterations to a small enough value. You can also try to help the e-matching engine by providing instantiations patterns (see e.g., the quantifier section in the Z3 guide).
There's also a related question that might help understanding: Z3 patterns and injectivity
Arie Gurfinkel pointed out that (check-sat-using qe-sat) solves this problem.

How to efficiently solve combinations of theories in Z3

I am trying to solve a problem that involves propositional satisfiability (with quantifiers), and linear arithmetic.
I have formulated the problem, and Z3 is able to solve it, but it is taking an unreasonably long time.
I have been trying to help Z3 along by specifying tactics, but I haven't made much progress (I have no knowledge of logic theories).
Following is a highly simplified problem that captures the essence of what I am trying to solve. Could anyone give suggestions?
I tried to read up on things like Nelson Oppen method, but there were a lot of unfamiliar notations, and it'll take a long time to learn it.
Also, does Z3 allow users to tweak these configurations? Lastly, how can I use these tactics with z3py?
(declare-datatypes () ((newtype (item1) (item2) (item3))))
(declare-fun f (newtype newtype) Bool)
(declare-fun cost (newtype newtype) Real)
(assert (exists ((x newtype)(y newtype)) (f x y)))
(assert (forall ((x newtype)(y newtype)) (=> (f x y) (> (cost x y) 0))))
(assert (forall ((x newtype) (y newtype)) (<= (cost x y) 5)))
(check-sat)
(get-model)
The sample problem you encoded uses quantification. Z3 uses a particular procedure for deciding satisfiability of a class of quantified formulas, referred to as model-based quantifier instantiation (the mbqi option). It works by extending a candidate model for the quantifier-free portion of your formulas into a model for also the quantifiers. This process may involve a lot
of search. You can extract statistics from the search process by running Z3 with the option /st and it will show selected statistics of the search process and give a rough idea of what is happening during search. There is no particular tactic combination that specializes to classes of formulas with arithmetic and quantifiers (there is a class of formulas that use bit-vectors and quantifiers that are handled by a default tactic for such formulas).
I tried to read up on things like Nelson Oppen method, but there were a lot of unfamiliar notations, and it'll take a long time to learn it.
This is going to be a bit tangential to understanding the search issue with quantifiers.
Also, does Z3 allow users to tweak these configurations?
Yes, you can configure Z3 from the command-line.
For example, you can disable MBQI using the command line:
z3 tt.smt2 -st smt.auto_config=false smt.mbqi=false
Z3 now returns "unknown" because the weaker quantifier engine that performs selected instantiations
is not going to be able to determine that the formula is satisfiable.
You can learn the command-line options by following the instructions from "z3 -?"
Lastly, how can I use these tactics with z3py?
You can use tactics from z3py. The file z3.py contains
brief information of how to combine tactics.
Though, I would expect that the difficulty of your problem class really has to do
with the search hardness involved with quantifiers. It is very easy to pose
formulas with quantifiers where theorem provers diverge as these classes of formulas
are generally highly undecidable.

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