列出所有可能的“最短”路径
我遇到了一个组合问题,这个问题可以看作是一个网络搜索问题。为了更好地可视化并使用已经实现的功能,我决定使用networkx这个库(其实我没有足够的时间去用其他方式实现)。
我的问题比较复杂,但我会尽量从最简单的地方开始讲解,以便大家理解。总的来说,我需要找出到达树的终点节点的组合。
下面的图是一个简单的例子:
在这个例子中,B
、D
、F
、H
是终点节点,而起点用O
表示。所以,一个路径组合可能是:
OAB
OCD
OED
OEF
OH
OGH
不过,我实际上是想寻找到达终点节点的“最短”或“最优”路径。这个图(或者说边)并没有提供关于路径“成本”的任何信息。成本的评估将根据找到的组合结果来进行。评估这些组合的“实际”成本是计算上非常耗费资源的。虽然这个图提供的信息不多,但有一点是明确的:为了到达H
,OH
始终比OGH
更好。因此,组合OGH
可以从可能的组合列表中排除。这本质上就像是距离的度量。
还有一点,实际上D
和F
是等效的节点(它们是不同的节点,但在我的应用中意义相同)。这样的信息只有在两个节点
- see each other
- see exactly the same nodes
仔细观察图形,我们还可以发现C
和E
也是等效节点。所以,更具体地说:组合OCD
和OED
实际上是相同的。一旦OCD
被添加到组合列表中,就不需要再添加OED
。从图中也可以看出,由于D
和F
是相同的,一旦OCD
被添加到列表中,就不需要再添加OCF
。
总之,在这种情况下,解决方案是:
OAB
anyone of OCD, OED, OCF, OEF
OH
为了绘制这个图,我参考了networkx的教程,然后创建了下面的代码:
import networkx as nx
import matplotlib.pyplot as plt
graph = [('O', 'A'), ('O', 'C'), ('O', 'E'), ('O', 'G'), ('O', 'H'),
('A', 'B'), ('A', 'O'),
('B', 'A'),
('C', 'D'), ('C', 'E'), ('C', 'F'), ('C', 'O'),
('D', 'E'), ('D', 'C'), ('D', 'F'),
('E', 'C'), ('E', 'D'), ('E', 'F'), ('E', 'O'),
('F', 'C'), ('F', 'D'), ('F', 'E'),
('G', 'H'), ('G', 'O'),
('H', 'G'), ('H', 'O')]
G=nx.DiGraph()
for edge in graph:
G.add_edge(edge[0], edge[1])
pos=nx.graphviz_layout(G,prog='dot')
nx.draw(G, pos)
plt.show()
所以,我的问题是希望能列出这样的序列,使用任何工具箱,但最好是networkx。第一步可能是简化(或减少)图形,然后再创建一个图对象。一旦得到了简化的图形,就可以使用nx.all_simple_path
命令列出所有的替代路径。我需要你的帮助来进行这样的图形简化。
我的图形不深,通常和例子中的大小差不多。
1 个回答
我看过整个模块的手册,也尝试了不同的搜索算法,但就是找不到现成的实现方法,或者针对这种特定情况的解决办法。
所以,根据评论中得到的建议,我自己写了一个简化器,先把所有“多余”的节点去掉,然后再创建图。我是通过把列表转换成集合,然后比较它们是否相同来做到这一点的。之后,我创建了图,并使用 nx.all_simple_paths
命令列出了所有的解决方案。一旦得到了路径,这次我又检查了一下,看看是否有一些路径(比如 OGH
),当去掉倒数第二个字母后,得到的路径(OH
)是否也在 nx.all_simple_paths
的列表中。如果有的话,我就把这个解决方案去掉。
我写的脚本有点杂乱,也没有用到什么特别的技巧。所以,我决定写下这个解决方案的方法论。