Merge lp:~taynaud/gephi/statistics-correction into lp:~gephi.team/gephi/0.8

Proposed by Thomas Aynaud
Status: Merged
Approved by: Sébastien Heymann
Approved revision: 2224
Merge reported by: Sébastien Heymann
Merged at revision: not available
Proposed branch: lp:~taynaud/gephi/statistics-correction
Merge into: lp:~gephi.team/gephi/0.8
Diff against target: 163 lines (+14/-39)
1 file modified
StatisticsPlugin/src/org/gephi/statistics/plugin/Modularity.java (+14/-39)
To merge this branch: bzr merge lp:~taynaud/gephi/statistics-correction
Reviewer Review Type Date Requested Status
Sébastien Heymann Approve
Review via email: mp+61108@code.launchpad.net

Description of the change

Correct a bug in modularity optimisation.

The Louvain algorithm study node one by one, and for each node :

remove it from its community
look for any neighboring community and select the one which maximizes modularity gain
put the node into this community.

The implemented algorithm was not removing the node from its community, resulting in a wrong gain computation. Now, the algorithm still not remove the node from its community (which would be slow with the current implementation) but compute the gain accurately.

There was also an issue with self loops counted twice.

To post a comment you must log in.
Revision history for this message
Sébastien Heymann (sebastien.heymann) :
review: Approve
Revision history for this message
Sébastien Heymann (sebastien.heymann) wrote :

Merged on rev 2222

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'StatisticsPlugin/src/org/gephi/statistics/plugin/Modularity.java'
2--- StatisticsPlugin/src/org/gephi/statistics/plugin/Modularity.java 2011-04-07 17:40:45 +0000
3+++ StatisticsPlugin/src/org/gephi/statistics/plugin/Modularity.java 2011-05-16 12:56:49 +0000
4@@ -96,6 +96,7 @@
5 int N;
6 HashMap<Integer, Community> invMap;
7
8+
9 CommunityStructure(HierarchicalUndirectedGraph hgraph) {
10 this.graph = hgraph;
11 N = hgraph.getNodeCount();
12@@ -116,9 +117,8 @@
13 Community hidden = new Community(structure);
14 hidden.nodes.add(index);
15 invMap.put(index, hidden);
16- communities.add(nodeCommunities[index]);
17+ communities.add(nodeCommunities[index]);
18 index++;
19-
20 if (isCanceled) {
21 return;
22 }
23@@ -140,7 +140,7 @@
24 nodeCommunities[node_index].connections.put(adjCom, 1);
25 nodeConnections[neighbor_index].put(nodeCommunities[node_index], 1);
26 nodeCommunities[neighbor_index].connections.put(nodeCommunities[node_index], 1);
27- graphWeightSum++;
28+ graphWeightSum++;//WARNING : may be an issue with self_loop
29 }
30
31 if (isCanceled) {
32@@ -275,8 +275,10 @@
33 for(Community adjCom : iter) {
34 int target = communities.indexOf(adjCom);
35 int weight = com.connections.get(adjCom);
36-
37- weightSum += weight;
38+ if(target == index)
39+ weightSum += 2*weight;
40+ else
41+ weightSum += weight;
42 ModEdge e = new ModEdge(index, target, weight);
43 newTopology[index].add(e);
44 }
45@@ -304,12 +306,10 @@
46 }
47
48 class Community {
49-
50 double weightSum;
51 CommunityStructure structure;
52 LinkedList<Integer> nodes;
53 HashMap<Community, Integer> connections;
54- Integer min;
55
56 public int size() {
57 return nodes.size();
58@@ -319,7 +319,6 @@
59 structure = com.structure;
60 connections = new HashMap<Community, Integer>();
61 nodes = new LinkedList<Integer>();
62- min = Integer.MAX_VALUE;
63 //mHidden = pCom.mHidden;
64 }
65
66@@ -332,15 +331,11 @@
67 public void seed(int node) {
68 nodes.add(node);
69 weightSum += structure.weights[node];
70- min = node;
71 }
72
73 public boolean add(int node) {
74 nodes.addLast(new Integer(node));
75 weightSum += structure.weights[node];
76- if (!isRandomized) {
77- min = Math.min(node, min);
78- }
79 return true;
80 }
81
82@@ -350,20 +345,8 @@
83 if (nodes.size() == 0) {
84 structure.communities.remove(this);
85 }
86- if (!isRandomized) {
87- if (node == min.intValue()) {
88- min = Integer.MAX_VALUE;
89- for (Integer other : nodes) {
90- min = Math.min(other, min);
91- }
92- }
93- }
94 return result;
95 }
96-
97- public int getMin() {
98- return min;
99- }
100 }
101
102 public void execute(GraphModel graphModel, AttributeModel attributeModel) {
103@@ -375,9 +358,7 @@
104 isCanceled = false;
105 Progress.start(progress);
106 Random rand = new Random();
107-
108 hgraph.readLock();
109-
110 structure = new CommunityStructure(hgraph);
111 if (isCanceled) {
112 hgraph.readUnlockAll();
113@@ -387,8 +368,6 @@
114 while (someChange) {
115 someChange = false;
116 boolean localChange = true;
117-
118-
119 while (localChange) {
120 localChange = false;
121 int start = 0;
122@@ -398,22 +377,16 @@
123 int step = 0;
124 for (int i = start; step < structure.N; i = (i + 1) % structure.N) {
125 step++;
126- double best = 0;
127- double current = q(i, structure.nodeCommunities[i]);
128+ double best = 0.;
129 Community bestCommunity = null;
130- int smallest = Integer.MAX_VALUE;
131+ Community nodecom = structure.nodeCommunities[i];
132 Set<Community> iter = structure.nodeConnections[i].keySet();
133 for(Community com : iter) {
134- double qValue = q(i, com) - current;
135+ double qValue = q(i, com);
136 if (qValue > best) {
137 best = qValue;
138 bestCommunity = com;
139- smallest = com.getMin();
140- } else if ((qValue == best) && (com.getMin() < smallest)) {
141- best = qValue;
142- bestCommunity = com;
143- smallest = com.getMin();
144- }
145+ }
146 }
147 if ((structure.nodeCommunities[i] != bestCommunity) && (bestCommunity != null)) {
148 structure.moveNodeTo(i, bestCommunity);
149@@ -518,11 +491,13 @@
150 }
151 double weightSum = community.weightSum;
152 double nodeWeight = structure.weights[node];
153- //double penalty = (nodeWeight * weightSum) / (2.0 * mStructure.graphWeightSum);
154 double qValue = edgesTo - (nodeWeight * weightSum) / (2.0 * structure.graphWeightSum);
155 if ((structure.nodeCommunities[node] == community) && (structure.nodeCommunities[node].size() > 1)) {
156 qValue = edgesTo - (nodeWeight * (weightSum - nodeWeight)) / (2.0 * structure.graphWeightSum);
157 }
158+ if ((structure.nodeCommunities[node] == community) && (structure.nodeCommunities[node].size() == 1)) {
159+ qValue = 0.;
160+ }
161 return qValue;
162 }
163 }

Subscribers

People subscribed via source and target branches