Пролог повторяющихся решений на симметричных отношениях
Рассмотрим эту маленькую программу:
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.