哪种语言可用于组合优化中的启发式快速原型设计?

时间:2010-08-31 00:18:14

标签: python algorithm haskell combinatorics rapid-prototyping

我必须为硬组合问题开发一种类似于快速启发式的算法。因此,我认为,最好先学习一种比C ++更具表现力的语言来解决这个问题,因为我认为需要很多不同的算法尝试才能解决我的任务。

关于某些候选语言的个人观点:

的Python:

语法好,表现力好,但非强类型 - >我赞成编译器错误而不是运行时错误,并且不希望为每个算法开发测试套件。

Haskell中:

语法好,表达力强,强类型,但我想我必须三思而后行才能申请 - >由于语言的纯洁性,可能有太多的界限

我想要/喜欢什么? (可以互相排斥!)

  • 快速发展的良好表现力
  • 强类型
  • 类似功能语言的高阶函数
  • 像数组一样的可变数据类型
  • 可能是某种泛型/模板
  • 也许是声明性编程的可能性(对于组合选择中的子问题)。

我不需要的内容:

  • 代码的最新性能(问题出在类np中,因此错误使用懒惰会导致缺少线性开销)
  • 并行化

我必须承认,我喜欢Python的表现力,但我不会用它生成好的和健壮的代码。

我喜欢函数式编程的艺术,但我也喜欢可变数据结构。也许是因为我没有足够的经验来在短时间内用这种语言中的“纯度”来制作算法。

有什么建议吗? 有类似的经历吗?

Clean,F#,Erlang ......?

10 个答案:

答案 0 :(得分:17)

我是一名Haskell程序员超过7年,从那时起我就没有使用任何其他语言进行认真的工作了。我的建议当然是Haskell。 : - )

根据我的经验,这是你对Haskell的期望:

  • 学习Haskell需要时间。数学倾向的人倾向于很快地接受它,但大多数程序员需要一段时间来忘记他们以前的经验并熟悉纯粹的函数式编程。如果您的项目应该在昨天完成,那么您最好使用您已经熟悉的语言。
  • 比C少约4x-10x代码。例如,这里是快速排序的原型实现

 qsort :: Ord a => [a] -> [a]
 qsort []     = []
 qsort (x:xs) = qsort (filter (<x) xs) ++ [x] ++ qsort (filter (>=x) xs)
  • 一旦您的源代码编译,它通常在第一次尝试时是正确的。类型系统和纯度,即缺乏可变数据结构,是造成这种情况的主要原因。
  • Haskell强迫你思考这个问题。如果编译器抛出一个拟合,那通常表明你还没有清楚地了解你的问题域。
  • 空间泄漏和堆栈溢出。它们发生了,但一旦出现它们通常不难修复。但是,这需要很好地理解执行模型,即延迟评估。这是typical example of a space leak
  • Haskell社区是一个很好的资源。如果您遇到了绊脚石,访问#haskell IRC频道或询问haskell-cafe@haskell.org或beginners@haskell.org邮件列表可能会解决您的问题。

我认为用经验以外的其他方式来支持这些经验是不可能的;所以,你必须接受我的话。

有几份经验报告已正式发布,另请参阅Haskell in Industry页面。我发现Haskell vs. Ada vs. C++ vs. Awk vs. ... An Experiment in Software Prototyping Productivity [pdf]特别有启发性。

答案 1 :(得分:7)

我认为你会发现大多数流行的非常高级的语言都是“弱类型”的原型。

此外,当我进行单元测试时,它几乎永远不会来确保事物的类型正确。这很难成为一个大问题。您应该进行单元测试,以确保算法的自由免受任何原因的错误。

你提到过python,所以我会建议你自己不熟悉haskell。 Python有Numpy并且与C集成得非常好。它还有stdlib中的itertools模块,它非常适合组合工作(明智地应用,它可以比平庸的C略胜一筹)。我目前正在开发一个类似的项目,我用python将其原型化。我目前正在将大部分内容翻译成C.这是一个很好的过程,因为我已经有了每个算法的python实现,所以一旦我将C包装为python,我可以测试两个相互之间的对确保它们在相同的输入上提供相同的输出。因为我在python中构建了一个原型,所以我得到了一个非常便宜的测试框架,用于我的应用程序一个用C编写的python模块。

