简体   繁体   English

在循环 networkx python 中查找边

[英]Find edges in a cycle networkx python

I would like to make an algorithm to find if an edge belongs to a cycle, in an undirected graph, using networkx in Python.我想制作一个算法来在无向图中使用 Python 中的 networkx 来查找边是否属于一个循环。 I am thinking to use cycle_basis and get all the cycles in the graph.我正在考虑使用cycle_basis并获取图中的所有循环。 My problem is that cycle_basis returns a list of nodes.我的问题是cycle_basis返回一个节点列表。 How can I convert them to edges?如何将它们转换为边缘?

You can construct the edges from the cycle by connecting adjacent nodes.您可以通过连接相邻节点来构建循环中的边。

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

Here is my take at it, using just lambda functions (I love lambda functions!):这是我的看法,仅使用 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))

in case you don't find a nice solution, here's an ugly one.如果你没有找到一个很好的解决方案,这里有一个丑陋的解决方案。

  1. with edges() you can get a list of edges that are adjacent to nodes in a cycle.使用edges()可以获得与循环中的节点相邻的边列表。 unfortunately, this includes edges adjacent to nodes outside the cycle不幸的是,这包括与循环外的节点相邻的边
  2. you can now filter the list of edges by removing those which connect nodes that are not part of the cycle.您现在可以通过删除那些连接不属于循环的节点的边来过滤边列表。

please keep us posted if you find a less wasteful solution.如果您找到了一个不那么浪费的解决方案,请通知我们。

With the help of Aric, and a little trick to check both directions, I finally did this that looks ok.在 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)

output:输出:

(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

You can directly obtain the edges in a cycle with the find_cycle method.您可以使用find_cycle方法直接获取循环中的边。 If you want to test if an edge belongs to a cycle, you should check if both of its vertices are part of the same cycle.如果你想测试一条边是否属于一个循环,你应该检查它的两个顶点是否属于同一个循环。

Using the example in the answers above:使用上述答案中的示例:

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

On the other hand, the edge (2, 3) (or (3, 2) as your graph is undirected) is part of a cycle defined first:另一方面,边(2, 3) (或(3, 2)因为你的图是无向的)是首先定义的循环的一部分:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM