gpt4 book ai didi

prolog - 查找图中节点之间的路径及其长度

转载 作者:行者123 更新时间:2023-12-02 11:33:36 26 4
gpt4 key购买 nike

我正在尝试解决这个问题,并且我已经阅读了 this答案,但我的问题是无限循环,即使我使用了访问过的节点列表。

让我们看看我的两次尝试:

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 卡住。

  • 我应该将什么定义为基本情况?
  • 如果是这种情况,为什么第二个实现会循环,即使我使用了访问节点列表和 diff() 来确保避免统一来回? 我输错了函数姓名。

我想摆脱 length/2 的使用。谢谢。

编辑:

所以,我发现这应该是更干净的方法,即使我想要更类似于第二个实现的东西,这会更容易在最短路径问题解决器中进行转换,因为这只是一分钟{ 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, _).

So essentially it's the use of the length/2 predicate. As long as the length of the path is not fixed, this fragment will not terminate. So for the query

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

Path 的长度不受限制,因此 length/2 将找到无限多个解决方案 - 因此不会终止。

但是,毕竟,你为什么想知道长度呢?路径参数已经隐式地描述了它。

对于您的定义path/4,5,请考虑查询内容

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

应该作为答案产生。 Path = [1] 也应该是一个解决方案吗?这有点关于路径/步行的确切定义的问题。我认为应该如此。

通用解决方案请引用this answer 。有了它,您可以定义您感兴趣的谓词,如下所示:

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

但是,我不想添加有关路径长度的额外参数。无论如何,您可以稍后随时添加该信息。

关于prolog - 查找图中节点之间的路径及其长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36187107/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com