【问题标题】:How can I estimate growth of function? [closed]我如何估计功能的增长? [关闭]
【发布时间】:2013-09-22 16:45:06
【问题描述】:

假设我有这些信息:

   N   seconds

  216      0.00
 1296      0.48
 7776     89.73
46656  16480.96

如何估计这个函数的增长?

什么是经验增长顺序?

如何估计经验增长顺序?

任何帮助将不胜感激!

【问题讨论】:

  • 为什么不将其放入电子表格并生成图表?你已经知道它的本质(线性?指数?)。一旦你获得了质量,就选择数量:找到一个接近的公式(可能再次使用电子表格,例如 libre office 或 gnumeric)。但通常您最关心的是它的性质(另请参阅大 O 表示法)。
  • 如果你知道函数的代码,你可以分析它来找出它的复杂性。如果你不这样做,你可以尝试提出一个非线性回归模型。有很多软件可以派上用场。 Excel、R-studio、Statistica 等等。
  • 获取更多数据点。我绘制了这个,虽然它显然不是线性的,但它是什么还不清楚。
  • 这个问题似乎跑题了,因为它是关于数学的。
  • wikipedia has an explanation:计算log(t2/t1) / log(n2/n1)。您的第一行是无用的(不能除以零),但对于接下来的三行,我们得到两个区间为 ~ n^2.92 和 ~ n^2.91。所以这是一个稳定的 n^2.9,给予或接受。

标签: algorithm time-complexity curve-fitting estimation


【解决方案1】:

绘制数据是一个好的开始;如果你在线性尺度和对数尺度上绘制它,你可能能够区分多项式增长函数和指数增长函数。

为了快速估计复杂性顺序,计算时间比率会增加。从命令

dc -e '46656 7776/ 16480.96 89.73/  7776 1296/ 89.73 0.48/f'

哪个输出

186
6
183
6

或python命令

python -c 'print 46656/7776, 16481/90, 7776/1296, 90/0.48'

哪个输出

6 183 6 187.5

人们看到,随着问题规模增加六倍,执行时间增加超过 180 倍,经验表明复杂度为 O(n³)。 (empirical 的发现是基于观察而不是理论的结果。将曲线拟合到黑盒函数中,您没有过程信息,只有输入和输出的知识。)

更一般地说,multiple regression 包可用于研究可能的曲线拟合函数。假设 x 是输入,而 y = f(x) 是观察到的输出。多元回归的想法是计算额外的输入值,例如 x², x³, ln x, x·(ln x), 等,然后找到最适合 y 这是输入值的线性组合。

作为一种粗略的近似,也可以编写一个程序来计算各种函数 g 和每个 x,y 的比率 y/g(x) 值对。以下是将此技术应用于问题中显示的数据的示例:

import math
Ns=(216,1296,7776,46656)
times=(0.00,0.48,89.73,16480.96)
for x,y in zip(Ns,times):
    print '{:5} {:8.2f} {:8.2} {:10.3} {:10.3} {:10.3} {:10.3}'.format(x, y, y/x, y/x**2, y/x**3, y/(x**2.92), y/(x**2 * math.log(x)**8))

产生

  216     0.00      0.0        0.0        0.0        0.0        0.0
 1296     0.48  0.00037   2.86e-07   2.21e-10   3.91e-10   4.11e-14
 7776    89.73    0.012   1.48e-06   1.91e-10   3.91e-10   3.58e-14
46656 16480.96     0.35   7.57e-06   1.62e-10   3.84e-10   4.24e-14

上述python程序中的最后两个函数,即g(x)=x2.92g(x)=x²·(ln x) ⁸,用于说明您可以测试相当复杂的功能。但请注意,这种技术有些临时性。

【讨论】:

  • 感谢您的帮助!你能给我一个估计复杂度顺序的 Java 或 Scala 命令吗?
  • 如果我们要估计理论上的增长顺序,答案是正确的。但是经验增长顺序是什么?
  • 非常感谢您的帮助,但是您可以使用 Scala 、Java 或 C 来说明您的示例吗?
  • 对于 Java 或 C,使用double Ns={216,1296,7776,46656}; 之类的数组声明和for (i=0; i<sizeof(Ns)/(sizeof double); ++i) { x=Ns[i]; y=times[i]; printf("%f5.0 %f8.2 %f10.3 (etc) \n", x, y, y/x, (etc)); } 之类的循环构造
【解决方案2】:

一种方法是使用任何电子表格软件(如 Excel)为您拥有的所有数据点生成图表。绘制N vs Seconds 将为您提供时间(秒)如何随着输入大小(N)的增加而增加的良好估计,为您提供有关它是否具有线性增长或指数增长或其他东西的信息。这里的要求是您应该有足够的数据点对观察到的增长有足够的信心。

现在,如果您可以访问该方法的代码,您可以查看代码并查看其复杂性,这将清楚地体现其增长

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    相关资源
    最近更新 更多