dominating_set.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. """Functions for finding node and edge dominating sets.
  2. A `dominating set`_ for an undirected graph *G* with vertex set *V*
  3. and edge set *E* is a subset *D* of *V* such that every vertex not in
  4. *D* is adjacent to at least one member of *D*. An `edge dominating set`_
  5. is a subset *F* of *E* such that every edge not in *F* is
  6. incident to an endpoint of at least one edge in *F*.
  7. .. _dominating set: https://en.wikipedia.org/wiki/Dominating_set
  8. .. _edge dominating set: https://en.wikipedia.org/wiki/Edge_dominating_set
  9. """
  10. from ...utils import not_implemented_for
  11. from ..matching import maximal_matching
  12. __all__ = ["min_weighted_dominating_set", "min_edge_dominating_set"]
  13. # TODO Why doesn't this algorithm work for directed graphs?
  14. @not_implemented_for("directed")
  15. def min_weighted_dominating_set(G, weight=None):
  16. r"""Returns a dominating set that approximates the minimum weight node
  17. dominating set.
  18. Parameters
  19. ----------
  20. G : NetworkX graph
  21. Undirected graph.
  22. weight : string
  23. The node attribute storing the weight of an node. If provided,
  24. the node attribute with this key must be a number for each
  25. node. If not provided, each node is assumed to have weight one.
  26. Returns
  27. -------
  28. min_weight_dominating_set : set
  29. A set of nodes, the sum of whose weights is no more than `(\log
  30. w(V)) w(V^*)`, where `w(V)` denotes the sum of the weights of
  31. each node in the graph and `w(V^*)` denotes the sum of the
  32. weights of each node in the minimum weight dominating set.
  33. Notes
  34. -----
  35. This algorithm computes an approximate minimum weighted dominating
  36. set for the graph `G`. The returned solution has weight `(\log
  37. w(V)) w(V^*)`, where `w(V)` denotes the sum of the weights of each
  38. node in the graph and `w(V^*)` denotes the sum of the weights of
  39. each node in the minimum weight dominating set for the graph.
  40. This implementation of the algorithm runs in $O(m)$ time, where $m$
  41. is the number of edges in the graph.
  42. References
  43. ----------
  44. .. [1] Vazirani, Vijay V.
  45. *Approximation Algorithms*.
  46. Springer Science & Business Media, 2001.
  47. """
  48. # The unique dominating set for the null graph is the empty set.
  49. if len(G) == 0:
  50. return set()
  51. # This is the dominating set that will eventually be returned.
  52. dom_set = set()
  53. def _cost(node_and_neighborhood):
  54. """Returns the cost-effectiveness of greedily choosing the given
  55. node.
  56. `node_and_neighborhood` is a two-tuple comprising a node and its
  57. closed neighborhood.
  58. """
  59. v, neighborhood = node_and_neighborhood
  60. return G.nodes[v].get(weight, 1) / len(neighborhood - dom_set)
  61. # This is a set of all vertices not already covered by the
  62. # dominating set.
  63. vertices = set(G)
  64. # This is a dictionary mapping each node to the closed neighborhood
  65. # of that node.
  66. neighborhoods = {v: {v} | set(G[v]) for v in G}
  67. # Continue until all vertices are adjacent to some node in the
  68. # dominating set.
  69. while vertices:
  70. # Find the most cost-effective node to add, along with its
  71. # closed neighborhood.
  72. dom_node, min_set = min(neighborhoods.items(), key=_cost)
  73. # Add the node to the dominating set and reduce the remaining
  74. # set of nodes to cover.
  75. dom_set.add(dom_node)
  76. del neighborhoods[dom_node]
  77. vertices -= min_set
  78. return dom_set
  79. def min_edge_dominating_set(G):
  80. r"""Returns minimum cardinality edge dominating set.
  81. Parameters
  82. ----------
  83. G : NetworkX graph
  84. Undirected graph
  85. Returns
  86. -------
  87. min_edge_dominating_set : set
  88. Returns a set of dominating edges whose size is no more than 2 * OPT.
  89. Notes
  90. -----
  91. The algorithm computes an approximate solution to the edge dominating set
  92. problem. The result is no more than 2 * OPT in terms of size of the set.
  93. Runtime of the algorithm is $O(|E|)$.
  94. """
  95. if not G:
  96. raise ValueError("Expected non-empty NetworkX graph!")
  97. return maximal_matching(G)