以下直接上代码:
def greedy_modularity_communities(G, weight=None):
N = len(G.nodes()) # 节点数
m = len(G.edges()) # 边数
q0 = 1.0 / (2.0*m)
label_for_node = dict((i, v) for i, v in enumerate(G.nodes())) # 将每一个节点都赋予其位置,例如第一个点标号为0, 第二个点标号为1,以此类推
# label_for_node = { 0:node1, 1:node2, 2:node3, ...}
node_for_label = dict((label_for_node[i], i) for i in range(N)) # 与上述定义的位置正相反
# node_for_label = { node1:0, node2:1, node3:2, ...}
k_for_label = G.degree(G.nodes(), weight=weight) # 每个节点的度
k = [k_for_label[label_for_node[i]] for i in range(N)] # 对于N个节点从0到N-1标号位置,各个位置上节点的度数
communities = dict((i, frozenset([i])) for i in range(N)) # 初始化社区划分
merges = [] # 初始化合并结果
partition = [[label_for_node[x] for x in c] for c in communities.values()] # 初始化分区方式
partition_id = [[x for x in c] for c in communities.values()] # 这一行个人认为无用
q_cnm = modularity(G, partition) # 初始化模块度
# 接下来初始化各个数据结构
# CNM Eq 8-9 (Eq 8 was missing a factor of 2 (from A_ij + A_ji)
# a[i]: i社区i中的边数对总边数的占比
# dq_dict[i][j]: 合并社区i, j所产生的dq增益度变化值字典,初始值将每一个点视作一个社区
# dq_heap[i][n] : dq变化值字典的堆表示,最大的排在前面,小的排在后面,便于取出最大值
# H[n]: (-dq, i, j) dq_ij中最大的n个值组成的向量,n的个数初始时为有边的节点的个数
a = [k[i]*q0 for i in range(N)] # a[i]组成的向量
dq_dict = dict(
(i, dict(
(j, 2*q0 - 2*k[i]*k[j]*q0*q0)