我正在编写一个遗传算法来生成字符串"helloworld“。但当n为10,000或更大时,演进函数会产生堆栈溢出。
module Genetics where
import Data.List (sortBy)
import Random (randomRIO)
import Control.Monad (foldM)
class Gene g where
-- How ideal is the gene from 0.0 to 1.0?
fitness :: g -> Float
-- How does a gene mutate?
mutate :: g -> IO g
-- How many species will be explored?
species :: [g] -> Int
orderFitness :: (Gene g) => [g] -> [g]
orderFitness = reverse . sortBy (\a b -> compare (fitness a) (fitness b))
compete :: (Gene g) => [g] -> IO [g]
compete pool = do
let s = species pool
variants <- (mapM (mapM mutate) . map (replicate s)) pool
let pool' = (map head . map orderFitness) variants
return pool'
evolve :: (Gene g) => Int -> [g] -> IO [g]
evolve 0 pool = return pool
evolve n pool = do
pool' <- compete pool
evolve (n - 1) pool'有了species pool = 8,8个基因库可以复制到8个组中。每一组都发生变异,每组中最适合的被选择进行进一步的进化(返回到8个基因)。
发布于 2011-05-11 06:39:12
如果您对性能感兴趣,我将使用快速随机数生成器,例如:
其次,compete看起来非常可疑,因为它完全是懒惰的,尽管它构建了一些潜在的大型结构。试着用deepseq锤子把它重写得更严格一点:
import Control.DeepSeq
compete :: (Gene g, NFData g) => [g] -> IO [g]
compete pool = do
let s = species pool
variants <- (mapM (mapM mutate) . map (replicate s)) pool
let pool' = (map head . map orderFitness) variants
pool' `deepseq` return pool'不过,这些东西都不需要放在IO中(单独发布)。类似于Rand monad的东西可能是more appropriate。
https://stackoverflow.com/questions/5956554
复制相似问题