如何按环长升序遍历图简单环并统计节点环成员情况?
我需要找出图中所有属于长度不超过给定max_length的简单环的节点,同时生成每个节点在各长度环中出现次数的直方图,目前正在寻找完成该任务的最优方案。
有一个更具体的相关问题:For a given node, how to find small cycles of which that node is a member?,二者并非重复问题。
我正在使用Python和graph-tool进行图分析,多项测试表明graph-tool是当前性能顶尖的Python图库之一,因此是合适的选择。其他库要么速度不足(如networkx),要么时间复杂度表现不佳(如igraph中的边删除操作),无法满足我的任务扩展需求。
思路1:按环长升序遍历所有环并记录节点
思路1.1:使用graph-tool的all_circuits函数
graph-tool提供了graph_tool.topology.all_circuits函数,但它似乎并非仅遍历简单环,或者无法按我需要的顺序遍历。我并不完全清楚它的具体行为,但可以确定的是该函数在我的图上会出现时间复杂度爆炸的问题。例如,在仅有34个节点的小型Zachary空手道俱乐部图中,它会找到1462130个环。而我需要分析的图约有200万个节点和400万条边,尝试运行该函数后,甚至无法获取到我关注的大部分短环,估计此类图的环搜索耗时将长达数年。
示例代码:
import graph_tool.collection import graph_tool.topology g = graph_tool.collection.data["karate"] print("number of nodes in graph:", g.num_vertices()) print() print(f"circ_idx\tcircuit") circuit_iter = graph_tool.topology.all_circuits(g) i = 0 for circuit in circuit_iter: i += 1 if i % 152371 == 0: print(f"{i}\t{circuit}") print("total number of circuits:", i)
输出结果:
number of nodes in graph: 34 circ_idx circuit 152371 [ 0 3 1 13 2 28 31 25 24 27 33 29 23 32 8] 304742 [ 0 7 1 30 32 23 33 27 24 25 31 28 2 3 12] 457113 [ 0 8 30 1 19 33 18 32 29 23 25 24 31] 609484 [ 0 8 33 27 24 25 23 29 32 2 3] 761855 [ 0 13 1 7 3 2 32 31 25 23 33 19] 914226 [ 0 17 1 7 3 2 32 31 24 27 23 29 33 30 8] 1066597 [ 0 19 33 27 24 25 23 29 32 30 1 3] 1218968 [ 0 31 24 27 23 29 26 33 22 32 2 3 12] 1371339 [ 0 31 32 23 25 24 27 33 13 3 2 1 30 8] total number of circuits: 1462130
思路1.2:自行实现环遍历逻辑
自行实现思路1的逻辑是可行的,但工作量较大,我不想重复造轮子。是否有更好的方法?
思路2:针对单个节点的BFS环搜索
作为思路1的替代方案,也可以针对每个节点,按环长升序遍历该节点所属的所有环,这可以通过从目标节点出发进行广度优先搜索(BFS)实现。通过这种方式,我可以检查节点是否属于这些环,然后处理下一个节点。该方法效率较低,因为同一个环会被其中包含的每个节点重复处理,但总体时间复杂度仍在可接受范围内。该方法的最大优势是实现难度低于思路1。
是否存在更优的方案?graph-tool是否提供了更适合该任务的工具?
内容的提问来源于Stack Exchange,提问作者Daniel S.

