2
from z3 import *

p = Int('p')
q = Int('q')

solve(Or(p==1,p==2,p==3), Or(q==1,q==2), Not(p==q), q==1)

Gives me [p = 2, q = 1], but p could be 2 or 3. So the answer should be {2,3}. How can I tell z3 to inform me about multiple answers?

trshmanx
  • 600
  • 7
  • 16
  • This comes up often. Here's the simplest way: https://stackoverflow.com/questions/63231398/trying-to-find-all-solutions-to-a-boolean-formula-using-z3-in-python – alias Aug 12 '20 at 21:59

1 Answers1

4

This question comes up often, and there are a few caveats. Essentially, you have to write a loop to "reject" earlier models and keep querying for satisfiability. For your particular problem, you can code it like this:

from z3 import *

p = Int('p')
q = Int('q')

s = Solver()
s.add(Or(p==1,p==2,p==3), Or(q==1,q==2), Not(p==q), q==1)

res = s.check()
while (res == sat):
  m = s.model()
  print(m)
  block = []
  for var in m:
      block.append(var() != m[var])
  s.add(Or(block))
  res = s.check()

When I run this, I get:

[p = 2, q = 1]
[p = 3, q = 1]

Note that z3 doesn't always produce a "full" model: It'll stop producing assignments once it determines the problem is sat. So, you might have to track your variables and use model-completion explicitly. See Trying to find all solutions to a boolean formula using Z3 in python for details on how to do that.

alias
  • 28,120
  • 2
  • 23
  • 40