Что логического «не» в Прологе? - PullRequest
35 голосов
/ 15 декабря 2011

Проблема, с которой я сталкиваюсь, немного тривиальна. Я хочу использовать логическое не в Прологе, но кажется, что not/1 это не то, что я хочу:

course(ai).
course(pl).
course(os).

have(X,Y) :- course(X),course(Y),not(X = Y).

Я запрашиваю:

have(X,Y), write(X-Y), nl , fail.

И я не получаю желаемый результат: (

Ответы [ 5 ]

36 голосов
/ 15 декабря 2011

Вместо not(X = Y) нужно написать \+ X = Y или X \= Y. Но попробуйте использовать dif(X,Y) вместо этого. dif/2 присутствует в B, SWI, YAP, SICStus. Чтобы увидеть разницу:

?- X = b, dif(a, X).
X = b.

?- X = b, \+ a = X.
X = b.

Так что до сих пор все в порядке. Но что, если мы просто обменять порядок двух голов?

?- \+ a = X, X = b.
false.

?- dif(a, X), X = b.
X = b.

(\+)/1 теперь дает нам другой результат, потому что есть ответ для a = X цель \+ a = X не будет достигнута.

(\+)/1, таким образом, не является отрицанием, но означает , который невозможно доказать на данном этапе во время .

Безопасное приближение из dif/2 возможно и в ISO Prolog.

14 голосов
/ 15 декабря 2011

В SWI-Prolog и GNU Prolog должно работать следующее:

have(X, Y) :- course(X), course(Y), X \= Y.

В SWI-Prolog вы также можете использовать dif/2, что может быть более удобным, поскольку вы можете использовать его раньшев предикате:

have(X, Y) :- dif(X, Y), course(X), course(Y).
5 голосов
/ 18 марта 2014

В качестве дополнения к ответу пользователя "false" выше, то есть

"Вместо not (X = Y) необходимо написать \ + X = Y,"

Это может создать впечатление, что:

a.«не» и «\ +» - это разные вещи

б.\ + Будет работать, тогда как не будет, ошибаться, нет.

Я понимаю, что "not" и "\ +" эквивалентны, но что \ + предпочтительнее в современных программах Prolog, потому что он передаетчувство, которое является более интуитивным.В частности, в то время как «not» может указывать на «не верно» для неосторожного кодера, «+ +» предполагает «не доказуемо», что намного ближе к истине того, что на самом деле говорит эта операция.В Прологе «не» является примером «отрицания как неудачи», но считается, что \ + прояснит для программиста только то, что именно утверждается в любом данном правиле.Таким образом, вы МОЖЕТЕ использовать «not» (большинство реализаций PL сохраняют его для обратной совместимости), но чтобы быть современным идиоматическим программистом PL, вам, вероятно, лучше использовать \ +.

2 голосов
/ 24 марта 2018

Читая книгу Самуила Камина в главе 8, пролог, я нашел это решение, которое также подходит и объясняет, как использовать cut:

Срез являетсяспособ дать программисту дополнительный контроль над вычислениями, позволяя ему указывать места, где возврат назад недопустим.В частности, сокращение записывается как восклицательный знак (!) В качестве цели в правой части предложения, например:

G :- H, !, R.

Предположим, что это предложение выбрано дляудовлетворить цель g , с которой G объединяет .Предпринята попытка удовлетворить H. В случае успеха R доказано. Если доказательство R успешно, то g доказано ;в этом случае разрез не играет роли. Если, однако, доказательство R терпит неудачу , а не откатывать назад и пытаться повторно доказать H, , то наличие сокращения приводит к тому, что цель g немедленно терпит неудачу ;это происходит, даже если есть дополнительные пункты, которые могут применяться к g.Примером является определение not-equals :

equals(X, X).
not-equals(X, Y) :- equals(X, Y), !, fail.
not-equals(X, Y).

not-equals(X, Y) должно быть успешным, если X не равно Y, и терпеть неудачу, если оно есть;X и Y должны быть привязаны к наземным выражениям (т.е. не иметь свободных переменных) при попытке достичь этой цели.

1 голос
/ 31 мая 2013

Как вы сказали, OP, это тривиально.

Попробуйте

course(ai).
course(pl).
course(os).

have(X,Y) :- course(X), course(Y), X \== Y).

Это должно исправить ваш предикат.

Хотя, глядя на шаг вперед, математически выразив,вы, вероятно, ищете решение (n C 2), а не (n P 2), которое ваш предикат в настоящее время предоставляет - комбинация вместо перестановки, выбор выбора в противоположностьдоговоренности о выборе выбора.Это то, что я думаю.

Если это то, что вы хотите, я бы посоветовал вам попробовать

course(ai).
course(pl).
course(os).

have(X,Y) :- course(X), course(Y), X @< Y).

, что предотвратит повторяющиеся результаты в обратном порядке.

@< означает атомно меньше, чем.< для целых чисел, @< для атомов.

...