haskell - 理解 Haskell 中的基本递归

标签 haskell recursion

我正在为我的人工智能类(class)编写一个遗传算法项目。我熟悉 GA 背后的概念,但我对 Haskell 的经验有限。程序中只剩下一件事要做,那就是创建一个循环我的其他函数的函数。我将展示我的功能并更详细地解释问题:

这是二代的功能。我找到 parent ,让他们交配并改 rebase 因组,然后将新的基因组传递到一个列表中:

generation1 = initialPopulation
generation2 = [(mutate (mate (fTTS generation1) (sTTS generation1))) | x <- [1..100]]

这很好用。我可以创建新一代并重复:

generation3 = [(mutate (mate (fTTS generation2) (sTTS generation2))) | x <- [1..100]]

因此,对于每一代,我都离目标基因组更近了一步(在我的例子中是一个字符串)。我想生成新一代,直到达到目标字符串。我认为基本的递归可以解决这个问题,如下所示:

g 0 = initialPopulation
g n = [(mutate (mate (fTTS (g (n - 1))) (sTTS (g (n - 1))))) | x <- [1..100]]

这在我的笔记本电脑上可以达到 g (3),但计算需要很长时间。我的问题是我真的不明白为什么。我认为 Haskell 递归的工作方式如下:

-- g 0 = [(mutate (mate (fTTS initialPopulation) (sTTS initialPopulation))) | x <- [1..100]] = ["N4kiT","Tu1RT","Tu1R<"]
-- g 1 = [(mutate (mate (fTTS (g 0)) (sTTS (g 0)))) | x <- [1..100]]
-- g 2 = [(mutate (mate (fTTS (g 1)) (sTTS (g 1)))) | x <- [1..100]]
-- g 3 = [(mutate (mate (fTTS (g 2)) (sTTS (g 2)))) | x <- [1..100]]

我脑子里应该和上面的generation3函数是一样的。如果对 Haskell 有更多了解的人可以解释为什么我能够毫无问题地运行“generation15”函数,但在我必须强制退出之前不超过“g (3)”函数,我将不胜感激控制台。

谢谢!

最佳答案

问题是 g n 没有被内存 - 它会在你的列表理解中重新计算 2 * 1000

g 0 = initialPopulation
g n = 
    let prev = g (n-1)
    in [(mutate (mate (fTTS prev) (sTTS prev))) | x <- [1..100]]

应该有所改进(我想获得严格的值也是一个好问题 - 但这可能是另一个问题)


但我不会那样使用它 - 而是写一个:

nextGen prev = [(mutate (mate (fTTS prev) (sTTS prev))) | x <- [1..100]]

函数然后你可以做类似的事情:

find gen = if goodEnough gen then gen else find (nextGen gen)

怀着希望

best = find initialPopulation

(请注意,也许你也应该在很多代之后有一个退出策略 - 所以你可能想要包括一个代数计数器或类似的东西)

关于haskell - 理解 Haskell 中的基本递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37189296/

相关文章:

haskell - 使用带有 cabal 的 Makefile?

algorithm - Haskell 递归极小极大树

c++ - 避免并行递归异步算法中的递归模板实例化溢出

R-使用覆盖和递归合并列表

c++ - 生成数组的所有排列而不重复结果

php - 合并两个关联数组并按一级键分组

algorithm - SPOJ 问题 Flibonakki time limit exceed

parsing - Monadic 解析函数珍珠 - 将多个解析器粘合在一起

haskell - 如何在多种条件下使用 map

haskell - 解决极端情况 Haskell 模块导入和导出