函数式编程语言实现的算法复杂度分析


10

今天了解到,算法分析基于计算模型而有所不同。这是我从未想过或从未听说过的事情。

@chi用户给我的示例进一步说明了这一点:

例如,考虑任务:给定 返回 。在RAM中,这可以在解决, 因为数组访问是固定时间的。使用TM,我们需要扫描整个输入,所以它是(i,x1,,xn)xiO(1)O(n)

这使我对功能语言感到疑惑。从我的理解,“函数式语言是密切相关的演算”(由尤瓦Filmus一个评论对这里)。因此,如果功能语言基于lambda演算,但它们在基于RAM的计算机上运行,​​那么对使用纯功能数据结构和语言实现的算法进行复杂度分析的正确方法是什么?

我没有机会阅读“ 纯粹的功能数据结构”,但是我浏览了Wikipedia页面上的主题,并且似乎某些数据结构确实用以下方法代替了传统的数组:

“数组可以用映射或随机访问列表替换,这允许使用纯功能实现,但是访问和更新时间是对数的。”

在那种情况下,计算模型会有所不同,对吗?


3
我绝对不是这个主题的专家,但我相信我听说过1)类似Lisp的机器(具有自己的成本模型)可以模拟具有附加因子的RAM程序(这看起来很容易证明),以及2)是否确实需要这个因素仍然是一个未解决的问题。此外,可以说在RAM模型中为阵列访问分配O(1)成本过于慷慨。在硬件中,内存访问必须遍历门,其中是物理内存的大小。O(logn)O(logn)n

1
还请记住,几乎所有现实世界中的FP语言都具有某种形式的数组,并保证了访问时间(如命令式语言一样)。通常可以解决将其添加为语言原语的问题。O(1)
2016年

1
不同计算模型的一个示例是在lambda演算项上完成的beta减少次数。在FP我们更因此采用打扮成演算冲压模型,如果是有道理的
库尔特·穆勒

1
@KurtMueller注意,仅减少贝特,就可以得到大小为的拉姆达项。这使得计算贝塔数的成本模型不现实。可以说,更好的方法可能是根据当前术语的大小来权衡每一步。但是,这不是唯一可能的模型:lambda项的最佳评估并不以幼稚的方式应用beta,而是希望使用一些更复杂的图形化约简机。在这种情况下,计算beta可能不合适。O(2n)O(n)
2016年

1
请注意,您还需要知道您的功能语言是急切的还是懒惰的/严格的或非严格的。我最近遇到了这样一种情况:在Haskell(非严格)中,真实世界算法是多项式,但是对OCaml(严格)的天真的转换是指数式的。
埃里克·利珀特

Answers:


6

这取决于您的功能语言的语义。您不能孤立地对编程语言进行算法分析,因为您不知道语句的实际含义。您的语言规范需要提供足够详细的语义。如果您的语言用lambda演算指定了所有内容,则需要某种成本度量来进行缩减(它们是O(1)还是取决于所缩减项的大小?)。

我认为大多数函数语言都不会那样做,而是提供更多有用的语句,例如“函数调用是O(1),附加到列表的开头是O(1)”,诸如此类。


我相信我有点理解您的答案(误解很可能是由于我对lambda微积分缺乏理解):您是说您基本上必须根据个案(以语言为例)进行分析,而不是一般的方法,因为某些操作对每种语言都有不同的含义。我的理解正确吗?
阿卜杜勒

是。您的语言设计师需要先告诉您可以用该语言编写的内容实际上意味着什么,然后才能分析算法的运行时间。
adrianN 2013年

“您不能单独对编程语言进行算法分析”-是指FP语言还是一般的语言?如果是早期版本,那么我们该如何在学校中以这种通用方式进行算法分析,即跨Java,C / C ++,Python问题进行分析?是因为它们非常相似吗?还是因为底层数据结构和ADT都相同并且以相同的方式实现?还是最后,是因为这些课程仅仅是出于教育目的,不一定必须严格准确吗?
阿卜杜勒

1
所有编程语言都是如此。为了严格正确,首先需要修复机器模型,例如RAM和它支持的指令(少量)。您只能使用这些指令对程序进行分析。然后,您可以考虑将编程语言映射到该机器模型。然后,您可以使用编程语言分析程序。要进行非常严格的处理,请查看《计算机编程艺术》中的Knuth是如何做的。由于big-O隐藏常数,很多这样的事情可以简化。
adrianN
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.