mis.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. """
  2. Algorithm to find a maximal (not maximum) independent set.
  3. """
  4. import networkx as nx
  5. from networkx.utils import not_implemented_for, py_random_state
  6. __all__ = ["maximal_independent_set"]
  7. @not_implemented_for("directed")
  8. @py_random_state(2)
  9. @nx._dispatchable
  10. def maximal_independent_set(G, nodes=None, seed=None):
  11. """Returns a random maximal independent set guaranteed to contain
  12. a given set of nodes.
  13. An independent set is a set of nodes such that the subgraph
  14. of G induced by these nodes contains no edges. A maximal
  15. independent set is an independent set such that it is not possible
  16. to add a new node and still get an independent set.
  17. Parameters
  18. ----------
  19. G : NetworkX graph
  20. nodes : list or iterable
  21. Nodes that must be part of the independent set. This set of nodes
  22. must be independent.
  23. seed : integer, random_state, or None (default)
  24. Indicator of random number generation state.
  25. See :ref:`Randomness<randomness>`.
  26. Returns
  27. -------
  28. indep_nodes : list
  29. List of nodes that are part of a maximal independent set.
  30. Raises
  31. ------
  32. NetworkXUnfeasible
  33. If the nodes in the provided list are not part of the graph or
  34. do not form an independent set, an exception is raised.
  35. NetworkXNotImplemented
  36. If `G` is directed.
  37. Examples
  38. --------
  39. >>> G = nx.path_graph(5)
  40. >>> nx.maximal_independent_set(G) # doctest: +SKIP
  41. [4, 0, 2]
  42. >>> nx.maximal_independent_set(G, [1]) # doctest: +SKIP
  43. [1, 3]
  44. Notes
  45. -----
  46. This algorithm does not solve the maximum independent set problem.
  47. """
  48. if not nodes:
  49. nodes = {seed.choice(list(G))}
  50. else:
  51. nodes = set(nodes)
  52. if not nodes.issubset(G):
  53. raise nx.NetworkXUnfeasible(f"{nodes} is not a subset of the nodes of G")
  54. neighbors = set.union(*[set(G.adj[v]) for v in nodes])
  55. if set.intersection(neighbors, nodes):
  56. raise nx.NetworkXUnfeasible(f"{nodes} is not an independent set of G")
  57. indep_nodes = list(nodes)
  58. available_nodes = set(G.nodes()).difference(neighbors.union(nodes))
  59. while available_nodes:
  60. node = seed.choice(list(available_nodes))
  61. indep_nodes.append(node)
  62. available_nodes.difference_update(list(G.adj[node]) + [node])
  63. return indep_nodes