Skip to content
This repository was archived by the owner on Apr 22, 2020. It is now read-only.

Commit 238a19a

Browse files
committed
3.4 return modularities louvain (#799)
* modularities * fix batching of writes with low node count * formatting
1 parent c4cafb6 commit 238a19a

File tree

6 files changed

+53
-10
lines changed

6 files changed

+53
-10
lines changed

algo/src/main/java/org/neo4j/graphalgo/LouvainProc.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ public Stream<LouvainResult> louvain(
102102
} else {
103103
louvain.compute(configuration.getIterations(10), configuration.get("innerIterations", 10));
104104
}
105-
builder.withIterations(louvain.getLevel()).withCommunityCount(louvain.getCommunityCount());
105+
builder.withIterations(louvain.getLevel())
106+
.withCommunityCount(louvain.getCommunityCount())
107+
.withModularities(louvain.getModularities())
108+
.withFinalModularity(louvain.getFinalModularity());
106109
}
107110

108111
if (configuration.isWriteFlag()) {

algo/src/main/java/org/neo4j/graphalgo/impl/louvain/Louvain.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public class Louvain extends Algorithm<Louvain> {
6060
private ProgressLogger progressLogger;
6161
private TerminationFlag terminationFlag;
6262
private int[] communities;
63+
private double[] modularities;
6364
private int[][] dendrogram;
6465
private double[] nodeWeights;
6566
private Graph root;
@@ -86,6 +87,7 @@ public Louvain compute(int maxLevel, int maxIterations) {
8687
Graph graph = this.root;
8788
// result arrays
8889
dendrogram = new int[maxLevel][];
90+
modularities = new double[maxLevel];
8991
int nodeCount = rootNodeCount;
9092
for (level = 0; level < maxLevel; level++) {
9193
// start modularity optimization
@@ -112,6 +114,7 @@ public Louvain compute(int maxLevel, int maxIterations) {
112114
}
113115
nodeCount = communityCount;
114116
dendrogram[level] = rebuildCommunityStructure(communityIds);
117+
modularities[level] = modularityOptimization.getModularity();
115118
graph = rebuildGraph(graph, communityIds, communityCount);
116119
}
117120
dendrogram = Arrays.copyOf(dendrogram, level);
@@ -132,6 +135,7 @@ public Louvain compute(WeightMapping communityMap, int maxLevel, int maxIteratio
132135
Graph graph = rebuildGraph(this.root, communities, nodeCount);
133136
// result arrays
134137
dendrogram = new int[maxLevel][];
138+
modularities = new double[maxLevel];
135139

136140
for (level = 0; level < maxLevel; level++) {
137141
// start modularity optimization
@@ -158,6 +162,7 @@ public Louvain compute(WeightMapping communityMap, int maxLevel, int maxIteratio
158162
}
159163
nodeCount = communityCount;
160164
dendrogram[level] = rebuildCommunityStructure(communityIds);
165+
modularities[level] = modularityOptimization.getModularity();
161166
graph = rebuildGraph(graph, communityIds, communityCount);
162167
}
163168
dendrogram = Arrays.copyOf(dendrogram, level);
@@ -232,6 +237,14 @@ public int[][] getDendrogram() {
232237
return dendrogram;
233238
}
234239

240+
public double[] getModularities() {
241+
return Arrays.copyOfRange(modularities, 0, level);
242+
}
243+
244+
public double getFinalModularity() {
245+
return modularities[level-1];
246+
}
247+
235248
/**
236249
* number of outer iterations
237250
*

algo/src/main/java/org/neo4j/graphalgo/impl/louvain/LouvainCommunityExporter.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
/**
22
* Copyright (c) 2017 "Neo4j, Inc." <http://neo4j.com>
3-
*
3+
* <p>
44
* This file is part of Neo4j Graph Algorithms <http://github.com/neo4j-contrib/neo4j-graph-algorithms>.
5-
*
5+
* <p>
66
* Neo4j Graph Algorithms is free software: you can redistribute it and/or modify
77
* it under the terms of the GNU General Public License as published by
88
* the Free Software Foundation, either version 3 of the License, or
99
* (at your option) any later version.
10-
*
10+
* <p>
1111
* This program is distributed in the hope that it will be useful,
1212
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1313
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414
* GNU General Public License for more details.
15-
*
15+
* <p>
1616
* You should have received a copy of the GNU General Public License
1717
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
*/
@@ -93,7 +93,7 @@ public void run() {
9393
private void writeEverything() {
9494
acceptInTransaction(statement -> {
9595
final Write dataWriteOperations = statement.dataWrite();
96-
for(PrimitiveIntIterator it = iterable.iterator(); it.hasNext(); ) {
96+
for (PrimitiveIntIterator it = iterable.iterator(); it.hasNext(); ) {
9797
final int id = it.next();
9898
// build int array
9999
final int[] data = new int[allCommunities.length];
@@ -121,7 +121,7 @@ private void writeEverything() {
121121
private void onlyWriteFinalCommunities() {
122122
acceptInTransaction(statement -> {
123123
final Write dataWriteOperations = statement.dataWrite();
124-
for(PrimitiveIntIterator it = iterable.iterator(); it.hasNext(); ) {
124+
for (PrimitiveIntIterator it = iterable.iterator(); it.hasNext(); ) {
125125
final int id = it.next();
126126

127127
dataWriteOperations.nodeSetProperty(

algo/src/main/java/org/neo4j/graphalgo/results/LouvainResult.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
*/
1919
package org.neo4j.graphalgo.results;
2020

21+
import java.util.ArrayList;
22+
import java.util.List;
23+
2124
/**
2225
* @author mknblch
2326
*/
@@ -29,14 +32,23 @@ public class LouvainResult {
2932
public final long nodes;
3033
public final long iterations;
3134
public final long communityCount;
35+
public final List<Double> modularities;
36+
public final double modularity;
3237

33-
private LouvainResult(long loadMillis, long computeMillis, long writeMillis, long nodes, long iterations, long communityCount) {
38+
private LouvainResult(long loadMillis, long computeMillis, long writeMillis, long nodes, long iterations,
39+
long communityCount, double[] modularities, double modularity) {
3440
this.loadMillis = loadMillis;
3541
this.computeMillis = computeMillis;
3642
this.writeMillis = writeMillis;
3743
this.nodes = nodes;
3844
this.iterations = iterations;
3945
this.communityCount = communityCount;
46+
47+
this.modularities = new ArrayList<>(modularities.length);
48+
for (double mod : modularities) this.modularities.add(mod);
49+
50+
51+
this.modularity = modularity;
4052
}
4153

4254
public static Builder builder() {
@@ -48,6 +60,8 @@ public static class Builder extends AbstractResultBuilder<LouvainResult> {
4860
private long nodes = 0;
4961
private long communityCount = 0;
5062
private long iterations = 1;
63+
private double[] modularities = new double[]{};
64+
private double modularity = -1.0;
5165

5266
public Builder withIterations(long iterations) {
5367
this.iterations = iterations;
@@ -64,8 +78,19 @@ public Builder withNodeCount(long nodes) {
6478
return this;
6579
}
6680

81+
public Builder withModularities(double[] modularities) {
82+
this.modularities = modularities;
83+
return this;
84+
}
85+
86+
public Builder withFinalModularity(double modularity) {
87+
this.modularity = modularity;
88+
return this;
89+
}
90+
6791
public LouvainResult build() {
68-
return new LouvainResult(loadDuration, evalDuration, writeDuration, nodes, iterations, communityCount);
92+
return new LouvainResult(loadDuration, evalDuration, writeDuration, nodes, iterations, communityCount,
93+
modularities, modularity);
6994
}
7095
}
7196
}

core/src/main/java/org/neo4j/graphalgo/core/utils/ParallelUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static Collection<PrimitiveIntIterable> batchIterables(int concurrency, i
5353
if (concurrency <= 0) {
5454
throw new IllegalArgumentException("concurrency must be > 0");
5555
}
56-
final int batchSize = nodeCount / concurrency;
56+
final int batchSize = Math.max(1, nodeCount / concurrency);
5757
int numberOfBatches = ParallelUtil.threadSize(batchSize, nodeCount);
5858
if (numberOfBatches == 1) {
5959
return Collections.singleton(new IdMap.IdIterable(0, nodeCount));

tests/src/test/java/org/neo4j/graphalgo/impl/LouvainMultiLevelTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,7 @@ public void testComplex() throws Exception {
140140

141141
assertArrayEquals(new int[]{0, 0, 0, 1, 1, 1, 2, 2, 2}, dendogram[0]);
142142
assertArrayEquals(new int[]{0, 0, 0, 1, 1, 1, 2, 2, 2}, algorithm.getCommunityIds());
143+
assertEquals(0.53, algorithm.getFinalModularity(), 0.01);
144+
assertArrayEquals(new double[]{0.53}, algorithm.getModularities(), 0.01);
143145
}
144146
}

0 commit comments

Comments
 (0)