簡體   English   中英

Networkx:提取包含給定節點的連通組件(有向圖)

[英]Networkx: extract the connected component containing a given node (directed graph)

我試圖從一個大圖中提取包含特定節點的所有連接節點的子圖。

Networkx庫中是否有解決方案?

[編輯]
我的圖是DiGraph

[編輯]
簡單地改寫:
我希望我的圖形的一部分包含我的特定節點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')]

您可以使用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')]

只需遍歷子圖,直到目標節點包含在子圖中。

對於有圖,我假設子圖是一個圖,這樣每個節點都可以從每個其他節點訪問。 這是一個強連接子圖和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()

在此輸入圖像描述

對於有向子圖( 有向圖 )示例,將相應的行更改為:

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

在此輸入圖像描述

請注意,其中一個節點位於連接組件中,但不在強連接組件中!

使用頁面末尾的示例connected_component_subgraphs

只需確保從列表中引用最后一個元素而不是第一個元素

>>> G=nx.path_graph(4)
>>> G.add_edge(5,6)
>>> H=nx.connected_component_subgraphs(G)[-1]

我找到了三種解決方案來解決您的需求,就像我的一樣。 我的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)

測試結果總結如下:

時間毫秒

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM