{- | Randomized functions for GEP applications. Attempting to isolate all code that needs to be run under the Rmonad here. Author: mjsottile\@computer.org -} module GEP.Random ( randomSymbol, randomSymbolList, newIndividual, newPopulation, mutate ) where import GEP.Types import GEP.Params import GEP.Rmonad {-| Select a random symbol from the provided list. -} randomSymbol :: [a] -- ^ List of symbols -> GEPMonad a -- ^ Selected symbol randomSymbol syms = do index <- nextR (length syms) return (syms !! (index-1)) {-| Select a sequence of random symbols from the provided list. -} randomSymbolList :: [a] -- ^ List of symbols -> Int -- ^ Number to select -> GEPMonad [a] -- ^ List of selected -- symbols randomSymbolList _ 0 = do return [] randomSymbolList syms n = do current <- randomSymbol syms rest <- randomSymbolList syms (n-1) return ([current]++rest) -- | Generate a new individual given a genome specification. newIndividual :: Genome -- ^ Genome for individual -> Int -- ^ Number of genes to generate -> GEPMonad Chromosome newIndividual _ 0 = do return [] newIndividual g n = do hI <- randomSymbolList (allsymbols g) head_len tI <- randomSymbolList (terminals g) tail_len otherGenes <- newIndividual g (n-1) return (hI++tI++otherGenes) where head_len = headLength g tail_len = tailLength g -- |Create a population of fresh random individuals given a genome -- |specification. newPopulation :: Genome -- ^ Genome of population -> Int -- ^ Number of individuals to create -> GEPMonad [Chromosome] newPopulation _ 0 = do return [] newPopulation g n = do p <- newPopulation g (n-1) i <- newIndividual g (numGenes g) return ([i]++p) -- | Mutate symbols in a gene. Symbols are chosen from terminals and allsymbols -- for head and tail of the gene respectively. mutateGene :: Genome -> Rates -> Gene -> GEPMonad Gene mutateGene g r gene = do let (h, t) = splitAt (headLength g) gene hMutated <- mapM mutateHeadSymbol h tMutated <- mapM mutateTailSymbol t return $ hMutated ++ tMutated where mutateTailSymbol :: Symbol -> GEPMonad Symbol mutateTailSymbol s = mutateSymbol r s $ terminals g mutateHeadSymbol :: Symbol -> GEPMonad Symbol mutateHeadSymbol s = mutateSymbol r s $ allsymbols g -- | Mutate single symbol with probability pMutate choosing from given symbol -- list. mutateSymbol :: Rates -> Symbol -> [Symbol] -> GEPMonad Symbol mutateSymbol r s ss = nextF 1.0 >>= \prob -> if prob < pMutate r then randomSymbol ss else return s mutate :: Genome -> Rates -> Chromosome -> GEPMonad Chromosome mutate g r s = do genes' <- mapM (\i -> mutateGene g r i) genes return $ genesToChrom genes' where genes = chromToGenes s (geneLength g)