Почему я получаю ошибку превышения предела стека при определении предиката, который преобразует отношение двух атомов? - PullRequest
0 голосов
/ 17 марта 2019

Я хочу знать, почему программа идет в бесконечной рекурсии в следующих случаях:

?- love(kay, amanda).

и

?- love(rob, amanda).

А вот и код:

love(amanda, kay).
love(kay, geo).
love(geo, rob).

love(X, Y) :-
   love(X, Z),
   love(Z, Y).
love(X, Y) :-
   love(Y, X).

1 Ответ

4 голосов
/ 17 марта 2019

Во-первых, ваша программа всегда идет в бесконечный цикл. Неважно, какие имена вы используете. Четные ?- loves(amanda, kay). петли. Чтобы лучше это увидеть, спросите ?- loves(amanda, kay), false. Почему я так уверен, что ваша программа всегда зацикливается?

Чтобы увидеть это, нам нужна подделка. Добавляя цели false в вашу программу, мы получаем новую программу, требующую меньших (или равных) выводов.

<s>love(amanda, kay) :- <b>false</b></s>.
<s>love(kay, geo) :- <b>false</b></s>.
<s>love(geo, rob) :- <b>false</b></s>.
love(X, Y) :-
   love(X, Z), <b>false</b>,
   <s>love(Z, Y)</s>.
<s>love(X, Y) :-  <b>false</b></s>,
   <s>love(Y, X)</s>.

Поскольку этот фрагмент (называемый ) не завершается, ваша исходная программа не завершается. Как видите, все люди были удалены. И поэтому настоящие имена не могут влиять на результат.

Если вы хотите исправить коммутативность, введите еще один предикат:

love2(X, Y) :- love1(X, Y).
love2(X, Y) :- love1(Y, X).

И чтобы включить транзитивное замыкание, используйте замыкание / 3 :

love3(X, Y) :-
   closure(love2, X, Y).
...