Using Z3's Horn clause solver:
If the answer is SAT
, one can get a satisfying assignment to the unknown predicates (which, in most applications, correspond to inductive invariants of some kind of transition system or procedure call system).
If the answer is unsat
, then this means the exists an unfolding of the Horn clauses and an assignment to the universally quantified variables in the Horn clauses such that at least one of the safety conditions (the clauses with a false
head) is violated. This constitutes a concrete witness why the system had no solution.
I suspect that if Z3 can conclude unsat
, then it has some form of such witness internally (and this anyway is the case in PDR, if I remember well). Is there a way to print it out?
Maybe I badly read the documentation, but I can't find a way. (get-proof)
prints something unreadable, and, besides, (set-option :produce-proofs true)
makes some problems intractable.
The refutation that Z3 produces for HORN logic problems is in the form of a tree of unit-resulting resolution steps. The counterexample you're looking for is hiding in the conclusions of the unit-resolution steps. These conclusions (the last arguments of the rules) are ground facts that correspond to program states (or procedure summaries or whatever) in the counterexample. The variable bindings that produce these facts can be found in "quant-inst" rules.
Obviously, this is not human readable, and actually is pretty hard to read by machine. For Boogie I implemented a more regular format, but it is currently only available with the duality engine and only for the fixedpoint format using "rule" and "query". You can get this using the following command.
(query :engine duality :print-certificate true)