生物医学网络科学Biomedical Network Science
Example02 / 15

Girvan–Newman 算法

所属专题
社团结构与社区发现
下载
Notebook · .py

对空手道网络运行 Girvan–Newman(反复删除边介数最大的边,每次删边后重新计算边介数), 记录每一层划分的社团数与模块度,选出 Q 最大的一层;再把第一次分裂(2 个社团)与真实两派比较。 输出:Q 在 5 个社团时达到最大(约 0.40);第一次分裂只有个别节点与真实分派不同。

Output输出图

Girvan–Newman 算法:输出图 1

Output文字输出

社团数  2  Q = 0.360
社团数  3  Q = 0.349
社团数  4  Q = 0.363
社团数  5  Q = 0.401
社团数  6  Q = 0.393
社团数  7  Q = 0.376
社团数  8  Q = 0.358
社团数  9  Q = 0.342
社团数 10  Q = 0.333
最佳:5 个社团,Q = 0.401
第一次分裂中与真实分派不一致的节点: [2, 8]

Code代码

# 对空手道网络运行 Girvan–Newman(反复删除边介数最大的边,每次删边后重新计算边介数),
# 记录每一层划分的社团数与模块度,选出 Q 最大的一层;再把第一次分裂(2 个社团)与真实两派比较。
# 输出:Q 在 5 个社团时达到最大(约 0.40);第一次分裂只有个别节点与真实分派不同。
import networkx as nx
import matplotlib.pyplot as plt

K = nx.karate_club_graph()
G = nx.Graph(K.edges())
truth = {n: K.nodes[n]["club"] for n in K}

levels = []                                   # [(社团数, Q, 划分), ...]
for comms in nx.community.girvan_newman(G):
    comms = [set(c) for c in comms]
    levels.append((len(comms), nx.community.modularity(G, comms), comms))
    if len(comms) >= 10:
        break

for n_c, q, _ in levels:
    print("社团数 %2d  Q = %.3f" % (n_c, q))
best = max(levels, key=lambda x: x[1])
print("最佳:%d 个社团,Q = %.3f" % (best[0], best[1]))
first = levels[0][2]
side_hi = first[0] if 0 in first[0] else first[1]           # 教练 0 号所在的一侧
wrong = [n for n in G if (n in side_hi) != (truth[n] == "Mr. Hi")]
print("第一次分裂中与真实分派不一致的节点:", wrong)

plt.plot([x[0] for x in levels], [x[1] for x in levels], "o-")
plt.xlabel("number of communities")
plt.ylabel("modularity Q")
plt.title("Girvan–Newman on karate club")
plt.show()

Run在浏览器中运行

首次加载 Python 环境约需 20–40 秒;可以修改参数后重新运行。

Girvan–Newman 算法