如何从Prolog中的选择中选择最短路径
我是一名prolog初学者,拥有以下代码,其中列出了从一个给定节点到另一个节点的所有可能路径。每一条边都是双向的,这是需要注意的如何从Prolog中的选择中选择最短路径,prolog,shortest-path,Prolog,Shortest Path,我是一名prolog初学者,拥有以下代码,其中列出了从一个给定节点到另一个节点的所有可能路径。每一条边都是双向的,这是需要注意的 nodeLink(1,2,4). nodeLink(1,3,10). nodeLink(1,5,2). nodeLink(2,1,4). nodeLink(2,5,1). nodeLink(2,4,6). nodeLink(2,6,1). nodeLink(3,1,10). nodeLink(3,5,2). nodeLink(3,4,1). nodeLink(4
nodeLink(1,2,4).
nodeLink(1,3,10).
nodeLink(1,5,2).
nodeLink(2,1,4).
nodeLink(2,5,1).
nodeLink(2,4,6).
nodeLink(2,6,1).
nodeLink(3,1,10).
nodeLink(3,5,2).
nodeLink(3,4,1).
nodeLink(4,3,1).
nodeLink(4,5,8).
nodeLink(4,2,6).
nodeLink(5,1,2).
nodeLink(5,2,1).
nodeLink(5,3,2).
nodeLink(5,4,8).
nodeLink(6,2,1).
path([B | BRest], B, [B | BRest], Length, Length).
path([A | ARest], B, Path, CurrentLength, Length) :-
nodeLink(A, C, X),
\+member(C, [A | ARest]),
NewLength is CurrentLength + X,
path([C, A | ARest], B, Path, NewLength, Length).
all_paths(Start, End) :-
path([Start], End, Path, 0, Length),
reverse(Path, RevPath),
write('Path: '),
printPath(RevPath),
write(' with a cost of '),
writeln(Length),
fail.
printPath([]).
printPath([X]) :-
!,
write(X).
printPath([X|Xrest]) :-
write(X),
write(', '),
printPath(Xrest).
例如:
?- all_paths(6,3).
打印出:
Path: 6, 2, 1, 3 with a cost of 15
Path: 6, 2, 1, 5, 3 with a cost of 9
Path: 6, 2, 1, 5, 4, 3 with a cost of 16
Path: 6, 2, 5, 1, 3 with a cost of 14
Path: 6, 2, 5, 3 with a cost of 4
Path: 6, 2, 5, 4, 3 with a cost of 11
Path: 6, 2, 4, 3 with a cost of 8
Path: 6, 2, 4, 5, 1, 3 with a cost of 27
Path: 6, 2, 4, 5, 3 with a cost of 17
false.
如何为给定的一对节点选择“最短”路径?
谢谢一般来说,在Prolog中,您不希望使用
write
和故障驱动循环来显示所有解决方案。一种规范的方法是为每个解决方案设置一个成功的谓词(正如path/5
谓词所做的那样),然后使用findall/3
或bagof/3
或setof/3
收集列表中的所有解决方案setof/3
有消除重复项和对结果集合排序的好处
这里有一个stackoverflow搜索。这已经在这个网站上被报道了很多次了,我不想只选择其中一个。我没有看到使用setof/3
,所以这里有一个采用这种方法的解决方案
我将使用您现有的path/5
定义。由于路径集合在设计上是唯一的,因此使用setof/3
将比使用findall/3
和msort/2
稍有改进,您可以在至少一个链接解决方案中找到这一点。这里的想法是创建一个成本路径
形式的解决方案列表,按成本
排序。然后,您需要从列表中选择最低成本,这是自订购以来的第一个元素
shortest_path(Start, End, ShortestPath, ShortestLength) :-
setof(Length-Path, path([Start], End, Path, 0, Length), [ShortestLength-ShortestPath|_]).
如果您想打印列表,可以使用maplist
:
print_path(Cost-Path) :-
write('Path: '),
write(Path),
write(' with a cost of '),
write(Cost), nl.
print_paths(CostPaths) :-
maplist(print_path, CostPaths).
其中,
costpath
是上面执行的setof/3
的结果。最简单的解决方案是将所有路径存储在一个列表中,然后选择最短路径。不是最优的,但实施速度快,易于管理understand@CFER你可能不接受我的回答。虽然它为枚举提供了有用的概念,但它并不是成本最低路径的最佳解决方案。一个合适的方法是使用。如果“这个网站已经讨论了这么多次”,你为什么不给出一个一劳永逸的明确的、通用的定义呢?@false,它已经被许多不同的方式讨论过了。目前,我不想说我发布的这个变体是其中最好的。@false:有更好的算法来寻找最短路径,所以这里提出的解决方案不应该是确定的解决方案。这样做的真正目的是一次又一次地发布非常相同的临时解决方案吗?@false不,不是。但我不认为这是“完全相同”的临时解决方案。在我的快速搜索中,我没有看到一个与之匹配的,尽管有些是相似的。这就是为什么我贴了它。然而,这并不意味着我的搜索不够彻底。如果你找到一个与我发布的“非常相同”的解决方案,我很乐意删除这个。