Вы должны уточнить, что вы подразумеваете под "это работает".На самом деле обе версии предиката travel/2
не заканчиваются.Но можно найти решение для очень специфического запроса.
Теперь спросите ?- travel(hamilton, losAngeles).
, который повторяется для обоих.
Так что ваше исправление работает только для некоторых запросов, но не для других.Разве нет более надежного выхода?
В общем, очень точную последовательность подстановок ответов, произведенных Прологом, трудно предсказать.Вам нужно будет смоделировать каждый крошечный шаг, который делает Пролог.
С другой стороны, существует очень родственное понятие (универсальное) завершение , которое намного легче предсказать, поскольку оно не зависит отмногие детали в вашей программе, такие как порядок появления ваших фактов.Самый простой способ запросить универсальное завершение - добавить цель false
в конце вашего запроса.
Но вы можете пойти еще дальше, добавив цели false
где хотите 1 .Такая модифицированная программа называется fault-slice .Независимо от того, как вы вставляете false
, выполняется следующее:
Если срез ошибки не завершается, то и ваша исходная программа не прерывается.
Теперь рассмотрим срез-срезы для двух вариантов travel/2
:
<s>travel(X,Y) :- <b>false</b>, byCar(X,Y)</s>.
<s>travel(X,Y) :- <b>false</b>, byTrain(X,Y)</s>.
<s>travel(X,Y) :- <b>false</b>, byPlane(X,Y)</s>.
travel(X,Y) :- travel(X,Z), <b>false</b>, <s>travel(Z,Y)</s>.
и вашей другой версии:
<s>travel(X,Y) :- <b>false</b>, byCar(X,Y)</s>.
<s>travel(X,Y) :- <b>false</b>, byTrain(X,Y)</s>.
<s>travel(X,Y) :- <b>false</b>, byPlane(X,Y)</s>.
travel(X,Y) :- travel(Z,Y), <b>false</b>, <s>travel(X,Z)</s>.
В обоих случаях ни X
, ни Y
считается вообще!Таким образом, два аргумента не влияют на завершение.И поэтому обе версии не заканчиваются.То есть они никогда не заканчиваются.
Теперь сравните этот вывод с более традиционным подходом к просмотру следа.Хотя срезы сбоев позволили нам сделать общие выводы ("... никогда не завершается"), конкретная трассировка может показать вам только детали одного конкретного выполнения.
Для того, чтобы это исправить, вам нужноизменить что-то в видимой части.Мое предложение будет использовать closure/3
.То есть:
travel(X, Y) :-
closure(connexion, X, Y).
connexion(X,Y) :- byCar(X,Y).
connexion(X,Y) :- byTrain(X,Y).
connexion(X,Y) :- byPlane(X,Y).
Или используйте более общий path/4
.
1 На самом деле, это работает только в чисто монотонных программах.Ваша программа одна из этих