attracting.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. """Attracting components."""
  2. import networkx as nx
  3. from networkx.utils.decorators import not_implemented_for
  4. __all__ = [
  5. "number_attracting_components",
  6. "attracting_components",
  7. "is_attracting_component",
  8. ]
  9. @not_implemented_for("undirected")
  10. @nx._dispatchable
  11. def attracting_components(G):
  12. """Generates the attracting components in `G`.
  13. An attracting component in a directed graph `G` is a strongly connected
  14. component with the property that a random walker on the graph will never
  15. leave the component, once it enters the component.
  16. The nodes in attracting components can also be thought of as recurrent
  17. nodes. If a random walker enters the attractor containing the node, then
  18. the node will be visited infinitely often.
  19. To obtain induced subgraphs on each component use:
  20. ``(G.subgraph(c).copy() for c in attracting_components(G))``
  21. Parameters
  22. ----------
  23. G : DiGraph, MultiDiGraph
  24. The graph to be analyzed.
  25. Returns
  26. -------
  27. attractors : generator of sets
  28. A generator of sets of nodes, one for each attracting component of G.
  29. Raises
  30. ------
  31. NetworkXNotImplemented
  32. If the input graph is undirected.
  33. See Also
  34. --------
  35. number_attracting_components
  36. is_attracting_component
  37. """
  38. scc = list(nx.strongly_connected_components(G))
  39. cG = nx.condensation(G, scc)
  40. for n in cG:
  41. if cG.out_degree(n) == 0:
  42. yield scc[n]
  43. @not_implemented_for("undirected")
  44. @nx._dispatchable
  45. def number_attracting_components(G):
  46. """Returns the number of attracting components in `G`.
  47. Parameters
  48. ----------
  49. G : DiGraph, MultiDiGraph
  50. The graph to be analyzed.
  51. Returns
  52. -------
  53. n : int
  54. The number of attracting components in G.
  55. Raises
  56. ------
  57. NetworkXNotImplemented
  58. If the input graph is undirected.
  59. See Also
  60. --------
  61. attracting_components
  62. is_attracting_component
  63. """
  64. return sum(1 for ac in attracting_components(G))
  65. @not_implemented_for("undirected")
  66. @nx._dispatchable
  67. def is_attracting_component(G):
  68. """Returns True if `G` consists of a single attracting component.
  69. Parameters
  70. ----------
  71. G : DiGraph, MultiDiGraph
  72. The graph to be analyzed.
  73. Returns
  74. -------
  75. attracting : bool
  76. True if `G` has a single attracting component. Otherwise, False.
  77. Raises
  78. ------
  79. NetworkXNotImplemented
  80. If the input graph is undirected.
  81. See Also
  82. --------
  83. attracting_components
  84. number_attracting_components
  85. """
  86. ac = list(attracting_components(G))
  87. if len(ac) == 1:
  88. return len(ac[0]) == len(G)
  89. return False