2
# Copyright (C) 2011 by
3
# Conrad Lee <conradlee@gmail.com>
4
# Aric Hagberg <hagberg@lanl.gov>
7
from collections import defaultdict
9
__author__ = """\n""".join(['Conrad Lee <conradlee@gmail.com>',
10
'Aric Hagberg <aric.hagberg@gmail.com>'])
11
__all__ = ['k_clique_communities']
13
def k_clique_communities(G, k, cliques=None):
14
"""Find k-clique communities in graph using the percolation method.
16
A k-clique community is the union of all cliques of size k that
17
can be reached through adjacent (sharing k-1 nodes) k-cliques.
24
Size of smallest clique
26
cliques: list or generator
27
Precomputed cliques (use networkx.find_cliques(G))
31
Yields sets of nodes, one for each k-clique community.
35
>>> G = nx.complete_graph(5)
36
>>> K5 = nx.convert_node_labels_to_integers(G,first_label=2)
37
>>> G.add_edges_from(K5.edges())
38
>>> c = list(nx.k_clique_communities(G, 4))
41
>>> list(nx.k_clique_communities(G, 6))
46
.. [1] Gergely Palla, Imre Derényi, Illés Farkas1, and Tamás Vicsek,
47
Uncovering the overlapping community structure of complex networks
48
in nature and society Nature 435, 814-818, 2005,
49
doi:10.1038/nature03607
52
raise nx.NetworkXError("k=%d, k must be greater than 1."%k)
54
cliques = nx.find_cliques(G)
55
cliques = [frozenset(c) for c in cliques if len(c) >= k]
57
# First index which nodes are in which cliques
58
membership_dict = defaultdict(list)
59
for clique in cliques:
61
membership_dict[node].append(clique)
63
# For each clique, see which adjacent cliques percolate
64
perc_graph = nx.Graph()
65
perc_graph.add_nodes_from(cliques)
66
for clique in cliques:
67
for adj_clique in _get_adjacent_cliques(clique, membership_dict):
68
if len(clique.intersection(adj_clique)) >= (k - 1):
69
perc_graph.add_edge(clique, adj_clique)
71
# Connected components of clique graph with perc edges
72
# are the percolated cliques
73
for component in nx.connected_components(perc_graph):
74
yield(frozenset.union(*component))
76
def _get_adjacent_cliques(clique, membership_dict):
77
adjacent_cliques = set()
79
for adj_clique in membership_dict[n]:
80
if clique != adj_clique:
81
adjacent_cliques.add(adj_clique)
82
return adjacent_cliques