Stack Exchange
Extracting boolean terms from Z3 model when using quantifiers
I am trying to use Z3 to explore the difference between two predicates, but the model contains exist-expressions where I would expect boolean constants.
I have the following program in smtlib:
    (set-option :produce-models true)
    (declare-fun a (Int) Bool)
    (declare-const t1 Bool)
    (declare-const t2 Bool)
    (assert (= t1 (exists ((i Int)) (and (a i) (or (= i 10) (= i 11) )))))
    (assert (= t2 (exists ((i Int)) (and (a i) (and (< i 13) (< 9 i))))))
    (assert (distinct t1 t2))
    (check-sat)
    (get-value (a))
    (get-value (t1 t2))

I am trying to find the values for t1 and t2 when the problem is satisfiable.
Z3 responds with
    sat
    ((a (store (store ((as const Array) true) 11 false) 10 false)))
    ((t1 (exists ((i Int)) (and (not (= i 10)) (not (= i 11)) (or (= i 10) (= i 11)))))
     (t2 (exists ((i Int))
      (and (not (= i 10)) (not (= i 11)) (not (<= 13 i)) (not (<= i 9))))))

The model for t1 and t2 does not give me boolean constants, but expressions. How can I persuade Z3 to give me the values of these expressions? (I believe the model for t1 is actually a contradiction, so it is always false.
I don't need to do this through smtlib, using the Z3 api would be sufficient.

You can only get a value for top-level values. And a simple exist (i.e., one that's not nested) is equivalent to a top-level declaration. (There are ways to deal with nested exists as well, via skolemization, but that's besides the point.) So, simply pull those exist-variables to the top:
(set-option :produce-models true)
(declare-fun a (Int) Bool)
(declare-const t1 Bool)
(declare-const t2 Bool)
(declare-const i1 Int)
(declare-const i2 Int)
(assert (= t1 (and (a i1) (or (= i1 10) (= i1 11) ))))
(assert (= t2 (and (a i2) (and (< i2 13) (< 9 i2)))))
(assert (distinct t1 t2))
(check-sat)
(get-value (a))
(get-value (i1 i2))
(get-value (t1 t2))

This prints:
sat
((a (store ((as const Array) true) 12 false)))
((i1 10)
 (i2 12))
((t1 true)
 (t2 false))

I believe this satisfies all your constraints and gives you the values of t1 and t2, along with i1 and i2 that make them distinct as requested.

Excellent, thank you. Out of curiosity, what's the definition of "top-level values"? What makes t1 and t2 in my original code not top-level?

Your t1 and t2 are top-level; but not i1 and i2; and those are crucial for getting the model you were after. So, I just pulled them to top-level. (i.e., your exists i declarations.)
