Skip to content

Commit bfc2956

Browse files
author
shogo-ma
committed
remove comment
1 parent 7a1f637 commit bfc2956

File tree

1 file changed

+51
-44
lines changed

1 file changed

+51
-44
lines changed

pylouvain.py

Lines changed: 51 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import sys
55
import copy
66

7-
from itertools import combinations
87
from itertools import permutations
98
from collections import defaultdict
109

@@ -24,90 +23,98 @@ def run(cls, graph):
2423
node2com, edge_weights = cls._setNode2Com(graph)
2524
all_edge_weights = graph.size(weight="weight")
2625

27-
node2com = cls._runInitFirstPhase(node2com, edge_weights, all_edge_weights, graph)
28-
node2coms = [node2com]
26+
node2com = cls._runFirstPhase(node2com, edge_weights)
2927
cls.show(node2com)
30-
print()
3128

29+
partition = copy.deepcopy(node2com)
3230
new_node2com, new_edge_weights = cls._runSecondPhase(node2com, edge_weights)
33-
node2coms.append(new_node2com)
3431
cls.show(new_node2com)
35-
print()
3632

3733
while True:
3834
new_node2com = cls._runFirstPhase(new_node2com, new_edge_weights)
39-
node2coms.append(copy.deepcopy(new_node2com))
35+
partition = cls._updatePartition(new_node2com, partition)
4036
_new_node2com, _new_edge_weights = cls._runSecondPhase(new_node2com, new_edge_weights)
41-
sys.exit()
37+
if new_node2com == _new_node2com:
38+
break
39+
return partition
40+
41+
@classmethod
42+
def computeModularity(cls):
43+
pass
4244

4345
@classmethod
44-
def _runInitFirstPhase(cls, node2com, edge_weights, all_edge_weights, graph):
46+
def _updatePartition(cls, new_node2com, partition):
47+
# new_node2com : {'古いcom_id' : "新しいcom_id"}
48+
reverse_partition = {v:k for k,v in partition.items()}
49+
for old_com_id, new_com_id in new_node2com.items():
50+
partition[reverse_partition[old_com_id]] = new_com_id
51+
return partition
52+
53+
@classmethod
54+
def _runFirstPhase(cls, node2com, edge_weights):
55+
all_edge_weights = sum([weight for start in edge_weights.keys() for end, weight in edge_weights[start].items()]) / 2
4556
status = True
4657
while status:
47-
print(sorted(graph.nodes()))
4858
statuses = []
49-
for node in sorted(graph.nodes()):
59+
for node in sorted(list(node2com.keys())):
5060
statuses = []
5161
com_id = node2com[node]
52-
neigh_nodes = list(graph[node].keys())
62+
neigh_nodes = sorted([edge[0] for edge in cls.getNeighborNodes(node, edge_weights)])
5363

5464
max_delta = 0.
5565
max_com_id = com_id
5666
max_n = None
67+
communities = {}
5768
for neigh_node in sorted(neigh_nodes):
5869
node2com_copy = copy.deepcopy(node2com)
70+
if node2com_copy[neigh_node] in communities:
71+
continue
72+
communities[node2com_copy[neigh_node]] = 1
5973
node2com_copy[node] = node2com_copy[neigh_node]
6074

6175
# 隣接クラスタに移動した際のModularityの差分
62-
delta_q = 2 * cls.getNodeWeightInCluster(node, node2com_copy, edge_weights, graph) - cls.getTotWeight(node, node2com_copy, edge_weights) * cls.getNodeWeights(node, edge_weights) / all_edge_weights
63-
print("neighbor_id: {}, k_i_in: {}, tot: {}, k_i: {}, max_delta: {}".format(neigh_node,
64-
cls.getNodeWeightInCluster(node, node2com_copy, edge_weights, graph),
65-
cls.getTotWeight(node, node2com_copy, edge_weights),
66-
cls.getNodeWeights(node, edge_weights),
76+
delta_q = 2 * cls.getNodeWeightInCluster(node, node2com_copy, edge_weights) - cls.getTotWeight(node, node2com_copy, edge_weights) * cls.getNodeWeights(node, edge_weights) / all_edge_weights
77+
# print("neighbor_id: {}, k_i_in: {}, tot: {}, k_i: {}, max_delta: {}".format(neigh_node,
78+
# cls.getNodeWeightInCluster(node, node2com_copy, edge_weights),
79+
# cls.getTotWeight(node, node2com_copy, edge_weights),
80+
# cls.getNodeWeights(node, edge_weights),
6781
delta_q))
6882

6983
if delta_q > max_delta:
7084
max_delta = delta_q
7185
max_com_id = node2com_copy[neigh_node]
7286
max_n = copy.deepcopy(node2com_copy)
7387

