这里是一个通用解决方案,用户可以提供任何节点条件来删除节点并重新组合图形。在注释中,我还放置了一些代码,允许用户重新组合具有不同权重的边。
import networkx as nx
from itertools import combinations
def simplify_graph_with_predicate(G: nx.Graph, node_removal_predicate: callable):
'''
Loop over the graph until all nodes that match the supplied predicate
have been removed and their incident edges fused.
'''
g = G.copy()
while any(node_removal_predicate(node) for node in g.nodes):
g0 = g.copy()
for node in g.nodes:
if node_removal_predicate(node):
if g.is_directed():
in_edges_containing_node = list(g0.in_edges(node))
out_edges_containing_node = list(g0.out_edges(node))
for in_src, _ in in_edges_containing_node:
for _, out_dst in out_edges_containing_node:
g0.add_edge(in_src, out_dst)
else:
edges_containing_node = g.edges(node)
dst_to_link = [e[1] for e in edges_containing_node]
dst_pairs_to_link = list(combinations(dst_to_link, r = 2))
for pair in dst_pairs_to_link:
g0.add_edge(pair[0], pair[1])
g0.remove_node(node)
break
g = g0
return g
示例用法1(提供的例子):
g = nx.DiGraph()
g.add_edges_from([(1,2),(2,3)])
res = simplify_graph_with_predicate(g, lambda node: node == 2)
print(res.edges)
示例用法2:
g = nx.DiGraph()
g.add_edge("node_one", "node_two")
g.add_edge("node_two", "node_three")
res = simplify_graph_with_predicate(g, lambda node: "two" in node)
print(res.edges)