Spaces:
Running
Running
File size: 4,312 Bytes
b200bda |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
"""Connected components."""
import networkx as nx
from networkx.utils.decorators import not_implemented_for
from ...utils import arbitrary_element
__all__ = [
"number_connected_components",
"connected_components",
"is_connected",
"node_connected_component",
]
@not_implemented_for("directed")
@nx._dispatch
def connected_components(G):
"""Generate connected components.
Parameters
----------
G : NetworkX graph
An undirected graph
Returns
-------
comp : generator of sets
A generator of sets of nodes, one for each component of G.
Raises
------
NetworkXNotImplemented
If G is directed.
Examples
--------
Generate a sorted list of connected components, largest first.
>>> G = nx.path_graph(4)
>>> nx.add_path(G, [10, 11, 12])
>>> [len(c) for c in sorted(nx.connected_components(G), key=len, reverse=True)]
[4, 3]
If you only want the largest connected component, it's more
efficient to use max instead of sort.
>>> largest_cc = max(nx.connected_components(G), key=len)
To create the induced subgraph of each component use:
>>> S = [G.subgraph(c).copy() for c in nx.connected_components(G)]
See Also
--------
strongly_connected_components
weakly_connected_components
Notes
-----
For undirected graphs only.
"""
seen = set()
for v in G:
if v not in seen:
c = _plain_bfs(G, v)
seen.update(c)
yield c
@nx._dispatch
def number_connected_components(G):
"""Returns the number of connected components.
Parameters
----------
G : NetworkX graph
An undirected graph.
Returns
-------
n : integer
Number of connected components
Examples
--------
>>> G = nx.Graph([(0, 1), (1, 2), (5, 6), (3, 4)])
>>> nx.number_connected_components(G)
3
See Also
--------
connected_components
number_weakly_connected_components
number_strongly_connected_components
Notes
-----
For undirected graphs only.
"""
return sum(1 for cc in connected_components(G))
@not_implemented_for("directed")
@nx._dispatch
def is_connected(G):
"""Returns True if the graph is connected, False otherwise.
Parameters
----------
G : NetworkX Graph
An undirected graph.
Returns
-------
connected : bool
True if the graph is connected, false otherwise.
Raises
------
NetworkXNotImplemented
If G is directed.
Examples
--------
>>> G = nx.path_graph(4)
>>> print(nx.is_connected(G))
True
See Also
--------
is_strongly_connected
is_weakly_connected
is_semiconnected
is_biconnected
connected_components
Notes
-----
For undirected graphs only.
"""
if len(G) == 0:
raise nx.NetworkXPointlessConcept(
"Connectivity is undefined ", "for the null graph."
)
return sum(1 for node in _plain_bfs(G, arbitrary_element(G))) == len(G)
@not_implemented_for("directed")
@nx._dispatch
def node_connected_component(G, n):
"""Returns the set of nodes in the component of graph containing node n.
Parameters
----------
G : NetworkX Graph
An undirected graph.
n : node label
A node in G
Returns
-------
comp : set
A set of nodes in the component of G containing node n.
Raises
------
NetworkXNotImplemented
If G is directed.
Examples
--------
>>> G = nx.Graph([(0, 1), (1, 2), (5, 6), (3, 4)])
>>> nx.node_connected_component(G, 0) # nodes of component that contains node 0
{0, 1, 2}
See Also
--------
connected_components
Notes
-----
For undirected graphs only.
"""
return _plain_bfs(G, n)
def _plain_bfs(G, source):
"""A fast BFS node generator"""
adj = G._adj
n = len(adj)
seen = {source}
nextlevel = [source]
while nextlevel:
thislevel = nextlevel
nextlevel = []
for v in thislevel:
for w in adj[v]:
if w not in seen:
seen.add(w)
nextlevel.append(w)
if len(seen) == n:
return seen
return seen
|