Доступные в GProlog элементы в графе

#prolog

#prolog

Вопрос:

У меня есть простая проблема, с которой у меня возникли проблемы, хотя я думаю, что ответ довольно прост. Вот оно начинается:

Предположим, что взвешенный ориентированный граф описывается с помощью предиката edge/3, такого, что ребро (X, Y, C) является истинным, если существует ребро от вершины X до вершины Y стоимостью C. Например, справа находится граф и его описание с использованием edge /3:

 edge(a, c,1).
edge(a,d,3).
edge(b,d,2).
edge(c,e,5).
edge(e, c,2).
edge(e,f,2).
edge(d,f,10).
 

Я должен это сделать . Определите предикат reachable/2, который вычисляет список узлов, к которым можно получить
доступ из данного узла. Например, на запрос достижимый (a, L) Prolog должен ответить L=[c, e,d,f]
(в любом порядке). (Помните findall .)

Вот что я написал на данный момент

 path(X,Y):-edge(X,Y,_).
path(X,Y):-edge(X,Z,_),path(Z,Y).

reachable(X,L):-findall(Y,path(X,Y),L).

 

Я не вижу, что не так, но он ходит кругами и останавливается из-за проблем с памятью.
Есть идеи, как это решить?

Пожалуйста, это помогло бы творчески!

Ответ №1:

Если у вашего графика есть ребро, например c → e → c → e → … , тогда ничто не останавливается path при каждом переходе от e туда c и обратно. Если мы не добавим что-то, чтобы предотвратить это.

Мы можем использовать список, содержащий все уже посещенные элементы, и запретить их посещение в другой раз:

 path(X, Y) :-
    path(X, Y, [X]).

path(X, Y, V) :-
    edge(X, Y, _),
      member(Y, V).
path(X, Y, V) :-
    edge(X,Z,_),
      member(Z, V),
    path(Z, Y, [Z|V]). 

таким образом, мы начинаем со списка, который содержит только X . Каждый раз, когда мы берем ребро, мы проверяем, не является ли цель ( Y или Z ) членом V , и в случае рекурсии мы добавляем Z в список.

Для данного графа:

изображение графа graphviz

таким образом, это приводит к:

 ?- path(X, Y).
X = a,
Y = c ;
X = a,
Y = d ;
X = b,
Y = d ;
X = c,
Y = e ;
X = e,
Y = c ;
X = e,
Y = f ;
X = d,
Y = f ;
X = a,
Y = e ;
X = a,
Y = f ;
X = a,
Y = f ;
X = b,
Y = f ;
X = c,
Y = f ;
false.