| """Functions for computing large cliques and maximum independent sets.""" |
|
|
| import networkx as nx |
| from networkx.algorithms.approximation import ramsey |
| from networkx.utils import not_implemented_for |
|
|
| __all__ = [ |
| "clique_removal", |
| "max_clique", |
| "large_clique_size", |
| "maximum_independent_set", |
| ] |
|
|
|
|
| @not_implemented_for("directed") |
| @not_implemented_for("multigraph") |
| @nx._dispatchable |
| def maximum_independent_set(G): |
| """Returns an approximate maximum independent set. |
| |
| Independent set or stable set is a set of vertices in a graph, no two of |
| which are adjacent. That is, it is a set I of vertices such that for every |
| two vertices in I, there is no edge connecting the two. Equivalently, each |
| edge in the graph has at most one endpoint in I. The size of an independent |
| set is the number of vertices it contains [1]_. |
| |
| A maximum independent set is a largest independent set for a given graph G |
| and its size is denoted $\\alpha(G)$. The problem of finding such a set is called |
| the maximum independent set problem and is an NP-hard optimization problem. |
| As such, it is unlikely that there exists an efficient algorithm for finding |
| a maximum independent set of a graph. |
| |
| The Independent Set algorithm is based on [2]_. |
| |
| Parameters |
| ---------- |
| G : NetworkX graph |
| Undirected graph |
| |
| Returns |
| ------- |
| iset : Set |
| The apx-maximum independent set |
| |
| Examples |
| -------- |
| >>> G = nx.path_graph(10) |
| >>> nx.approximation.maximum_independent_set(G) |
| {0, 2, 4, 6, 9} |
| |
| Raises |
| ------ |
| NetworkXNotImplemented |
| If the graph is directed or is a multigraph. |
| |
| Notes |
| ----- |
| Finds the $O(|V|/(log|V|)^2)$ apx of independent set in the worst case. |
| |
| References |
| ---------- |
| .. [1] `Wikipedia: Independent set |
| <https://en.wikipedia.org/wiki/Independent_set_(graph_theory)>`_ |
| .. [2] Boppana, R., & Halldórsson, M. M. (1992). |
| Approximating maximum independent sets by excluding subgraphs. |
| BIT Numerical Mathematics, 32(2), 180–196. Springer. |
| """ |
| iset, _ = clique_removal(G) |
| return iset |
|
|
|
|
| @not_implemented_for("directed") |
| @not_implemented_for("multigraph") |
| @nx._dispatchable |
| def max_clique(G): |
| r"""Find the Maximum Clique |
| |
| Finds the $O(|V|/(log|V|)^2)$ apx of maximum clique/independent set |
| in the worst case. |
| |
| Parameters |
| ---------- |
| G : NetworkX graph |
| Undirected graph |
| |
| Returns |
| ------- |
| clique : set |
| The apx-maximum clique of the graph |
| |
| Examples |
| -------- |
| >>> G = nx.path_graph(10) |
| >>> nx.approximation.max_clique(G) |
| {8, 9} |
| |
| Raises |
| ------ |
| NetworkXNotImplemented |
| If the graph is directed or is a multigraph. |
| |
| Notes |
| ----- |
| A clique in an undirected graph G = (V, E) is a subset of the vertex set |
| `C \subseteq V` such that for every two vertices in C there exists an edge |
| connecting the two. This is equivalent to saying that the subgraph |
| induced by C is complete (in some cases, the term clique may also refer |
| to the subgraph). |
| |
| A maximum clique is a clique of the largest possible size in a given graph. |
| The clique number `\omega(G)` of a graph G is the number of |
| vertices in a maximum clique in G. The intersection number of |
| G is the smallest number of cliques that together cover all edges of G. |
| |
| https://en.wikipedia.org/wiki/Maximum_clique |
| |
| References |
| ---------- |
| .. [1] Boppana, R., & Halldórsson, M. M. (1992). |
| Approximating maximum independent sets by excluding subgraphs. |
| BIT Numerical Mathematics, 32(2), 180–196. Springer. |
| doi:10.1007/BF01994876 |
| """ |
| |
| |
| cgraph = nx.complement(G) |
| iset, _ = clique_removal(cgraph) |
| return iset |
|
|
|
|
| @not_implemented_for("directed") |
| @not_implemented_for("multigraph") |
| @nx._dispatchable |
| def clique_removal(G): |
| r"""Repeatedly remove cliques from the graph. |
| |
| Results in a $O(|V|/(\log |V|)^2)$ approximation of maximum clique |
| and independent set. Returns the largest independent set found, along |
| with found maximal cliques. |
| |
| Parameters |
| ---------- |
| G : NetworkX graph |
| Undirected graph |
| |
| Returns |
| ------- |
| max_ind_cliques : (set, list) tuple |
| 2-tuple of Maximal Independent Set and list of maximal cliques (sets). |
| |
| Examples |
| -------- |
| >>> G = nx.path_graph(10) |
| >>> nx.approximation.clique_removal(G) |
| ({0, 2, 4, 6, 9}, [{0, 1}, {2, 3}, {4, 5}, {6, 7}, {8, 9}]) |
| |
| Raises |
| ------ |
| NetworkXNotImplemented |
| If the graph is directed or is a multigraph. |
| |
| References |
| ---------- |
| .. [1] Boppana, R., & Halldórsson, M. M. (1992). |
| Approximating maximum independent sets by excluding subgraphs. |
| BIT Numerical Mathematics, 32(2), 180–196. Springer. |
| """ |
| graph = G.copy() |
| c_i, i_i = ramsey.ramsey_R2(graph) |
| cliques = [c_i] |
| isets = [i_i] |
| while graph: |
| graph.remove_nodes_from(c_i) |
| c_i, i_i = ramsey.ramsey_R2(graph) |
| if c_i: |
| cliques.append(c_i) |
| if i_i: |
| isets.append(i_i) |
| |
| maxiset = max(isets, key=len) |
| return maxiset, cliques |
|
|
|
|
| @not_implemented_for("directed") |
| @not_implemented_for("multigraph") |
| @nx._dispatchable |
| def large_clique_size(G): |
| """Find the size of a large clique in a graph. |
| |
| A *clique* is a subset of nodes in which each pair of nodes is |
| adjacent. This function is a heuristic for finding the size of a |
| large clique in the graph. |
| |
| Parameters |
| ---------- |
| G : NetworkX graph |
| |
| Returns |
| ------- |
| k: integer |
| The size of a large clique in the graph. |
| |
| Examples |
| -------- |
| >>> G = nx.path_graph(10) |
| >>> nx.approximation.large_clique_size(G) |
| 2 |
| |
| Raises |
| ------ |
| NetworkXNotImplemented |
| If the graph is directed or is a multigraph. |
| |
| Notes |
| ----- |
| This implementation is from [1]_. Its worst case time complexity is |
| :math:`O(n d^2)`, where *n* is the number of nodes in the graph and |
| *d* is the maximum degree. |
| |
| This function is a heuristic, which means it may work well in |
| practice, but there is no rigorous mathematical guarantee on the |
| ratio between the returned number and the actual largest clique size |
| in the graph. |
| |
| References |
| ---------- |
| .. [1] Pattabiraman, Bharath, et al. |
| "Fast Algorithms for the Maximum Clique Problem on Massive Graphs |
| with Applications to Overlapping Community Detection." |
| *Internet Mathematics* 11.4-5 (2015): 421--448. |
| <https://doi.org/10.1080/15427951.2014.986778> |
| |
| See also |
| -------- |
| |
| :func:`networkx.algorithms.approximation.clique.max_clique` |
| A function that returns an approximate maximum clique with a |
| guarantee on the approximation ratio. |
| |
| :mod:`networkx.algorithms.clique` |
| Functions for finding the exact maximum clique in a graph. |
| |
| """ |
| degrees = G.degree |
|
|
| def _clique_heuristic(G, U, size, best_size): |
| if not U: |
| return max(best_size, size) |
| u = max(U, key=degrees) |
| U.remove(u) |
| N_prime = {v for v in G[u] if degrees[v] >= best_size} |
| return _clique_heuristic(G, U & N_prime, size + 1, best_size) |
|
|
| best_size = 0 |
| nodes = (u for u in G if degrees[u] >= best_size) |
| for u in nodes: |
| neighbors = {v for v in G[u] if degrees[v] >= best_size} |
| best_size = _clique_heuristic(G, neighbors, 1, best_size) |
| return best_size |
|
|