Что логического "не" в Прологе?

Проблема, с которой я сталкиваюсь, немного тривиальна. Я хочу использовать логическое не в Прологе, но кажется, что 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).

Что предотвратит повторяющиеся результаты.

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

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