clique.py 7.5 KB

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