dominating.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. """Functions for computing dominating sets in a graph."""
  2. from itertools import chain
  3. import networkx as nx
  4. from networkx.utils import arbitrary_element
  5. __all__ = ["dominating_set", "is_dominating_set"]
  6. def dominating_set(G, start_with=None):
  7. r"""Finds a dominating set for the graph G.
  8. A *dominating set* for a graph with node set *V* is a subset *D* of
  9. *V* such that every node not in *D* is adjacent to at least one
  10. member of *D* [1]_.
  11. Parameters
  12. ----------
  13. G : NetworkX graph
  14. start_with : node (default=None)
  15. Node to use as a starting point for the algorithm.
  16. Returns
  17. -------
  18. D : set
  19. A dominating set for G.
  20. Notes
  21. -----
  22. This function is an implementation of algorithm 7 in [2]_ which
  23. finds some dominating set, not necessarily the smallest one.
  24. See also
  25. --------
  26. is_dominating_set
  27. References
  28. ----------
  29. .. [1] https://en.wikipedia.org/wiki/Dominating_set
  30. .. [2] Abdol-Hossein Esfahanian. Connectivity Algorithms.
  31. http://www.cse.msu.edu/~cse835/Papers/Graph_connectivity_revised.pdf
  32. """
  33. all_nodes = set(G)
  34. if start_with is None:
  35. start_with = arbitrary_element(all_nodes)
  36. if start_with not in G:
  37. raise nx.NetworkXError(f"node {start_with} is not in G")
  38. dominating_set = {start_with}
  39. dominated_nodes = set(G[start_with])
  40. remaining_nodes = all_nodes - dominated_nodes - dominating_set
  41. while remaining_nodes:
  42. # Choose an arbitrary node and determine its undominated neighbors.
  43. v = remaining_nodes.pop()
  44. undominated_neighbors = set(G[v]) - dominating_set
  45. # Add the node to the dominating set and the neighbors to the
  46. # dominated set. Finally, remove all of those nodes from the set
  47. # of remaining nodes.
  48. dominating_set.add(v)
  49. dominated_nodes |= undominated_neighbors
  50. remaining_nodes -= undominated_neighbors
  51. return dominating_set
  52. @nx._dispatch
  53. def is_dominating_set(G, nbunch):
  54. """Checks if `nbunch` is a dominating set for `G`.
  55. A *dominating set* for a graph with node set *V* is a subset *D* of
  56. *V* such that every node not in *D* is adjacent to at least one
  57. member of *D* [1]_.
  58. Parameters
  59. ----------
  60. G : NetworkX graph
  61. nbunch : iterable
  62. An iterable of nodes in the graph `G`.
  63. See also
  64. --------
  65. dominating_set
  66. References
  67. ----------
  68. .. [1] https://en.wikipedia.org/wiki/Dominating_set
  69. """
  70. testset = {n for n in nbunch if n in G}
  71. nbrs = set(chain.from_iterable(G[n] for n in testset))
  72. return len(set(G) - testset - nbrs) == 0