另外我已经找到了最佳(或至少是足够的)算法,如果我遇到一个新算法,我可以快速修改不同分支中的python以测试它的效率。

无论您选择何种语言,请考虑确保它与您的终极目标语言完美整合,以利用类似的特权。

答案 2 :(得分:2)

我没有使用过Python,而且我只使用了一点Haskell,完全是你描述的目的 - 原型设计。需要注意的是懒惰给你带来的减速,而不是看似恒定空间算法可以space leaks 消耗所有可用内存的事实,其中thunk表示未评估的块代码空间泄漏很难看到。

当然,你可以担心它们,并搜索你的程序寻找它们,用seq和其他形式的丑陋消灭它们......但使用原型语言的目的是避免所有这些令人头疼的问题。

如果您正在玩的问题规模如此之小,以至于如果在程序中的每个评估步骤中从头到尾为内存创建thunk并不重要,那么我可以推荐Haskell。

答案 3 :(得分:2)

虽然我鼓励你学习更多的语言,但如果你的目标是尽可能快地解决这个问题,我会坚持使用C ++(因为你似乎已经熟练掌握了它)。

虽然如果你现在只了解C ++,其他语言可能更适合原型设计,你可能会有一个合理的大学习曲线,这会让你慢下来,至少你会失去它对这个项目的优势(特别是如果你是看看主要的范式变化)。

另一方面,如果这实际上更多是为了扩展您对未来的知识,那么几乎任何脚本语言都会这样做。

答案 4 :(得分:2)

如果您可以将问题域表示为“嵌入式域特定语言”(eDSL),那么Haskell可以真正发挥作用。这实际上只是一个带有pretensions的函数库,但诀窍是定义一个底层抽象和函数来操作它。如果不更好地理解你的领域,很难用更具体的术语来解释,但我希望你想给一个潜在的组合算法提供一些关于首先解决问题的哪些部分的提示,以及如何识别有希望的部分解决方案。

首先看一下monad列表。如果你的问题不是太复杂,那么这可能就是你所需要的。有关更多信息,请查看this page,了解有关如何添加回溯和修剪的建议。

答案 5 :(得分:1)

C#4.0

它几乎拥有您需要的所有功能。

  1. Functional programming
  2. 高阶函数
  3. .NET Parallel extensions
  4. Lazyness
  5. 泛型
  6. Arrays
  7. Some ProjectEular Examples

    注意:我自己会使用Python并用C ++编写一些模块。 ;)

答案 6 :(得分:0)

我不会使用C ++,因为它不会捕获数据末尾缺少索引的东西,因为它不会为您提供垃圾收集器。就个人而言,我会使用Java,因为这就是我所熟悉的。

我会考虑您熟悉的内容,您希望与之合作或至少与之沟通的人员,以及您可能想要使用的库。这可能包括I / O或用于后处理结果的图形库,以及特殊的组合算法。您也可以查找分析工具,这样您就可以看到算法在所有时间内花费的时间。

答案 7 :(得分:0)

我建议给D一个机会。它接近C ++,但更容易推理和没有所有丑陋的疣。如果你正在考虑用C ++编写最终的实现,那么将D转换为C ++就像Python一样容易得多,而且你可以选择继续使用D,因为它的性能与C ++相当。

答案 8 :(得分:0)

也许R是您正在寻找的答案?

答案 9 :(得分:0)

我必须为一个难以组合的问题开发一种类似于快速启发式的算法。

对于这些问题,请自己尝试一下并选择一种功能语言。它们更适合表达数学属性和抽象。支持高阶函数,lambdas和闭包的语言应该适合您的工作类型。

注意:Smalltalk和Ruby也可以沿着这条路走得很远,因为它们是半功能的(它们对闭包有很好的支持,特别是因为块闭包的语法非常轻巧和可读),但我认为你会发现像Haskell或Lisp这样的语言更适合你正在开发的算法类型。