igraphを用いて重み付きグラフを生成する。
from igraph import *
重み付き隣接行列は以下で与える。
adj = np.array([[1, 2, 3], [2, 2, 1], [3, 1, 5]])
#Graph.Adjacency
Graph.Adjacencyという関数で隣接行列からグラフを生成できる。
adj = [[1, 2, 3], [2, 2, 1], [3, 1, 5]]#igraphにおいてはリストで与えないとエラーを起こしてしまう。
G = Graph.Adjacency(adj)
print(G.is_weighted())
#False
print(G.is_multiple())
#[False, False, True, False, True, True, False, True, False, True, False, False, True, True, False, False, True, True, True, True]
このようにうまく生成することができなかった。
この原因として、隣接行列の定義が考えられる。
頂点$i$と$j$の間に辺が1本存在するとき隣接行列の$(i, j)$成分が1と定義されている。
つまり例の隣接行列の$(1, 2)$成分の値は2であるが、それは2本の辺が頂点$1$と$2$の間に存在することを意味する。
そのため多重辺が存在するグラフを生成してしまった。
#GraphBase.Weighted_Adjacency
重み付き隣接行列を読み込む関数があった。
G = GraphBase.Weighted_Adjacency(adj, mode=ADJ_UNDIRECTED)
print(G.is_multiple())
#[False, False, False, False, False, False]
多重辺と認識せずに読み込んでくれた。
GraphのEdge Sequenceから重みを読み込む。
print(G.es['weight'])
#AttributeError: 'igraph.Graph' object has no attribute 'es'
このようなエラーが出力されてしまった。
うまく重み付き行列が入力されているのかわからず、少し大きな隣接行列を読み込みコミュニティ抽出を行おうとしたところうまくいかずこの関数はよくなかった。
#networkx (解決策)
networkxで生成したグラフを保存しigraphで呼び出すことでうまくいった。
networkxで生成し、保存。
G = nx.from_numpy_array(adj)
nx.write_gml(G, 'graph.gml')
それをigraphで呼び出す
G = Graph.Read_GML('graph.gml')
print(G.es['weight'])
#[1.0, 2.0, 3.0, 2.0, 1.0, 5.0]
うまく実装できた。
#コミュニティ抽出
networkxでコミュニティ抽出を失敗したため、igraphで重み付きグラフの生成を始めた。
networkxでコミュニティ抽出(greedy法)を行おうとしたところ、うまく分類できなかった。
それはnetworkxにおいて重み付きのグラフが対応していなかったためである。
Find communities in graph using Clauset-Newman-Moore greedy modularity maximization. This method currently supports the Graph class and does not consider edge weights.
引用元: greedy_modularity_communities
networkxで用いた方法により揉み付きグラフのコミュニティ分類を行えた。
txt = G.community_fastgreedy()
print(txt)
#Dendrogram, 3 elements, 2 merges
#
#2 0 1
#| | |
#| `-'
#| |
#`--'
重みがない隣接行列でもうまく生成できている。