Skip to content

Commit 17d5beb

Browse files
Fix modularity when self loops exist (#487)
1 parent efa3ad5 commit 17d5beb

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

src/community/modularity.jl

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ julia> barbell = blockdiag(complete_graph(3), complete_graph(3));
4848
julia> add_edge!(barbell, 1, 4);
4949
5050
julia> modularity(barbell, [1, 1, 1, 2, 2, 2])
51-
0.35714285714285715
51+
0.3571428571428571
5252
5353
julia> modularity(barbell, [1, 1, 1, 2, 2, 2], γ=0.5)
5454
0.6071428571428571
@@ -90,14 +90,20 @@ function modularity(
9090
c2 = c[v]
9191
if c1 == c2
9292
Q += distmx[u, v]
93+
if u == v && !is_directed(g)
94+
#Since we do not look at each end in outer loop
95+
Q += distmx[u, v]
96+
end
9397
end
9498
kout[c1] += distmx[u, v]
9599
kin[c2] += distmx[u, v]
100+
if u == v && !is_directed(g)
101+
#Since we do not look at each end in outer loop
102+
kout[c1] += distmx[u, v]
103+
kin[c2] += distmx[u, v]
104+
end
96105
end
97106
end
98-
Q = Q * m
99-
@inbounds for i in 1:nc
100-
Q -= γ * kin[i] * kout[i]
101-
end
102-
return Q / m^2
107+
Q = Q/m - γ * sum(kin .* kout) / m^2
108+
return Q
103109
end

test/community/modularity.jl

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@
2424
@test isapprox(Q2, 0.6071428571428571, atol=1e-3)
2525
end
2626

27+
# Test with self loop
28+
add_edge!(barbell, 1, 1)
29+
for g in test_generic_graphs(barbell)
30+
Q = @inferred(modularity(g, c))
31+
@test isapprox(Q, 0.3671875, atol=1e-3)
32+
end
33+
2734
# 2. directed test cases
2835
triangle = SimpleDiGraph(3)
2936
add_edge!(triangle, 1, 2)
@@ -65,6 +72,20 @@
6572
Q = @inferred(modularity(g, c, distmx=d))
6673
@test isapprox(Q, 0.045454545454545456, atol=1e-3)
6774
end
75+
# Add self loop with weight 5
76+
add_edge!(barbell, 1, 1)
77+
d = [
78+
[5 1 1 0 0 0]
79+
[1 0 1 0 0 0]
80+
[1 1 0 1 0 0]
81+
[0 0 1 0 1 1]
82+
[0 0 0 1 0 1]
83+
[0 0 0 1 1 0]
84+
]
85+
for g in test_generic_graphs(barbell)
86+
Q = @inferred(modularity(g, c, distmx=d))
87+
@test isapprox(Q, 0.329861, atol=1e-3)
88+
end
6889

6990
# 3.2. directed and weighted test cases
7091
triangle = SimpleDiGraph(3)
@@ -73,12 +94,12 @@
7394
add_edge!(triangle, 3, 1)
7495

7596
barbell = blockdiag(triangle, triangle)
76-
add_edge!(barbell, 1, 4) # this edge has a weight of 5
97+
add_edge!(barbell, 3, 4) # this edge has a weight of 5
7798
c = [1, 1, 1, 2, 2, 2]
7899
d = [
79-
[0 1 0 5 0 0]
100+
[0 1 0 0 0 0]
80101
[0 0 1 0 0 0]
81-
[1 0 0 0 0 0]
102+
[1 0 0 5 0 0]
82103
[0 0 0 0 1 0]
83104
[0 0 0 0 0 1]
84105
[0 0 0 1 0 0]
@@ -87,4 +108,18 @@
87108
Q = @inferred(modularity(g, c, distmx=d))
88109
@test isapprox(Q, 0.1487603305785124, atol=1e-3)
89110
end
111+
# Add self loop with weight 5
112+
add_edge!(barbell, 1, 1)
113+
d = [
114+
[5 1 0 0 0 0]
115+
[0 0 1 0 0 0]
116+
[1 0 0 1 0 0]
117+
[0 0 0 0 1 0]
118+
[0 0 0 0 0 1]
119+
[0 0 0 1 0 0]
120+
]
121+
for g in test_generic_graphs(barbell)
122+
Q = @inferred(modularity(g, c, distmx=d))
123+
@test isapprox(Q, 0.333333333, atol=1e-3)
124+
end
90125
end

0 commit comments

Comments
 (0)