Repository URL to install this package:
Version:
3.2.1 ▾
|
import pytest
import networkx as nx
from networkx.algorithms.community import (
greedy_modularity_communities,
naive_greedy_modularity_communities,
)
@pytest.mark.parametrize(
"func", (greedy_modularity_communities, naive_greedy_modularity_communities)
)
def test_modularity_communities(func):
G = nx.karate_club_graph()
john_a = frozenset(
[8, 14, 15, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33]
)
mr_hi = frozenset([0, 4, 5, 6, 10, 11, 16, 19])
overlap = frozenset([1, 2, 3, 7, 9, 12, 13, 17, 21])
expected = {john_a, overlap, mr_hi}
assert set(func(G, weight=None)) == expected
@pytest.mark.parametrize(
"func", (greedy_modularity_communities, naive_greedy_modularity_communities)
)
def test_modularity_communities_categorical_labels(func):
# Using other than 0-starting contiguous integers as node-labels.
G = nx.Graph(
[
("a", "b"),
("a", "c"),
("b", "c"),
("b", "d"), # inter-community edge
("d", "e"),
("d", "f"),
("d", "g"),
("f", "g"),
("d", "e"),
("f", "e"),
]
)
expected = {frozenset({"f", "g", "e", "d"}), frozenset({"a", "b", "c"})}
assert set(func(G)) == expected
def test_greedy_modularity_communities_components():
# Test for gh-5530
G = nx.Graph([(0, 1), (2, 3), (4, 5), (5, 6)])
# usual case with 3 components
assert greedy_modularity_communities(G) == [{4, 5, 6}, {0, 1}, {2, 3}]
# best_n can make the algorithm continue even when modularity goes down
assert greedy_modularity_communities(G, best_n=3) == [{4, 5, 6}, {0, 1}, {2, 3}]
assert greedy_modularity_communities(G, best_n=2) == [{0, 1, 4, 5, 6}, {2, 3}]
assert greedy_modularity_communities(G, best_n=1) == [{0, 1, 2, 3, 4, 5, 6}]
def test_greedy_modularity_communities_relabeled():
# Test for gh-4966
G = nx.balanced_tree(2, 2)
mapping = {0: "a", 1: "b", 2: "c", 3: "d", 4: "e", 5: "f", 6: "g", 7: "h"}
G = nx.relabel_nodes(G, mapping)
expected = [frozenset({"e", "d", "a", "b"}), frozenset({"c", "f", "g"})]
assert greedy_modularity_communities(G) == expected
def test_greedy_modularity_communities_directed():
G = nx.DiGraph(
[
("a", "b"),
("a", "c"),
("b", "c"),
("b", "d"), # inter-community edge
("d", "e"),
("d", "f"),
("d", "g"),
("f", "g"),
("d", "e"),
("f", "e"),
]
)
expected = [frozenset({"f", "g", "e", "d"}), frozenset({"a", "b", "c"})]
assert greedy_modularity_communities(G) == expected
# with loops
G = nx.DiGraph()
G.add_edges_from(
[(1, 1), (1, 2), (1, 3), (2, 3), (1, 4), (4, 4), (5, 5), (4, 5), (4, 6), (5, 6)]
)
expected = [frozenset({1, 2, 3}), frozenset({4, 5, 6})]
assert greedy_modularity_communities(G) == expected
@pytest.mark.parametrize(
"func", (greedy_modularity_communities, naive_greedy_modularity_communities)
)
def test_modularity_communities_weighted(func):
G = nx.balanced_tree(2, 3)
for a, b in G.edges:
if ((a == 1) or (a == 2)) and (b != 0):
G[a][b]["weight"] = 10.0
else:
G[a][b]["weight"] = 1.0
expected = [{0, 1, 3, 4, 7, 8, 9, 10}, {2, 5, 6, 11, 12, 13, 14}]
assert func(G, weight="weight") == expected
assert func(G, weight="weight", resolution=0.9) == expected
assert func(G, weight="weight", resolution=0.3) == expected
assert func(G, weight="weight", resolution=1.1) != expected
def test_modularity_communities_floating_point():
# check for floating point error when used as key in the mapped_queue dict.
# Test for gh-4992 and gh-5000
G = nx.Graph()
G.add_weighted_edges_from(
[(0, 1, 12), (1, 4, 71), (2, 3, 15), (2, 4, 10), (3, 6, 13)]
)
expected = [{0, 1, 4}, {2, 3, 6}]
assert greedy_modularity_communities(G, weight="weight") == expected
assert (
greedy_modularity_communities(G, weight="weight", resolution=0.99) == expected
)
def test_modularity_communities_directed_weighted():
G = nx.DiGraph()
G.add_weighted_edges_from(
[
(1, 2, 5),
(1, 3, 3),
(2, 3, 6),
(2, 6, 1),
(1, 4, 1),
(4, 5, 3),
(4, 6, 7),
(5, 6, 2),
(5, 7, 5),
(5, 8, 4),
(6, 8, 3),
]
)
expected = [frozenset({4, 5, 6, 7, 8}), frozenset({1, 2, 3})]
assert greedy_modularity_communities(G, weight="weight") == expected
# A large weight of the edge (2, 6) causes 6 to change group, even if it shares
# only one connection with the new group and 3 with the old one.
G[2][6]["weight"] = 20
expected = [frozenset({1, 2, 3, 6}), frozenset({4, 5, 7, 8})]
assert greedy_modularity_communities(G, weight="weight") == expected
def test_greedy_modularity_communities_multigraph():
G = nx.MultiGraph()
G.add_edges_from(
[
(1, 2),
(1, 2),
(1, 3),
(2, 3),
(1, 4),
(2, 4),
(4, 5),
(5, 6),
(5, 7),
(5, 7),
(6, 7),
(7, 8),
(5, 8),
]
)
expected = [frozenset({1, 2, 3, 4}), frozenset({5, 6, 7, 8})]
assert greedy_modularity_communities(G) == expected
# Converting (4, 5) into a multi-edge causes node 4 to change group.
G.add_edge(4, 5)
expected = [frozenset({4, 5, 6, 7, 8}), frozenset({1, 2, 3})]
assert greedy_modularity_communities(G) == expected
def test_greedy_modularity_communities_multigraph_weighted():
G = nx.MultiGraph()
G.add_weighted_edges_from(
[
(1, 2, 5),
(1, 2, 3),
(1, 3, 6),
(1, 3, 6),
(2, 3, 4),
(1, 4, 1),
(1, 4, 1),
(2, 4, 3),
(2, 4, 3),
(4, 5, 1),
(5, 6, 3),
(5, 6, 7),
(5, 6, 4),
(5, 7, 9),
(5, 7, 9),
(6, 7, 8),
(7, 8, 2),
(7, 8, 2),
(5, 8, 6),
(5, 8, 6),
]
)
expected = [frozenset({1, 2, 3, 4}), frozenset({5, 6, 7, 8})]
assert greedy_modularity_communities(G, weight="weight") == expected
# Adding multi-edge (4, 5, 16) causes node 4 to change group.
G.add_edge(4, 5, weight=16)
expected = [frozenset({4, 5, 6, 7, 8}), frozenset({1, 2, 3})]
assert greedy_modularity_communities(G, weight="weight") == expected
# Increasing the weight of edge (1, 4) causes node 4 to return to the former group.
G[1][4][1]["weight"] = 3
expected = [frozenset({1, 2, 3, 4}), frozenset({5, 6, 7, 8})]
assert greedy_modularity_communities(G, weight="weight") == expected
def test_greed_modularity_communities_multidigraph():
G = nx.MultiDiGraph()
G.add_edges_from(
[
(1, 2),
(1, 2),
(3, 1),
(2, 3),
(2, 3),
(3, 2),
(1, 4),
(2, 4),
(4, 2),
(4, 5),
(5, 6),
(5, 6),
(6, 5),
(5, 7),
(6, 7),
(7, 8),
(5, 8),
(8, 4),
]
)
expected = [frozenset({1, 2, 3, 4}), frozenset({5, 6, 7, 8})]
assert greedy_modularity_communities(G, weight="weight") == expected
def test_greed_modularity_communities_multidigraph_weighted():
G = nx.MultiDiGraph()
G.add_weighted_edges_from(
[
(1, 2, 5),
(1, 2, 3),
(3, 1, 6),
(1, 3, 6),
(3, 2, 4),
(1, 4, 2),
(1, 4, 5),
(2, 4, 3),
(3, 2, 8),
(4, 2, 3),
(4, 3, 5),
(4, 5, 2),
(5, 6, 3),
(5, 6, 7),
(6, 5, 4),
(5, 7, 9),
(5, 7, 9),
(7, 6, 8),
(7, 8, 2),
(8, 7, 2),
(5, 8, 6),
(5, 8, 6),
]
)
expected = [frozenset({1, 2, 3, 4}), frozenset({5, 6, 7, 8})]
assert greedy_modularity_communities(G, weight="weight") == expected
def test_resolution_parameter_impact():
G = nx.barbell_graph(5, 3)
gamma = 1
expected = [frozenset(range(5)), frozenset(range(8, 13)), frozenset(range(5, 8))]
assert greedy_modularity_communities(G, resolution=gamma) == expected
assert naive_greedy_modularity_communities(G, resolution=gamma) == expected
gamma = 2.5
expected = [{0, 1, 2, 3}, {9, 10, 11, 12}, {5, 6, 7}, {4}, {8}]
assert greedy_modularity_communities(G, resolution=gamma) == expected
assert naive_greedy_modularity_communities(G, resolution=gamma) == expected
gamma = 0.3
expected = [frozenset(range(8)), frozenset(range(8, 13))]
assert greedy_modularity_communities(G, resolution=gamma) == expected
assert naive_greedy_modularity_communities(G, resolution=gamma) == expected
def test_cutoff_parameter():
G = nx.circular_ladder_graph(4)
# No aggregation:
expected = [{k} for k in range(8)]
assert greedy_modularity_communities(G, cutoff=8) == expected
# Aggregation to half order (number of nodes)
expected = [{k, k + 1} for k in range(0, 8, 2)]
assert greedy_modularity_communities(G, cutoff=4) == expected
# Default aggregation case (here, 2 communities emerge)
expected = [frozenset(range(4)), frozenset(range(4, 8))]
assert greedy_modularity_communities(G, cutoff=1) == expected
def test_best_n():
G = nx.barbell_graph(5, 3)
# Same result as without enforcing cutoff:
best_n = 3
expected = [frozenset(range(5)), frozenset(range(8, 13)), frozenset(range(5, 8))]
assert greedy_modularity_communities(G, best_n=best_n) == expected
# One additional merging step:
best_n = 2
expected = [frozenset(range(8)), frozenset(range(8, 13))]
assert greedy_modularity_communities(G, best_n=best_n) == expected
# Two additional merging steps:
best_n = 1
expected = [frozenset(range(13))]
assert greedy_modularity_communities(G, best_n=best_n) == expected