Пролог Бесконечный цикл (циклический граф)

Это может быть простой проблемой, но мне нужно сделать это по-другому. Проблема в том, что я должен найти в прологе возможные маршруты полетов. У меня есть эта база знаний

from_to(fresno,seattle).
from_to(fresno,albany).          
from_to(albany,dallas).     
from_to(fresno,boston). 
from_to(dallas,seattle).         
from_to(dallas,albany).
from_to(seattle,dallas).           
from_to(seattle,omaha).         
from_to(atlanta,albany).
from_to(atlanta,dallas).
from_to(atlanta,boston).
from_to(omaha,atlanta).         
from_to(omaha,albany).
from_to(albany,seattle).

И я должен сделать маршрут предиката (X,Y), который проверяет, можем ли мы перейти от X к Y. Я сделал следующее:

route(X,Y):-from_to(X,Y).
route(X,Y):-from_to(X,Z), route(Z,Y).

Но это не работает, потому что график циклический. Я искал в Интернете, и единственное, что все сказали, это использовать список и проверять посещенные пути. Но я не могу использовать списки! Я должен сделать маршрут предиката (X,Y) без использования списков, как я могу сделать это без списка? Спасибо

4 ответа

route(X0,X) :-
   from_to(X0,X1),
   closure0(from_to,X1,X).

Смотрите этот вопрос для определения closure0/3,

Таким образом, вы не можете использовать списки (интересно почему), но вы можете использовать переменную счетчика? Попробуйте итеративно углубить поиск, где вы выполняете поиск в глубину, сначала в глубину 1, затем 2 и так далее. Это предотвратит бесконечные циклы с циклами.

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

Если вам не требуется строго использовать SWI-Prolog, вы можете легко сделать это в системе Prolog с поддержкой табулирования. В B-Prolog я просто добавил :- table route/2. и теперь это работает:

?- route(fresno, omaha).
yes

?- route(fresno, fresno).
no

?- route(atlanta, atlanta).
yes

?- route(atlanta, X).
X = albany ?;
X = dallas ?;
X = boston ?;
X = seattle ?;
X = omaha ?;
X = atlanta
yes

Я бы попробовал

:- dynamic visited/1.

route(X,Y) :- retractall(visited(_)), route_(X,Y).
route_(X,Y) :- from_to(X,Y).
route_(X,Y) :- from_to(X,Z), \+ visited(Z), asserta(visited(Z)), route_(Z,Y).

тестовое задание:

1 ?- route(fresno, omaha).
true ;
false.

2 ?- route(fresno, omaha).
true ;
false.

3 ?- route(fresno, fresno).
false.

4 ?- route(atlanta, atlanta).
true ;
false.

Поскольку граф определен в исходном коде, альтернативой может быть:

:- dynamic from_to/2.

route(X,Y):-retract(from_to(X,Y)).
route(X,Y):-retract(from_to(X,Z)), route(Z,Y).

но после первого вызова требуется перезагрузка базы данных.

Другие вопросы по тегам