2

Consider these two formulae:

  • Exists y. Forall x. (y>x), which is unsat.
  • Forall x. Exists y. (y>x), which is sat.

Note that we cannot find “models” for the sat formula, e.g., using Z3 it outputs Z3Exception: model is not available for the following code:

phi = ForAll([x],Exists([y], lit))

s_def = Solver()
s_def.add(phi)
print(s_def.model())

Also, quantifier elimination does not output an elimination, but a satisfiability result [[]] (i.e., True):

x, y = Reals('x, y')

t = Tactic("qe")

lit = (y>x)

ae = Goal()
ae.add(ForAll([x],Exists([y], lit)))
ae_qe = t(ae)

print(ae_qe)

I think this happens because the value of y fully depends on x (e.g., if x is 5 then y can be 6). Thus, I have some questions:

  • Am I right with this interpretation?
  • What would be the meaning of “a model of a universally quantified formula”?
  • Do we say a formula accepts quantifier elimination even if it never eliminates the quantifier but "only: evaluate to True or False?
  • Is there a way to synthetise or construct a model/function that represents a y that holds the constraint (y>x); e.g. f(x)=x+1. In other words, does it make sense that the quantifier elimination of a Forall x. Exists y. Phi(x,y) like the example would be Forall x. Phi(x,f(x))?
Theo Deep
  • 666
  • 4
  • 15

1 Answers1

2

You get a model-not-available, because you didn't call check. A model is only available after a call to check. Try this:

from z3 import *

x, y = Ints('x y')

phi = ForAll([x], Exists([y], y > x))

s = Solver()
s.add(phi)
print(s.check())
print(s.model())

This prints:

sat
[]

Now, you're correct that you won't get a meaningful/helpful model when you have a universal-quantifier; because the model will depend on the choice of x in each case. (You only get values for top-level existentials.) This is why the model is printed as the empty-list.

Side Note In certain cases, you can use the skolemization trick (https://en.wikipedia.org/wiki/Skolem_normal_form) to get rid of the nested existential and get a mapping function, but this doesn't always work with SMT solvers as they can only build "finite" skolem functions. (For your example, there isn't such a finite function; i.e., a function that can be written as a case-analysis on the inputs, or an if-then-else chain.) For your specific questions:

  • Yes; value of y depends on x and thus cannot be displayed as is. Sometimes skolemization will let you work around this, but SMT solvers can only build finite skolem-functions.

  • Model of a universally quantified formula is more or less meaningless. It's true for all values of the universally quantified variables. Only top-level existentials are meaningful in a model.

  • Quantifier elimination did work here; it got rid of the whole formula. Note that QE preserves satisfiability; so it has done its job.

  • This is the skolem function. As you noted, this skolem function is not finite (can't be written as a chain of finite if-then-elses on concrete values), and thus existing SMT solvers cannot find/print them for you. If you try, you'll see that the solver simply loops:

from z3 import *

x = Int('x')

skolem = Function('skolem', IntSort(), IntSort())
phi = ForAll([x], skolem(x) > x)

s = Solver()
s.add(phi)
print(s)
print(s.check())
print(s.model())

The above never terminates, unfortunately. This sort of problem is simply too complicated for the push-button approach of SMT solving.

alias
  • 28,120
  • 2
  • 23
  • 40
  • This is a perfect answer, thanks a lot. As for the last paragraph, is there any "not push-button" approach to construct this kind of skolem function? I would like to construct your referred `skolem = Function('skolem', IntSort(), IntSort())`, where `phi = ForAll([x], skolem(x) > x)`. Can you give me any reference? Thanks again! – Theo Deep Jan 12 '23 at 08:37
  • 1
    So far as I know, creation of skolem functions are typically a user-level task; showing their existence. Typically achieved by providing the skolem function itself. Though most of the time, you don't really care what the skolem function itself is, but just that it exists. The wikipedia article I linked is actually pretty good. You might also want to look into Isabelle/Coq etc. to see how they deal with such cases. (I'm not an expert on those tools.) – alias Jan 12 '23 at 17:24
  • Hi @alias, for the example above, would `f(x)=x+1` seems like a valid "model".. can this function be called a 'Skolem function'? – Theo Deep Jan 18 '23 at 14:37
  • 1
    Yes, `f(x) = x + 1` is a good skolem function for this one. But z3 will not synthesize this function for you, since it's not "finite," i.e., cannot be written as a finite table (plus an extra element that maps everything else). Of course, things might change and z3 might be able to synthesize such functions in a future version. (Though I wouldn't hold my breath for that to happen any time soon.) – alias Jan 18 '23 at 16:52