簡體   English   中英

查找圖中節點之間的路徑及其長度

[英]Find path and its length between nodes in a graph

我正在嘗試解決這個問題,我已經閱讀了這個答案,但我的問題是無限循環,即使我使用了訪問節點列表。

讓我們看看我的兩次嘗試:

edge(1,2).
edge(1,4).
edge(1,3).
edge(2,3).
edge(2,5).
edge(3,4).
edge(3,5).
edge(4,5).


% ------ simple path finding in a directed graph

% -----  simple exploration

path0(A,B, Result) :-
    path0(A, B, [], Result).

path0(A, B, _, [e(A,B)]):- 
    edge(A,B).    
path0(A, B, Visited, [e(A,X)|Path]):-
    edge(A, X), dif(X, B),
    \+ member(X, Visited),
    path0(X, B, [A|Visited], Path ).    


%---- 1. exploration and length    

path(A, B, _, [e(A,B)], 1):- 
    edge(A,B).    
path(A, B, Visited, [e(A,X)|Path], Length):-
    edge(A, X),
    \+ member(X, Visited),
    length(Path, L),        % ERR: Path refers to a open list
    Length is L + 1,
    path(X, B, [A|Visited], Path, _).

% --- 2. not working

path2(A,B, Result, Length) :-
    path2(A, B, [], Result, Length).

path2(A, B, [], [e(A,B)], 1):- 
    edge(A,B).    
path2(A, B, Visited, [e(A,X)|Path], Length):-
    edge(A, X), dif(X, B),
    \+ member(X, Visited),
    path2(X, B, [A|Visited], Path, Len),
    Length is Len + 1.

這給了我類似的答案,即:

 ?- path(1,3, Path, Length).
Path = [e(1, 3)],
Length = 1 ;
Path = [e(1, 2), e(2, 3)],
Length = 2 ;

然后 Swi-Prolog IDE 就死機了。

  • 我應該將什么定義為基本情況?
  • 為什么第二個實現循環,如果是這樣,即使我使用了訪問節點列表和 dif() 來確保避免統一來回? 我打錯了函數名。

我想擺脫 length/2 的使用。 謝謝。

編輯:

所以,我發現這應該是更簡潔的方法,即使我想要更類似於第二個實現的東西,它更容易在最短路徑問題求解器中轉換,因為它只是一個 min{ pathLengths }從 path3/4 的第一次調用開始。

% ---- 3. working    
%   
min(A,B,A):- A =< B, !.       % for future use (shortest path)
min(_,B,B).

path3(From, To, Path, Len):-    
    path0(From, To, [], Path),
    length(Path, Len).
    %min(Len, MinLength, ?)

這是第二個實現路徑2的更正版本:

% --- 2. 
% errors: 1. in base case I have to return Visited trough _, 
%             I can't pass a void list []
%         2. dif(X,B) is unuseful since base case it's the first clause

path2(A,B, Result, Length) :-
    path2(A, B, [], Result, Length).

path2(A, B, _, [e(A,B)], 1):-      % If an edge is found
    edge(A,B).    
path2(A, B, Visited, [e(A,X)|Path], Length):-
    edge(A, X),  
    %tab(1),write(A),write('-'),write(X),
    \+ member(X, Visited),
    %tab(1),write([A|Visited]),write(' visited'),nl,
    path2(X, B, [A|Visited], Path, Len),
    Length is Len + 1.

path/4path2/4公開類似的非終止行為的原因是因為它們都使用相同的輔助謂詞path/5 您可能指的是path2/5

path2(A,B, Result, Length) :-
    path(A, B, [], Result, Length).
 %  ^^^^ replace by path2

也許首先,讓我們看看為什么您的path/4定義循環。 為了看到這一點,我將在你的程序中插入目標false 這些目標將減少推理的數量。 當剩余的片段仍然循環時,我們可以確定我們看到了負責非終止的部分。 經過一些實驗,我發現了以下片段,稱為

edge(1,2).
edge(1,4) :- false.
edge(1,3) :- false.
edge(2,3) :- false.
edge(2,5) :- false.
edge(3,4) :- false.
edge(3,5) :- false.
edge(4,5) :- false.

path(A,B, Result, Length) :-
    path(A, B, [], Result, Length), false.

path(A, B, _, [e(A,B)], 1):- false,
    edge(A,B).
path(A, B, Visited, [e(A,X)|Path], Length):-
    edge(A, X),
    \+ member(X, Visited),
    length(Path, L), false,
    Length is L + 1,
    path(X, B, [A|Visited], Path, _).

所以本質上是使用length/2謂詞。 只要路徑的長度不固定,這個片段就不會終止。 所以對於查詢

?- path(1, 3, Path, N).

Path的長度不受限制,因此length/2將找到無限多個解——因此不會終止。

但是,畢竟,你為什么要知道長度呢? path 參數已經隱式地描述了它。

對於您的定義path/4,5考慮查詢的內容

?- path(1, X, Path, N).

應該產生作為答案。 Path = [1]應該是一個解決方案嗎? 路徑/步行的確切定義有點問題。 我覺得應該。

有關通用解決方案,請參閱此答案 有了它,您可以像這樣定義您感興趣的謂詞:

yourpath(A,B, Path, N) :-
   path(edge, Path, A,B),
   length(Path, N).

但是,我寧願不添加有關路徑長度的額外參數。 無論如何,您以后可以隨時添加該信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM