112 lines
2.6 KiB
Python
112 lines
2.6 KiB
Python
"""Attracting components."""
|
|
import networkx as nx
|
|
from networkx.utils.decorators import not_implemented_for
|
|
|
|
__all__ = [
|
|
"number_attracting_components",
|
|
"attracting_components",
|
|
"is_attracting_component",
|
|
]
|
|
|
|
|
|
@not_implemented_for("undirected")
|
|
def attracting_components(G):
|
|
"""Generates the attracting components in `G`.
|
|
|
|
An attracting component in a directed graph `G` is a strongly connected
|
|
component with the property that a random walker on the graph will never
|
|
leave the component, once it enters the component.
|
|
|
|
The nodes in attracting components can also be thought of as recurrent
|
|
nodes. If a random walker enters the attractor containing the node, then
|
|
the node will be visited infinitely often.
|
|
|
|
To obtain induced subgraphs on each component use:
|
|
``(G.subgraph(c).copy() for c in attracting_components(G))``
|
|
|
|
Parameters
|
|
----------
|
|
G : DiGraph, MultiDiGraph
|
|
The graph to be analyzed.
|
|
|
|
Returns
|
|
-------
|
|
attractors : generator of sets
|
|
A generator of sets of nodes, one for each attracting component of G.
|
|
|
|
Raises
|
|
------
|
|
NetworkXNotImplemented
|
|
If the input graph is undirected.
|
|
|
|
See Also
|
|
--------
|
|
number_attracting_components
|
|
is_attracting_component
|
|
|
|
"""
|
|
scc = list(nx.strongly_connected_components(G))
|
|
cG = nx.condensation(G, scc)
|
|
for n in cG:
|
|
if cG.out_degree(n) == 0:
|
|
yield scc[n]
|
|
|
|
|
|
@not_implemented_for("undirected")
|
|
def number_attracting_components(G):
|
|
"""Returns the number of attracting components in `G`.
|
|
|
|
Parameters
|
|
----------
|
|
G : DiGraph, MultiDiGraph
|
|
The graph to be analyzed.
|
|
|
|
Returns
|
|
-------
|
|
n : int
|
|
The number of attracting components in G.
|
|
|
|
Raises
|
|
------
|
|
NetworkXNotImplemented
|
|
If the input graph is undirected.
|
|
|
|
See Also
|
|
--------
|
|
attracting_components
|
|
is_attracting_component
|
|
|
|
"""
|
|
return sum(1 for ac in attracting_components(G))
|
|
|
|
|
|
@not_implemented_for("undirected")
|
|
def is_attracting_component(G):
|
|
"""Returns True if `G` consists of a single attracting component.
|
|
|
|
Parameters
|
|
----------
|
|
G : DiGraph, MultiDiGraph
|
|
The graph to be analyzed.
|
|
|
|
Returns
|
|
-------
|
|
attracting : bool
|
|
True if `G` has a single attracting component. Otherwise, False.
|
|
|
|
Raises
|
|
------
|
|
NetworkXNotImplemented
|
|
If the input graph is undirected.
|
|
|
|
See Also
|
|
--------
|
|
attracting_components
|
|
number_attracting_components
|
|
|
|
"""
|
|
ac = list(attracting_components(G))
|
|
if len(ac) == 1:
|
|
return len(ac[0]) == len(G)
|
|
return False
|