2016-05-12 74 views
3

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

这是第二代的功能。我得到父母,将它们配对并突变基因组,然后将新基因组传递到列表中:

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]] 

这工作对我的笔记本电脑多达克(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有更多了解的人可以解释为什么我可以在没有任何麻烦但不超过“g(3)”函数的情况下运行“generation15”功能,然后我必须强制退出安慰。

谢谢!

回答

5

问题是g nmemoized - 在列表中,理解它将会被重新计算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 

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

+1

谢谢你Carsten!我认为这与我处理名单的方式有关,但现在我知道了! 我有一个“maximumGen”诠释,应该设置一个屋顶,应该通过多少代的工作:) –