Python-igraph 是 Python 中的另一个图形模块,可以计算给定节点对之间的所有最短路径。计算所有路径是没有意义的,因为你有无限多条这样的路径。
以下是从顶点0计算所有最短路径的示例:
>>> from igraph import Graph
>>> g = Graph.Lattice([10, 10], circular=False)
>>> g.get_all_shortest_paths(0)
[...a list of 3669 shortest paths starting from vertex 0...]
如果您拥有igraph 0.6或更高版本(这是编写本文时的开发版本),则可以将get_all_shortest_paths
的结果限制为给定的终点顶点:
>>> g.get_all_shortest_paths(0, 15)
[[0, 1, 2, 3, 4, 14, 15],
[0, 1, 2, 12, 13, 14, 15],
[0, 10, 11, 12, 13, 14, 15],
[0, 1, 11, 12, 13, 14, 15],
[0, 1, 2, 3, 13, 14, 15],
[0, 1, 2, 3, 4, 5, 15]]
当然你需要小心;比如,假设你有一个100 x 100的网格图(可以通过igraph中的
Graph.Lattice([100, 100], circular=False)
轻松生成)。从左上节点到右下节点的最短路径数量等于从200个元素中选择100个元素的可能性数(证明:最短路径的长度为200条边,其中100条会“水平”穿过网格,另外100条会“垂直”穿过网格)。这可能不适合你的内存,因此即使计算出所有这两个节点之间的
最短路径也并不真正可行。
如果你确实需要所有节点之间的路径,你可以使用igraph重写给出的网页函数,这可能比纯Python解决方案更快,因为igraph的核心是用C实现的。
def find_all_paths(graph, start, end, path=[]):
path = path + [start]
if start == end:
return [path]
paths = []
for node in set(graph.neighbors(start)) - set(path):
paths.extend(find_all_paths(graph, node, end, path))
return paths
如果将图转换为邻接表表示形式,可以进行更多优化,因为这样可以避免对 graph.neighbors
的重复调用:
def find_all_paths(graph, start, end):
def find_all_paths_aux(adjlist, start, end, path):
path = path + [start]
if start == end:
return [path]
paths = []
for node in adjlist[start] - set(path):
paths.extend(find_all_paths_aux(adjlist, node, end, path))
return paths
adjlist = [set(graph.neighbors(node)) for node in xrange(graph.vcount())]
return find_all_paths_aux(adjlist, start, end, [])
编辑:已修复第一个示例,可���在 igraph 0.5.3 和 igraph 0.6 中都可以工作。