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. 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`. 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. 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 """ chains = nx.chain_decomposition(G, root=root) chain_edges = set(chain.from_iterable(chains)) for u, v in G.edges(): if (u, v) not in chain_edges and (v, u) not in chain_edges: yield u, v
def test_barbell_graph(self): # The (3, 0) barbell graph has two triangles joined by a single edge. G = nx.barbell_graph(3, 0) chains = list(nx.chain_decomposition(G, root=0)) expected = [ [(0, 1), (1, 2), (2, 0)], [(3, 4), (4, 5), (5, 3)], ] self.assertEqual(len(chains), len(expected)) for chain in chains: self.assertContainsChain(chain, expected)
def test_disconnected_graph_root_node(self): """Test for a single component of a disconnected graph.""" G = nx.barbell_graph(3, 0) H = nx.barbell_graph(3, 0) mapping = dict(zip(range(6), 'abcdef')) nx.relabel_nodes(H, mapping, copy=False) G = nx.union(G, H) chains = list(nx.chain_decomposition(G, root='a')) expected = [ [('a', 'b'), ('b', 'c'), ('c', 'a')], [('d', 'e'), ('e', 'f'), ('f', 'd')], ] self.assertEqual(len(chains), len(expected)) for chain in chains: self.assertContainsChain(chain, expected)
def test_disconnected_graph(self): """Test for a graph with multiple connected components.""" G = nx.barbell_graph(3, 0) H = nx.barbell_graph(3, 0) mapping = dict(zip(range(6), 'abcdef')) nx.relabel_nodes(H, mapping, copy=False) G = nx.union(G, H) chains = list(nx.chain_decomposition(G)) expected = [ [(0, 1), (1, 2), (2, 0)], [(3, 4), (4, 5), (5, 3)], [('a', 'b'), ('b', 'c'), ('c', 'a')], [('d', 'e'), ('e', 'f'), ('f', 'd')], ] self.assertEqual(len(chains), len(expected)) for chain in chains: self.assertContainsChain(chain, expected)
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. 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`. 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 implementation uses the :func:`networkx.chain_decomposition` function, so it shares its worst-case time complexity, :math:`O(m + n)`, ignoring polylogarithmic factors, where *n* is the number of nodes in the graph and *m* is the number of edges. """ chains = nx.chain_decomposition(G, root=root) chain_edges = set(chain.from_iterable(chains)) for u, v in G.edges(): if (u, v) not in chain_edges and (v, u) not in chain_edges: yield u, v
def test_decomposition(self): edges = [ # DFS tree edges. (1, 2), (2, 3), (3, 4), (3, 5), (5, 6), (6, 7), (7, 8), (5, 9), (9, 10), # Nontree edges. (1, 3), (1, 4), (2, 5), (5, 10), (6, 8) ] G = nx.Graph(edges) expected = [ [(1, 3), (3, 2), (2, 1)], [(1, 4), (4, 3)], [(2, 5), (5, 3)], [(5, 10), (10, 9), (9, 5)], [(6, 8), (8, 7), (7, 6)], ] chains = list(nx.chain_decomposition(G, root=1)) self.assertEqual(len(chains), len(expected))
def chain(self): """ Return a list of tuples of nodes in the serial chain, rooted at datum if datum is in the chain. Warning ------- Do not prerve the edges orientations """ # set root if self.datum in self.nodes: root = self.datum else: root = None # Convert graph type to undirected graph with no parallel edge. simple_graph = nwxGraph(self) # Return chain decomposition return list(chain_decomposition(simple_graph, root=root))[0]
f.write(wd + "\n") # path btw two nodes pf = nx.shortest_path(G=G_skip, source="nemzet", target="okos") pn = nx.shortest_path(G=G_skip, source="nő", target="okos") print(pf, pn) pf = nx.shortest_path(G=G_embed, source="nemzet", target="okos") pn = nx.shortest_path(G=G_embed, source="nő", target="okos") print(pf, pn) sp_ffi = nx.shortest_simple_paths(G=G_embed, source="férfi", target="okos") sp_no = nx.shortest_simple_paths(G=G_embed, source="nő", target="okos") # chain decomposition ff_chain = nx.chain_decomposition(G=G_embed, root="férfi") ff_chain = [e for e in ff_chain if 40 > len(e) > 10] fn = max([len(e) for e in ff_chain]) fi = [len(e) for e in ff_chain].index(fn) no_chain = nx.chain_decomposition(G=G_embed, root="nő") no_chain = [e for e in no_chain if 40 > len(e) > 10] nn = max([len(e) for e in no_chain]) no = [len(e) for e in no_chain].index(nn) ff_path = ff_chain[fi] no_path = no_chain[no] G = nx.Graph() for e in ff_path: G.add_edge(e[0], e[1])
def crust_algorithm(self, show=False): # Guaranteed to result in the proper contour, but may not contain all points in specific, rare pixel # configurations def _simplices2edges(_deltri, _crust_set): unique_edges = {'points': [], 'indices': []} for simplex in _deltri.simplices: del_edges_i = combinations(simplex, 2) for _del_edge_i in del_edges_i: _del_edge_i = np.sort(_del_edge_i) _del_edge = _crust_set[_del_edge_i, :] unique_edges['points'].append(_del_edge) unique_edges['indices'].append(_del_edge_i) unique_edges['points'] = np.unique(unique_edges['points'], axis=0) unique_edges['indices'] = np.unique(unique_edges['indices'], axis=0) return unique_edges vor = Voronoi(self.edge_points) list_edge_points = self.edge_points.tolist() crust_set = np.unique(np.concatenate((self.edge_points, vor.vertices)), axis=0) deltri = Delaunay(crust_set) all_edges = _simplices2edges(deltri, crust_set) crust_edges = {'points': [], 'indices': []} for del_edge, edge_id in zip(all_edges['points'], all_edges['indices']): if del_edge[0].tolist() in list_edge_points and del_edge[1].tolist( ) in list_edge_points: crust_edges['points'].append(del_edge) crust_edges['indices'].append(tuple(edge_id)) G = nx.Graph() G.add_nodes_from([tuple(point) for point in crust_set]) G.add_edges_from(crust_edges['indices']) point_id = int(np.min(np.array(crust_edges['indices'])[:, 0])) try: cd = list(nx.chain_decomposition(G, point_id))[0] except IndexError: # raised when there is no chain. The leaves of the graph must be connected. leaves = np.array([v for v, d in list(G.degree) if d == 1]) leaf_dists = cdist(crust_set[leaves], crust_set[leaves]) closest_leaves = [] for leaf in leaf_dists: closest_leaves.append( min(enumerate(leaf), key=lambda x: x[1] if x[1] > 0 else float('inf'))[0]) leaf_edges = [[ leaf1, leaf2 ] for leaf1, leaf2 in zip(leaves, leaves[closest_leaves])] leaf_edges = sorted(leaf_edges, key=lambda x: x[0]) unique_edges = np.unique(leaf_edges).reshape((-1, 2)) unique_edges = [tuple(edge) for edge in unique_edges] G.add_edges_from(list(unique_edges)) cd = list(nx.chain_decomposition(G, point_id))[0] graph_path = [x[0] for x in list(cd)] G.remove_edges_from(crust_edges['indices']) nx.add_path(G, graph_path) _sorted_points = np.array(crust_set[graph_path]) if show: plt.subplot(121) plt.plot(self.edge_points[:, 0], self.edge_points[:, 1], 'r.') for crust_edge in crust_edges['points']: plt.plot(crust_edge[:, 0], crust_edge[:, 1], 'b') plt.title('Found edges') plt.subplot(122) plt.title('Crust algorithm result') plt.plot(_sorted_points[:, 0], _sorted_points[:, 1], 'b') plt.plot(self.edge_points[:, 0], self.edge_points[:, 1], 'r.') plt.scatter(_sorted_points[0][0], _sorted_points[0][1], c='g', marker='d', s=80) plt.scatter(_sorted_points[-1][0], _sorted_points[-1][1], c='k', marker='d') plt.show() return _sorted_points
import networkx as nx g = nx.Graph() g.add_edge(1, 4) g.add_edge(1, 5) g.add_edge(1, 2) g.add_edge(4, 5) g.add_edge(2, 5) g.add_edge(3, 5) g.add_edge(3, 4) g.add_edge(3, 2) g.add_edge(3, 6) g.add_edge(6, 7) g.add_edge(7, 8) g.add_edge(6, 8) chains = nx.chain_decomposition(g) print('\n'.join(map(str, list(chains))))