Типичный способ кодирования таких проблем следующий:
from z3 import *
a, b, c = Bools('a b c')
s = Solver()
s.add(Or([a, b, c]))
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()
Это напечатает:
[b = True, a = False, c = False]
[a = True]
[c = True, a = False]
Вы заметите, что не все модели являются «завершенными». Это связано с тем, что z3 обычно "прекращает" присвоение переменных, как только решает, что проблема решена, так как другие переменные не имеют значения. all-False, у вас должна быть модель. Если вы хотите получить значения всех ваших переменных таким образом, вы должны явно запросить их, например:
from z3 import *
a, b, c = Bools('a b c')
s = Solver()
s.add(Or([a, b, c]))
myvars = [a, b, c]
res = s.check()
while (res == sat):
m = s.model()
block = []
for var in myvars:
v = m.evaluate(var, model_completion=True)
print("%s = %s " % (var, v)),
block.append(var != v)
s.add(Or(block))
print("\n")
res = s.check()
Это напечатает:
a = False b = True c = False
a = True b = False c = False
a = True b = True c = False
a = True b = True c = True
a = True b = False c = True
a = False b = False c = True
a = False b = True c = True
И есть ровно 7 моделей, как и следовало ожидать.
Обратите внимание на параметр model_completion
. Это распространенная ошибка новичков, поскольку в z3 нет "готового" метода для получения всех возможных назначений, поэтому вы должны быть осторожны при написании кода самостоятельно, как описано выше. Причина, по которой такой функции нет, заключается в том, что ее действительно сложно реализовать в целом: подумайте о том, как она должна работать, если бы ваши переменные были функциями, массивами, пользовательскими типами данных и т. Д. c. в отличие от простых логических значений. Может быть очень сложно реализовать общую функцию c all-sat со всеми этими возможностями, обрабатываемыми правильно и эффективно. Таким образом, это остается на усмотрение пользователя, поскольку в большинстве случаев вас интересует только конкретное c понятие all-sat, которое, как правило, несложно закодировать, если вы изучите основные c идиомы.