1"""Functions for computing large cliques and maximum independent sets."""
2
3import networkx as nx
4from networkx.algorithms.approximation import ramsey
5from networkx.utils import not_implemented_for
6
7__all__ = [
8 "clique_removal",
9 "max_clique",
10 "large_clique_size",
11 "maximum_independent_set",
12]
13
14
15@not_implemented_for("directed")
16@not_implemented_for("multigraph")
17@nx._dispatchable
18def maximum_independent_set(G):
19 """Returns an approximate maximum independent set.
20
21 Independent set or stable set is a set of vertices in a graph, no two of
22 which are adjacent. That is, it is a set I of vertices such that for every
23 two vertices in I, there is no edge connecting the two. Equivalently, each
24 edge in the graph has at most one endpoint in I. The size of an independent
25 set is the number of vertices it contains [1]_.
26
27 A maximum independent set is a largest independent set for a given graph G
28 and its size is denoted $\\alpha(G)$. The problem of finding such a set is called
29 the maximum independent set problem and is an NP-hard optimization problem.
30 As such, it is unlikely that there exists an efficient algorithm for finding
31 a maximum independent set of a graph.
32
33 The Independent Set algorithm is based on [2]_.
34
35 Parameters
36 ----------
37 G : NetworkX graph
38 Undirected graph
39
40 Returns
41 -------
42 iset : Set
43 The apx-maximum independent set
44
45 Examples
46 --------
47 >>> G = nx.path_graph(10)
48 >>> nx.approximation.maximum_independent_set(G)
49 {0, 2, 4, 6, 9}
50
51 Raises
52 ------
53 NetworkXNotImplemented
54 If the graph is directed or is a multigraph.
55
56 Notes
57 -----
58 Finds the $O(|V|/(log|V|)^2)$ apx of independent set in the worst case.
59
60 References
61 ----------
62 .. [1] `Wikipedia: Independent set
63 <https://en.wikipedia.org/wiki/Independent_set_(graph_theory)>`_
64 .. [2] Boppana, R., & Halldórsson, M. M. (1992).
65 Approximating maximum independent sets by excluding subgraphs.
66 BIT Numerical Mathematics, 32(2), 180–196. Springer.
67 """
68 iset, _ = clique_removal(G)
69 return iset
70
71
72@not_implemented_for("directed")
73@not_implemented_for("multigraph")
74@nx._dispatchable
75def max_clique(G):
76 r"""Find the Maximum Clique
77
78 Finds the $O(|V|/(log|V|)^2)$ apx of maximum clique/independent set
79 in the worst case.
80
81 Parameters
82 ----------
83 G : NetworkX graph
84 Undirected graph
85
86 Returns
87 -------
88 clique : set
89 The apx-maximum clique of the graph
90
91 Examples
92 --------
93 >>> G = nx.path_graph(10)
94 >>> nx.approximation.max_clique(G)
95 {8, 9}
96
97 Raises
98 ------
99 NetworkXNotImplemented
100 If the graph is directed or is a multigraph.
101
102 Notes
103 -----
104 A clique in an undirected graph G = (V, E) is a subset of the vertex set
105 `C \subseteq V` such that for every two vertices in C there exists an edge
106 connecting the two. This is equivalent to saying that the subgraph
107 induced by C is complete (in some cases, the term clique may also refer
108 to the subgraph).
109
110 A maximum clique is a clique of the largest possible size in a given graph.
111 The clique number `\omega(G)` of a graph G is the number of
112 vertices in a maximum clique in G. The intersection number of
113 G is the smallest number of cliques that together cover all edges of G.
114
115 https://en.wikipedia.org/wiki/Maximum_clique
116
117 References
118 ----------
119 .. [1] Boppana, R., & Halldórsson, M. M. (1992).
120 Approximating maximum independent sets by excluding subgraphs.
121 BIT Numerical Mathematics, 32(2), 180–196. Springer.
122 doi:10.1007/BF01994876
123 """
124 # finding the maximum clique in a graph is equivalent to finding
125 # the independent set in the complementary graph
126 cgraph = nx.complement(G)
127 iset, _ = clique_removal(cgraph)
128 return iset
129
130
131@not_implemented_for("directed")
132@not_implemented_for("multigraph")
133@nx._dispatchable
134def clique_removal(G):
135 r"""Repeatedly remove cliques from the graph.
136
137 Results in a $O(|V|/(\log |V|)^2)$ approximation of maximum clique
138 and independent set. Returns the largest independent set found, along
139 with found maximal cliques.
140
141 Parameters
142 ----------
143 G : NetworkX graph
144 Undirected graph
145
146 Returns
147 -------
148 max_ind_cliques : (set, list) tuple
149 2-tuple of Maximal Independent Set and list of maximal cliques (sets).
150
151 Examples
152 --------
153 >>> G = nx.path_graph(10)
154 >>> nx.approximation.clique_removal(G)
155 ({0, 2, 4, 6, 9}, [{0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}])
156
157 Raises
158 ------
159 NetworkXNotImplemented
160 If the graph is directed or is a multigraph.
161
162 References
163 ----------
164 .. [1] Boppana, R., & Halldórsson, M. M. (1992).
165 Approximating maximum independent sets by excluding subgraphs.
166 BIT Numerical Mathematics, 32(2), 180–196. Springer.
167 """
168 graph = G.copy()
169 c_i, i_i = ramsey.ramsey_R2(graph)
170 cliques = [c_i]
171 isets = [i_i]
172 while graph:
173 graph.remove_nodes_from(c_i)
174 c_i, i_i = ramsey.ramsey_R2(graph)
175 if c_i:
176 cliques.append(c_i)
177 if i_i:
178 isets.append(i_i)
179 # Determine the largest independent set as measured by cardinality.
180 maxiset = max(isets, key=len)
181 return maxiset, cliques
182
183
184@not_implemented_for("directed")
185@not_implemented_for("multigraph")
186@nx._dispatchable
187def large_clique_size(G):
188 """Find the size of a large clique in a graph.
189
190 A *clique* is a subset of nodes in which each pair of nodes is
191 adjacent. This function is a heuristic for finding the size of a
192 large clique in the graph.
193
194 Parameters
195 ----------
196 G : NetworkX graph
197
198 Returns
199 -------
200 k: integer
201 The size of a large clique in the graph.
202
203 Examples
204 --------
205 >>> G = nx.path_graph(10)
206 >>> nx.approximation.large_clique_size(G)
207 2
208
209 Raises
210 ------
211 NetworkXNotImplemented
212 If the graph is directed or is a multigraph.
213
214 Notes
215 -----
216 This implementation is from [1]_. Its worst case time complexity is
217 :math:`O(n d^2)`, where *n* is the number of nodes in the graph and
218 *d* is the maximum degree.
219
220 This function is a heuristic, which means it may work well in
221 practice, but there is no rigorous mathematical guarantee on the
222 ratio between the returned number and the actual largest clique size
223 in the graph.
224
225 References
226 ----------
227 .. [1] Pattabiraman, Bharath, et al.
228 "Fast Algorithms for the Maximum Clique Problem on Massive Graphs
229 with Applications to Overlapping Community Detection."
230 *Internet Mathematics* 11.4-5 (2015): 421--448.
231 <https://doi.org/10.1080/15427951.2014.986778>
232
233 See also
234 --------
235
236 :func:`networkx.algorithms.approximation.clique.max_clique`
237 A function that returns an approximate maximum clique with a
238 guarantee on the approximation ratio.
239
240 :mod:`networkx.algorithms.clique`
241 Functions for finding the exact maximum clique in a graph.
242
243 """
244 degrees = G.degree
245
246 def _clique_heuristic(G, U, size, best_size):
247 if not U:
248 return max(best_size, size)
249 u = max(U, key=degrees)
250 U.remove(u)
251 N_prime = {v for v in G[u] if degrees[v] >= best_size}
252 return _clique_heuristic(G, U & N_prime, size + 1, best_size)
253
254 best_size = 0
255 nodes = (u for u in G if degrees[u] >= best_size)
256 for u in nodes:
257 neighbors = {v for v in G[u] if degrees[v] >= best_size}
258 best_size = _clique_heuristic(G, neighbors, 1, best_size)
259 return best_size