chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
from easygraph.utils.decorators import *
|
||||
|
||||
|
||||
__all__ = [
|
||||
"is_connected",
|
||||
"number_connected_components",
|
||||
"connected_components",
|
||||
"connected_components_directed",
|
||||
"connected_component_of_node",
|
||||
]
|
||||
|
||||
|
||||
@not_implemented_for("multigraph")
|
||||
def is_connected(G):
|
||||
"""Returns whether the graph is connected or not.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : easygraph.Graph or easygraph.DiGraph
|
||||
|
||||
Returns
|
||||
-------
|
||||
is_biconnected : boolean
|
||||
`True` if the graph is connected.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
>>> is_connected(G)
|
||||
|
||||
"""
|
||||
assert len(G) != 0, "No node in the graph."
|
||||
arbitrary_node = next(iter(G)) # Pick an arbitrary node to run BFS
|
||||
return len(G) == sum(1 for node in _plain_bfs(G, arbitrary_node))
|
||||
|
||||
|
||||
@not_implemented_for("multigraph")
|
||||
def number_connected_components(G):
|
||||
"""Returns the number of connected components.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : easygraph.Graph
|
||||
|
||||
Returns
|
||||
-------
|
||||
number_connected_components : int
|
||||
The number of connected components.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> number_connected_components(G)
|
||||
|
||||
"""
|
||||
return sum(1 for component in _generator_connected_components(G))
|
||||
|
||||
|
||||
@not_implemented_for("multigraph")
|
||||
@hybrid("cpp_connected_components_undirected")
|
||||
def connected_components(G):
|
||||
"""Returns a list of connected components, each of which denotes the edges set of a connected component.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : easygraph.Graph
|
||||
Returns
|
||||
-------
|
||||
connected_components : list of list
|
||||
Each element list is the edges set of a connected component.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> connected_components(G)
|
||||
|
||||
"""
|
||||
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("multigraph")
|
||||
@hybrid("cpp_connected_components_directed")
|
||||
def connected_components_directed(G):
|
||||
"""Returns a list of connected components, each of which denotes the edges set of a connected component.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : easygraph.DiGraph
|
||||
Returns
|
||||
-------
|
||||
connected_components : list of list
|
||||
Each element list is the edges set of a connected component.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> connected_components(G)
|
||||
|
||||
"""
|
||||
seen = set()
|
||||
for v in G:
|
||||
if v not in seen:
|
||||
c = set(_plain_bfs(G, v))
|
||||
seen.update(c)
|
||||
yield c
|
||||
|
||||
|
||||
def _generator_connected_components(G):
|
||||
seen = set()
|
||||
for v in G:
|
||||
if v not in seen:
|
||||
component = set(_plain_bfs(G, v))
|
||||
yield component
|
||||
seen.update(component)
|
||||
|
||||
|
||||
@not_implemented_for("multigraph")
|
||||
def connected_component_of_node(G, node):
|
||||
"""Returns the connected component that *node* belongs to.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
G : easygraph.Graph
|
||||
|
||||
node : object
|
||||
The target node
|
||||
|
||||
Returns
|
||||
-------
|
||||
connected_component_of_node : set
|
||||
The connected component that *node* belongs to.
|
||||
|
||||
Examples
|
||||
--------
|
||||
Returns the connected component of one node `Jack`.
|
||||
|
||||
>>> connected_component_of_node(G, node='Jack')
|
||||
|
||||
"""
|
||||
return set(_plain_bfs(G, node))
|
||||
|
||||
|
||||
@hybrid("cpp_plain_bfs")
|
||||
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:
|
||||
yield v
|
||||
seen.add(v)
|
||||
nextlevel.update(G_adj[v])
|
||||
Reference in New Issue
Block a user