【问题标题】:Finding Successors of Successors in a Directed Graph in NetworkX在 NetworkX 的有向图中寻找后继者的后继者
【发布时间】:2011-07-31 00:39:01
【问题描述】:

我正在为 NetworkX 中的有向图编写一些代码,并且遇到了一个问题,这可能是我有问题的编程经验的结果。我正在尝试做的是以下内容:

我有一个有向图 G,顶部有两个“父节点”,所有其他节点都从中流出。在绘制此网络图时,我想将作为“父 1”后代的每个节点绘制为一种颜色,而将所有其他节点绘制为另一种颜色。这意味着我需要一份 Parent 1 的继任者名单。

现在,我可以使用以下方法轻松获得它们的第一层:

descend= G.successors(parent1)

问题是这只给了我第一代继任者。最好是,我想要后继者的后继者,后继者的后继者等。任意,因为能够运行分析并制作图表而不必确切知道其中有多少代,这将是非常有用的.

知道如何解决这个问题吗?

【问题讨论】:

    标签: python networkx directed-graph


    【解决方案1】:

    您不需要后代列表,您只想为它们着色。为此,您只需选择一种遍历图形的算法并使用它为边缘着色。

    例如,你可以这样做

    from networkx.algorithms.traversal.depth_first_search import dfs_edges
    
    G = DiGraph( ... )
    for edge in dfs_edges(G, parent1):
        color(edge)
    

    https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.traversal.depth_first_search.dfs_edges.html?highlight=traversal

    【讨论】:

    • 看起来 DFS 算法可能是我最好的选择。我没有使用上面建议的代码,而是使用了 dfs_successors,看起来这给了我一个包含父 1 的所有后继者的字典。现在只需将该字典转换为有用的格式。 讨厌字典。
    • 稍微修改上面的答案,最终使用 dfs_successors(G, parent1) 确实返回了所有后继者的字典,将该字典转换为列表,然后根据stackoverflow.com/questions/952914/… 对列表进行优化。感谢两位评论者的帮助。
    • 不起作用...在示例中没有明确说明。
    【解决方案2】:

    如果你想获得所有后继节点,而不通过边,另一种方法可能是:

    import networkx as nx
    G = DiGraph( ... )
    successors = nx.nodes(nx.dfs_tree(G, your_node))
    

    我注意到,如果您改为打电话:

    successors = list(nx.dfs_successors(G, your_node)
    

    底层的节点不知何故不包括在内。

    【讨论】:

    • 甜蜜!正在寻找类似nx.dfs_tree
    • 这应该更高,即使接受的答案解决了 OP 的问题,但问题实际上是以只有这个问题才能回答的方式提出的
    【解决方案3】:

    嗯,继承人的继承人只是后代的继承人吧?

    # First successors
    descend = G.successors(parent1)
    # 2nd level successors
    def allDescendants(d1):
       d2 = []
       for d in d1:
           d2 += G.successors(d)
       return d2
    
    descend2 = allDescendants(descend)
    

    要获取 3 级后代,请调用 allDescendants(d2) 等。

    编辑: 问题一: allDescend = descend + descend2 为您提供两组组合,对更多级别的后代执行相同操作。

    问题2:如果你的图中有循环,那么你需要先修改代码来测试你之前是否访问过那个后代,例如:

    def allDescendants(d1, exclude):
       d2 = []
       for d in d1:
           d2 += filter(lambda s: s not in exclude, G.successors(d))
       return d2
    

    这样,您将allDescend 作为第二个参数传递给上述函数,因此它不会包含在未来的后代中。你一直这样做,直到allDescandants() 返回一个空数组,在这种情况下你知道你已经探索了整个图表,然后你停止。

    既然这开始看起来像家庭作业,我会让你弄清楚如何自己拼凑所有这些。 ;)

    【讨论】:

    • 两个问题。 1:运行上面的代码只给出第二级后代。有没有办法附加结果以获得所有后代的运行列表? 2:这个解决方案假设我知道我有多少级别。有没有办法让它运行 n 个级别,直到它基本上停止获得新的后代?
    • 顺便说一句,这不是家庭作业。到目前为止,我已经完成了作业并进入“太好了,这听起来是一个绝妙的想法,去实现它......”
    • 快速评论:使用+=append 更昂贵,因为新的list 对象在每次循环迭代中被销毁和创建。 pymplerline_profiler 可以用来观察差异。
    【解决方案4】:

    为了让以后偶然发现它的人更容易找到答案,下面是我最终使用的代码:

    G = DiGraph() # Creates an empty directed graph G
    infile = open(sys.argv[1])
    for edge in infile:
        edge1, edge2 = edge.split() #Splits data on the space
        node1 = int(edge1) #Creates integer version of the node names 
        node2 = int(edge2)
        G.add_edge(node1,node2) #Adds an edge between two nodes
    
    parent1=int(sys.argv[2])   
    parent2=int(sys.argv[3])
    
    data_successors = dfs_successors(G,parent1)
    successor_list = data_successors.values()
    allsuccessors = [item for sublist in successor_list for item in sublist]
    
    pos = graphviz_layout(G,prog='dot') 
    plt.figure(dpi=300)
    draw_networkx_nodes(G,pos,node_color="LightCoral")
    draw_networkx_nodes(G,pos,nodelist=allsuccessors, node_color="SkyBlue")
    draw_networkx_edges(G,pos,arrows=False) 
    draw_networkx_labels(G,pos,font_size=6,font_family='sans-serif',labels=labels)
    

    【讨论】:

      【解决方案5】:

      我相信自几年前@Jochen Ritzel 的回答以来,Networkx 已经发生了变化。

      现在以下成立,只是改变了 import 语句。

      import networkx
      from networkx import dfs_edges
      
      G = DiGraph( ... )
      for edge in dfs_edges(G, parent1):
          color(edge)
      

      【讨论】:

        【解决方案6】:

        Oneliner:

        descendents = sum(nx.dfs_successors(G, parent).values(), [])
        

        【讨论】:

          【解决方案7】:
          猜你喜欢
          • 2013-11-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-18
          • 2012-01-14
          • 1970-01-01
          • 2022-01-06
          • 1970-01-01
          相关资源
          最近更新 更多