如何在networkx python中找到长度等于某个数字的最短路径的节点?
Posted
技术标签:
【中文标题】如何在networkx python中找到长度等于某个数字的最短路径的节点?【英文标题】:How to find a node with a shortest path of length equal to some number in networkx python? 【发布时间】:2021-04-17 18:32:16 【问题描述】:我有一个简单的代码在networkx中创建一个图形,G。
import networkx as nx
import matplotlib.pyplot as plt
%matplotlib notebook
G = nx.DiGraph()
G.add_edge(1,2); G.add_edge(1,4)
G.add_edge(3,1); G.add_edge(3,2)
G.add_edge(3,4); G.add_edge(2,3)
G.add_edge(4,3)
我想找到“G中的哪个节点通过长度等于G直径的最短路径连接到其他节点”。
其中有两种组合,[1,3]和[2,4],分别可以通过nx.shortest_path(G, 1)和nx.shortest_path(G, 2)找到。
或者,例如, 如果我使用 nx.shortest_path_length(G, source=2) 那么我得到 2: 0, 3: 1, 1: 2, 4: 2。所以length=2是从节点2到节点4,这样就ok了。
现在,我正在尝试将其推广到所有节点,看看是否可以找到目标节点。
for node in G.nodes():
target = [k for k,v in nx.shortest_path_length(G, node).items() if v == nx.diameter(G)]
print(target)
我得到了这个奇怪的结果:
[3]
[1, 4]
[1, 2]
[]
谁能解释一下这个结果是什么意思?因为我正在尝试应用这种方法来解决更大的问题。
【问题讨论】:
【参考方案1】:对于您提供的图表:
G = nx.DiGraph()
G.add_edge(1,2); G.add_edge(1,4)
G.add_edge(3,1); G.add_edge(3,2)
G.add_edge(3,4); G.add_edge(2,3)
G.add_edge(4,3)
以下内容:
for node in G.nodes():
target = [k for k,v in nx.shortest_path_length(G, node).items() if v == nx.diameter(G)]
print(target)
将打印与node
距离等于nx.diameter(G)
的目标
我建议不要计算 for
循环内的直径,因为那样会非常昂贵。
相比之下,对于 200 个节点的图 (nx.barabasi_albert_graph(200, 2, seed=1)
),在 for
循环之外进行直径计算大约需要 74 毫秒。另一个选项(在 for 循环中计算直径)需要......好吧它仍在运行:´) 但我会说它需要太长时间。
此外,为了便于阅读,不仅仅是目标打印开始和结束节点:
diameter = nx.diameter(G)
for node in G.nodes():
start_end_nodes = [(node, k) for k,v in nx.shortest_path_length(G, node).items() if v == diameter]
print(start_end_nodes)
屈服:
[(1, 3)] # the path from 1 to 3 has lenght 2 = nx.diameter(G)
[(2, 1), (2, 4)] # the paths from 2 to 1 and 2 to 4 have lenght 2
[(4, 1), (4, 2)] # the paths from 4 to 1 and 4 to 2 have lenght 2
[] # there is no path starting at 3 that has lenght 2
【讨论】:
是的,我喜欢像你这样的人使用 ***!这说得通。我仍然不确定为什么它会在 v=2 的末尾生成一个空列表 [ ]。谢谢! 我的意思是 '3' 应该在 '2' 和 '4' 之间,而 nx.总是把它的空列表放在最后。我根本不希望在那里看到一个空列表,因为它的长度不是 2。 没问题哈哈! ;) 基本上它会产生空列表,因为 没有从 3 开始的路径 长度为nx.diameter = 2
顺便说一句,你知道如何在没有 IndexError 的情况下从这里访问元组 (1,3) 吗?基于它的长度只有 1 个元组。
您可以使用通常的索引从列表[(1,3)]
中访问元组(1,3)
,特别是这里[(1,3)][0]
。【参考方案2】:
对上面willcrack回复的代码稍作修改(注意增加了对sorted的调用):
diameter = nx.diameter(G)
for node in sorted(G.nodes()):
start_end_nodes = sorted([(node, k) for k,v in nx.shortest_path_length(G, node).items()
if v == diameter])
print(node, ":", start_end_nodes)
将产生:
1 : [(1, 3)]
2 : [(2, 1), (2, 4)]
3 : []
4 : [(4, 1), (4, 2)]
关键是 G.nodes() 根据图的内部表示以任意方式返回节点,该图可能将节点存储在未排序的类集合结构中。
【讨论】:
以上是关于如何在networkx python中找到长度等于某个数字的最短路径的节点?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 python 的 networkx 模块从节点列表生成完全连接的子图