Что логического "не" в Прологе?
Проблема, с которой я сталкиваюсь, немного тривиальна. Я хочу использовать логическое не в Прологе, но кажется, что 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 ответов
На месте 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.
В 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).
В качестве дополнения к ответу пользователя "ложь" выше, т.е.
"Вместо (X = Y) вам нужно написать \+ X = Y"
Это может создать впечатление, что:
а. "не" и "\+" это разные вещи
б. \ + Будет работать, тогда как не будет, ошибаться, нет.
Насколько я понимаю, "не" и "+" эквивалентны, но \ + предпочтительнее в современных программах на Прологе, потому что он передает более интуитивное чувство. В частности, в то время как "not" может указывать на "не верно" для неосторожного кодера, "+ +" предполагает "не доказуемо", что намного ближе к истине того, что на самом деле говорит эта операция. В Прологе "не" является примером "отрицание как неудача", но считается, что \ + прояснит для программиста только то, что именно утверждается в любом данном правиле. Таким образом, вы МОЖЕТЕ использовать "not" (большинство реализаций PL сохраняют его для обратной совместимости), но, чтобы быть современным идиоматическим программистом PL, вам, вероятно, предпочтительнее использовать \+.
Читая книгу Самуила Камина по 8-й главе, пролог, я нашел это решение, которое также подходит здесь и объясняет, как использовать cut
:
Сокращение - это способ дать программисту дополнительный контроль над вычислениями, позволяя ему указывать места, где возврат назад недопустим. В частности, сокращение записывается в виде восклицательного знака (!) В качестве цели в правой части предложения, например:
G :- H, !, R.
Предположим, что это предложение выбрано для удовлетворения цели g, с которой G объединяется. Предпринята попытка удовлетворить H. В случае успеха R доказано. Если доказательство R успешно, то g доказано; в этом случае разрез не играет никакой роли. Однако, если доказательство R терпит неудачу, а не возвращаться назад и пытаться повторно доказать H, наличие разреза немедленно приводит к провалу цели g; это происходит, даже если есть дополнительные пункты, которые могут применяться к g. Примером является определение не равно:
equals(X, X).
not-equals(X, Y) :- equals(X, Y), !, fail.
not-equals(X, Y).
not-equals(X, Y)
должен преуспеть, если X не равен Y, и потерпеть неудачу, если он есть; X и Y должны быть связаны с основными выражениями (то есть не иметь свободных переменных) при попытке достичь этой цели.
Как вы сказали, 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).
Что предотвратит повторяющиеся результаты.
@<
значит атомно меньше чем. <
для целых чисел, @<
для атомов.