123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- """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")
- 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
- 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")
- 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
- 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
- """
- if G is None:
- raise ValueError("Expected NetworkX graph!")
- # finding the maximum clique in a graph is equivalent to finding
- # the independent set in the complementary graph
- cgraph = nx.complement(G)
- iset, _ = clique_removal(cgraph)
- return iset
- @not_implemented_for("directed")
- @not_implemented_for("multigraph")
- 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).
- 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)
- # Determine the largest independent set as measured by cardinality.
- maxiset = max(isets, key=len)
- return maxiset, cliques
- @not_implemented_for("directed")
- @not_implemented_for("multigraph")
- 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.
- 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
|