【发布时间】:2014-06-03 17:53:40
【问题描述】:
我想在 Python 中使用 networkx 在无向图中创建一个算法来查找边是否属于循环。
我正在考虑使用cycle_basis 并获取图中的所有周期。
我的问题是 cycle_basis 返回一个节点列表。如何将它们转换为边缘?
【问题讨论】:
我想在 Python 中使用 networkx 在无向图中创建一个算法来查找边是否属于循环。
我正在考虑使用cycle_basis 并获取图中的所有周期。
我的问题是 cycle_basis 返回一个节点列表。如何将它们转换为边缘?
【问题讨论】:
您可以通过连接相邻节点来构造循环中的边。
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)]]
【讨论】:
这是我的看法,只使用 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))
【讨论】:
如果你找不到一个好的解决方案,这里有一个丑陋的解决方案。
edges(),您可以获得与循环中的节点相邻的边列表。不幸的是,这包括与循环外节点相邻的边如果您发现浪费较少的解决方案,请随时通知我们。
【讨论】:
在 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
【讨论】:
你可以通过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)]
【讨论】: