以编程方式找到算法的Landau表示法(Big O或Theta表示法)?


11

我习惯于手动搜索我的算法的Landau(Big O,Theta ...)表示法,以确保它们已尽可能地优化,但是当函数变得真正又大又复杂时,它就在不断发展。手工做的时间太多。它也容易出现人为错误。

我花了一些时间在Codility(编码/算法练习)上,并注意到它们会为您提交的解决方案(时间和内存使用量)提供Landau表示法。

我想知道他们是怎么做到的...你会怎么做?

除了词法分析或代码解析之外,还有其他方法吗?

这个问题主要涉及PHP和/或JavaScript,但是我对任何语言和理论都开放。


4
从SO 检查此答案。听起来像您要找的东西。
Deco 2012年

2
如果您可以创建一个解决每种算法问题的程序,您将以“反对图灵的人”而闻名。
user281377 2012年

1
有关证明通常无法确定运行时间的证据,请在此处此处查看 -那里的答案实际上比您要求的要多。
亚历克斯十布林克

Answers:


13

我想知道他们是怎么做到的...你会怎么做?

我想他们实际上是通过针对不同的问题大小运行该程序,测量时间和空间使用率以及将曲线拟合到结果来估计 Big O度量。

这种方法的问题在于,如果成本函数随着N的增大而改变形状,则会出错。例如1000 N + N^1.5

除了词法分析或代码解析之外,还有其他方法吗?

词法分析和解析是不够的。您还需要对算法的行为进行一些推理。对于以前未知的算法,自动执行此操作很困难。


6
“很难为以前未知的算法自动执行该操作” –更准确地说:这等效于解决暂停问题。
约尔格W¯¯米塔格

嗯...不完全是。解决暂停问题等同于能够对所有以前未知的算法执行此操作。
斯蒂芬·C

2
是的对不起 为一种算法执行此操作等效于(或暗示)证明终止。
约尔格W¯¯米塔格

1
这样做的实用性是:1)无法证明或反驳某些算法的终止,但是2)大多数算法都没有这种理论上的障碍,但是3)定理证明的最新技术还远远不够先进仍然能够做到这一点……除了相对简单的情况。因此,我想我想他们正在以不同的方式这样做。但是显然,如果不查看代码,就无法确定他们的实际操作方式。
斯蒂芬·C

3

他们不能不分析代码。

以下带有人工“复杂度的通货膨胀/通货紧缩”的示例证明,仅测量程序运行时不足以可靠地估计Big-O

void lets_trick_runtime(int n) {
   if (n == 10 || n == 25 || n == 118) {
      // unfair speed-up
      do_precalculated_solution_in_constant_time(n);
      return;
   }
   if (n == 11 || n == 26 || n == 119) {
      // unfair slow-down
      do_some_fake_processing_in_n_cube_time(n);
      return;
   }
   // fair solution
   do_general_solution_in_quadratic_time(n);
}

上面的运行时估计很可能会给出虚假的估计-对于n存在预先计算的解决方案的值,恒定的时间;对于在其中存在的值的立方时间,unfair slow-down而不是“合理的”二次时间。


但是,如果他们确实碰巧检查了“不公平”情况,则他们仍然可以假设最坏的情况确实是在估计Big-O的复杂性。
Yam Marcovic

1

我认为这是不可能的。

如果您使用固定数量的不同输入大小运行某些测试,则可以轻松地计算一个多项式,该多项式近似于您测得的良好运行时。因此,对于每个可能的程序,您最终都会得到一个多项式,这意味着P = NP(yeah!;))。

如果尝试通过符号操作来完成此操作,则最终会到达halting problem。由于无法确定程序是否会停止,因此无法确定程序将具有何种运行时复杂性。

但是,在某些特殊情况下,可以使用后一种方法。但是这些情况可能很小,是否付出努力值得怀疑。


1
+1,尽管我认为暂停问题可以被认为是罕见的。
Yam Marcovic

0

我该怎么办?我解决几乎任何我不想坐下来解决的问题的方式。我模拟。

对于许多问题,使用各种大小多次运行算法,然后对这些结果拟合回归曲线可能就足够了。这样可以快速确定算法的某些特定“固定”开销成本(曲线的截距),以及随着问题规模的增加如何扩展。

需要采取一些修补措施来捕获特别复杂的解决方案,但是特别是如果您只是在寻找合理的估计,则应该能够以这种方式获得它,并查看您的估计与实际结果有何不同,并确定是否可接受的近似值。

在我的脑海里最致命的弱点用此方法是,如果你的算法尺度确实不好,那最初的“运行一大堆的时间”的步骤是会得到丑陋。但坦率地说,事实就是如此,仅此一项就可以表明您可能想退后一步并重新考虑事情。


0

我的直觉是,不可能普遍解决该问题。这样就断言关于算法运行时的先验事实,而无需运行它们(您暗指词法分析)。就是说,某种启发式算法可以用于一类(可能很大)的算法(因为我们一直都在这样做),但是一个通用的算法就相当于解决了Entscheidungs问题,众所周知这并不是可能的(参见Church,Turing等人)。我现在想起来,大约有99.9%的把握…

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.