| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 | 
							- """Bridge-finding algorithms."""
 
- from itertools import chain
 
- import networkx as nx
 
- from networkx.utils import not_implemented_for
 
- __all__ = ["bridges", "has_bridges", "local_bridges"]
 
- @not_implemented_for("directed")
 
- def bridges(G, root=None):
 
-     """Generate all bridges in a graph.
 
-     A *bridge* in a graph is an edge whose removal causes the number of
 
-     connected components of the graph to increase.  Equivalently, a bridge is an
 
-     edge that does not belong to any cycle. Bridges are also known as cut-edges,
 
-     isthmuses, or cut arcs.
 
-     Parameters
 
-     ----------
 
-     G : undirected graph
 
-     root : node (optional)
 
-        A node in the graph `G`. If specified, only the bridges in the
 
-        connected component containing this node will be returned.
 
-     Yields
 
-     ------
 
-     e : edge
 
-        An edge in the graph whose removal disconnects the graph (or
 
-        causes the number of connected components to increase).
 
-     Raises
 
-     ------
 
-     NodeNotFound
 
-        If `root` is not in the graph `G`.
 
-     NetworkXNotImplemented
 
-         If `G` is a directed graph.
 
-     Examples
 
-     --------
 
-     The barbell graph with parameter zero has a single bridge:
 
-     >>> G = nx.barbell_graph(10, 0)
 
-     >>> list(nx.bridges(G))
 
-     [(9, 10)]
 
-     Notes
 
-     -----
 
-     This is an implementation of the algorithm described in [1]_.  An edge is a
 
-     bridge if and only if it is not contained in any chain. Chains are found
 
-     using the :func:`networkx.chain_decomposition` function.
 
-     The algorithm described in [1]_ requires a simple graph. If the provided
 
-     graph is a multigraph, we convert it to a simple graph and verify that any
 
-     bridges discovered by the chain decomposition algorithm are not multi-edges.
 
-     Ignoring polylogarithmic factors, the worst-case time complexity is the
 
-     same as the :func:`networkx.chain_decomposition` function,
 
-     $O(m + n)$, where $n$ is the number of nodes in the graph and $m$ is
 
-     the number of edges.
 
-     References
 
-     ----------
 
-     .. [1] https://en.wikipedia.org/wiki/Bridge_%28graph_theory%29#Bridge-Finding_with_Chain_Decompositions
 
-     """
 
-     multigraph = G.is_multigraph()
 
-     H = nx.Graph(G) if multigraph else G
 
-     chains = nx.chain_decomposition(H, root=root)
 
-     chain_edges = set(chain.from_iterable(chains))
 
-     H_copy = H.copy()
 
-     if root is not None:
 
-         H = H.subgraph(nx.node_connected_component(H, root)).copy()
 
-     for u, v in H.edges():
 
-         if (u, v) not in chain_edges and (v, u) not in chain_edges:
 
-             if multigraph and len(G[u][v]) > 1:
 
-                 continue
 
-             yield u, v
 
- @not_implemented_for("directed")
 
- def has_bridges(G, root=None):
 
-     """Decide whether a graph has any bridges.
 
-     A *bridge* in a graph is an edge whose removal causes the number of
 
-     connected components of the graph to increase.
 
-     Parameters
 
-     ----------
 
-     G : undirected graph
 
-     root : node (optional)
 
-        A node in the graph `G`. If specified, only the bridges in the
 
-        connected component containing this node will be considered.
 
-     Returns
 
-     -------
 
-     bool
 
-        Whether the graph (or the connected component containing `root`)
 
-        has any bridges.
 
-     Raises
 
-     ------
 
-     NodeNotFound
 
-        If `root` is not in the graph `G`.
 
-     NetworkXNotImplemented
 
-         If `G` is a directed graph.
 
-     Examples
 
-     --------
 
-     The barbell graph with parameter zero has a single bridge::
 
-         >>> G = nx.barbell_graph(10, 0)
 
-         >>> nx.has_bridges(G)
 
-         True
 
-     On the other hand, the cycle graph has no bridges::
 
-         >>> G = nx.cycle_graph(5)
 
-         >>> nx.has_bridges(G)
 
-         False
 
-     Notes
 
-     -----
 
-     This implementation uses the :func:`networkx.bridges` function, so
 
-     it shares its worst-case time complexity, $O(m + n)$, ignoring
 
-     polylogarithmic factors, where $n$ is the number of nodes in the
 
-     graph and $m$ is the number of edges.
 
-     """
 
-     try:
 
-         next(bridges(G, root=root))
 
-     except StopIteration:
 
-         return False
 
-     else:
 
-         return True
 
- @not_implemented_for("multigraph")
 
- @not_implemented_for("directed")
 
- def local_bridges(G, with_span=True, weight=None):
 
-     """Iterate over local bridges of `G` optionally computing the span
 
-     A *local bridge* is an edge whose endpoints have no common neighbors.
 
-     That is, the edge is not part of a triangle in the graph.
 
-     The *span* of a *local bridge* is the shortest path length between
 
-     the endpoints if the local bridge is removed.
 
-     Parameters
 
-     ----------
 
-     G : undirected graph
 
-     with_span : bool
 
-         If True, yield a 3-tuple `(u, v, span)`
 
-     weight : function, string or None (default: None)
 
-         If function, used to compute edge weights for the span.
 
-         If string, the edge data attribute used in calculating span.
 
-         If None, all edges have weight 1.
 
-     Yields
 
-     ------
 
-     e : edge
 
-         The local bridges as an edge 2-tuple of nodes `(u, v)` or
 
-         as a 3-tuple `(u, v, span)` when `with_span is True`.
 
-     Raises
 
-     ------
 
-     NetworkXNotImplemented
 
-         If `G` is a directed graph or multigraph.
 
-     Examples
 
-     --------
 
-     A cycle graph has every edge a local bridge with span N-1.
 
-        >>> G = nx.cycle_graph(9)
 
-        >>> (0, 8, 8) in set(nx.local_bridges(G))
 
-        True
 
-     """
 
-     if with_span is not True:
 
-         for u, v in G.edges:
 
-             if not (set(G[u]) & set(G[v])):
 
-                 yield u, v
 
-     else:
 
-         wt = nx.weighted._weight_function(G, weight)
 
-         for u, v in G.edges:
 
-             if not (set(G[u]) & set(G[v])):
 
-                 enodes = {u, v}
 
-                 def hide_edge(n, nbr, d):
 
-                     if n not in enodes or nbr not in enodes:
 
-                         return wt(n, nbr, d)
 
-                     return None
 
-                 try:
 
-                     span = nx.shortest_path_length(G, u, v, weight=hide_edge)
 
-                     yield u, v, span
 
-                 except nx.NetworkXNoPath:
 
-                     yield u, v, float("inf")
 
 
  |