2016-05-12 101 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」詮釋,應該設置一個屋頂,應該通過多少代的工作:) –