Почему Z3 возвращает сыгранные и неудовлетворительные условия для аналогичных ограничений?

Я новичок в изучении Z3 и пытаюсь решить с его помощью головоломку «ОТПРАВИТЬ + БОЛЬШЕ = ДЕНЬГИ». Я решил пару ошибок, скопировав чужой код, но не совсем понимаю, почему это работает.

Вопрос 1: Почему существует разница между этими двумя ограничениями?

Код:

from z3 import *

digits = Ints('s e n d m o r y')
s,e,n,d,m,o,r,y = digits
sendmore = 1000*s+100*e+10*n+d+1000*m+100*o+10*r+e
money = 10000*m+1000*o+100*n+10*e+y

solver = Solver()

solver.add([s>0, m>0])
for d in digits:
    solver.add([d>=0, d<=9])
solver.add(Distinct(digits))
solver.add( sendmore == money )
print(solver.check())   #sat
solver.add( 1000*s+100*e+10*n+d+1000*m+100*o+10*r+e == 10000*m+1000*o+100*n+10*e+y )
print(solver.check())   #unsat

Изначально я использовал второй способ и нашел его неудовлетворительным. Поэтому я погуглил решение, которое является первым методом и возвращает sat. Так в чем же разница?

Q2: Какое значение имеет изменение положения определений?

Код:

from z3 import *

digits = Ints('s e n d m o r y')
s,e,n,d,m,o,r,y = digits

solver = Solver()

solver.add([s>0, m>0])
for d in digits:
    solver.add([d>=0, d<=9])
solver.add(Distinct(digits))

sendmore = 1000*s+100*e+10*n+d+1000*m+100*o+10*r+e
money = 10000*m+1000*o+100*n+10*e+y
solver.add( sendmore == money )
print(solver.check())   #unsat

Итак, я возился с кодом и случайно обнаружил, что перемещение определения sendmore и Money также влияет на результат. Почему?

Обновлено: я только что заменил цикл for на solver.add([And(d>=0, d<=9) for d in digits]), и все прошло идеально, до сих пор не знаю почему.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Недостаток заключается в цикле for для ограничения диапазона digits:

solver = Solver()
solver.add([s>0, m>0])
for dig in digits:
    solver.add([dig>=0, dig<=9])
solver.add(Distinct(digits))
solver.add( 1000*s+100*e+10*n+d+1000*m+100*o+10*r+e == 10000*m+1000*o+100*n+10*e+y )
res = solver.check()
print(res)  
if res == sat:
    M = solver.model()
    print(M[s],M[e],M[n],M[d],"+",M[m],M[o],M[r],M[e])
    print(M[m],M[o],M[n],M[e],M[y])

Переменная цикла d конфликтовала с переменной решения d.
Поэтому его необходимо переименовать.

ужасно, это было неожиданно.....

Kagami 09.06.2024 21:17

Другие вопросы по теме