z3
can solve optimisation problems using z3.Optimize
. My goal is to apply it in the following way: Given a Boolean formula of propositional logic and a set of constraints, find all models that optimise the constraints, i.e. fulfil as many as possible. My ultimate goal is to select one of these models randomly.
Minimal example: Given the formula Or(x,y)
and constraints Not(x)
and Not(y)
, find the solutions [x: True, y: False]
and [x: False, y: True]
.
While z3.Optimize.model()
prints one optimal solution, it seems to be deterministic and to always print the solution [x: False, y: True]
:
from z3 import *
x, y = Bools('x y')
s = Optimize()
s.add(Or(x,y))
s.add_soft(Not(x), weight="1")
s.add_soft(Not(y), weight="1")
s.check()
print(s.model())
When all_smt()
provided by @alias is applied to this problem, list(all_smt(s, [x,y]))
outputs:
[[x = False, y = True], [y = False, x = True], [y = True, x = True]]
So all_smt()
finds all solutions, including the non-optimal [x: True, y: True]
.
What is the best way to find all optimal solutions? Alternatively, is it possible to find an optimal solution in a random way without generating all optimal solutions first?