我希望networkx在我的定向中找到绝对最长的路径, 非循环图。
我知道贝尔曼 - 福特,所以我否定了我的图表长度。问题: networkx的bellman_ford()需要一个源节点。我想找到 绝对最长路径(或否定后的最短路径),而不是 来自给定节点的最长路径。
当然,我可以在图表中的每个节点上运行bellman_ford() 排序,但是有更有效的方法吗?
从我读过的内容(例如, http://en.wikipedia.org/wiki/Longest_path_problem)我意识到了 实际上可能不是一个更有效的方法,但是想知道是否 任何人都有任何想法(和/或已证明P = NP(笑))。
编辑:我的图中的所有边长都是+1(否定后为-1),因此只需访问大多数节点的方法也可以。通常,当然不可能访问所有节点。
编辑:好的,我刚刚意识到我可以添加一个额外的节点,它只是连接到图中的每个其他节点,然后从该节点运行bellman_ford。还有其他建议吗?
答案 0 :(得分:5)
http://en.wikipedia.org/wiki/Longest_path_problem
中提到了线性时间算法这是一个(非常轻微测试)的实现
编辑,这显然是错误的,见下文。在发布之前,为了将来的测试而不仅仅是+1,import networkx as nx
def longest_path(G):
dist = {} # stores [node, distance] pair
for node in nx.topological_sort(G):
pairs = [[dist[v][0]+1,v] for v in G.pred[node]] # incoming pairs
if pairs:
dist[node] = max(pairs)
else:
dist[node] = (0, node)
node, max_dist = max(dist.items())
path = [node]
while node in dist:
node, length = dist[node]
path.append(node)
return list(reversed(path))
if __name__=='__main__':
G = nx.DiGraph()
G.add_path([1,2,3,4])
print longest_path(G)
编辑:更正版本(使用风险自负,请报告错误)
def longest_path(G):
dist = {} # stores [node, distance] pair
for node in nx.topological_sort(G):
# pairs of dist,node for all incoming edges
pairs = [(dist[v][0]+1,v) for v in G.pred[node]]
if pairs:
dist[node] = max(pairs)
else:
dist[node] = (0, node)
node,(length,_) = max(dist.items(), key=lambda x:x[1])
path = []
while length > 0:
path.append(node)
length,node = dist[node]
return list(reversed(path))
if __name__=='__main__':
G = nx.DiGraph()
G.add_path([1,2,3,4])
G.add_path([1,20,30,31,32,4])
# G.add_path([20,2,200,31])
print longest_path(G)
答案 1 :(得分:0)
Aric修改后的答案很好,我发现它已被networkx库采用link
但是,我发现这种方法存在一些缺陷。
if pairs:
dist[node] = max(pairs)
else:
dist[node] = (0, node)
因为pairs是(int,nodetype)元组的列表。比较元组时,python会比较第一个元素,如果它们相同,则会处理比较第二个元素,即nodetype。但是,在我的情况下,nodetype是一个自定义类,其中未定义比较方法。因此,Python会抛出类似'TypeError:unorderable types:xxx()>的错误。 XXX()'
对于可能的改进,我说行
dist[node] = max(pairs)
可以替换为
dist[node] = max(pairs,key=lambda x:x[0])
抱歉格式化,因为这是我第一次发帖。我希望我能在Aric的答案下面发表评论作为评论,但该网站禁止我这样做,说明我没有足够的声誉(很好......)