What is the correct way to handle quantified formulas with respect to empty models? - z3

I'm playing with uninterpreted sorts and functions and cannot quite understand how quantified formulas interact with empty models. Here (also here http://rise4fun.com/Z3Py/6ets) are some simple examples that somewhat confuse me:
[∀v : False] is unsat, while "intuitively" it holds for an empty model.
Checking [∃v : v = v] yields an empty model while that does not have a satisfying assignment.
Some formulas, seemingly equivalent to [∃v : v = v], somehow prevent z3 from producing empty models. [∃v, v1 : v = v1] is one such example. E.g., if we add such formula to a solver and then try to create something resembling an allsat procedure (adding more and more constraints to rule out more and more models), we would run into unsat before getting an empty model.
So, could you please refer me to any documents/papers describing how z3 handles quantifiers and empty models?
Also, if I choose to restrict my attention to nonempty models only, what is the correct way to ask z3 for that? Things like [∃v, v1 : v = v1] seem to do the trick, but is there a better way?

Z3 does not consider empty models. This is a standard assumption in first-order logic. For more details search "first-order logic empty models", you will get many links explaining the motivation for this convention. The wikipedia page for first-order logic has a brief description (section "Empty domains").
Moreover, we should not confuse [] with the empty model. It is just saying that for satisfying the input formulas, Z3 does not need to assign an interpretation to any uninterpreted symbol in the input formula. Z3 displays only the interpretation of symbols that are needed to satisfy the formula. For example, the formula [∃v : v = v] does not contain any uninterpreted symbol, then Z3 just displays the empty assignment [].

Related

Basic error using solver in Z3-Python: it is returning [] as a model

Maybe I have slept bad today, but I am really struggling with this simple query to Z3-Python:
from z3 import *
a = Bool('a')
b = Bool('b')
sss = Solver()
sss.add(Exists([a,b], True))
print(sss.check())
print(sss.model())
The check prints out sat, but the model is []. However, it should be printing some (anyone) concrete assignment, such as a=True, b=True.
The same is happening if I change the formula to, say: sss.add(Exists([a,b], Not(And(a,b)))). Also tested sss.add(True). Thus, I am missing something really basic, so sorry for the basic nature of this question.
Other codes are working normally (even with optimizers instead of solvers), so it is not a problem of my environment (Collab)
Any help?
Note that there's a big difference between:
a = Bool('a')
b = Bool('b')
sss.add(Exists([a, b], True))
and
a = Bool('a')
b = Bool('b')
sss.add(True) # redundant, but to illustrate
In the first case, you're checking if the statement Exists a. Exists b. True is satisfiable; which trivially is; but there is no model to display: The variables a and b are inside quantification; and they don't play any role in model construction.
In the second case, a and b are part of the model, and hence will be displayed.
What's confusing is why do you need to declare the a and b in the first case. That is, why can't we just say:
sss.add(Exists([a, b], True))
without any a or b in the environment? After all, they are irrelevant as far as the problem is concerned. This is merely a peculiarity of the Python API; there's really no good reason other than this is how it is implemented.
You can see the generated SMTLib by adding a statement of the form:
print(sss.sexpr())
and if you do that for the above segments, you'll see the first one doesn't even declare the variables at all.
So, long story short, the formula exists a, b. True has no "model" variables and thus there's nothing to display. The only reason you declare them in z3py is because of an implementation trick that they use (so they can figure out the type of the variable), nothing more than that.
Here're some specific comments about your questions:
An SMT solver will only construct model-values for top-level declared variables. If you create "local" variables via exists/forall, they are not going to be displayed in models constructed. Note that you could have two totally separate assertions that talk about the "same" existentially quantified variable: It wouldn't even have a way of referring to that item. Rule-of-thumb: If you want to see the value in a model, it has to be declared at the top-level.
Yes, this is the reason for the trick. So they can figure out what type those variables are. (And other bookkeeping.) There's just no syntax afforded by z3py to let you say something like Exists([Int(a), Int(b)], True) or some such. Note that this doesn't mean something like this cannot be implemented. They just didn't. (And is probably not worth it.)
No you understood correctly. The reason you get [] is because there are absolutely no constraints on those a and b, and z3's model constructor will not assign any values because they are irrelevant. You can recover their values via model_completion parameter. But the best way to experiment with this is to add some extra constraints at the top level. (It might be easier to play around if you make a and b Ints. At the top level, assert that a = 5, b = 12. At the "existential" level assert something else. You'll see that your model will only satisfy the top-level constraints. Interestingly, if you assert something that's unsatisfiable in your existential query, the whole thing will become unsat; which is another sign of how they are treated.
I said trivially true because your formula is Exists a. Exists b. True. There're no constraints, so any assignment to a and b satisfy it. It's trivial in this sense. (And all SMTLib logics work over non-empty domains, so you can always assign values freely.)
Quantified variables can always be alpha-renamed without changing the semantics. So, whenever there's collision between quantified names and top-level names, imagine renaming them to be unique. I think you'll be able to answer your own question if you think of it this way.
Extended discussions over comments is really not productive. Feel free to ask new questions if anything isn't clear.

how to solve equation instead of giving one model in z3

