我已经实现了一种算法,该算法使用另外两种算法来计算图中的最短路径:Dijkstra和Bellman-Ford。基于这些算法的时间复杂度,我可以计算出我的实现的运行时间,这很容易给出代码。
现在,我想通过实验验证我的计算方法。具体来说,我想将运行时间绘制为输入大小的函数(我遵循描述的方法here)。问题是我有两个参数 - 边数和顶点数。
我试图修复一个参数并更改另一个参数,但这种方法会产生两个图 - 一个用于不同数量的边,另一个用于不同数量的顶点。
这引出了我的问题 - 如何根据两个图来确定增长的顺序?通常,如何通过实验确定具有多个参数的算法的运行时复杂度?
答案 0 :(得分:2)
一般来说非常困难。
通过实验测量单变量情况下的运行时间的常用方法是,插入一个计数器,当您的数据结构执行基本(推定O(1)
)操作时递增计数器,然后获取许多不同输入大小的数据,并将其绘制在log-log
图上。也就是说,log T
与log N
。如果运行时间的格式为n^k
,则应看到斜率k
的直线,或接近此值的内容。如果运行时间类似于T(n) = n^{k log n}
或其他什么,那么你应该看到一个抛物线。如果T
中的n
呈指数增长,您仍应看到指数增长。
您只能希望在执行此操作时获取有关最高订单字词的信息 - 从n
变大后影响越来越小的意义上的低阶条款被滤除。
在两个变量的情况下,你可以尝试做一个类似的方法 - 基本上,采取三维数据,做一个log-log-log
图,并尝试将平面拟合到那个。
然而,只有在大多数政权中只有一个主导词占主导地位时,这才会真正起作用。
假设我的实际功能是T(n, m) = n^4 + n^3 * m^3 + m^4
。
当m = O(1)
时,T(n) = O(n^4)
。
当n = O(1)
时,T(n) = O(m^4)
。
当n = m
,然后是T(n) = O(n^6)
。
在每个制度中,"切片"沿着可能n
,m
值的平面,不同的一个术语是主导词。
因此,无法通过采用固定m
的某些点和某些具有固定n
的点来确定该函数。如果你这样做,你将无法得到n = m
的正确答案 - 你将无法发现"中间"这样的主导词。
我建议,当你有很多变量/复杂的数据结构时,预测渐近增长的最好方法是使用铅笔和纸,并进行传统的算法分析。或者可能是混合方法。尝试将效率问题分解为不同的部分 - 如果你可以将问题分成几个不同功能的总和或产品,也许你可以抽象地确定其中一些,有些你可以通过实验估算。
答案 1 :(得分:1)
幸运的是,两个输入参数仍然很容易在三维散点图中可视化(第三维是测量的运行时间),您可以检查它是否看起来像一个平面(以log-log-log标度)或是否是弯曲。测量中自然的随机变化也起到了作用。
在Matlab中,我通常计算这样的双变量函数的最小二乘解(只是水平地连接x
和y
的不同幂和组合,.*
是一个元素 - 明智的产品):
x = log(parameter_x);
y = log(parameter_y);
% Find a least-squares fit
p = [x.^2, x.*y, y.^2, x, y, ones(length(x),1)] \ log(time)
然后,这可用于估计较大问题实例的运行时间,理想情况下,这些实例将通过实验确认拟合模型的工作原理。
这种方法也适用于更高的维度,但生成起来很乏味,也许有一种更通用的方法来实现这一点,这只是我缺乏知识的解决方法。
答案 2 :(得分:0)
我打算写下自己的解释,但它不会比this更好。