Skip to content

Commit e42d407

Browse files
author
cindeem
committed
Merge pull request #9 from cindeem/fix_newman
Fix newman_partion from creating empty partitions
2 parents 91fe832 + dcb6ca1 commit e42d407

File tree

2 files changed

+47
-17
lines changed

2 files changed

+47
-17
lines changed

brainx/modularity.py

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,13 +1270,20 @@ def simulated_annealing(g, p0=None, temperature = 50, temp_scaling = 0.995, tmin
12701270

12711271
def modularity_matrix(g):
12721272
"""Modularity matrix of the graph.
1273+
1274+
Parameters
1275+
----------
1276+
g : NetworkX graph
1277+
input graph
12731278
1274-
The eigenvector corresponding to the largest eigenvalue of the modularity
1275-
matrix is analyzed to assign clusters.
1276-
1279+
Returns
1280+
-------
1281+
B : numpy array
1282+
modularity matrix (graph laplacian)
1283+
12771284
"""
12781285
A = np.asarray(nx.adjacency_matrix(g))
1279-
k = np.sum(A, axis=0)
1286+
k = np.sum(A, axis=0) #vertex degree
12801287
M = np.sum(k) # 2x number of edges
12811288

12821289
return A - ((k * k[:, None]) / float(M))
@@ -1300,6 +1307,10 @@ def newman_partition(g, max_div=np.inf):
13001307
13011308
"""
13021309
A = np.asarray(nx.adjacency_matrix(g))
1310+
if not A.sum() == A.astype(bool).sum():
1311+
raise ValueError('Adjacency matrix is weighted, need binary matrix')
1312+
## add line to binarize adj_matrix if not binary
1313+
## warning?
13031314
k = np.sum(A, axis=0)
13041315
M = np.sum(A) # 2x number of edges
13051316
B = modularity_matrix(g)
@@ -1312,15 +1323,13 @@ def _divide_partition(p, max_div=np.inf):
13121323
----------
13131324
p : array of ints
13141325
Node labels.
1315-
B : ndarray
1316-
Modularity matrix.
1326+
max_div : int
1327+
maximum number of divisions (default np.inf)
13171328
13181329
Returns
13191330
-------
1320-
pp, qq : list of ints
1321-
Partitioning of node labels. If the partition is indivisible, then
1322-
only `pp` is returned.
1323-
1331+
out : list of ints
1332+
Partitioning of node labels.
13241333
"""
13251334
p = np.asarray(p)
13261335

@@ -1329,13 +1338,11 @@ def _divide_partition(p, max_div=np.inf):
13291338

13301339
# Construct the subgraph modularity matrix
13311340
A_ = A[p, p[:, None]]
1332-
k_ = np.sum(A_, axis=0)
1333-
M_ = np.sum(k_)
1334-
1335-
B_ = B[p, p[:, None]]
1336-
B_ = B_ - np.diag(k_ - k[p] * M_ / float(M))
1337-
1338-
# w, v = nl.eigh(B_)
1341+
graph_A_ = nx.from_numpy_matrix(A_, nx.Graph())
1342+
# make sure partition has edges
1343+
if graph_A_.number_of_edges() <= 1:
1344+
return [p]
1345+
B_ = modularity_matrix(graph_A_)
13391346
w, v = sl.eigh(B_, eigvals=(len(B_) - 2, len(B_) - 1))
13401347

13411348
# Find the maximum eigenvalue of the modularity matrix
@@ -1349,6 +1356,11 @@ def _divide_partition(p, max_div=np.inf):
13491356
# to nodes in the first partition and 1 for nodes in the second
13501357
v_max = v[:, n]
13511358
mask = (v_max < 0)
1359+
# if the mask is all True or all False, this will not split the partition
1360+
# and would create an empty partition
1361+
# catch by checking max vector contains pos and neg values
1362+
if np.abs(v_max.sum()) == np.abs(v_max).sum():
1363+
return [p]
13521364
s = np.ones_like(v_max)
13531365
s[mask] = -1
13541366

brainx/tests/test_modularity.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,24 @@ def test_badindex_graphpartition():
795795
{0:set(g.nodes()[:-1])})
796796
npt.assert_raises(TypeError, mod.GraphPartition, g, g.nodes())
797797

798+
def test_newman_partition():
799+
""" Test Newman Partition function """
800+
tmpmat = np.random.random((10,10))
801+
tmpmat[tmpmat < .5] = 0
802+
graph = nx.from_numpy_matrix(tmpmat, nx.Graph(weighted = False))
803+
npt.assert_raises(ValueError, mod.newman_partition, graph)
804+
tmpmat[:] = 0
805+
# test that no edges raises error (from GraphPartition)
806+
graph = nx.from_numpy_matrix(tmpmat, nx.Graph(weighted = False))
807+
npt.assert_raises(ValueError, mod.newman_partition, graph)
808+
tmpmat[:] = 1
809+
util.fill_diagonal(tmpmat, 0)
810+
graph = nx.from_numpy_matrix(tmpmat, nx.Graph(weighted=False))
811+
part = mod.newman_partition(graph)
812+
## if all edges are connected expect only one partition
813+
expected_part = {0: set([0,1,2,3,4,5,6,7,8,9])}
814+
nt.assert_equal(part.index, expected_part)
815+
798816

799817
if __name__ == "__main__":
800818
npt.run_module_suite()

0 commit comments

Comments
 (0)