【问题标题】:Networkx: extract the connected component containing a given node (directed graph)Networkx:提取包含给定节点的连通分量(有向图)
【发布时间】:2012-12-17 13:15:48
【问题描述】:

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

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')]

【问题讨论】:

  • 从您的问题中不清楚您想要什么子图。如果您想要一个包含节点 N_i 而没有孤立节点的子图,那么例如N_i 的邻居满足这一点。如果您想要包含 N_i 但没有孤立节点的最大子图,则从图中删除所有孤立节点将起作用(只要 N_i 不是 0 度)。该图不一定是连接的。如果您希望从 N_i 可以访问所有节点,请考虑 nx.shortest_path(G,N_i)...
  • 不确定您是否正在检查此内容,但请检查我对您的标题所做的编辑。你所拥有的实际上并不是你最终提出的问题。

标签: python networkx


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    对于有向图,我假设子图是一个图,每个节点都可以从其他节点访问。这是一个strongly connected 子图,而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):
    

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

    【讨论】:

    • @AlbanSoupper 正如strongly_connected_component_subgraphs 所指出的,确实适用于有向图(有向图)。
    • 我是图新手,但在我看来,在有向图中,子图不是强连接的……想想有向的 path_graph……
    • @AlbanSoupper 当您说子图时,您不清楚您的意图是什么……如果没有指向数学定义的链接,将很难为您提供帮助。当您第一次提出问题时,诸如有向图或无向图之类的细节也很重要!
    • 对不起,我会改写我的问题,让我等 5 分钟
    • 我接受你的回答,因为如果我使用的是无向图,这将是完美的答案:) 谢谢
    【解决方案3】:

    我找到了三个解决方案来解决您的要求,就像我的一样。我的 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)
    

    测试结果总结如下:

    【讨论】:

    • create_subgraph_shortpath(G, node) 帮助我找到了有向图的连通分量。但是,感觉就像我可能忽略了 API 中一个明显的函数来直接为有向图获得这样的结果。对于Graphs,使用connected_components() 比较容易。
    【解决方案4】:

    使用页面末尾的示例connected_component_subgraphs

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

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

    【讨论】:

    • 在我看来,这将提取 最大 子图,而不是“包含特定节点”的子图(如 OP 注释)。
    • @Hooked:我对主题 extract the smallest connected subgraph 产生了误导,在这种情况下,返回的列表将按大小降序排列。相反,如果 OP 想要具有特定节点的子图,那么您的解决方案是有意义的
    • 当前文档中最相关的页面似乎是thisconnected_component_subgraphs 本身已经消失。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 2019-07-14
    • 1970-01-01
    相关资源
    最近更新 更多