I'm working on proving satisfiability and reviewing models of a FOL theory. I'm trying to understand why sometimes z3 takes too long to build a model when I add a seemingly innocuous assertion to a previous set of assertions for which a model is found quickly. I've created a small example of something that I don't understand, which may shed light on why I'm having this problem. First declarations:
(declare-const x Int)
(declare-fun q (Int Int Int) Bool)
(declare-fun p (Int Int Int) Bool)
The main assertion is
(forall ((a Int) (b Int) (c Int))
(=> (p a b c) (and (q a x c) (q b x c) (q c y c))))
For that I get a model with one individual and p and q always false. That's fine.
If I add
(p x x x)
I would expect the model to include it and one or two more q tuples. It does, but it also includes a second individual and for the model:
(define-fun p ((x!0 Int) (x!1 Int) (x!2 Int)) Bool
true)
(define-fun q ((x!0 Int) (x!1 Int) (x!2 Int)) Bool
true)
Evaluating the model I get 8 (3^2) tuples for each of p and q. While I don't expect that z3 gets minimal models, I was surprised that this model is created when the minimal model is just two tuples, and because I don't get this model without it, even though it is still valid.
One can show that the model has much more than required by ruling out most possibilities:
(forall ((a Int) (b Int) (c Int))
(and (=> (p a b c) (and (= a x) (= b x) (= c x)))
(=> (q a b c) (and (= a x) (= c x) (or (= b y) (= b x))))))
Which gives me a model with just these
(p x x x)
(q x y x)
(q x x x)
as the only tuples in the model, or by equating x and y
(= x y)
the model reduces the two q tuples to one.
Can someone explain what's going on, and perhaps how to avoid it?
My hypothesis is that this sort of blowup is happening more generally and that it's why sat and model finding goes from quick to too slow to wait (a second or two -> more than hours) when I'm working with the full set, which has at least 25 or so individuals.