PROLOG图最长路径实现:现有最短路径代码如何适配修改
Prolog最短路径算法改最长路径实现方案
核心修改思路
- 首先修复原始路径搜索逻辑的缺陷:原始
path谓词没有判断节点是否重复访问,如果图存在环会触发无限递归,尤其是最长路径场景下如果存在正权环会不存在有限解,因此需要新增已访问节点校验,限制搜索的路径为无重复节点的简单路径。 - 调整排序逻辑:原始最短路径是对路径总权重做升序排序取首项,最长路径需要对总权重做降序排序取首项,可通过对权重取负后升序排序,或直接调用Prolog的降序排序能力实现。
完整修改后代码
% 边的定义示例,可根据你的实际图结构替换 % edge(a,b,2). % edge(b,c,3). % edge(a,c,4). % 内部路径搜索谓词,第三个参数为已访问节点列表,避免重复走节点 path(X,Y,Visited,[X,Y],L):- edge(X,Y,L), \+ member(Y, Visited). path(X,Y,Visited,[X|W],L):- edge(X,Z,L1), \+ member(Z, Visited), path(Z,Y,[Z|Visited],W,L2), L is L1 + L2. % 对外暴露的路径查询入口,初始化已访问列表 path(X,Y,P,L) :- path(X,Y,[X],P,L). % 最长路径查询:起点终点相同的特殊情况,不需要的话可以注释该行以支持搜索同点的最长回路 longestPath(X,X,[X,X],0):- !. longestPath(X,Y,MaxP,MaxD):- findall([L,P],path(X,Y,P,L),Set), % 兼容性写法:对权重取负后升序排序,兼容所有Prolog版本 findall([NegL, P], (member([L, P], Set), NegL is -L), NegSet), sort(NegSet, SortedNeg), SortedNeg = [[NegMaxD, MaxP]|_], MaxD is -NegMaxD. % 如果你使用的Prolog支持自定义排序规则(比如SWI-Prolog),可以用更简洁的写法替换上面的longestPath实现: % longestPath(X,Y,MaxP,MaxD):- % findall([L,P],path(X,Y,P,L),Set), % sort(1, @>=, Set, Sorted), % Sorted = [[MaxD, MaxP]|_].
注意事项
- 最长路径问题本身属于NP完全问题,当前暴力枚举所有简单路径的方案仅适用于节点规模很小的图,节点数超过15后性能会出现明显下降。
- 本方案默认限制路径为无重复节点的简单路径,如果你的业务场景允许走环且图中存在正权环,不存在有限的最长路径,本方案不适用。
内容的提问来源于stack exchange,提问作者Emanuel Salvadinho
相关产品推荐
相关产品推荐

