如何在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 模块从节点列表生成完全连接的子图

如何在 Python 中重塑 networkx 图?

减少networkx中图的节点/边数

Python数模笔记-NetworkX最短路径

如何使用 `networkx` 中的 `pos` 参数创建流程图样式的图表? (Python 3)

在networkx(Python)中获取有向图的根(头)