Это ошибка в моей программе или ошибка в Прологе? Как бы это исправить?
Это ошибка юзабилити используемого вами верхнего уровня. Если вы присмотритесь очень внимательно, вы можете найти крошечный намек:
81#=_42146<<4 .
^ SPACE
Это крошечное пространство означает: пожалуйста, обратите внимание, что есть больше, чем этот ответ. И на самом деле, есть два ответа. Первый ответ (от 'ADD'
) - подделка, он не содержит никакого решения. Только второй ответ содержит одно решение.
Обратите внимание, что Пролог в основном дает ответы, а не решения. Вот почему мы говорим о заменах ответов . Связь между ответами и решениями неуловима. Ответ может содержать от нуля до бесконечного числа решений.
Так почему же Prolog не производит решения напрямую?
Прежде всего, для бесконечных решений, которые были бы очень неэффективными. Подумайте о length(L,3)
, который имеет единственный ответ, который содержит все списки длины 3 с любыми возможными элементами, а значит, бесконечное количество решений. Как L = [1,2,3]
или L = [bof, toto, machin-
maschin
]
или L = [louis_XVI, bernie, bernie]
и так далее. С помощью логической переменной мы можем свернуть эту бесконечность трехэлементных списков в следующий ответ: L = [_A,_B,_C]
. Это сила логической переменной!
Эта сила также используется в ограничениях. Но с этой силой приходит большая ответственность и много бремени. В конце концов, многие задачи легко вычислить в одном направлении, а наоборот - сложно. Вы обнаружили такую проблему. В этом случае можно улучшить clpfd
, чтобы легко справиться с этим случаем, но в общем случае это неразрешимо. Таким образом, иногда нет никакого алгоритма вообще. И в таких случаях дать ложный ответ (несоответствие, Scheinlösung, решение бланш) - это лучшее, что может сделать система. В качестве альтернативы это может вызвать ошибку и прервать все вычисления. Но это грубо. Часто мы можем жить с такими несоответствиями.
Возьмите ваш случай, если вы действительно хотите быть уверенным в существовании решения, удалите ограничения из ответа, обозначив их!
?- asm(I,81), I = instruction(_,[R]).
I = instruction('ADD', [R]),
R in 0..1023,
81#=R<<4
; I = instruction('SUB', [R]),
R in 0..1023,
80#=R<<4.
?- asm(I,81), I = instruction(_,[R]), labeling([],[R]).
I = instruction('SUB', [5]),
R = 5
; false.
Другой метод - сделать ограничения сильнее, как показывал @ Guy-Coder. Это может работать (и тогда это хорошо), но более сложно понять. И может также быть менее эффективным в определенных ситуациях. Это настоящая инженерная проблема. Когда мы принимаем несоответствие в качестве цены для более быстрых решений в определенных случаях?