はじめに
数学(グラフ理論)でグラフとは、node(頂点)とedge(辺)からなる概念です。基本情報技術者試験を受けた人はシステムの状態遷移を示すオートマトンが最もなじみ深いかもしれません。オートマトンはグラフの中でも特に各辺に方向が定義された有向グラフです。
Pythonでグラフを可視化するにはNetworkXが便利す。本記事ではPythonライブラリであるNetworkXを使ってグラフを可視化する方法、またNetworkXに用意されている完全グラフやパスグラフなどに関する便利なメソッドを紹介します。
早速コードを書いていきましょう
準備
まずJupiter Lab環境をお使いの方はpipでNetworkXをinstallしてください。
pip install networkx
これで用意は完了です。
完全グラフ
完全グラフとは任意の頂点が他のすべての頂点と辺で接続されているグラフのことです。
import matplotlib.pyplot as plt
import networkx as nx
G = nx.complete_graph(6) # 頂点数
plt.figure(figsize=(10,10))
nx.draw_networkx(G, node_color="skyblue")
plt.show()
このように書けば直ちに頂点数6の完全グラフ(Complete Graph)ができます。
Balanced Tree
平衡木(Balanced Tree)もこのように書くことができます。
import matplotlib.pyplot as plt
import networkx as nx
G = nx.balanced_tree(2, 4) # 分裂数, 深さ
plt.figure(figsize=(10,10))
nx.draw_networkx(G, node_color="skyblue")
plt.show()
実行結果は、
となります。このように子nodeが2つとなる平衡木を特に平衡二分木(Binary Tree)といいます。
頂点が重なって表示されてしまうときは図のサイズを変更したり、何度か実行して調整するときれいにできるので試してみてください。
ユーザー定義グラフ
もちろんユーザーがグラフを定義することもできます。その場合は頂点と辺をそれぞれリストの形でグラフに追加していきます。無向グラフのオブジェクトはnetworkx.Graph()
とすれば生成できます。また有向グラフオブジェクトはnetworkx.DiGraph()
とすれば生成できます。これらは異なる種類のオブジェクトなので注意してください。
有向グラフで2つの頂点に対して互いに行き来できるような二本の辺があるときは辺を曲線にするとその様子をよく可視化できます。その場合はconnectionstyle="arc3, rad=0.2"
と添えてください。
import networkx as nx
import matplotlib.pyplot as plt
# 有向グラフの作成
G = nx.DiGraph()
# 頂点の追加
G.add_nodes_from([0, 1, 2, 3, 4, 5])
# 一つずつのときはadd_node()
# 頂点と辺の追加
G.add_edges_from([(0,1),(1,2),(2,3),(3,4),(4,5),(5,0),(0,3),(5,1),(2,0),(2,1),(3,2),(5,4)])
# グラフの描画
# connectionstyle="arc3, rad=0.2"で辺を曲線に
plt.figure(figsize=(10,10))
nx.draw_networkx(G, with_labels=True, node_color="skyblue", connectionstyle="arc3, rad=0.2")
plt.show()
このようにしてユーザー定義のグラフも可視化することができました。
他にも色を設定したり、グラフを結合したりすることもできます。
Relaxed Caveman Graph
「リラックスしたゴリラのグラフ?」NetworkXの公式文書をGoogleの自動翻訳頼りで読んでいた折、ついぞ聞いたことのない言葉に出会いました。この翻訳はもちろん誤りでRelaxed Caveman Graphは"(条件を)緩和した原始人グラフ"というのがより正確な表現だと思われます。原始人グラフの説明はwikiに任せることとして、参照した公式文書の説明では次のようにあります。
Returns a relaxed caveman graph.
A relaxed caveman graph starts with l cliques of size k. Edges are then randomly rewired with probability p to link different cliques.
NetworkX公式文書
原始人グラフとは複数の完全グラフを用意し、その頂点から延びる辺を一定の割合で別の完全グラフに配線しなおしたものです。原始人が顔見知りしかいない小集団を作りながらも、時折外の小集団とも関りをもつ様子に由来しているらしいです。
グループの数、グループの数あたりの頂点数、再配線の割合を与えてやると直ちにプロットできます。0から1までの浮動小数で再配線の割合を変化させて観察してみましょう。
import matplotlib.pyplot as plt
import networkx as nx
# p = 0.01, 0.05, 0.1で実験
p = 0.01
G = nx.relaxed_caveman_graph(10, 30, p)
plt.figure(figsize=(40,40))
nx.draw_networkx(G)
plt.show()
このようなコードの実行結果は次の通りです。
これはp = 0.01 における原始人グラフです。それぞれの集団がかなり孤立しています。
p = 0.05 における原始人グラフでは目に見えて"繋がり"が強化されています。
最後にp = 0.1 における原始人グラフです。ここまで来てもコロニーの存在は目視できます。
SNSの相互フォローや社会的な繋がりを辺、アカウントや生身の人間を頂点に置き換えれば社会もこのようなグラフという描像で見つめなおすことができるのではないでしょうか。
フィルターバブルという言葉が言われて久しいですが、それを原始人グラフでモデル化した研究もあります。
We believe that by taking this characteristic into account, awareness campaigns can be improved. For this reason, this article will study the evolution of the security awareness of a group of people according to their interactions.
Guillén et al. (2025)
セキュリティ意識をスコア化する社会物理学の研究では人が身近な人の意見を重視するということを原始人グラフで説明しています。社会を数学や物理学で記述する、門外漢なので大したことは言えませんがとても魅力的なテーマだと個人的には感じました。