Math 从运行时确定时间复杂性的最简单方法

Math 从运行时确定时间复杂性的最简单方法,math,complexity-theory,big-o,curve-fitting,Math,Complexity Theory,Big O,Curve Fitting,假设我正在分析一个算法,我所能做的就是用不同的输入运行它。我可以将一组点(x,y)构造为(样本大小,运行时)。 我想动态地将算法分类为一个复杂度类(线性、二次、指数、对数等) 理想情况下,我可以给出一个或多或少近似于行为的方程式。 我只是不知道最好的方法是什么 对于任何次多项式,我都可以创建回归曲线,并提出一些适合度的度量,但对于任何非多项式函数,我真的不知道该如何做。更难的是,因为我之前不知道我应该试着适合什么形状 这可能更像是一个数学问题,而不是一个编程问题,但对我来说很有趣。我不是数学家,

假设我正在分析一个算法,我所能做的就是用不同的输入运行它。我可以将一组点(x,y)构造为(样本大小,运行时)。 我想动态地将算法分类为一个复杂度类(线性、二次、指数、对数等) 理想情况下,我可以给出一个或多或少近似于行为的方程式。 我只是不知道最好的方法是什么

对于任何次多项式,我都可以创建回归曲线,并提出一些适合度的度量,但对于任何非多项式函数,我真的不知道该如何做。更难的是,因为我之前不知道我应该试着适合什么形状


这可能更像是一个数学问题,而不是一个编程问题,但对我来说很有趣。我不是数学家,所以可能有一种更简单的方法,可以从我不知道的一组点得到一个合理的函数。有人对解决这样的问题有什么想法吗?有没有一个C的数字库可以帮助我处理这些数字呢?

曲线拟合曾经是一门艺术,但现在不知何故变得颓废了:)(这对周围的物理学家来说是个笑话)

已经取得了很多进展,这使得普通人能够猜测(一些)非平凡的函数依赖关系

我不会对这些方法和限制进行描述,但我会让你们参考,这是康奈尔大学开发的一款非常好的软件

Eureqa(发音为“eureka”)是一种软件工具,用于检测数据中的方程式和隐藏的数学关系。其目标是确定最简单的数学公式,以描述产生数据的潜在机制。Eureqa可免费下载和使用。查找程序下载、视频教程、用户论坛和其他参考资料。

如果模型不太复杂的话,我试过几次eureqa,结果都很好。我认为它足以区分多项式、对数和指数

后脚本:
遗憾的是,软件不再是免费的:(

那么,你真正关心的复杂度类别就不多了,比如:线性、二次、多项式(次数>2)、指数和对数

对于其中的每一个,你可以使用最大的(x,y)对来求解未知变量。让y=f(x)表示算法的运行时间,作为样本大小的函数。让我们假设f(1)=0,如果不是,我们总是可以从每个y中减去该值y(1),这只是消除f(x)中的常数。让y(结束)表示(x,y)数据集中y的最后(和最大)值

在这一点上,我们可以解决每个标准形式中的未知问题:

f(x) = c*x
f(x) = c*x^2
f(x) = x^c
f(x) = c^x
f(x) = log(x)/log(c)

由于每个方程中只有一个未知量,所以我们可以为它求解任何一个点。考虑下面的数据从一个多项式的随机度>2:< /P>

x = [ 1 2 3 4 5 6 7 8 9 10 ];
y = [ 0 6 19 44 81 135 206 297 411 550 ];
如果我们使用最后一个点为每种可能性解c(假设这是最小的噪声估计)

我们现在可以比较这些函数与剩余数据的拟合程度,下面是一个图:

我是新来的,不能发布图片,请看这里的情节:


真实数据显示在红色星号中,与绿线呈线性,蓝色为二次曲线,黑色为多项式,粉色为指数,绿色为对数图,带有O。从残差中可以清楚地看出,什么函数最适合您的数据。

我认为“从残差中应该很清楚什么函数最适合你的数据”可能不是真的。曲线拟合方法已经发展了200年,可能从Legendre()开始。即使渐近行为有界于一个小函数集,任何其他函数都可能出现添加,在无穷远处占主导地位(但由于你事先不知道问题的常数,你不知道你离“无限”有多远)为了简单起见,我喜欢这个,尽管我担心精度。我可以使用更多的点来获得多项式>2的更接近近似值,我不太关心提取完美方程,但我希望它相当稳健。CaptnCraig,是的,你可以使用所有的点,对前3个函数进行最小二乘,但其余的都是n太简单了。我试着将其余部分重新格式化为优化,但它们并不都是凸的,也不容易求解,更不用说有一个封闭的形式了。Eureqa看起来很酷。它看起来可以完成我需要的数学类型,但我真的希望我可以在C#应用程序中运行。@CaptnCraig Eureqa有一个开放的API,允许使用eureqa服务器的客户端。请看,我的最终目标是运行一种基本的单元测试,以确保不同大小的输入的代码在一定的时间复杂度内运行。
550 = c*10    -> c = 55
550 = c*10^2  -> c = 5.5
550 = 10^c    -> c = log(550)/log(10) ~= 2.74
550 = c^10    -> c = 550^(1/10) ~= 1.88
550 = log(x)/log(c) -> c = 10^(1/550) ~= 1.0042