Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/networkx/algorithms/bridges.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 # -*- coding: utf-8 -*- | |
| 2 # bridges.py - bridge-finding algorithms | |
| 3 # | |
| 4 # Copyright 2004-2019 NetworkX developers. | |
| 5 # | |
| 6 # This file is part of NetworkX. | |
| 7 # | |
| 8 # NetworkX is distributed under a BSD license; see LICENSE.txt for more | |
| 9 # information. | |
| 10 """Bridge-finding algorithms.""" | |
| 11 from itertools import chain | |
| 12 | |
| 13 import networkx as nx | |
| 14 from networkx.utils import not_implemented_for | |
| 15 | |
| 16 __all__ = ['bridges', 'has_bridges', 'local_bridges'] | |
| 17 | |
| 18 | |
| 19 @not_implemented_for('multigraph') | |
| 20 @not_implemented_for('directed') | |
| 21 def bridges(G, root=None): | |
| 22 """Generate all bridges in a graph. | |
| 23 | |
| 24 A *bridge* in a graph is an edge whose removal causes the number of | |
| 25 connected components of the graph to increase. Equivalently, a bridge is an | |
| 26 edge that does not belong to any cycle. | |
| 27 | |
| 28 Parameters | |
| 29 ---------- | |
| 30 G : undirected graph | |
| 31 | |
| 32 root : node (optional) | |
| 33 A node in the graph `G`. If specified, only the bridges in the | |
| 34 connected component containing this node will be returned. | |
| 35 | |
| 36 Yields | |
| 37 ------ | |
| 38 e : edge | |
| 39 An edge in the graph whose removal disconnects the graph (or | |
| 40 causes the number of connected components to increase). | |
| 41 | |
| 42 Raises | |
| 43 ------ | |
| 44 NodeNotFound | |
| 45 If `root` is not in the graph `G`. | |
| 46 | |
| 47 Examples | |
| 48 -------- | |
| 49 The barbell graph with parameter zero has a single bridge: | |
| 50 | |
| 51 >>> G = nx.barbell_graph(10, 0) | |
| 52 >>> list(nx.bridges(G)) | |
| 53 [(9, 10)] | |
| 54 | |
| 55 Notes | |
| 56 ----- | |
| 57 This is an implementation of the algorithm described in _[1]. An edge is a | |
| 58 bridge if and only if it is not contained in any chain. Chains are found | |
| 59 using the :func:`networkx.chain_decomposition` function. | |
| 60 | |
| 61 Ignoring polylogarithmic factors, the worst-case time complexity is the | |
| 62 same as the :func:`networkx.chain_decomposition` function, | |
| 63 $O(m + n)$, where $n$ is the number of nodes in the graph and $m$ is | |
| 64 the number of edges. | |
| 65 | |
| 66 References | |
| 67 ---------- | |
| 68 .. [1] https://en.wikipedia.org/wiki/Bridge_%28graph_theory%29#Bridge-Finding_with_Chain_Decompositions | |
| 69 """ | |
| 70 chains = nx.chain_decomposition(G, root=root) | |
| 71 chain_edges = set(chain.from_iterable(chains)) | |
| 72 for u, v in G.edges(): | |
| 73 if (u, v) not in chain_edges and (v, u) not in chain_edges: | |
| 74 yield u, v | |
| 75 | |
| 76 | |
| 77 @not_implemented_for('multigraph') | |
| 78 @not_implemented_for('directed') | |
| 79 def has_bridges(G, root=None): | |
| 80 """Decide whether a graph has any bridges. | |
| 81 | |
| 82 A *bridge* in a graph is an edge whose removal causes the number of | |
| 83 connected components of the graph to increase. | |
| 84 | |
| 85 Parameters | |
| 86 ---------- | |
| 87 G : undirected graph | |
| 88 | |
| 89 root : node (optional) | |
| 90 A node in the graph `G`. If specified, only the bridges in the | |
| 91 connected component containing this node will be considered. | |
| 92 | |
| 93 Returns | |
| 94 ------- | |
| 95 bool | |
| 96 Whether the graph (or the connected component containing `root`) | |
| 97 has any bridges. | |
| 98 | |
| 99 Raises | |
| 100 ------ | |
| 101 NodeNotFound | |
| 102 If `root` is not in the graph `G`. | |
| 103 | |
| 104 Examples | |
| 105 -------- | |
| 106 The barbell graph with parameter zero has a single bridge:: | |
| 107 | |
| 108 >>> G = nx.barbell_graph(10, 0) | |
| 109 >>> nx.has_bridges(G) | |
| 110 True | |
| 111 | |
| 112 On the other hand, the cycle graph has no bridges:: | |
| 113 | |
| 114 >>> G = nx.cycle_graph(5) | |
| 115 >>> nx.has_bridges(G) | |
| 116 False | |
| 117 | |
| 118 Notes | |
| 119 ----- | |
| 120 This implementation uses the :func:`networkx.bridges` function, so | |
| 121 it shares its worst-case time complexity, $O(m + n)$, ignoring | |
| 122 polylogarithmic factors, where $n$ is the number of nodes in the | |
| 123 graph and $m$ is the number of edges. | |
| 124 | |
| 125 """ | |
| 126 try: | |
| 127 next(bridges(G)) | |
| 128 except StopIteration: | |
| 129 return False | |
| 130 else: | |
| 131 return True | |
| 132 | |
| 133 | |
| 134 @not_implemented_for('multigraph') | |
| 135 @not_implemented_for('directed') | |
| 136 def local_bridges(G, with_span=True, weight=None): | |
| 137 """Iterate over local bridges of `G` optionally computing the span | |
| 138 | |
| 139 A *local bridge* is an edge whose endpoints have no common neighbors. | |
| 140 That is, the edge is not part of a triangle in the graph. | |
| 141 | |
| 142 The *span* of a *local bridge* is the shortest path length between | |
| 143 the endpoints if the local bridge is removed. | |
| 144 | |
| 145 Parameters | |
| 146 ---------- | |
| 147 G : undirected graph | |
| 148 | |
| 149 with_span : bool | |
| 150 If True, yield a 3-tuple `(u, v, span)` | |
| 151 | |
| 152 weight : function, string or None (default: None) | |
| 153 If function, used to compute edge weights for the span. | |
| 154 If string, the edge data attribute used in calculating span. | |
| 155 If None, all edges have weight 1. | |
| 156 | |
| 157 Yields | |
| 158 ------ | |
| 159 e : edge | |
| 160 The local bridges as an edge 2-tuple of nodes `(u, v)` or | |
| 161 as a 3-tuple `(u, v, span)` when `with_span is True`. | |
| 162 | |
| 163 Examples | |
| 164 -------- | |
| 165 A cycle graph has every edge a local bridge with span N-1. | |
| 166 | |
| 167 >>> G = nx.cycle_graph(9) | |
| 168 >>> (0, 8, 8) in set(nx.local_bridges(G)) | |
| 169 True | |
| 170 """ | |
| 171 if with_span is not True: | |
| 172 for u, v in G.edges: | |
| 173 if not (set(G[u]) & set(G[v])): | |
| 174 yield u, v | |
| 175 else: | |
| 176 wt = nx.weighted._weight_function(G, weight) | |
| 177 for u, v in G.edges: | |
| 178 if not (set(G[u]) & set(G[v])): | |
| 179 enodes = {u, v} | |
| 180 | |
| 181 def hide_edge(n, nbr, d): | |
| 182 if n not in enodes or nbr not in enodes: | |
| 183 return wt(n, nbr, d) | |
| 184 return None | |
| 185 | |
| 186 try: | |
| 187 span = nx.shortest_path_length(G, u, v, weight=hide_edge) | |
| 188 yield u, v, span | |
| 189 except nx.NetworkXNoPath: | |
| 190 yield u, v, float('inf') |
