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

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

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

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

I запрос:

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

И я не получаю результат, который хочу: (

Ответ 1

Вместо 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, таким образом, не является отрицанием, но означает, что в этой точке не доказуемо вовремя.

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

Ответ 2

В обоих 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).

Ответ 3

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

"Вместо not (X = Y) вам нужно написать \+ X = Y,"

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

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

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

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

Ответ 4

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

Try

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).

Это предотвратит дублирование результатов.

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