This might not beyond the scope of z3, I know in Z3 we can simplify expression, but I wonder if z3 can solve the equation instead of giving a model.
For example, I want the following equation always be true for any value of a. Using ForAll quantifier in this case would return unsat.
a == b - c + 2
The solution I expect is a formula for one specified variable while simplify doesn't deal with this, like
b == a + c - 2 or c == b - a + 2
Is there any API for this ? Thanks in advance.
Not sure what exactly the question is here, but it sounds like you want to get all satisfying solutions instead of a single satisfying solution. It is possible to encode that (with quantifiers), but not necessarily easy to solve; depending on the fragment of logic used within the quantifiers, Z3 may be slow, or it may simply give up relatively early (returning unknown). There is no dedicated API for this purpose, but the existing API has all the pieces required to solve the puzzle (e.g., use an uninterpreted function f to encode the solution symbolically and then get the func_interp for f from the model.)
For more information about getting more than one solution, see also Z3: finding all satisfying models and Z3 Enumerating all satisfying assignments.

models with uninterpreted sorts

When Z3 returns a model with an uninterpreted sort, say Q, it uses constants of the form Q!val!0.
However, if I create a query from scratch and refer to this symbol as an inhabitant of Q, then Z3 rightfully complains that Q!val!0 is an unknown constant.
Essentially, I'm trying to get Z3 to enumerate all the inhabitants of Q, by asking it to give me a model that's not the same as the previously returned one. Hence, in subsequent calls to Z3, I need to refer to these constants.
Is there a way to do this using the SMT-Lib2 interface?

Can the output of intermediate models be disabled?

A formula with quantifiers contains declaration of trans function. Z3 successfully finds the model and prints it. But it also prints models for functions like trans!1!4464, trans!7!4463 .. which are not used anywhere in the model. What is it? How can I disable this output?
Here is the query: http://dl.dropbox.com/u/444947/asyn_arbiter_bound_16.smt2
and here is Z3's output - http://dl.dropbox.com/u/444947/asyn_arbiter_bound_16_result.txt
Recall that the models returned by Z3 can be viewed as simple functional programs.
Your formula is in the UFBV fragment. Z3 uses several modules to decide this fragment. Each module converts a formula F into a "simpler" formula F', and produces a procedure that converts a model for F' into a model for F. We call these procedures: "model converters". Model converters will, for example, eliminate interpretations for auxiliary functions and constants introduced in the F to F' conversion. Some auxiliary definitions can't be removed seems they are used to give interpretation of other definitions. We should view them as "auxiliary functions". They also create an interpretation for symbols that have been eliminated..
In your example, the following happens: the last module produces a model that contains the trans!... and k!... symbols. This model is for a formula that does not even contain trans. The function trans has been eliminated. As we apply the model converters, the interpretation for trans is constructed based on the interpretation of all trans!.... At this point, trans!... and k!... symbols are still being used since the interpretation of trans has a reference to all trans!... symbols and the interpretation of the trans!... functions have references to the k!... function symbols. At this step, there are no unnecessary symbols in the model. However, in a later step, the interpretation of trans is simplified by unfolding the definitions of trans!... and k!.... So, after this simplification step, trans!... and k!... are essentially "dead code".
That being said, the model returned by Z3 is correct, that is, it is a model for your formula. I acknowledge that these extra symbols are annoying and unnecessary. To eliminate them, we have apply the equivalent of a "dead code" elimination step. We are really close to the next release. So, this feature will not be available in the next release, but I will add it for the release following the next one.

Can Z3 check the satisfiability of recursive functions on bounded data structures?

I know that Z3 cannot check the satisfiability of formulas that contain recursive functions. But, I wonder if Z3 can handle such formulas over bounded data structures. For example, I've defined a list of length at most two in my Z3 program and a function, called last, to return the last element of the list. However, Z3 does not terminate when asked to check the satisfiability of a formula that contains last.
Is there a way to use recursive functions over bounded lists in Z3?
(Note that this related to your other question as well.) We looked at such cases as part of the Leon verifier project. What we are doing there is avoiding the use of quantifiers and instead "unrolling" the recursive function definitions: if we see the term length(lst) in the formula, we expand it using the definition of length by introducing a new equality: length(lst) = if(isNil(lst)) 0 else 1 + length(tail(lst)). You can view this as a manual quantifier instantiation procedure.
If you're interested in lists of length at most two, doing the manual instantiation for all terms, then doing it once more for the new list terms should be enough, as long as you add the term:
isCons(lst) => ((isCons(tail(lst)) => isNil(tail(tail(lst))))
for each list. In practice you of course don't want to generate these equalities and implications manually; in our case, we wrote a program that is essentially a loop around Z3 adding more such axioms when needed.
A very interesting property (very related to your question) is that it turns out that for some functions (such as length), using successive unrollings will give you a complete decision procedure. Ie. even if you don't constrain the size of the datastructures, you will eventually be able to conclude SAT or UNSAT (for the quantifier-free case).
You can find more details in our paper Satisfiability Modulo Recursive Programs, or I'm happy to give more here.
You may be interested in the work of Erik Reeber on SULFA, the ``Subclass of Unrollable List Formulas in ACL2.'' He showed in his PhD thesis how a large class of list-oriented formulas can be proven by unrolling function definitions and applying SAT-based methods. He proved decidability for the SULFA class using these methods.
See, e.g., http://www.cs.utexas.edu/~reeber/IJCAR-2006.pdf .

Resources