NetworkX - 删除节点并重新连接边缘

Rya*_*uck 10 networkx

我在图中有一个节点,它充当一种“临时连接器”节点。我想删除该节点并更新图中的边,以便其所有直接前辈都指向其直接后继者。

是否有内置功能可以做到这一点networkx,还是我需要推出自己的解决方案?

例子:

我有一个图表1 > 2 > 3。我想删除 node2并最终得到 graph 1 > 3

这是我目前的做法:

In [230]: g = nx.DiGraph()

In [231]: g.add_edges_from([(1,2),(2,3)])

In [232]: g.edges()
Out[232]: [(1, 2), (2, 3)]

In [233]: predecessors = g.predecessors(2)

In [234]: successors = g.successors(2)

In [235]: new_edges = [(p,s) for p in predecessors for s in successors]

In [236]: new_edges
Out[236]: [(1, 3)]

In [237]: g.remove_node(2)

In [238]: g.add_edges_from(new_edges)

In [239]: g.nodes()
Out[239]: [1, 3]

In [240]: g.edges()
Out[240]: [(1, 3)]
Run Code Online (Sandbox Code Playgroud)

mjk*_*aak 0

我不知道我的解决方案是否比 Ryan 已经建议的更好,但我在这里发布了一个函数,因为它试图从不同的角度解决这个问题。关键是,a 中的graph 1 > 2 > 3节点的2度数为 2(即有 2 个边与其连接)。一般来说,从所提出的问题的意义上简化图意味着删除所有此类 2 度节点。下面的函数正是这样做的。

def simplifyGraph(G):
    ''' Loop over the graph until all nodes of degree 2 have been removed and their incident edges fused '''

    g = G.copy()

    while any(degree==2 for _, degree in g.degree):

        g0 = g.copy() #<- simply changing g itself would cause error `dictionary changed size during iteration` 
        for node, degree in g.degree():
            if degree==2:

                if g.is_directed(): #<-for directed graphs
                    a0,b0 = list(g.in_edges(node))[0]
                    a1,b1 = list(g.out_edges(node))[0]

                else:
                    edges = g.edges(node)
                    edges = list(edges.__iter__())
                    a0,b0 = edges[0]
                    a1,b1 = edges[1]

                e0 = a0 if a0!=node else b0
                e1 = a1 if a1!=node else b1

                g0.remove_node(node)
                g0.add_edge(e0, e1)
        g = g0

    return g
Run Code Online (Sandbox Code Playgroud)

一个例子:

>>> G = nx.DiGraph()
>>> G.add_edges_from([(1,2),(2,3)])
>>> list(G.edges)
[(1, 2), (2, 3)]

>>> g = simplifyGraph(G)
>>> list(g.edges)
[(1, 3)]
Run Code Online (Sandbox Code Playgroud)