我在图中有一个节点,它充当一种“临时连接器”节点。我想删除该节点并更新图中的边,以便其所有直接前辈都指向其直接后继者。
是否有内置功能可以做到这一点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)
我不知道我的解决方案是否比 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)
| 归档时间: |
|
| 查看次数: |
1404 次 |
| 最近记录: |