我习惯于手动搜索我的算法的Landau(Big O,Theta ...)表示法,以确保它们已尽可能地优化,但是当函数变得真正又大又复杂时,它就在不断发展。手工做的时间太多。它也容易出现人为错误。
我花了一些时间在Codility(编码/算法练习)上,并注意到它们会为您提交的解决方案(时间和内存使用量)提供Landau表示法。
我想知道他们是怎么做到的...你会怎么做?
除了词法分析或代码解析之外,还有其他方法吗?
这个问题主要涉及PHP和/或JavaScript,但是我对任何语言和理论都开放。
我习惯于手动搜索我的算法的Landau(Big O,Theta ...)表示法,以确保它们已尽可能地优化,但是当函数变得真正又大又复杂时,它就在不断发展。手工做的时间太多。它也容易出现人为错误。
我花了一些时间在Codility(编码/算法练习)上,并注意到它们会为您提交的解决方案(时间和内存使用量)提供Landau表示法。
我想知道他们是怎么做到的...你会怎么做?
除了词法分析或代码解析之外,还有其他方法吗?
这个问题主要涉及PHP和/或JavaScript,但是我对任何语言和理论都开放。
Answers:
我想知道他们是怎么做到的...你会怎么做?
我想他们实际上是通过针对不同的问题大小运行该程序,测量时间和空间使用率以及将曲线拟合到结果来估计 Big O度量。
这种方法的问题在于,如果成本函数随着N的增大而改变形状,则会出错。例如1000 N + N^1.5。
除了词法分析或代码解析之外,还有其他方法吗?
词法分析和解析是不够的。您还需要对算法的行为进行一些推理。对于以前未知的算法,自动执行此操作很困难。
他们不能不分析代码。
以下带有人工“复杂度的通货膨胀/通货紧缩”的示例证明,仅测量程序运行时不足以可靠地估计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而不是“合理的”二次时间。
我认为这是不可能的。
如果您使用固定数量的不同输入大小运行某些测试,则可以轻松地计算一个多项式,该多项式近似于您测得的良好运行时。因此,对于每个可能的程序,您最终都会得到一个多项式,这意味着P = NP(yeah!;))。
如果尝试通过符号操作来完成此操作,则最终会到达halting problem。由于无法确定程序是否会停止,因此无法确定程序将具有何种运行时复杂性。
但是,在某些特殊情况下,可以使用后一种方法。但是这些情况可能很小,是否付出努力值得怀疑。
我该怎么办?我解决几乎任何我不想坐下来解决的问题的方式。我模拟。
对于许多问题,使用各种大小多次运行算法,然后对这些结果拟合回归曲线可能就足够了。这样可以快速确定算法的某些特定“固定”开销成本(曲线的截距),以及随着问题规模的增加如何扩展。
需要采取一些修补措施来捕获特别复杂的解决方案,但是特别是如果您只是在寻找合理的估计,则应该能够以这种方式获得它,并查看您的估计与实际结果有何不同,并确定是否可接受的近似值。
在我的脑海里最致命的弱点用此方法是,如果你的算法尺度确实不好,那最初的“运行一大堆的时间”的步骤是会得到丑陋。但坦率地说,事实就是如此,仅此一项就可以表明您可能想退后一步并重新考虑事情。