嗨我正在处理一些大(抱歉含糊不清的)图表, 29,981个节点数 150,000个定向边在里面。
我正在使用模块 networkx 处理它,这在图理论家中现在被广泛使用。
我今天早上在Jupyter执行了以下脚本,但无法估计何时完成:
import netowkx as nx
import pickle
# to read the graph
with open ('/home/zachary/H{}'.format("29981"), 'rb') as fp:
H = pickle.load(fp)
print(list(nx.simple_cycles(H)))
我怎样才能粗略猜出这个剧本的完成时间?
我有点知道big O
和small O
是什么......但通常这种理论知识在我的脑海中尚未成熟,工业上使用这些知识来计算和估计计算时间
答案 0 :(得分:2)
正如NetworkX documentation中所述,simple_cycles
使用Johnson的算法来查找基本周期。算法的复杂性为O((V+E).(1+C))
其中
V
是顶点数; E
是边数; 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
运行时间没有表现出约翰逊算法的复杂性,那么有一个非算法因素会减慢/阻止计算 - 这需要进行调查。
<强>后续强> 这些是您提供的图表的一些调查结果。我尝试使用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 |
正如我们所看到的,至少对于G
小于~2,500
个边缘的子图,周期数大致遵循以下幂律
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个边时,常数不会改变,大约的周期数将是... {{1} }
=&GT;看起来你实际上正在打算算法复杂性墙。考虑到这一点,我不知道您希望选择哪种替代方案 - 可能存在非指数近似算法?
注意强>
为了试验~10^359
的子图,我使用了以下命令 - 指定目标节点数,例如3,000个节点:
G