Python用の別のグラフモジュールであるigraphは、ノードの特定のペア間のすべての最短経路を計算できます。このようなパスは無限にあるため、すべてのパスを計算しても意味がありません。
頂点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のグリッドグラフ(Graph.Lattice([100, 100], circular=False)
igraphで簡単に生成できる)があるとします。左上のノードから右下のノードにつながる最短経路の数は、200から100の要素を選択する可能性の数に等しくなります(証明:そこにある最短経路の長さには200のエッジがあり、そのうち100は「水平」になりますグリッド内にあり、そのうち100個は「垂直方向」に移動します)。これはおそらくあなたの記憶に収まらないので、これら2つのノード間のすべての最短経路を計算することさえここでは実際には実行可能ではありません。
2つのノード間のすべてのパスが本当に必要な場合は、igraphを使用して、前述のWebページに記載されている関数を書き直すことができます。これは、igraphのコアがCで実装されているため、純粋なPythonソリューションよりも高速です。
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.6だけでなく、igraph0.5.3でも機能するように最初の例を修正しました。