减少networkx中图的节点/边数

Posted

技术标签:

【中文标题】减少networkx中图的节点/边数【英文标题】:Reduce number of nodes/edges of a Graph in nedworkx 【发布时间】:2021-09-30 14:24:54 【问题描述】:

我有一个带有许多 2 级节点的 Graph(从 LineString 派生)。为了简化图表,我想将其简化为度数不等于 2 但仍包含相同整体连接的节点。你可以在下面的图片中找到我的意思的一个例子。 所以如果两个度数为3的节点之间有多个节点mit degree=2,则中间的所有节点和边都应该被删除,两个deg=3节点之间的单个连接应该与权重相同省略边的总和。

Example Picture of reduced Graph

【问题讨论】:

欢迎来到 SO!请告诉我们你到目前为止尝试了什么?你的代码呢? 【参考方案1】:

您可以通过以下方式识别链:1) 诱导仅包含度数为 2 的节点的子图,以及 2) 然后识别诱导子图中的各个组件。然后,只需将每条链中的权重相加,并在连接到链端点的节点之间创建一条具有该权重的新边。

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx


def contract(g):
    """
    Contract chains of neighbouring vertices with degree 2 into a single edge.

    Arguments:
    ----------
    g -- networkx.Graph or networkx.DiGraph instance

    Returns:
    --------
    h -- networkx.Graph or networkx.DiGraph instance
        the contracted graph

    """

    # create subgraph of all nodes with degree 2
    is_chain = [node for node, degree in g.degree() if degree == 2]
    chains = g.subgraph(is_chain)

    # contract connected components (which should be chains of variable length) into single node
    components = list(nx.components.connected_component_subgraphs(chains))

    hyper_edges = []
    for component in components:
        end_points = [node for node, degree in component.degree() if degree < 2]
        candidates = set([neighbor for node in end_points for neighbor in g.neighbors(node)])
        connectors = candidates - set(list(component.nodes()))
        hyper_edge = list(connectors)
        weights = [component.get_edge_data(*edge)['weight'] for edge in component.edges()]
        hyper_edges.append((hyper_edge, np.sum(weights)))

    # initialise new graph with all other nodes
    not_chain = [node for node in g.nodes() if not node in is_chain]
    h = g.subgraph(not_chain).copy()
    for hyper_edge, weight in hyper_edges:
        h.add_edge(*hyper_edge, weight=weight)

    return h

# create weighted graph
edges = np.random.randint(0, 20, size=(int(400*0.2), 2))
weights = np.random.rand(len(edges))
g = nx.Graph()
for edge, weight in zip(edges, weights):
    g.add_edge(*edge, weight=weight)
h = nx.algorithms.minimum_spanning_tree(g)

# contract
i = contract(h)

# plot
pos = nx.spring_layout(h)

fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True)
nx.draw(h, pos=pos, ax=ax1)
nx.draw(i, pos=pos, ax=ax2)
plt.show()

【讨论】:

以上是关于减少networkx中图的节点/边数的主要内容,如果未能解决你的问题,请参考以下文章

python networkx 都可以干啥

在networkx中聚合节点

改进 Python NetworkX 图形布局

networkx draw_network 在绘图周围绘制一个框架。我怎样才能防止这种情况?

Social Network Analysis的Centrality总结,以及networkx实现EigenCentrality,PageRank和KatzCentrality的对比

使用默认为节点名称的节点标签绘制 networkx 图