2015-05-22 3 views
0

У меня есть код, который вычисляет минимальное расстояние пути Дийкстра. Можете ли вы мне помочь изменить свой код, чтобы не только печатать минимальное расстояние, но и полный путь?Путь Дийкстра (не только расстояние)

% min_dist(+Graph,+Start,-MinDist) 
min_dist(Graph,Start,MinDist):- 
    dijkstra(Graph,[],[Start-0],MinDist). 

edge(g(Es,Vs),V1,V2,Value):- 
    member(e(V1,V2,Value),Vs) ; 
    member(e(V2,V1,Value),Vs). 

neighbourhood(Graph,V,NB):- 
    setof(V1-E,edge(Graph,V,V1,E),NB). 

% dijkstra(+Graph,+ClosedVertices,+OpenVertices,-Distances) 
dijkstra(_,MinDist,[],MinDist). 
dijkstra(Graph,Closed,Open,MinDist):- 
    choose_v(Open,V-D,RestOpen), 
    neighbourhood(Graph,V,NB), % NB is a list of adjacent vertices+distance to V 
    diff(NB,Closed,NewNB), 
    merge(NewNB,RestOpen,D,NewOpen), 
    dijkstra(Graph,[V-D|Closed],NewOpen,MinDist). 

% choose_v(+OpenVertices,-VertexToExpand,-RestOpenVertices) 
choose_v([H|T],MinV,Rest):- 
    choose_minv(T,H,MinV,Rest). 
choose_minv([],MinV,MinV,[]). 
choose_minv([H|T],M,MinV,[H2|Rest]):- 
    H=V1-D1, M=V-D, 
    (D1<D -> NextM=H,H2=M 
      ; NextM=M,H2=H), 
    choose_minv(T,NextM,MinV,Rest). 

% diff(+ListOfVertices,+Closed,-ListOfNonClosedVertices) 
diff([],_,[]). 
diff([H|T],Closed,L):- 
    H=V-D, 
    (member(V-_,Closed) -> L=NewT ; L=[H|NewT]), 
    diff(T,Closed,NewT). 

% merge(+ListOfVertices,+OldOpenVertices,-AllOpenVertices) 
merge([],L,_,L). 
merge([V1-D1|T],Open,D,NewOpen):- 
    (remove(Open,V1-D2,RestOpen) 
     -> VD is min(D2,D+D1) 
     ; RestOpen=Open,VD is D+D1), 
    NewOpen=[V1-VD|SubOpen], 
    merge(T,RestOpen,D,SubOpen). 

remove([H|T],H,T). 
remove([H|T],X,[H|NT]):- 
    H\=X, 
    remove(T,X,NT). 

Спасибо!
EDIT: Я редактировал свой код, потому что забыл добавить окрестности и предикаты края.

+0

«ваш» код имеет одноточие, маловероятно, что он работает. По крайней мере, добавьте пример запроса, чтобы увидеть формат графика ... – CapelliC

+0

Singletons (V1, V в «choose_minv» и D в «diff») могут быть заменены на _. Это не ошибки. –

ответ

1

Хороший источник, хорошо организованный и хорошо прокомментировал.

Предлагаю вам изменить свои операторы «слияния», чтобы не только обновлять минимальные расстояния, но и включать третье поле с вершиной, которая дает этот минимум.

(предупреждение: комментарий для инструкций тезисов не содержит одного аргумента).

Что-то вроде:

merge([V1-D1|T],Open,V-D-_,[V1-VD-O|SubOpen]):- 
    (remove(Open,V1-D2-O2,RestOpen) 
     -> (D2<D+D1 -> VD=D2, O=O2 ; VD is D+D1, O=V) 
     ; RestOpen=Open,VD is D+D1,O=V), 
    merge(T,RestOpen,D,SubOpen). 

, что означает, что вы должны адаптировать все остальные пройти члены вида "Vertice-Distance-Origin".

+0

Благодарим вас за ответ, но можете ли вы просмотреть мой первый пост? Я отредактировал его, потому что забыл добавить окрестности и предикаты края ... И, кстати, вот как я запускаю свою программу: min_dist (g ([a, b, c, d], [e (a, b, 3)), e (b, d, 4), e (a, d, 2), e (c, d, 1)]), a, X). И результатом будет: X = [c-3, b-3, d-2, a-0]. Теперь, как я могу сделать, чтобы напечатать путь тоже? – charqus

+1

Без изменений в комментарии, используйте термин Vertex-Distance-Origin. Результатом «min_dist» будет вся вершина с ее минимальным расстоянием и предыдущей вершиной. В конце, вернитесь с последнего узла, чтобы начать. –

+0

спасибо @pasaba; Меняя предикат слияния с вашим, больше не возвращает мне список, он возвращает false – charqus