21

我正在尝试从大图中提取包含特定节点的所有连接节点的子图。

Networkx 库中有解决方案吗?

[编辑]
我的图是有向图

[编辑]
简单地说:
我想要我的图形部分包含我的特定节点 N_i 以及使用任何传入或传出边直接或间接连接(通过其他节点)的所有节点。
例子:

>>> g = nx.DiGraph()
>>> g.add_path(['A','B','C',])
>>> g.add_path(['X','Y','Z',])
>>> g.edges()
[('A', 'B'), ('B', 'C'), ('Y', 'Z'), ('X', 'Y')]

我想要的结果是:

>>> g2 = getSubGraph(g, 'B')
>>> g2.nodes()
['A', 'B', 'C']
>>> g2.edges()
[('A', 'B'), ('B', 'C')]
4

4 回答 4

23

您可以使用 shortest_path() 查找从给定节点可到达的所有节点。在您的情况下,您需要首先将图形转换为无向表示,以便同时跟踪入边和出边。

In [1]: import networkx as nx

In [2]: >>> g = nx.DiGraph()

In [3]: >>> g.add_path(['A','B','C',])

In [4]: >>> g.add_path(['X','Y','Z',])

In [5]: u = g.to_undirected()

In [6]: nodes = nx.shortest_path(u,'B').keys()

In [7]: nodes
Out[7]: ['A', 'C', 'B']

In [8]: s = g.subgraph(nodes)

In [9]: s.edges()
Out[9]: [('A', 'B'), ('B', 'C')]

或者在一行

In [10]: s = g.subgraph(nx.shortest_path(g.to_undirected(),'B'))

In [11]: s.edges()
Out[11]: [('A', 'B'), ('B', 'C')]
于 2012-12-18T13:29:52.797 回答
13

只需遍历子图,直到目标节点包含在子图中。

对于有图,我假设子图是一个图,使得每个节点都可以从每个其他节点访问。这是一个强连通子图,其networkx函数是strongly_connected_component_subgraphs

(MWE)最小的工作示例:

import networkx as nx
import pylab as plt

G = nx.erdos_renyi_graph(30,.05)
target_node = 13

pos=nx.graphviz_layout(G,prog="neato")

for h in nx.connected_component_subgraphs(G):
    if target_node in h:
        nx.draw(h,pos,node_color='red')
    else:
        nx.draw(h,pos,node_color='white')

plt.show()

在此处输入图像描述

对于有向子图 ( digraph ) 示例,将相应的行更改为:

G = nx.erdos_renyi_graph(30,.05, directed=True)
...
for h in nx.strongly_connected_component_subgraphs(G):

在此处输入图像描述

请注意,其中一个节点在连通分量中,但不在强连通分量中!

于 2012-12-17T15:31:35.287 回答
2

我找到了三个解决方案来解决您的要求,就像我的一样。我的 Digraph 的大小在 6000 到 12000 个节点之间,最大子图大小将达到 3700。我使用的三个函数是:

def create_subgraph_dfs(G, node):
    """ bidirection, O(1)"""
    edges = nx.dfs_successors(G, node)
    nodes = []
    for k,v in edges.items():
        nodes.extend([k])
        nodes.extend(v)
    return G.subgraph(nodes)

def create_subgraph_shortpath(G, node):
    """ unidirection, O(1)"""
    nodes = nx.single_source_shortest_path(G,node).keys()
    return G.subgraph(nodes)

def create_subgraph_recursive(G, sub_G, start_node):
    """ bidirection, O(nlogn)"""
    for n in G.successors_iter(start_node):
        sub_G.add_path([start_node, n])
        create_subgraph_recursive(G, sub_G, n)

测试结果总结如下:

时间毫秒

于 2017-08-15T05:23:01.953 回答
1

使用页面connected_component_subgraphs末尾的示例。

只需确保引用列表中的最后一个元素而不是第一个元素

>>> G=nx.path_graph(4)
>>> G.add_edge(5,6)
>>> H=nx.connected_component_subgraphs(G)[-1]
于 2012-12-17T13:18:20.777 回答