using for loop to install conda package
This commit is contained in:
6
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/__init__.py
vendored
Normal file
6
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/__init__.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
from .connected import *
|
||||
from .strongly_connected import *
|
||||
from .weakly_connected import *
|
||||
from .attracting import *
|
||||
from .biconnected import *
|
||||
from .semiconnected import *
|
||||
BIN
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/__pycache__/connected.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/__pycache__/connected.cpython-311.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
111
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/attracting.py
vendored
Normal file
111
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/attracting.py
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
"""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
|
||||
388
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/biconnected.py
vendored
Normal file
388
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/biconnected.py
vendored
Normal file
@@ -0,0 +1,388 @@
|
||||
"""Biconnected components and articulation points."""
|
||||
from itertools import chain
|
||||
|
||||
from networkx.utils.decorators import not_implemented_for
|
||||
|
||||
__all__ = [
|
||||
"biconnected_components",
|
||||
"biconnected_component_edges",
|
||||
"is_biconnected",
|
||||
"articulation_points",
|
||||
]
|
||||
|
||||
|
||||
@not_implemented_for("directed")
|
||||
def is_biconnected(G):
|
||||
"""Returns True if the graph is biconnected, False otherwise.
|
||||
|
||||
A graph is biconnected if, and only if, it cannot be disconnected by
|
||||
removing only one node (and all edges incident on that node). If
|
||||
removing a node increases the number of disconnected components
|
||||
in the graph, that node is called an articulation point, or cut
|
||||
vertex. A biconnected graph has no articulation points.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX Graph
|
||||
An undirected graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
biconnected : bool
|
||||
True if the graph is biconnected, False otherwise.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If the input graph is not undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> G = nx.path_graph(4)
|
||||
>>> print(nx.is_biconnected(G))
|
||||
False
|
||||
>>> G.add_edge(0, 3)
|
||||
>>> print(nx.is_biconnected(G))
|
||||
True
|
||||
|
||||
See Also
|
||||
--------
|
||||
biconnected_components
|
||||
articulation_points
|
||||
biconnected_component_edges
|
||||
is_strongly_connected
|
||||
is_weakly_connected
|
||||
is_connected
|
||||
is_semiconnected
|
||||
|
||||
Notes
|
||||
-----
|
||||
The algorithm to find articulation points and biconnected
|
||||
components is implemented using a non-recursive depth-first-search
|
||||
(DFS) that keeps track of the highest level that back edges reach
|
||||
in the DFS tree. A node `n` is an articulation point if, and only
|
||||
if, there exists a subtree rooted at `n` such that there is no
|
||||
back edge from any successor of `n` that links to a predecessor of
|
||||
`n` in the DFS tree. By keeping track of all the edges traversed
|
||||
by the DFS we can obtain the biconnected components because all
|
||||
edges of a bicomponent will be traversed consecutively between
|
||||
articulation points.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Hopcroft, J.; Tarjan, R. (1973).
|
||||
"Efficient algorithms for graph manipulation".
|
||||
Communications of the ACM 16: 372–378. doi:10.1145/362248.362272
|
||||
|
||||
"""
|
||||
bccs = biconnected_components(G)
|
||||
try:
|
||||
bcc = next(bccs)
|
||||
except StopIteration:
|
||||
# No bicomponents (empty graph?)
|
||||
return False
|
||||
try:
|
||||
next(bccs)
|
||||
except StopIteration:
|
||||
# Only one bicomponent
|
||||
return len(bcc) == len(G)
|
||||
else:
|
||||
# Multiple bicomponents
|
||||
return False
|
||||
|
||||
|
||||
@not_implemented_for("directed")
|
||||
def biconnected_component_edges(G):
|
||||
"""Returns a generator of lists of edges, one list for each biconnected
|
||||
component of the input graph.
|
||||
|
||||
Biconnected components are maximal subgraphs such that the removal of a
|
||||
node (and all edges incident on that node) will not disconnect the
|
||||
subgraph. Note that nodes may be part of more than one biconnected
|
||||
component. Those nodes are articulation points, or cut vertices.
|
||||
However, each edge belongs to one, and only one, biconnected component.
|
||||
|
||||
Notice that by convention a dyad is considered a biconnected component.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX Graph
|
||||
An undirected graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
edges : generator of lists
|
||||
Generator of lists of edges, one list for each bicomponent.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If the input graph is not undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> G = nx.barbell_graph(4, 2)
|
||||
>>> print(nx.is_biconnected(G))
|
||||
False
|
||||
>>> bicomponents_edges = list(nx.biconnected_component_edges(G))
|
||||
>>> len(bicomponents_edges)
|
||||
5
|
||||
>>> G.add_edge(2, 8)
|
||||
>>> print(nx.is_biconnected(G))
|
||||
True
|
||||
>>> bicomponents_edges = list(nx.biconnected_component_edges(G))
|
||||
>>> len(bicomponents_edges)
|
||||
1
|
||||
|
||||
See Also
|
||||
--------
|
||||
is_biconnected,
|
||||
biconnected_components,
|
||||
articulation_points,
|
||||
|
||||
Notes
|
||||
-----
|
||||
The algorithm to find articulation points and biconnected
|
||||
components is implemented using a non-recursive depth-first-search
|
||||
(DFS) that keeps track of the highest level that back edges reach
|
||||
in the DFS tree. A node `n` is an articulation point if, and only
|
||||
if, there exists a subtree rooted at `n` such that there is no
|
||||
back edge from any successor of `n` that links to a predecessor of
|
||||
`n` in the DFS tree. By keeping track of all the edges traversed
|
||||
by the DFS we can obtain the biconnected components because all
|
||||
edges of a bicomponent will be traversed consecutively between
|
||||
articulation points.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Hopcroft, J.; Tarjan, R. (1973).
|
||||
"Efficient algorithms for graph manipulation".
|
||||
Communications of the ACM 16: 372–378. doi:10.1145/362248.362272
|
||||
|
||||
"""
|
||||
yield from _biconnected_dfs(G, components=True)
|
||||
|
||||
|
||||
@not_implemented_for("directed")
|
||||
def biconnected_components(G):
|
||||
"""Returns a generator of sets of nodes, one set for each biconnected
|
||||
component of the graph
|
||||
|
||||
Biconnected components are maximal subgraphs such that the removal of a
|
||||
node (and all edges incident on that node) will not disconnect the
|
||||
subgraph. Note that nodes may be part of more than one biconnected
|
||||
component. Those nodes are articulation points, or cut vertices. The
|
||||
removal of articulation points will increase the number of connected
|
||||
components of the graph.
|
||||
|
||||
Notice that by convention a dyad is considered a biconnected component.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX Graph
|
||||
An undirected graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
nodes : generator
|
||||
Generator of sets of nodes, one set for each biconnected component.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If the input graph is not undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> G = nx.lollipop_graph(5, 1)
|
||||
>>> print(nx.is_biconnected(G))
|
||||
False
|
||||
>>> bicomponents = list(nx.biconnected_components(G))
|
||||
>>> len(bicomponents)
|
||||
2
|
||||
>>> G.add_edge(0, 5)
|
||||
>>> print(nx.is_biconnected(G))
|
||||
True
|
||||
>>> bicomponents = list(nx.biconnected_components(G))
|
||||
>>> len(bicomponents)
|
||||
1
|
||||
|
||||
You can generate a sorted list of biconnected components, largest
|
||||
first, using sort.
|
||||
|
||||
>>> G.remove_edge(0, 5)
|
||||
>>> [len(c) for c in sorted(nx.biconnected_components(G), key=len, reverse=True)]
|
||||
[5, 2]
|
||||
|
||||
If you only want the largest connected component, it's more
|
||||
efficient to use max instead of sort.
|
||||
|
||||
>>> Gc = max(nx.biconnected_components(G), key=len)
|
||||
|
||||
To create the components as subgraphs use:
|
||||
``(G.subgraph(c).copy() for c in biconnected_components(G))``
|
||||
|
||||
See Also
|
||||
--------
|
||||
is_biconnected
|
||||
articulation_points
|
||||
biconnected_component_edges
|
||||
k_components : this function is a special case where k=2
|
||||
bridge_components : similar to this function, but is defined using
|
||||
2-edge-connectivity instead of 2-node-connectivity.
|
||||
|
||||
Notes
|
||||
-----
|
||||
The algorithm to find articulation points and biconnected
|
||||
components is implemented using a non-recursive depth-first-search
|
||||
(DFS) that keeps track of the highest level that back edges reach
|
||||
in the DFS tree. A node `n` is an articulation point if, and only
|
||||
if, there exists a subtree rooted at `n` such that there is no
|
||||
back edge from any successor of `n` that links to a predecessor of
|
||||
`n` in the DFS tree. By keeping track of all the edges traversed
|
||||
by the DFS we can obtain the biconnected components because all
|
||||
edges of a bicomponent will be traversed consecutively between
|
||||
articulation points.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Hopcroft, J.; Tarjan, R. (1973).
|
||||
"Efficient algorithms for graph manipulation".
|
||||
Communications of the ACM 16: 372–378. doi:10.1145/362248.362272
|
||||
|
||||
"""
|
||||
for comp in _biconnected_dfs(G, components=True):
|
||||
yield set(chain.from_iterable(comp))
|
||||
|
||||
|
||||
@not_implemented_for("directed")
|
||||
def articulation_points(G):
|
||||
"""Yield the articulation points, or cut vertices, of a graph.
|
||||
|
||||
An articulation point or cut vertex is any node whose removal (along with
|
||||
all its incident edges) increases the number of connected components of
|
||||
a graph. An undirected connected graph without articulation points is
|
||||
biconnected. Articulation points belong to more than one biconnected
|
||||
component of a graph.
|
||||
|
||||
Notice that by convention a dyad is considered a biconnected component.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX Graph
|
||||
An undirected graph.
|
||||
|
||||
Yields
|
||||
------
|
||||
node
|
||||
An articulation point in the graph.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If the input graph is not undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
>>> G = nx.barbell_graph(4, 2)
|
||||
>>> print(nx.is_biconnected(G))
|
||||
False
|
||||
>>> len(list(nx.articulation_points(G)))
|
||||
4
|
||||
>>> G.add_edge(2, 8)
|
||||
>>> print(nx.is_biconnected(G))
|
||||
True
|
||||
>>> len(list(nx.articulation_points(G)))
|
||||
0
|
||||
|
||||
See Also
|
||||
--------
|
||||
is_biconnected
|
||||
biconnected_components
|
||||
biconnected_component_edges
|
||||
|
||||
Notes
|
||||
-----
|
||||
The algorithm to find articulation points and biconnected
|
||||
components is implemented using a non-recursive depth-first-search
|
||||
(DFS) that keeps track of the highest level that back edges reach
|
||||
in the DFS tree. A node `n` is an articulation point if, and only
|
||||
if, there exists a subtree rooted at `n` such that there is no
|
||||
back edge from any successor of `n` that links to a predecessor of
|
||||
`n` in the DFS tree. By keeping track of all the edges traversed
|
||||
by the DFS we can obtain the biconnected components because all
|
||||
edges of a bicomponent will be traversed consecutively between
|
||||
articulation points.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Hopcroft, J.; Tarjan, R. (1973).
|
||||
"Efficient algorithms for graph manipulation".
|
||||
Communications of the ACM 16: 372–378. doi:10.1145/362248.362272
|
||||
|
||||
"""
|
||||
seen = set()
|
||||
for articulation in _biconnected_dfs(G, components=False):
|
||||
if articulation not in seen:
|
||||
seen.add(articulation)
|
||||
yield articulation
|
||||
|
||||
|
||||
@not_implemented_for("directed")
|
||||
def _biconnected_dfs(G, components=True):
|
||||
# depth-first search algorithm to generate articulation points
|
||||
# and biconnected components
|
||||
visited = set()
|
||||
for start in G:
|
||||
if start in visited:
|
||||
continue
|
||||
discovery = {start: 0} # time of first discovery of node during search
|
||||
low = {start: 0}
|
||||
root_children = 0
|
||||
visited.add(start)
|
||||
edge_stack = []
|
||||
stack = [(start, start, iter(G[start]))]
|
||||
edge_index = {}
|
||||
while stack:
|
||||
grandparent, parent, children = stack[-1]
|
||||
try:
|
||||
child = next(children)
|
||||
if grandparent == child:
|
||||
continue
|
||||
if child in visited:
|
||||
if discovery[child] <= discovery[parent]: # back edge
|
||||
low[parent] = min(low[parent], discovery[child])
|
||||
if components:
|
||||
edge_index[parent, child] = len(edge_stack)
|
||||
edge_stack.append((parent, child))
|
||||
else:
|
||||
low[child] = discovery[child] = len(discovery)
|
||||
visited.add(child)
|
||||
stack.append((parent, child, iter(G[child])))
|
||||
if components:
|
||||
edge_index[parent, child] = len(edge_stack)
|
||||
edge_stack.append((parent, child))
|
||||
|
||||
except StopIteration:
|
||||
stack.pop()
|
||||
if len(stack) > 1:
|
||||
if low[parent] >= discovery[grandparent]:
|
||||
if components:
|
||||
ind = edge_index[grandparent, parent]
|
||||
yield edge_stack[ind:]
|
||||
del edge_stack[ind:]
|
||||
|
||||
else:
|
||||
yield grandparent
|
||||
low[grandparent] = min(low[parent], low[grandparent])
|
||||
elif stack: # length 1 so grandparent is root
|
||||
root_children += 1
|
||||
if components:
|
||||
ind = edge_index[grandparent, parent]
|
||||
yield edge_stack[ind:]
|
||||
del edge_stack[ind:]
|
||||
if not components:
|
||||
# root node is articulation point if it has more than 1 child
|
||||
if root_children > 1:
|
||||
yield start
|
||||
203
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/connected.py
vendored
Normal file
203
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/connected.py
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
"""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",
|
||||
]
|
||||
|
||||
|
||||
@nx._dispatch
|
||||
@not_implemented_for("directed")
|
||||
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
|
||||
|
||||
|
||||
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))
|
||||
|
||||
|
||||
@nx._dispatch
|
||||
@not_implemented_for("directed")
|
||||
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)
|
||||
|
||||
|
||||
@nx._dispatch
|
||||
@not_implemented_for("directed")
|
||||
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"""
|
||||
G_adj = G.adj
|
||||
seen = set()
|
||||
nextlevel = {source}
|
||||
while nextlevel:
|
||||
thislevel = nextlevel
|
||||
nextlevel = set()
|
||||
for v in thislevel:
|
||||
if v not in seen:
|
||||
seen.add(v)
|
||||
nextlevel.update(G_adj[v])
|
||||
return seen
|
||||
64
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/semiconnected.py
vendored
Normal file
64
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/semiconnected.py
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
"""Semiconnectedness."""
|
||||
import networkx as nx
|
||||
from networkx.utils import not_implemented_for, pairwise
|
||||
|
||||
__all__ = ["is_semiconnected"]
|
||||
|
||||
|
||||
@not_implemented_for("undirected")
|
||||
def is_semiconnected(G, topo_order=None):
|
||||
"""Returns True if the graph is semiconnected, False otherwise.
|
||||
|
||||
A graph is semiconnected if, and only if, for any pair of nodes, either one
|
||||
is reachable from the other, or they are mutually reachable.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX graph
|
||||
A directed graph.
|
||||
|
||||
topo_order: list or tuple, optional
|
||||
A topological order for G (if None, the function will compute one)
|
||||
|
||||
Returns
|
||||
-------
|
||||
semiconnected : bool
|
||||
True if the graph is semiconnected, False otherwise.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If the input graph is undirected.
|
||||
|
||||
NetworkXPointlessConcept
|
||||
If the graph is empty.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> G = nx.path_graph(4, create_using=nx.DiGraph())
|
||||
>>> print(nx.is_semiconnected(G))
|
||||
True
|
||||
>>> G = nx.DiGraph([(1, 2), (3, 2)])
|
||||
>>> print(nx.is_semiconnected(G))
|
||||
False
|
||||
|
||||
See Also
|
||||
--------
|
||||
is_strongly_connected
|
||||
is_weakly_connected
|
||||
is_connected
|
||||
is_biconnected
|
||||
"""
|
||||
if len(G) == 0:
|
||||
raise nx.NetworkXPointlessConcept(
|
||||
"Connectivity is undefined for the null graph."
|
||||
)
|
||||
|
||||
if not nx.is_weakly_connected(G):
|
||||
return False
|
||||
|
||||
G = nx.condensation(G)
|
||||
if topo_order is None:
|
||||
topo_order = nx.topological_sort(G)
|
||||
|
||||
return all(G.has_edge(u, v) for u, v in pairwise(topo_order))
|
||||
438
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/strongly_connected.py
vendored
Normal file
438
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/strongly_connected.py
vendored
Normal file
@@ -0,0 +1,438 @@
|
||||
"""Strongly connected components."""
|
||||
import networkx as nx
|
||||
from networkx.utils.decorators import not_implemented_for
|
||||
|
||||
__all__ = [
|
||||
"number_strongly_connected_components",
|
||||
"strongly_connected_components",
|
||||
"is_strongly_connected",
|
||||
"strongly_connected_components_recursive",
|
||||
"kosaraju_strongly_connected_components",
|
||||
"condensation",
|
||||
]
|
||||
|
||||
|
||||
@nx._dispatch
|
||||
@not_implemented_for("undirected")
|
||||
def strongly_connected_components(G):
|
||||
"""Generate nodes in strongly connected components of graph.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX Graph
|
||||
A directed graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
comp : generator of sets
|
||||
A generator of sets of nodes, one for each strongly connected
|
||||
component of G.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If G is undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Generate a sorted list of strongly connected components, largest first.
|
||||
|
||||
>>> G = nx.cycle_graph(4, create_using=nx.DiGraph())
|
||||
>>> nx.add_cycle(G, [10, 11, 12])
|
||||
>>> [
|
||||
... len(c)
|
||||
... for c in sorted(nx.strongly_connected_components(G), key=len, reverse=True)
|
||||
... ]
|
||||
[4, 3]
|
||||
|
||||
If you only want the largest component, it's more efficient to
|
||||
use max instead of sort.
|
||||
|
||||
>>> largest = max(nx.strongly_connected_components(G), key=len)
|
||||
|
||||
See Also
|
||||
--------
|
||||
connected_components
|
||||
weakly_connected_components
|
||||
kosaraju_strongly_connected_components
|
||||
|
||||
Notes
|
||||
-----
|
||||
Uses Tarjan's algorithm[1]_ with Nuutila's modifications[2]_.
|
||||
Nonrecursive version of algorithm.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Depth-first search and linear graph algorithms, R. Tarjan
|
||||
SIAM Journal of Computing 1(2):146-160, (1972).
|
||||
|
||||
.. [2] On finding the strongly connected components in a directed graph.
|
||||
E. Nuutila and E. Soisalon-Soinen
|
||||
Information Processing Letters 49(1): 9-14, (1994)..
|
||||
|
||||
"""
|
||||
preorder = {}
|
||||
lowlink = {}
|
||||
scc_found = set()
|
||||
scc_queue = []
|
||||
i = 0 # Preorder counter
|
||||
neighbors = {v: iter(G[v]) for v in G}
|
||||
for source in G:
|
||||
if source not in scc_found:
|
||||
queue = [source]
|
||||
while queue:
|
||||
v = queue[-1]
|
||||
if v not in preorder:
|
||||
i = i + 1
|
||||
preorder[v] = i
|
||||
done = True
|
||||
for w in neighbors[v]:
|
||||
if w not in preorder:
|
||||
queue.append(w)
|
||||
done = False
|
||||
break
|
||||
if done:
|
||||
lowlink[v] = preorder[v]
|
||||
for w in G[v]:
|
||||
if w not in scc_found:
|
||||
if preorder[w] > preorder[v]:
|
||||
lowlink[v] = min([lowlink[v], lowlink[w]])
|
||||
else:
|
||||
lowlink[v] = min([lowlink[v], preorder[w]])
|
||||
queue.pop()
|
||||
if lowlink[v] == preorder[v]:
|
||||
scc = {v}
|
||||
while scc_queue and preorder[scc_queue[-1]] > preorder[v]:
|
||||
k = scc_queue.pop()
|
||||
scc.add(k)
|
||||
scc_found.update(scc)
|
||||
yield scc
|
||||
else:
|
||||
scc_queue.append(v)
|
||||
|
||||
|
||||
@not_implemented_for("undirected")
|
||||
def kosaraju_strongly_connected_components(G, source=None):
|
||||
"""Generate nodes in strongly connected components of graph.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX Graph
|
||||
A directed graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
comp : generator of sets
|
||||
A generator of sets of nodes, one for each strongly connected
|
||||
component of G.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If G is undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Generate a sorted list of strongly connected components, largest first.
|
||||
|
||||
>>> G = nx.cycle_graph(4, create_using=nx.DiGraph())
|
||||
>>> nx.add_cycle(G, [10, 11, 12])
|
||||
>>> [
|
||||
... len(c)
|
||||
... for c in sorted(
|
||||
... nx.kosaraju_strongly_connected_components(G), key=len, reverse=True
|
||||
... )
|
||||
... ]
|
||||
[4, 3]
|
||||
|
||||
If you only want the largest component, it's more efficient to
|
||||
use max instead of sort.
|
||||
|
||||
>>> largest = max(nx.kosaraju_strongly_connected_components(G), key=len)
|
||||
|
||||
See Also
|
||||
--------
|
||||
strongly_connected_components
|
||||
|
||||
Notes
|
||||
-----
|
||||
Uses Kosaraju's algorithm.
|
||||
|
||||
"""
|
||||
post = list(nx.dfs_postorder_nodes(G.reverse(copy=False), source=source))
|
||||
|
||||
seen = set()
|
||||
while post:
|
||||
r = post.pop()
|
||||
if r in seen:
|
||||
continue
|
||||
c = nx.dfs_preorder_nodes(G, r)
|
||||
new = {v for v in c if v not in seen}
|
||||
seen.update(new)
|
||||
yield new
|
||||
|
||||
|
||||
@not_implemented_for("undirected")
|
||||
def strongly_connected_components_recursive(G):
|
||||
"""Generate nodes in strongly connected components of graph.
|
||||
|
||||
Recursive version of algorithm.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX Graph
|
||||
A directed graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
comp : generator of sets
|
||||
A generator of sets of nodes, one for each strongly connected
|
||||
component of G.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If G is undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Generate a sorted list of strongly connected components, largest first.
|
||||
|
||||
>>> G = nx.cycle_graph(4, create_using=nx.DiGraph())
|
||||
>>> nx.add_cycle(G, [10, 11, 12])
|
||||
>>> [
|
||||
... len(c)
|
||||
... for c in sorted(
|
||||
... nx.strongly_connected_components_recursive(G), key=len, reverse=True
|
||||
... )
|
||||
... ]
|
||||
[4, 3]
|
||||
|
||||
If you only want the largest component, it's more efficient to
|
||||
use max instead of sort.
|
||||
|
||||
>>> largest = max(nx.strongly_connected_components_recursive(G), key=len)
|
||||
|
||||
To create the induced subgraph of the components use:
|
||||
>>> S = [G.subgraph(c).copy() for c in nx.weakly_connected_components(G)]
|
||||
|
||||
See Also
|
||||
--------
|
||||
connected_components
|
||||
|
||||
Notes
|
||||
-----
|
||||
Uses Tarjan's algorithm[1]_ with Nuutila's modifications[2]_.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] Depth-first search and linear graph algorithms, R. Tarjan
|
||||
SIAM Journal of Computing 1(2):146-160, (1972).
|
||||
|
||||
.. [2] On finding the strongly connected components in a directed graph.
|
||||
E. Nuutila and E. Soisalon-Soinen
|
||||
Information Processing Letters 49(1): 9-14, (1994)..
|
||||
|
||||
"""
|
||||
|
||||
def visit(v, cnt):
|
||||
root[v] = cnt
|
||||
visited[v] = cnt
|
||||
cnt += 1
|
||||
stack.append(v)
|
||||
for w in G[v]:
|
||||
if w not in visited:
|
||||
yield from visit(w, cnt)
|
||||
if w not in component:
|
||||
root[v] = min(root[v], root[w])
|
||||
if root[v] == visited[v]:
|
||||
component[v] = root[v]
|
||||
tmpc = {v} # hold nodes in this component
|
||||
while stack[-1] != v:
|
||||
w = stack.pop()
|
||||
component[w] = root[v]
|
||||
tmpc.add(w)
|
||||
stack.remove(v)
|
||||
yield tmpc
|
||||
|
||||
visited = {}
|
||||
component = {}
|
||||
root = {}
|
||||
cnt = 0
|
||||
stack = []
|
||||
for source in G:
|
||||
if source not in visited:
|
||||
yield from visit(source, cnt)
|
||||
|
||||
|
||||
@not_implemented_for("undirected")
|
||||
def number_strongly_connected_components(G):
|
||||
"""Returns number of strongly connected components in graph.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX graph
|
||||
A directed graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
n : integer
|
||||
Number of strongly connected components
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If G is undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> G = nx.DiGraph([(0, 1), (1, 2), (2, 0), (2, 3), (4, 5), (3, 4), (5, 6), (6, 3), (6, 7)])
|
||||
>>> nx.number_strongly_connected_components(G)
|
||||
3
|
||||
|
||||
See Also
|
||||
--------
|
||||
strongly_connected_components
|
||||
number_connected_components
|
||||
number_weakly_connected_components
|
||||
|
||||
Notes
|
||||
-----
|
||||
For directed graphs only.
|
||||
"""
|
||||
return sum(1 for scc in strongly_connected_components(G))
|
||||
|
||||
|
||||
@not_implemented_for("undirected")
|
||||
def is_strongly_connected(G):
|
||||
"""Test directed graph for strong connectivity.
|
||||
|
||||
A directed graph is strongly connected if and only if every vertex in
|
||||
the graph is reachable from every other vertex.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX Graph
|
||||
A directed graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
connected : bool
|
||||
True if the graph is strongly connected, False otherwise.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> G = nx.DiGraph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 2)])
|
||||
>>> nx.is_strongly_connected(G)
|
||||
True
|
||||
>>> G.remove_edge(2, 3)
|
||||
>>> nx.is_strongly_connected(G)
|
||||
False
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If G is undirected.
|
||||
|
||||
See Also
|
||||
--------
|
||||
is_weakly_connected
|
||||
is_semiconnected
|
||||
is_connected
|
||||
is_biconnected
|
||||
strongly_connected_components
|
||||
|
||||
Notes
|
||||
-----
|
||||
For directed graphs only.
|
||||
"""
|
||||
if len(G) == 0:
|
||||
raise nx.NetworkXPointlessConcept(
|
||||
"""Connectivity is undefined for the null graph."""
|
||||
)
|
||||
|
||||
return len(next(strongly_connected_components(G))) == len(G)
|
||||
|
||||
|
||||
@not_implemented_for("undirected")
|
||||
def condensation(G, scc=None):
|
||||
"""Returns the condensation of G.
|
||||
|
||||
The condensation of G is the graph with each of the strongly connected
|
||||
components contracted into a single node.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX DiGraph
|
||||
A directed graph.
|
||||
|
||||
scc: list or generator (optional, default=None)
|
||||
Strongly connected components. If provided, the elements in
|
||||
`scc` must partition the nodes in `G`. If not provided, it will be
|
||||
calculated as scc=nx.strongly_connected_components(G).
|
||||
|
||||
Returns
|
||||
-------
|
||||
C : NetworkX DiGraph
|
||||
The condensation graph C of G. The node labels are integers
|
||||
corresponding to the index of the component in the list of
|
||||
strongly connected components of G. C has a graph attribute named
|
||||
'mapping' with a dictionary mapping the original nodes to the
|
||||
nodes in C to which they belong. Each node in C also has a node
|
||||
attribute 'members' with the set of original nodes in G that
|
||||
form the SCC that the node in C represents.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If G is undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Contracting two sets of strongly connected nodes into two distinct SCC
|
||||
using the barbell graph.
|
||||
|
||||
>>> G = nx.barbell_graph(4, 0)
|
||||
>>> G.remove_edge(3, 4)
|
||||
>>> G = nx.DiGraph(G)
|
||||
>>> H = nx.condensation(G)
|
||||
>>> H.nodes.data()
|
||||
NodeDataView({0: {'members': {0, 1, 2, 3}}, 1: {'members': {4, 5, 6, 7}}})
|
||||
>>> H.graph['mapping']
|
||||
{0: 0, 1: 0, 2: 0, 3: 0, 4: 1, 5: 1, 6: 1, 7: 1}
|
||||
|
||||
Contracting a complete graph into one single SCC.
|
||||
|
||||
>>> G = nx.complete_graph(7, create_using=nx.DiGraph)
|
||||
>>> H = nx.condensation(G)
|
||||
>>> H.nodes
|
||||
NodeView((0,))
|
||||
>>> H.nodes.data()
|
||||
NodeDataView({0: {'members': {0, 1, 2, 3, 4, 5, 6}}})
|
||||
|
||||
Notes
|
||||
-----
|
||||
After contracting all strongly connected components to a single node,
|
||||
the resulting graph is a directed acyclic graph.
|
||||
|
||||
"""
|
||||
if scc is None:
|
||||
scc = nx.strongly_connected_components(G)
|
||||
mapping = {}
|
||||
members = {}
|
||||
C = nx.DiGraph()
|
||||
# Add mapping dict as graph attribute
|
||||
C.graph["mapping"] = mapping
|
||||
if len(G) == 0:
|
||||
return C
|
||||
for i, component in enumerate(scc):
|
||||
members[i] = component
|
||||
mapping.update((n, i) for n in component)
|
||||
number_of_components = i + 1
|
||||
C.add_nodes_from(range(number_of_components))
|
||||
C.add_edges_from(
|
||||
(mapping[u], mapping[v]) for u, v in G.edges() if mapping[u] != mapping[v]
|
||||
)
|
||||
# Add a list of members (ie original nodes) to each node (ie scc) in C.
|
||||
nx.set_node_attributes(C, members, "members")
|
||||
return C
|
||||
0
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/__init__.py
vendored
Normal file
0
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/__init__.py
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
70
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_attracting.py
vendored
Normal file
70
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_attracting.py
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx import NetworkXNotImplemented
|
||||
|
||||
|
||||
class TestAttractingComponents:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.G1 = nx.DiGraph()
|
||||
cls.G1.add_edges_from(
|
||||
[
|
||||
(5, 11),
|
||||
(11, 2),
|
||||
(11, 9),
|
||||
(11, 10),
|
||||
(7, 11),
|
||||
(7, 8),
|
||||
(8, 9),
|
||||
(3, 8),
|
||||
(3, 10),
|
||||
]
|
||||
)
|
||||
cls.G2 = nx.DiGraph()
|
||||
cls.G2.add_edges_from([(0, 1), (0, 2), (1, 1), (1, 2), (2, 1)])
|
||||
|
||||
cls.G3 = nx.DiGraph()
|
||||
cls.G3.add_edges_from([(0, 1), (1, 2), (2, 1), (0, 3), (3, 4), (4, 3)])
|
||||
|
||||
cls.G4 = nx.DiGraph()
|
||||
|
||||
def test_attracting_components(self):
|
||||
ac = list(nx.attracting_components(self.G1))
|
||||
assert {2} in ac
|
||||
assert {9} in ac
|
||||
assert {10} in ac
|
||||
|
||||
ac = list(nx.attracting_components(self.G2))
|
||||
ac = [tuple(sorted(x)) for x in ac]
|
||||
assert ac == [(1, 2)]
|
||||
|
||||
ac = list(nx.attracting_components(self.G3))
|
||||
ac = [tuple(sorted(x)) for x in ac]
|
||||
assert (1, 2) in ac
|
||||
assert (3, 4) in ac
|
||||
assert len(ac) == 2
|
||||
|
||||
ac = list(nx.attracting_components(self.G4))
|
||||
assert ac == []
|
||||
|
||||
def test_number_attacting_components(self):
|
||||
assert nx.number_attracting_components(self.G1) == 3
|
||||
assert nx.number_attracting_components(self.G2) == 1
|
||||
assert nx.number_attracting_components(self.G3) == 2
|
||||
assert nx.number_attracting_components(self.G4) == 0
|
||||
|
||||
def test_is_attracting_component(self):
|
||||
assert not nx.is_attracting_component(self.G1)
|
||||
assert not nx.is_attracting_component(self.G2)
|
||||
assert not nx.is_attracting_component(self.G3)
|
||||
g2 = self.G3.subgraph([1, 2])
|
||||
assert nx.is_attracting_component(g2)
|
||||
assert not nx.is_attracting_component(self.G4)
|
||||
|
||||
def test_connected_raise(self):
|
||||
G = nx.Graph()
|
||||
with pytest.raises(NetworkXNotImplemented):
|
||||
next(nx.attracting_components(G))
|
||||
pytest.raises(NetworkXNotImplemented, nx.number_attracting_components, G)
|
||||
pytest.raises(NetworkXNotImplemented, nx.is_attracting_component, G)
|
||||
248
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_biconnected.py
vendored
Normal file
248
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_biconnected.py
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx import NetworkXNotImplemented
|
||||
|
||||
|
||||
def assert_components_edges_equal(x, y):
|
||||
sx = {frozenset(frozenset(e) for e in c) for c in x}
|
||||
sy = {frozenset(frozenset(e) for e in c) for c in y}
|
||||
assert sx == sy
|
||||
|
||||
|
||||
def assert_components_equal(x, y):
|
||||
sx = {frozenset(c) for c in x}
|
||||
sy = {frozenset(c) for c in y}
|
||||
assert sx == sy
|
||||
|
||||
|
||||
def test_barbell():
|
||||
G = nx.barbell_graph(8, 4)
|
||||
nx.add_path(G, [7, 20, 21, 22])
|
||||
nx.add_cycle(G, [22, 23, 24, 25])
|
||||
pts = set(nx.articulation_points(G))
|
||||
assert pts == {7, 8, 9, 10, 11, 12, 20, 21, 22}
|
||||
|
||||
answer = [
|
||||
{12, 13, 14, 15, 16, 17, 18, 19},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7},
|
||||
{22, 23, 24, 25},
|
||||
{11, 12},
|
||||
{10, 11},
|
||||
{9, 10},
|
||||
{8, 9},
|
||||
{7, 8},
|
||||
{21, 22},
|
||||
{20, 21},
|
||||
{7, 20},
|
||||
]
|
||||
assert_components_equal(list(nx.biconnected_components(G)), answer)
|
||||
|
||||
G.add_edge(2, 17)
|
||||
pts = set(nx.articulation_points(G))
|
||||
assert pts == {7, 20, 21, 22}
|
||||
|
||||
|
||||
def test_articulation_points_repetitions():
|
||||
G = nx.Graph()
|
||||
G.add_edges_from([(0, 1), (1, 2), (1, 3)])
|
||||
assert list(nx.articulation_points(G)) == [1]
|
||||
|
||||
|
||||
def test_articulation_points_cycle():
|
||||
G = nx.cycle_graph(3)
|
||||
nx.add_cycle(G, [1, 3, 4])
|
||||
pts = set(nx.articulation_points(G))
|
||||
assert pts == {1}
|
||||
|
||||
|
||||
def test_is_biconnected():
|
||||
G = nx.cycle_graph(3)
|
||||
assert nx.is_biconnected(G)
|
||||
nx.add_cycle(G, [1, 3, 4])
|
||||
assert not nx.is_biconnected(G)
|
||||
|
||||
|
||||
def test_empty_is_biconnected():
|
||||
G = nx.empty_graph(5)
|
||||
assert not nx.is_biconnected(G)
|
||||
G.add_edge(0, 1)
|
||||
assert not nx.is_biconnected(G)
|
||||
|
||||
|
||||
def test_biconnected_components_cycle():
|
||||
G = nx.cycle_graph(3)
|
||||
nx.add_cycle(G, [1, 3, 4])
|
||||
answer = [{0, 1, 2}, {1, 3, 4}]
|
||||
assert_components_equal(list(nx.biconnected_components(G)), answer)
|
||||
|
||||
|
||||
def test_biconnected_components1():
|
||||
# graph example from
|
||||
# https://web.archive.org/web/20121229123447/http://www.ibluemojo.com/school/articul_algorithm.html
|
||||
edges = [
|
||||
(0, 1),
|
||||
(0, 5),
|
||||
(0, 6),
|
||||
(0, 14),
|
||||
(1, 5),
|
||||
(1, 6),
|
||||
(1, 14),
|
||||
(2, 4),
|
||||
(2, 10),
|
||||
(3, 4),
|
||||
(3, 15),
|
||||
(4, 6),
|
||||
(4, 7),
|
||||
(4, 10),
|
||||
(5, 14),
|
||||
(6, 14),
|
||||
(7, 9),
|
||||
(8, 9),
|
||||
(8, 12),
|
||||
(8, 13),
|
||||
(10, 15),
|
||||
(11, 12),
|
||||
(11, 13),
|
||||
(12, 13),
|
||||
]
|
||||
G = nx.Graph(edges)
|
||||
pts = set(nx.articulation_points(G))
|
||||
assert pts == {4, 6, 7, 8, 9}
|
||||
comps = list(nx.biconnected_component_edges(G))
|
||||
answer = [
|
||||
[(3, 4), (15, 3), (10, 15), (10, 4), (2, 10), (4, 2)],
|
||||
[(13, 12), (13, 8), (11, 13), (12, 11), (8, 12)],
|
||||
[(9, 8)],
|
||||
[(7, 9)],
|
||||
[(4, 7)],
|
||||
[(6, 4)],
|
||||
[(14, 0), (5, 1), (5, 0), (14, 5), (14, 1), (6, 14), (6, 0), (1, 6), (0, 1)],
|
||||
]
|
||||
assert_components_edges_equal(comps, answer)
|
||||
|
||||
|
||||
def test_biconnected_components2():
|
||||
G = nx.Graph()
|
||||
nx.add_cycle(G, "ABC")
|
||||
nx.add_cycle(G, "CDE")
|
||||
nx.add_cycle(G, "FIJHG")
|
||||
nx.add_cycle(G, "GIJ")
|
||||
G.add_edge("E", "G")
|
||||
comps = list(nx.biconnected_component_edges(G))
|
||||
answer = [
|
||||
[
|
||||
tuple("GF"),
|
||||
tuple("FI"),
|
||||
tuple("IG"),
|
||||
tuple("IJ"),
|
||||
tuple("JG"),
|
||||
tuple("JH"),
|
||||
tuple("HG"),
|
||||
],
|
||||
[tuple("EG")],
|
||||
[tuple("CD"), tuple("DE"), tuple("CE")],
|
||||
[tuple("AB"), tuple("BC"), tuple("AC")],
|
||||
]
|
||||
assert_components_edges_equal(comps, answer)
|
||||
|
||||
|
||||
def test_biconnected_davis():
|
||||
D = nx.davis_southern_women_graph()
|
||||
bcc = list(nx.biconnected_components(D))[0]
|
||||
assert set(D) == bcc # All nodes in a giant bicomponent
|
||||
# So no articulation points
|
||||
assert len(list(nx.articulation_points(D))) == 0
|
||||
|
||||
|
||||
def test_biconnected_karate():
|
||||
K = nx.karate_club_graph()
|
||||
answer = [
|
||||
{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
31,
|
||||
32,
|
||||
33,
|
||||
},
|
||||
{0, 4, 5, 6, 10, 16},
|
||||
{0, 11},
|
||||
]
|
||||
bcc = list(nx.biconnected_components(K))
|
||||
assert_components_equal(bcc, answer)
|
||||
assert set(nx.articulation_points(K)) == {0}
|
||||
|
||||
|
||||
def test_biconnected_eppstein():
|
||||
# tests from http://www.ics.uci.edu/~eppstein/PADS/Biconnectivity.py
|
||||
G1 = nx.Graph(
|
||||
{
|
||||
0: [1, 2, 5],
|
||||
1: [0, 5],
|
||||
2: [0, 3, 4],
|
||||
3: [2, 4, 5, 6],
|
||||
4: [2, 3, 5, 6],
|
||||
5: [0, 1, 3, 4],
|
||||
6: [3, 4],
|
||||
}
|
||||
)
|
||||
G2 = nx.Graph(
|
||||
{
|
||||
0: [2, 5],
|
||||
1: [3, 8],
|
||||
2: [0, 3, 5],
|
||||
3: [1, 2, 6, 8],
|
||||
4: [7],
|
||||
5: [0, 2],
|
||||
6: [3, 8],
|
||||
7: [4],
|
||||
8: [1, 3, 6],
|
||||
}
|
||||
)
|
||||
assert nx.is_biconnected(G1)
|
||||
assert not nx.is_biconnected(G2)
|
||||
answer_G2 = [{1, 3, 6, 8}, {0, 2, 5}, {2, 3}, {4, 7}]
|
||||
bcc = list(nx.biconnected_components(G2))
|
||||
assert_components_equal(bcc, answer_G2)
|
||||
|
||||
|
||||
def test_null_graph():
|
||||
G = nx.Graph()
|
||||
assert not nx.is_biconnected(G)
|
||||
assert list(nx.biconnected_components(G)) == []
|
||||
assert list(nx.biconnected_component_edges(G)) == []
|
||||
assert list(nx.articulation_points(G)) == []
|
||||
|
||||
|
||||
def test_connected_raise():
|
||||
DG = nx.DiGraph()
|
||||
with pytest.raises(NetworkXNotImplemented):
|
||||
next(nx.biconnected_components(DG))
|
||||
with pytest.raises(NetworkXNotImplemented):
|
||||
next(nx.biconnected_component_edges(DG))
|
||||
with pytest.raises(NetworkXNotImplemented):
|
||||
next(nx.articulation_points(DG))
|
||||
pytest.raises(NetworkXNotImplemented, nx.is_biconnected, DG)
|
||||
117
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_connected.py
vendored
Normal file
117
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_connected.py
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx import NetworkXNotImplemented
|
||||
from networkx import convert_node_labels_to_integers as cnlti
|
||||
from networkx.classes.tests import dispatch_interface
|
||||
|
||||
|
||||
class TestConnected:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
G1 = cnlti(nx.grid_2d_graph(2, 2), first_label=0, ordering="sorted")
|
||||
G2 = cnlti(nx.lollipop_graph(3, 3), first_label=4, ordering="sorted")
|
||||
G3 = cnlti(nx.house_graph(), first_label=10, ordering="sorted")
|
||||
cls.G = nx.union(G1, G2)
|
||||
cls.G = nx.union(cls.G, G3)
|
||||
cls.DG = nx.DiGraph([(1, 2), (1, 3), (2, 3)])
|
||||
cls.grid = cnlti(nx.grid_2d_graph(4, 4), first_label=1)
|
||||
|
||||
cls.gc = []
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from(
|
||||
[
|
||||
(1, 2),
|
||||
(2, 3),
|
||||
(2, 8),
|
||||
(3, 4),
|
||||
(3, 7),
|
||||
(4, 5),
|
||||
(5, 3),
|
||||
(5, 6),
|
||||
(7, 4),
|
||||
(7, 6),
|
||||
(8, 1),
|
||||
(8, 7),
|
||||
]
|
||||
)
|
||||
C = [[3, 4, 5, 7], [1, 2, 8], [6]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from([(1, 2), (1, 3), (1, 4), (4, 2), (3, 4), (2, 3)])
|
||||
C = [[2, 3, 4], [1]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from([(1, 2), (2, 3), (3, 2), (2, 1)])
|
||||
C = [[1, 2, 3]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
# Eppstein's tests
|
||||
G = nx.DiGraph({0: [1], 1: [2, 3], 2: [4, 5], 3: [4, 5], 4: [6], 5: [], 6: []})
|
||||
C = [[0], [1], [2], [3], [4], [5], [6]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph({0: [1], 1: [2, 3, 4], 2: [0, 3], 3: [4], 4: [3]})
|
||||
C = [[0, 1, 2], [3, 4]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph()
|
||||
C = []
|
||||
cls.gc.append((G, C))
|
||||
|
||||
# This additionally tests the @nx._dispatch mechanism, treating
|
||||
# nx.connected_components as if it were a re-implementation from another package
|
||||
@pytest.mark.parametrize("wrapper", [lambda x: x, dispatch_interface.convert])
|
||||
def test_connected_components(self, wrapper):
|
||||
cc = nx.connected_components
|
||||
G = wrapper(self.G)
|
||||
C = {
|
||||
frozenset([0, 1, 2, 3]),
|
||||
frozenset([4, 5, 6, 7, 8, 9]),
|
||||
frozenset([10, 11, 12, 13, 14]),
|
||||
}
|
||||
assert {frozenset(g) for g in cc(G)} == C
|
||||
|
||||
def test_number_connected_components(self):
|
||||
ncc = nx.number_connected_components
|
||||
assert ncc(self.G) == 3
|
||||
|
||||
def test_number_connected_components2(self):
|
||||
ncc = nx.number_connected_components
|
||||
assert ncc(self.grid) == 1
|
||||
|
||||
def test_connected_components2(self):
|
||||
cc = nx.connected_components
|
||||
G = self.grid
|
||||
C = {frozenset([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])}
|
||||
assert {frozenset(g) for g in cc(G)} == C
|
||||
|
||||
def test_node_connected_components(self):
|
||||
ncc = nx.node_connected_component
|
||||
G = self.grid
|
||||
C = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
|
||||
assert ncc(G, 1) == C
|
||||
|
||||
def test_is_connected(self):
|
||||
assert nx.is_connected(self.grid)
|
||||
G = nx.Graph()
|
||||
G.add_nodes_from([1, 2])
|
||||
assert not nx.is_connected(G)
|
||||
|
||||
def test_connected_raise(self):
|
||||
with pytest.raises(NetworkXNotImplemented):
|
||||
next(nx.connected_components(self.DG))
|
||||
pytest.raises(NetworkXNotImplemented, nx.number_connected_components, self.DG)
|
||||
pytest.raises(NetworkXNotImplemented, nx.node_connected_component, self.DG, 1)
|
||||
pytest.raises(NetworkXNotImplemented, nx.is_connected, self.DG)
|
||||
pytest.raises(nx.NetworkXPointlessConcept, nx.is_connected, nx.Graph())
|
||||
|
||||
def test_connected_mutability(self):
|
||||
G = self.grid
|
||||
seen = set()
|
||||
for component in nx.connected_components(G):
|
||||
assert len(seen & component) == 0
|
||||
seen.update(component)
|
||||
component.clear()
|
||||
55
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_semiconnected.py
vendored
Normal file
55
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_semiconnected.py
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
from itertools import chain
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
class TestIsSemiconnected:
|
||||
def test_undirected(self):
|
||||
pytest.raises(nx.NetworkXNotImplemented, nx.is_semiconnected, nx.Graph())
|
||||
pytest.raises(nx.NetworkXNotImplemented, nx.is_semiconnected, nx.MultiGraph())
|
||||
|
||||
def test_empty(self):
|
||||
pytest.raises(nx.NetworkXPointlessConcept, nx.is_semiconnected, nx.DiGraph())
|
||||
pytest.raises(
|
||||
nx.NetworkXPointlessConcept, nx.is_semiconnected, nx.MultiDiGraph()
|
||||
)
|
||||
|
||||
def test_single_node_graph(self):
|
||||
G = nx.DiGraph()
|
||||
G.add_node(0)
|
||||
assert nx.is_semiconnected(G)
|
||||
|
||||
def test_path(self):
|
||||
G = nx.path_graph(100, create_using=nx.DiGraph())
|
||||
assert nx.is_semiconnected(G)
|
||||
G.add_edge(100, 99)
|
||||
assert not nx.is_semiconnected(G)
|
||||
|
||||
def test_cycle(self):
|
||||
G = nx.cycle_graph(100, create_using=nx.DiGraph())
|
||||
assert nx.is_semiconnected(G)
|
||||
G = nx.path_graph(100, create_using=nx.DiGraph())
|
||||
G.add_edge(0, 99)
|
||||
assert nx.is_semiconnected(G)
|
||||
|
||||
def test_tree(self):
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from(
|
||||
chain.from_iterable([(i, 2 * i + 1), (i, 2 * i + 2)] for i in range(100))
|
||||
)
|
||||
assert not nx.is_semiconnected(G)
|
||||
|
||||
def test_dumbbell(self):
|
||||
G = nx.cycle_graph(100, create_using=nx.DiGraph())
|
||||
G.add_edges_from((i + 100, (i + 1) % 100 + 100) for i in range(100))
|
||||
assert not nx.is_semiconnected(G) # G is disconnected.
|
||||
G.add_edge(100, 99)
|
||||
assert nx.is_semiconnected(G)
|
||||
|
||||
def test_alternating_path(self):
|
||||
G = nx.DiGraph(
|
||||
chain.from_iterable([(i, i - 1), (i, i + 1)] for i in range(0, 100, 2))
|
||||
)
|
||||
assert not nx.is_semiconnected(G)
|
||||
205
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_strongly_connected.py
vendored
Normal file
205
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_strongly_connected.py
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx import NetworkXNotImplemented
|
||||
|
||||
|
||||
class TestStronglyConnected:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.gc = []
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from(
|
||||
[
|
||||
(1, 2),
|
||||
(2, 3),
|
||||
(2, 8),
|
||||
(3, 4),
|
||||
(3, 7),
|
||||
(4, 5),
|
||||
(5, 3),
|
||||
(5, 6),
|
||||
(7, 4),
|
||||
(7, 6),
|
||||
(8, 1),
|
||||
(8, 7),
|
||||
]
|
||||
)
|
||||
C = {frozenset([3, 4, 5, 7]), frozenset([1, 2, 8]), frozenset([6])}
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from([(1, 2), (1, 3), (1, 4), (4, 2), (3, 4), (2, 3)])
|
||||
C = {frozenset([2, 3, 4]), frozenset([1])}
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from([(1, 2), (2, 3), (3, 2), (2, 1)])
|
||||
C = {frozenset([1, 2, 3])}
|
||||
cls.gc.append((G, C))
|
||||
|
||||
# Eppstein's tests
|
||||
G = nx.DiGraph({0: [1], 1: [2, 3], 2: [4, 5], 3: [4, 5], 4: [6], 5: [], 6: []})
|
||||
C = {
|
||||
frozenset([0]),
|
||||
frozenset([1]),
|
||||
frozenset([2]),
|
||||
frozenset([3]),
|
||||
frozenset([4]),
|
||||
frozenset([5]),
|
||||
frozenset([6]),
|
||||
}
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph({0: [1], 1: [2, 3, 4], 2: [0, 3], 3: [4], 4: [3]})
|
||||
C = {frozenset([0, 1, 2]), frozenset([3, 4])}
|
||||
cls.gc.append((G, C))
|
||||
|
||||
def test_tarjan(self):
|
||||
scc = nx.strongly_connected_components
|
||||
for G, C in self.gc:
|
||||
assert {frozenset(g) for g in scc(G)} == C
|
||||
|
||||
def test_tarjan_recursive(self):
|
||||
scc = nx.strongly_connected_components_recursive
|
||||
for G, C in self.gc:
|
||||
assert {frozenset(g) for g in scc(G)} == C
|
||||
|
||||
def test_kosaraju(self):
|
||||
scc = nx.kosaraju_strongly_connected_components
|
||||
for G, C in self.gc:
|
||||
assert {frozenset(g) for g in scc(G)} == C
|
||||
|
||||
def test_number_strongly_connected_components(self):
|
||||
ncc = nx.number_strongly_connected_components
|
||||
for G, C in self.gc:
|
||||
assert ncc(G) == len(C)
|
||||
|
||||
def test_is_strongly_connected(self):
|
||||
for G, C in self.gc:
|
||||
if len(C) == 1:
|
||||
assert nx.is_strongly_connected(G)
|
||||
else:
|
||||
assert not nx.is_strongly_connected(G)
|
||||
|
||||
def test_contract_scc1(self):
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from(
|
||||
[
|
||||
(1, 2),
|
||||
(2, 3),
|
||||
(2, 11),
|
||||
(2, 12),
|
||||
(3, 4),
|
||||
(4, 3),
|
||||
(4, 5),
|
||||
(5, 6),
|
||||
(6, 5),
|
||||
(6, 7),
|
||||
(7, 8),
|
||||
(7, 9),
|
||||
(7, 10),
|
||||
(8, 9),
|
||||
(9, 7),
|
||||
(10, 6),
|
||||
(11, 2),
|
||||
(11, 4),
|
||||
(11, 6),
|
||||
(12, 6),
|
||||
(12, 11),
|
||||
]
|
||||
)
|
||||
scc = list(nx.strongly_connected_components(G))
|
||||
cG = nx.condensation(G, scc)
|
||||
# DAG
|
||||
assert nx.is_directed_acyclic_graph(cG)
|
||||
# nodes
|
||||
assert sorted(cG.nodes()) == [0, 1, 2, 3]
|
||||
# edges
|
||||
mapping = {}
|
||||
for i, component in enumerate(scc):
|
||||
for n in component:
|
||||
mapping[n] = i
|
||||
edge = (mapping[2], mapping[3])
|
||||
assert cG.has_edge(*edge)
|
||||
edge = (mapping[2], mapping[5])
|
||||
assert cG.has_edge(*edge)
|
||||
edge = (mapping[3], mapping[5])
|
||||
assert cG.has_edge(*edge)
|
||||
|
||||
def test_contract_scc_isolate(self):
|
||||
# Bug found and fixed in [1687].
|
||||
G = nx.DiGraph()
|
||||
G.add_edge(1, 2)
|
||||
G.add_edge(2, 1)
|
||||
scc = list(nx.strongly_connected_components(G))
|
||||
cG = nx.condensation(G, scc)
|
||||
assert list(cG.nodes()) == [0]
|
||||
assert list(cG.edges()) == []
|
||||
|
||||
def test_contract_scc_edge(self):
|
||||
G = nx.DiGraph()
|
||||
G.add_edge(1, 2)
|
||||
G.add_edge(2, 1)
|
||||
G.add_edge(2, 3)
|
||||
G.add_edge(3, 4)
|
||||
G.add_edge(4, 3)
|
||||
scc = list(nx.strongly_connected_components(G))
|
||||
cG = nx.condensation(G, scc)
|
||||
assert sorted(cG.nodes()) == [0, 1]
|
||||
if 1 in scc[0]:
|
||||
edge = (0, 1)
|
||||
else:
|
||||
edge = (1, 0)
|
||||
assert list(cG.edges()) == [edge]
|
||||
|
||||
def test_condensation_mapping_and_members(self):
|
||||
G, C = self.gc[1]
|
||||
C = sorted(C, key=len, reverse=True)
|
||||
cG = nx.condensation(G)
|
||||
mapping = cG.graph["mapping"]
|
||||
assert all(n in G for n in mapping)
|
||||
assert all(0 == cN for n, cN in mapping.items() if n in C[0])
|
||||
assert all(1 == cN for n, cN in mapping.items() if n in C[1])
|
||||
for n, d in cG.nodes(data=True):
|
||||
assert set(C[n]) == cG.nodes[n]["members"]
|
||||
|
||||
def test_null_graph(self):
|
||||
G = nx.DiGraph()
|
||||
assert list(nx.strongly_connected_components(G)) == []
|
||||
assert list(nx.kosaraju_strongly_connected_components(G)) == []
|
||||
assert list(nx.strongly_connected_components_recursive(G)) == []
|
||||
assert len(nx.condensation(G)) == 0
|
||||
pytest.raises(
|
||||
nx.NetworkXPointlessConcept, nx.is_strongly_connected, nx.DiGraph()
|
||||
)
|
||||
|
||||
def test_connected_raise(self):
|
||||
G = nx.Graph()
|
||||
with pytest.raises(NetworkXNotImplemented):
|
||||
next(nx.strongly_connected_components(G))
|
||||
with pytest.raises(NetworkXNotImplemented):
|
||||
next(nx.kosaraju_strongly_connected_components(G))
|
||||
with pytest.raises(NetworkXNotImplemented):
|
||||
next(nx.strongly_connected_components_recursive(G))
|
||||
pytest.raises(NetworkXNotImplemented, nx.is_strongly_connected, G)
|
||||
pytest.raises(
|
||||
nx.NetworkXPointlessConcept, nx.is_strongly_connected, nx.DiGraph()
|
||||
)
|
||||
pytest.raises(NetworkXNotImplemented, nx.condensation, G)
|
||||
|
||||
strong_cc_methods = (
|
||||
nx.strongly_connected_components,
|
||||
nx.kosaraju_strongly_connected_components,
|
||||
nx.strongly_connected_components_recursive,
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("get_components", strong_cc_methods)
|
||||
def test_connected_mutability(self, get_components):
|
||||
DG = nx.path_graph(5, create_using=nx.DiGraph)
|
||||
G = nx.disjoint_union(DG, DG)
|
||||
seen = set()
|
||||
for component in get_components(G):
|
||||
assert len(seen & component) == 0
|
||||
seen.update(component)
|
||||
component.clear()
|
||||
90
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_weakly_connected.py
vendored
Normal file
90
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/tests/test_weakly_connected.py
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx import NetworkXNotImplemented
|
||||
|
||||
|
||||
class TestWeaklyConnected:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.gc = []
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from(
|
||||
[
|
||||
(1, 2),
|
||||
(2, 3),
|
||||
(2, 8),
|
||||
(3, 4),
|
||||
(3, 7),
|
||||
(4, 5),
|
||||
(5, 3),
|
||||
(5, 6),
|
||||
(7, 4),
|
||||
(7, 6),
|
||||
(8, 1),
|
||||
(8, 7),
|
||||
]
|
||||
)
|
||||
C = [[3, 4, 5, 7], [1, 2, 8], [6]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from([(1, 2), (1, 3), (1, 4), (4, 2), (3, 4), (2, 3)])
|
||||
C = [[2, 3, 4], [1]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from([(1, 2), (2, 3), (3, 2), (2, 1)])
|
||||
C = [[1, 2, 3]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
# Eppstein's tests
|
||||
G = nx.DiGraph({0: [1], 1: [2, 3], 2: [4, 5], 3: [4, 5], 4: [6], 5: [], 6: []})
|
||||
C = [[0], [1], [2], [3], [4], [5], [6]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
G = nx.DiGraph({0: [1], 1: [2, 3, 4], 2: [0, 3], 3: [4], 4: [3]})
|
||||
C = [[0, 1, 2], [3, 4]]
|
||||
cls.gc.append((G, C))
|
||||
|
||||
def test_weakly_connected_components(self):
|
||||
for G, C in self.gc:
|
||||
U = G.to_undirected()
|
||||
w = {frozenset(g) for g in nx.weakly_connected_components(G)}
|
||||
c = {frozenset(g) for g in nx.connected_components(U)}
|
||||
assert w == c
|
||||
|
||||
def test_number_weakly_connected_components(self):
|
||||
for G, C in self.gc:
|
||||
U = G.to_undirected()
|
||||
w = nx.number_weakly_connected_components(G)
|
||||
c = nx.number_connected_components(U)
|
||||
assert w == c
|
||||
|
||||
def test_is_weakly_connected(self):
|
||||
for G, C in self.gc:
|
||||
U = G.to_undirected()
|
||||
assert nx.is_weakly_connected(G) == nx.is_connected(U)
|
||||
|
||||
def test_null_graph(self):
|
||||
G = nx.DiGraph()
|
||||
assert list(nx.weakly_connected_components(G)) == []
|
||||
assert nx.number_weakly_connected_components(G) == 0
|
||||
with pytest.raises(nx.NetworkXPointlessConcept):
|
||||
next(nx.is_weakly_connected(G))
|
||||
|
||||
def test_connected_raise(self):
|
||||
G = nx.Graph()
|
||||
with pytest.raises(NetworkXNotImplemented):
|
||||
next(nx.weakly_connected_components(G))
|
||||
pytest.raises(NetworkXNotImplemented, nx.number_weakly_connected_components, G)
|
||||
pytest.raises(NetworkXNotImplemented, nx.is_weakly_connected, G)
|
||||
|
||||
def test_connected_mutability(self):
|
||||
DG = nx.path_graph(5, create_using=nx.DiGraph)
|
||||
G = nx.disjoint_union(DG, DG)
|
||||
seen = set()
|
||||
for component in nx.weakly_connected_components(G):
|
||||
assert len(seen & component) == 0
|
||||
seen.update(component)
|
||||
component.clear()
|
||||
186
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/weakly_connected.py
vendored
Normal file
186
.CondaPkg/env/Lib/site-packages/networkx/algorithms/components/weakly_connected.py
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
"""Weakly connected components."""
|
||||
import networkx as nx
|
||||
from networkx.utils.decorators import not_implemented_for
|
||||
|
||||
__all__ = [
|
||||
"number_weakly_connected_components",
|
||||
"weakly_connected_components",
|
||||
"is_weakly_connected",
|
||||
]
|
||||
|
||||
|
||||
@nx._dispatch
|
||||
@not_implemented_for("undirected")
|
||||
def weakly_connected_components(G):
|
||||
"""Generate weakly connected components of G.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX graph
|
||||
A directed graph
|
||||
|
||||
Returns
|
||||
-------
|
||||
comp : generator of sets
|
||||
A generator of sets of nodes, one for each weakly connected
|
||||
component of G.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If G is undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Generate a sorted list of weakly connected components, largest first.
|
||||
|
||||
>>> G = nx.path_graph(4, create_using=nx.DiGraph())
|
||||
>>> nx.add_path(G, [10, 11, 12])
|
||||
>>> [
|
||||
... len(c)
|
||||
... for c in sorted(nx.weakly_connected_components(G), key=len, reverse=True)
|
||||
... ]
|
||||
[4, 3]
|
||||
|
||||
If you only want the largest component, it's more efficient to
|
||||
use max instead of sort:
|
||||
|
||||
>>> largest_cc = max(nx.weakly_connected_components(G), key=len)
|
||||
|
||||
See Also
|
||||
--------
|
||||
connected_components
|
||||
strongly_connected_components
|
||||
|
||||
Notes
|
||||
-----
|
||||
For directed graphs only.
|
||||
|
||||
"""
|
||||
seen = set()
|
||||
for v in G:
|
||||
if v not in seen:
|
||||
c = set(_plain_bfs(G, v))
|
||||
seen.update(c)
|
||||
yield c
|
||||
|
||||
|
||||
@not_implemented_for("undirected")
|
||||
def number_weakly_connected_components(G):
|
||||
"""Returns the number of weakly connected components in G.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX graph
|
||||
A directed graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
n : integer
|
||||
Number of weakly connected components
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If G is undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> G = nx.DiGraph([(0, 1), (2, 1), (3, 4)])
|
||||
>>> nx.number_weakly_connected_components(G)
|
||||
2
|
||||
|
||||
See Also
|
||||
--------
|
||||
weakly_connected_components
|
||||
number_connected_components
|
||||
number_strongly_connected_components
|
||||
|
||||
Notes
|
||||
-----
|
||||
For directed graphs only.
|
||||
|
||||
"""
|
||||
return sum(1 for wcc in weakly_connected_components(G))
|
||||
|
||||
|
||||
@nx._dispatch
|
||||
@not_implemented_for("undirected")
|
||||
def is_weakly_connected(G):
|
||||
"""Test directed graph for weak connectivity.
|
||||
|
||||
A directed graph is weakly connected if and only if the graph
|
||||
is connected when the direction of the edge between nodes is ignored.
|
||||
|
||||
Note that if a graph is strongly connected (i.e. the graph is connected
|
||||
even when we account for directionality), it is by definition weakly
|
||||
connected as well.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : NetworkX Graph
|
||||
A directed graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
connected : bool
|
||||
True if the graph is weakly connected, False otherwise.
|
||||
|
||||
Raises
|
||||
------
|
||||
NetworkXNotImplemented
|
||||
If G is undirected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> G = nx.DiGraph([(0, 1), (2, 1)])
|
||||
>>> G.add_node(3)
|
||||
>>> nx.is_weakly_connected(G) # node 3 is not connected to the graph
|
||||
False
|
||||
>>> G.add_edge(2, 3)
|
||||
>>> nx.is_weakly_connected(G)
|
||||
True
|
||||
|
||||
See Also
|
||||
--------
|
||||
is_strongly_connected
|
||||
is_semiconnected
|
||||
is_connected
|
||||
is_biconnected
|
||||
weakly_connected_components
|
||||
|
||||
Notes
|
||||
-----
|
||||
For directed graphs only.
|
||||
|
||||
"""
|
||||
if len(G) == 0:
|
||||
raise nx.NetworkXPointlessConcept(
|
||||
"""Connectivity is undefined for the null graph."""
|
||||
)
|
||||
|
||||
return len(next(weakly_connected_components(G))) == len(G)
|
||||
|
||||
|
||||
def _plain_bfs(G, source):
|
||||
"""A fast BFS node generator
|
||||
|
||||
The direction of the edge between nodes is ignored.
|
||||
|
||||
For directed graphs only.
|
||||
|
||||
"""
|
||||
Gsucc = G.succ
|
||||
Gpred = G.pred
|
||||
|
||||
seen = set()
|
||||
nextlevel = {source}
|
||||
while nextlevel:
|
||||
thislevel = nextlevel
|
||||
nextlevel = set()
|
||||
for v in thislevel:
|
||||
if v not in seen:
|
||||
seen.add(v)
|
||||
nextlevel.update(Gsucc[v])
|
||||
nextlevel.update(Gpred[v])
|
||||
yield v
|
||||
Reference in New Issue
Block a user