如NetworkX documentation 中所述,simple_cycles 使用约翰逊算法来查找基本循环。算法的复杂度是O((V+E).(1+C)) 其中
在您的情况下V+E ~= 150,000,因此假设python进程没有过载,我们可以预期运行时间为150,000.K.C。
要尝试找到 K 的估计值,您可以在较小的图上运行算法,使用 10 的幂 (V+E = 10, 100, 1000 ...) 以确保 simple_cycles 的运行时间与 (V+E)(1+C) 保持成比例,得到K 的粗略值,并根据您期望找到的周期数估计图表的运行时间。更准确地说,如果我们记下 R(V+E,C) 每个实验小图的实际运行时间,以及 C0, C1, ...Cn 它们各自的周期数,那么我们预计会有
R(100,C1) / R(10,C0) ~= 10.K.[(1+C1) / (1+C0)]
R(1000,C1) / R(100,C0) ~= 10.K.[(1+C2) / (1+C1)]
...
如果simple_cycles 的运行时间没有表现出 Johnson 算法的复杂性,那么就有一个非算法因素正在减慢/阻止计算 - 这需要进行调查。
跟进
这些是使用您提供的图表进行的一些调查的结果。我尝试使用 NetworkX 库计算较小子图的周期数,并在下面复制了一些有趣的结果。每个子图都有节点数和边数以及计算的循环数。
\#Nodes | \#Edges | \#Cycles (computed)
----------------------------------------
1,000 | 186 | 17
2,000 | 675 | 37
3,000 | 1,460 | 72
4,000 | 2,538 | 2,147
4,250 | 2,881 | 2,351,883
我在#Nodes = 4000 停了下来,几分钟内我没有得到任何结果。
让我们计算每个值的值
log10(C)/E with C = \#Cycles and E = \#Edges.
E = \#Edges | C = \#Cycles (computed) | log(C)/E |
----------------------------------------------------
186 | 17 | 0.0067 |
675 | 37 | 0.0023 |
1,460 | 72 | 0.0013 |
2,538 | 2,147 | 0,0013 |
2,881 | 2,351,883 | 0,0022 |
正如我们所见,至少对于具有少于~2,500 边的G 的子图,周期数大致遵循以下幂律
log10(C) = 0.0013.E => C = 1.003^E
经验值 1.003 来自图的拓扑结构(作为旁注,maximum theoretical number of cycles given the number of edges 估计为1.443^E。
请注意,我们不知道这个常数是否随着图形变大而保持不变 - 这将是一件有趣的事情,但使用与这种蛮力方法不同的方法(我们已经有一千个当我们达到 5000 条边时,十亿个周期)。
在这种情况下(并且仅在这种情况下)常数不会随着图形变大直到 G 的 150,000 条边而改变,循环的近似数将是...~10^359
=> 看来您实际上遇到了算法复杂性墙。考虑到这一点,我不知道您希望选择哪种替代方案 - 也许存在非指数近似算法?
注意
为了试验G 的子图,我使用了以下命令 - 指定目标节点数,例如 3,000 个节点:
H = G.copy()
H.remove_nodes_from(list(nodes)[3000:])
len(list(nx.simple_cycles(H)))