Пролог повторяющихся решений на симметричных отношениях

Рассмотрим эту маленькую программу:

married(bill, hillary).
spouse(X, Y) :- married(X, Y); married(Y, X).
likes(X, Y) :- spouse(X, Y).

Теперь я хочу оценить цель

?- likes(X, Y).
X = bill
Y = hillary ?;
X = hillary
Y = bill
yes 

Есть ли способ предотвратить повторение этого симметричного отношения при возврате и сохранить симметрию для таких целей, как ?- likes(hillary, X).?

2 ответа

Решение

Вот способ определить spouse/2:

married(bill, hillary).
married(tom, mary).
married(sam, linda).

spouse(X, Y) :-
     \+ married(X, Y) -> married(Y, X) ; married(X, Y).

Так что, если нет возможности сделать married(X, Y) правда, тогда попробую married(Y, X), Иначе, married(X, Y),

| ?- spouse(X, Y).

X = bill
Y = hillary ? ;

X = tom
Y = mary ? ;

X = sam
Y = linda

(1 ms) yes
| ?- spouse(tom, Y).

X = tom
Y = mary

yes
| ?- spouse(X, tom).

X = mary
Y = tom

yes

На первый взгляд может показаться, что следующий, несколько более простой, предикат может быть эквивалентен, но он не найдет все решения:

spouse(X, Y) :-
     married(X, Y) -> true ; married(Y, X).

| ?- spouse(X, Y).

X = bill
Y = hillary ? ;

(1 ms) yes
| ?-

ДОПОЛНЕНИЕ

Опираясь на наблюдения Сергея:

| ?- Y = bill, spouse(X, Y).

X = hillary
Y = bill

yes

Но:

| ?- spouse(X, Y), Y = bill.

no

Этот результат противоречив, потому что, ограничивая spouse/2 к уникальным решениям, которые считают симметричные решения избыточными, предикат по существу говорит, что только один из spouse(bill, hillary) а также spouse(hillary, bill) может быть правдой в любой момент времени. Если первый аргумент предварительно определен как billэто означает, что второй аргумент должен быть hillary, Если ни один из аргументов не создан и spouse(X, Y) указывает на решение X = bill а также Y = hillaryзатем последующий запрос Y = bill выходит из строя.

Итак, опять же, как @Sergey указал в своем комментарии, этот вид предиката должен использоваться с осторожностью, понимая, что его логическое значение несколько ограничено и даже противоречиво в некоторых контекстах.

Невозможно определить предикат так, чтобы он все еще сохранял свои реляционные свойства и выполнял ваши пожелания, как @SergeyDymchenko заметил в комментарии.

Мне непонятно, почему ты так хочешь. Может быть, вы хотите уменьшить объем производства? Затем просто задайте другой запрос:

?- spouse(X,Y), X @=< Y.
Другие вопросы по тегам