SciPy グラフ構造
グラフ構造はアルゴリズム学において最も強力なフレームワークの一つです。
グラフは様々な関係のノードとエッジの集合であり、ノードはオブジェクトに対応する頂点、エッジはオブジェクト間の接続です。
SciPy はグラフ構造を処理するための scipy.sparse.csgraph モジュールを提供しています。
隣接行列
隣接行列(Adjacency Matrix)は、頂点間の隣接関係を表す行列です。
隣接行列の論理構造は、V と E の2つの集合に分けられます。ここで、V は頂点、E は辺であり、辺にはノード間の接続の強さを表す重みがある場合があります。

1次元配列でグラフ内のすべての頂点データを格納し、2次元配列で頂点間の関係(辺または弧)のデータを格納します。この2次元配列を隣接行列と呼びます。
次の図の例を見てみましょう:

頂点は A、B、C で、辺の重みは 1 と 2 です。
A と B は接続されており、重みは 1 です。
A と C は接続されており、重みは 2 です。
C と B は接続されていません。
この隣接行列は、次の2次元配列で表すことができます:
A B C
A:[0 1 2]
B:[1 0 0]
C:[2 0 0]
隣接行列は、有向グラフの隣接行列と無向グラフの隣接行列に分けられます。
無向グラフは双方向の関係であり、辺に方向はありません:


注:上記2つの図の D ノードは自己ループです。自己ループとは、1つの辺の両端が同じノードであることを指します。
連結成分
すべての連結成分を確認するには、connected_components() メソッドを使用します。
例
from scipy.sparse.csgraph import connected_components
from scipy.sparse import csr_matrix
arr = np.array([
[0, 1, 2],
[1, 0, 0],
[2, 0, 0]
])
newarr = csr_matrix(arr)
print(connected_components(newarr))
上記のコードの出力結果は次のとおりです:
(1, array([0, 0, 0], dtype=int32))
Dijkstra -- 最短経路アルゴリズム
Dijkstra(ダイクストラ)最短経路アルゴリズムは、あるノードから他のすべてのノードへの最短経路を計算するために使用されます。
Scipy は dijkstra() メソッドを使用して、ある要素から他の要素への最短経路を計算します。
dijkstra() メソッドでは、以下のパラメータを設定できます:- return_predecessors:ブール値。True に設定するとすべての経路を走査します。すべての経路を走査したくない場合は False に設定できます。
- indices:要素のインデックス。その要素のすべての経路を返します。
- limit:経路の最大重み。
例
要素 1 から 2 への最短経路を検索します:
from scipy.sparse.csgraph import dijkstra
from scipy.sparse import csr_matrix
arr = np.array([
[0, 1, 2],
[1, 0, 0],
[2, 0, 0]
])
newarr = csr_matrix(arr)
print(dijkstra(newarr, return_predecessors=True, indices=0))
上記のコードの出力結果は次のとおりです:
(array([ 0., 1., 2.]), array([-9999, 0, 0], dtype=int32))
Floyd Warshall -- フロイド-ワーシャル法
フロイド-ワーシャル法は、任意の2点間の最短経路を求めるアルゴリズムです。
Scipy は floyd_warshall() メソッドを使用して、すべての要素ペア間の最短経路を検索します。
例
すべての要素ペア間の最短経路を検索します:
from scipy.sparse.csgraph import floyd_warshall
from scipy.sparse import csr_matrix
arr = np.array([
[0, 1, 2],
[1, 0, 0],
[2, 0, 0]
])
newarr = csr_matrix(arr)
print(floyd_warshall(newarr, return_predecessors=True))
上記のコードの出力結果は次のとおりです:
(array([[ 0., 1., 2.],
[ 1., 0., 3.],
[ 2., 3., 0.]]), array([[-9999, 0, 0],
[ 1, -9999, 0],
[ 2, 0, -9999]], dtype=int32))
Bellman Ford -- ベルマン-フォード法
ベルマン-フォード法は、任意の2点間の最短経路を求めるアルゴリズムです。
Scipy は bellman_ford() メソッドを使用して、すべての要素ペア間の最短経路を検索します。これは通常、有向グラフや負の重みの辺を持つグラフを含む、あらゆるグラフで使用できます。
例
負の重みを持つ辺を使用したグラフで、要素 1 から要素 2 への最短経路を検索します:
from scipy.sparse.csgraph import bellman_ford
from scipy.sparse import csr_matrix
arr = np.array([
[0, -1, 2],
[1, 0, 0],
[2, 0, 0]
])
newarr = csr_matrix(arr)
print(bellman_ford(newarr, return_predecessors=True, indices=0))
上記のコードの出力結果は次のとおりです:
(array([ 0., -1., 2.]), array([-9999, 0, 0], dtype=int32))
深さ優先順序
depth_first_order() メソッドは、あるノードから深さ優先探索の順序を返します。
以下のパラメータを受け取ることができます:
- 图
- グラフの走査を開始する要素
例
隣接行列が与えられた場合、深さ優先探索の順序を返します:
from scipy.sparse.csgraph import depth_first_order
from scipy.sparse import csr_matrix
arr = np.array([
[0, 1, 0, 1],
[1, 1, 1, 1],
[2, 1, 1, 0],
[0, 1, 0, 1]
])
newarr = csr_matrix(arr)
print(depth_first_order(newarr, 1))
上記のコードの出力結果は次のとおりです:
(array([1, 0, 3, 2], dtype=int32), array([ 1, -9999, 1, 0], dtype=int32))
幅優先順序
breadth_first_order() メソッドは、あるノードから幅優先探索の順序を返します。
以下のパラメータを受け取ることができます:
- 图
- グラフの走査を開始する要素
例
隣接行列が与えられた場合、幅優先探索の順序を返します:
from scipy.sparse.csgraph import breadth_first_order
from scipy.sparse import csr_matrix
arr = np.array([
[0, 1, 0, 1],
[1, 1, 1, 1],
[2, 1, 1, 0],
[0, 1, 0, 1]
])
newarr = csr_matrix(arr)
print(breadth_first_order(newarr, 1))
上記のコードの出力結果は次のとおりです:
(array([1, 0, 2, 3], dtype=int32), array([ 1, -9999, 1, 1], dtype=int32))その他の拡張