broadcasting.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. """Routines to calculate the broadcast time of certain graphs.
  2. Broadcasting is an information dissemination problem in which a node in a graph,
  3. called the originator, must distribute a message to all other nodes by placing
  4. a series of calls along the edges of the graph. Once informed, other nodes aid
  5. the originator in distributing the message.
  6. The broadcasting must be completed as quickly as possible subject to the
  7. following constraints:
  8. - Each call requires one unit of time.
  9. - A node can only participate in one call per unit of time.
  10. - Each call only involves two adjacent nodes: a sender and a receiver.
  11. """
  12. import networkx as nx
  13. from networkx.utils import not_implemented_for
  14. __all__ = [
  15. "tree_broadcast_center",
  16. "tree_broadcast_time",
  17. ]
  18. def _get_max_broadcast_value(G, U, v, values):
  19. adj = sorted(set(G.neighbors(v)) & U, key=values.get, reverse=True)
  20. return max(values[u] + i for i, u in enumerate(adj, start=1))
  21. def _get_broadcast_centers(G, v, values, target):
  22. adj = sorted(G.neighbors(v), key=values.get, reverse=True)
  23. j = next(i for i, u in enumerate(adj, start=1) if values[u] + i == target)
  24. return set([v] + adj[:j])
  25. @not_implemented_for("directed")
  26. @not_implemented_for("multigraph")
  27. @nx._dispatchable
  28. def tree_broadcast_center(G):
  29. """Return the broadcast center of a tree.
  30. The broadcast center of a graph `G` denotes the set of nodes having
  31. minimum broadcast time [1]_. This function implements a linear algorithm
  32. for determining the broadcast center of a tree with ``n`` nodes. As a
  33. by-product, it also determines the broadcast time from the broadcast center.
  34. Parameters
  35. ----------
  36. G : Graph
  37. The graph should be an undirected tree.
  38. Returns
  39. -------
  40. b_T, b_C : (int, set) tuple
  41. Minimum broadcast time of the broadcast center in `G`, set of nodes
  42. in the broadcast center.
  43. Raises
  44. ------
  45. NetworkXNotImplemented
  46. If `G` is directed or is a multigraph.
  47. NotATree
  48. If `G` is not a tree.
  49. References
  50. ----------
  51. .. [1] Slater, P.J., Cockayne, E.J., Hedetniemi, S.T,
  52. Information dissemination in trees. SIAM J.Comput. 10(4), 692–701 (1981)
  53. """
  54. # Assert that the graph G is a tree
  55. if not nx.is_tree(G):
  56. raise nx.NotATree("G is not a tree")
  57. # step 0
  58. if (n := len(G)) < 3:
  59. return n - 1, set(G)
  60. # step 1
  61. U = {node for node, deg in G.degree if deg == 1}
  62. values = {n: 0 for n in U}
  63. T = G.copy()
  64. T.remove_nodes_from(U)
  65. # step 2
  66. W = {node for node, deg in T.degree if deg == 1}
  67. values.update((w, G.degree[w] - 1) for w in W)
  68. # step 3
  69. while len(T) >= 2:
  70. # step 4
  71. w = min(W, key=values.get)
  72. v = next(T.neighbors(w))
  73. # step 5
  74. U.add(w)
  75. W.remove(w)
  76. T.remove_node(w)
  77. # step 6
  78. if T.degree(v) == 1:
  79. # update t(v)
  80. values.update({v: _get_max_broadcast_value(G, U, v, values)})
  81. W.add(v)
  82. # step 7
  83. v = nx.utils.arbitrary_element(T)
  84. b_T = _get_max_broadcast_value(G, U, v, values)
  85. return b_T, _get_broadcast_centers(G, v, values, b_T)
  86. @not_implemented_for("directed")
  87. @not_implemented_for("multigraph")
  88. @nx._dispatchable
  89. def tree_broadcast_time(G, node=None):
  90. """Return the minimum broadcast time of a (node in a) tree.
  91. The minimum broadcast time of a node is defined as the minimum amount
  92. of time required to complete broadcasting starting from that node.
  93. The broadcast time of a graph is the maximum over
  94. all nodes of the minimum broadcast time from that node [1]_.
  95. This function returns the minimum broadcast time of `node`.
  96. If `node` is `None`, the broadcast time for the graph is returned.
  97. Parameters
  98. ----------
  99. G : Graph
  100. The graph should be an undirected tree.
  101. node : node, optional (default=None)
  102. Starting node for the broadcasting. If `None`, the algorithm
  103. returns the broadcast time of the graph instead.
  104. Returns
  105. -------
  106. int
  107. Minimum broadcast time of `node` in `G`, or broadcast time of `G`
  108. if no node is provided.
  109. Raises
  110. ------
  111. NetworkXNotImplemented
  112. If `G` is directed or is a multigraph.
  113. NodeNotFound
  114. If `node` is not a node in `G`.
  115. NotATree
  116. If `G` is not a tree.
  117. References
  118. ----------
  119. .. [1] Harutyunyan, H. A. and Li, Z.
  120. "A Simple Construction of Broadcast Graphs."
  121. In Computing and Combinatorics. COCOON 2019
  122. (Ed. D. Z. Du and C. Tian.) Springer, pp. 240-253, 2019.
  123. """
  124. if node is not None and node not in G:
  125. err = f"node {node} not in G"
  126. raise nx.NodeNotFound(err)
  127. b_T, b_C = tree_broadcast_center(G)
  128. if node is None:
  129. return b_T + sum(1 for _ in nx.bfs_layers(G, b_C)) - 1
  130. return b_T + next(
  131. d for d, layer in enumerate(nx.bfs_layers(G, b_C)) if node in layer
  132. )