74-
print("k_i_in: {}, tot: {}, k_i: {}, max_delta: {}".format(cls.getNodeWeightInCluster(node, node2com_copy, edge_weights, graph),
75-
cls.getTotWeight(node, max_n, edge_weights),
76-
cls.getNodeWeights(node, edge_weights),
77-
max_delta))
78-
print(node2com, max_com_id)
88+
#print("k_i_in: {}, tot: {}, k_i: {}, max_delta: {}".format(cls.getNodeWeightInCluster(node, node2com_copy, edge_weights),
89+
# cls.getTotWeight(node, max_n, edge_weights),
90+
# cls.getNodeWeights(node, edge_weights),
91+
# max_delta))
92+
#print(node2com, max_com_id)
7993
node2com[node] = max_com_id
80-
print(com_id, max_com_id)
94+
#print(com_id, max_com_id)
8195
statuses.append(com_id != max_com_id)
8296

8397
if sum(statuses) == 0:
8498
break
8599

86100
return node2com
87101

88-
@classmethod
89-
def _runFirstPhase(cls, node2com, all_edge_weights):
90-
pass
91-
92102
@classmethod
93103
def _runSecondPhase(cls, node2com, edge_weights):
94-
# クラスタ内のノードの一括集約
95-
# 1. cluster内のノードを一括集約. cluster内のエッジの重みの総和を2乗して,自身へのエッジとする
96-
# 2. cluster間ノードはcluster内のノードが別のクラスタへ接続していたノードへのエッジの総和とする
97104
com2node = defaultdict(list)
98105

99106
new_node2com = {}
100107
new_edge_weights = defaultdict(lambda : defaultdict(float))
101108

102-
# ノードの集約
103109
for node, com_id in node2com.items():
104110
com2node[com_id].append(node)
105111
if com_id not in new_node2com:
106112
new_node2com[com_id] = com_id
107113

108-
# cluster間エッジの重み
109114
nodes = list(node2com.keys())
110115
for edge in permutations(nodes, 2):
116+
if edge[0] not in edge_weights: continue
117+
if edge[1] not in edge_weights[edge[0]]: continue
111118
new_edge_weights[new_node2com[node2com[edge[0]]]][new_node2com[node2com[edge[1]]]] += edge_weights[edge[0]][edge[1]]
112119

113120
for node in new_node2com.keys():
@@ -117,7 +124,6 @@ def _runSecondPhase(cls, node2com, edge_weights):
117124

118125
@classmethod
119126
def getTotWeight(cls, node, node2com, edge_weights):
120-
# 街灯ノードを除いたクラスタの隣接エッジの総和
121127
nodes = []
122128
for n, com_id in node2com.items():
123129
if com_id == node2com[node] and node != n:
@@ -129,21 +135,22 @@ def getTotWeight(cls, node, node2com, edge_weights):
129135
return weight
130136

131137
@classmethod
132-
def getNodeWeightInCluster(cls, node, node2com, edge_weights, graph):
133-
# nodeに接続しているcluster内のedgeの重みの総和
134-
neigh_nodes = graph[node].items()
138+
def getNeighborNodes(cls, node, edge_weights):
139+
if node not in edge_weights:
140+
return 0
141+
return list(edge_weights[node].items())
142+
143+
@classmethod
144+
def getNodeWeightInCluster(cls, node, node2com, edge_weights):
145+
neigh_nodes = cls.getNeighborNodes(node, edge_weights)
135146
node_com = node2com[node]
136147
weights = 0.
137148
for neigh_node in neigh_nodes:
138149
if node_com == node2com[neigh_node[0]]:
139-
weights += neigh_node[1]["weight"]
150+
weights += neigh_node[1]
140151

141152
return weights
142-
143-
@classmethod
144-
def _getNodeWeights(cls, node, graph):
145-
return graph.degree(node, weight="weight")
146-
153+
147154
@classmethod
148155
def getNodeWeights(cls, node, edge_weights):
149156
return sum([weight for weight in edge_weights[node].values()])
@@ -152,11 +159,11 @@ def getNodeWeights(cls, node, edge_weights):
152159
def _setNode2Com(cls, graph):
153160
# initialize
154161
node2com = {}
155-
edge_weights = defaultdict(lambda : defaultdict(float))
162+
edge_weights = {}
156163
for idx, node in enumerate(sorted(graph.nodes())):
157164
node2com[node] = idx
165+
edge_weights[node] = {}
158166
for edge in graph[node].items():
159-
# edge = (node, {"weight" : edge_weight})
160167
edge_weights[node][edge[0]] = edge[1]["weight"]
161168

162169
return node2com, edge_weights

0 commit comments

Comments
 (0)