Example #1
0
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
Example #2
0
 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)
Example #3
0
 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)
Example #4
0
 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)
Example #5
0
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
Example #6
0
 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)
Example #7
0
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
Example #8
0
 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))
Example #9
0
    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]
Example #10
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
Example #12
0
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))))