【问题标题】:Find edges in a cycle networkx python在循环网络x python中查找边
【发布时间】:2014-06-03 17:53:40
【问题描述】:

我想在 Python 中使用 networkx 在无向图中创建一个算法来查找边是否属于循环。 我正在考虑使用cycle_basis 并获取图中的所有周期。 我的问题是 cycle_basis 返回一个节点列表。如何将它们转换为边缘?

【问题讨论】:

    标签: python graph networkx


    【解决方案1】:

    您可以通过连接相邻节点来构造循环中的边。

    In [1]: import networkx as nx
    
    In [2]: G = nx.Graph()
    
    In [3]: G.add_cycle([1,2,3,4])
    
    In [4]: G.add_cycle([10,20,30])
    
    In [5]: basis = nx.cycle_basis(G)
    
    In [6]: basis
    Out[6]: [[2, 3, 4, 1], [20, 30, 10]]
    
    In [7]: edges = [zip(nodes,(nodes[1:]+nodes[:1])) for nodes in basis]
    
    In [8]: edges
    Out[8]: [[(2, 3), (3, 4), (4, 1), (1, 2)], [(20, 30), (30, 10), (10, 20)]]
    

    【讨论】:

    • 我在想类似的事情,但是如果我搜索边缘 (3,2) 会怎样。我认为对此的解决方案可能是both_direction = [] for edge in edges:new_edge = [] for a,b in edge:new_edge.append((a,b))new_edge.append((b,a))both_direction。追加(新边缘)
    • 在这种情况下,您需要检查 (2,3) 和 (3,2) 的元组。根据您的应用程序,我想您可能需要更复杂的数据结构(甚至可能是图表)。
    【解决方案2】:

    这是我的看法,只使用 lambda 函数(我喜欢 lambda 函数!):

    import networkx as nx
    
    G = nx.Graph()
    
    G.add_cycle([1,2,3,4])
    
    G.add_cycle([10,20,30])
    
    G.add_edge(1,10)
    
    
    in_path = lambda e, path: (e[0], e[1]) in path or (e[1], e[0]) in path
    cycle_to_path = lambda path: list(zip(path+path[:1], path[1:] + path[:1]))
    in_a_cycle = lambda e, cycle: in_path(e, cycle_to_path(cycle))
    in_any_cycle = lambda e, g: any(in_a_cycle(e, c) for c in nx.cycle_basis(g))
    
    for edge in G.edges():
        print(edge, 'in a cycle:', in_any_cycle(edge, G))
    

    【讨论】:

      【解决方案3】:

      如果你找不到一个好的解决方案,这里有一个丑陋的解决方案。

      1. 使用edges(),您可以获得与循环中的节点相邻的边列表。不幸的是,这包括与循环外节点相邻的边
      2. 您现在可以通过删除连接不属于循环的节点的边来过滤边列表。

      如果您发现浪费较少的解决方案,请随时通知我们。

      【讨论】:

        【解决方案4】:

        在 Aric 的帮助下,加上一个检查两个方向的小技巧,我终于做到了,看起来还不错。

        import networkx as nx
        
        G = nx.Graph()
        
        G.add_cycle([1,2,3,4])
        
        G.add_cycle([10,20,30])
        
        G.add_edge(1,10)
        
        
        def edge_in_cycle(edge, graph):
            u, v = edge
            basis = nx.cycle_basis(graph)
            edges = [zip(nodes,(nodes[1:]+nodes[:1])) for nodes in basis]
            found = False
            for cycle in edges:
                if (u, v) in cycle or (v, u) in cycle:
                    found = True            
            return found
        
        for edge in G.edges():
            print edge, 'in a cycle:', edge_in_cycle(edge, G)
        

        输出:

        (1, 2) in a cycle: True
        (1, 4) in a cycle: True
        (1, 10) in a cycle: False
        (2, 3) in a cycle: True
        (3, 4) in a cycle: True
        (10, 20) in a cycle: True
        (10, 30) in a cycle: True
        (20, 30) in a cycle: True
        

        【讨论】:

          【解决方案5】:

          你可以通过find_cycle方法直接获取循环中的边。如果你想测试一条边是否属于一个循环,你应该检查它的两个顶点是否属于同一个循环。

          使用上述答案中的示例:

          import networkx as nx
          
          G = nx.Graph()
          G.add_cycle([1,2,3,4])
          G.add_cycle([10,20,30])
          G.add_edge(1,10)
          nx.find_cycle(G, 1) # [(1, 2), (2, 3), (3, 4), (4, 1)]
          nx.find_cycle(G, 10) # [(10, 20), (20, 30), (30, 10)]
          

          另一方面,边(2, 3)(或(3, 2),因为您的图是无向的)是首先定义的循环的一部分:

          nx.find_cycle(G, 2) # [(2, 1), (1, 4), (4, 3), (3, 2)]
          

          【讨论】:

            猜你喜欢
            • 2021-11-26
            • 1970-01-01
            • 2020-06-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-07-26
            • 2013-07-04
            • 2014-02-27
            相关资源
            最近更新 更多