{-# LANGUAGE OverloadedStrings #-} -- |control center for external using module AI.Heukarya.Center( module G ,module S ,EcoConfig(..) ,EcoUnWritable(..) ,EcoSystem(..) ,initGeneration ,nextGeneration ,evolveGeneration ,evolveCheckGeneration ,readEcoSystem ,writeEcoSystem ,defaultEcoConfig ) where import Prelude hiding (map) import System.Random import Control.Monad.IO.Class import AI.Heukarya.Gene as G(Tree,evalTreeGene) import AI.Heukarya.Jungle import Data.Text(Text,unpack) import Data.Sequence(mapWithIndex) import Data.Sequence as S(Seq) smap x = mapWithIndex (\_->x) -- |configuration of ecosystem data EcoConfig = EcoConfig { num :: Int -- ^the number of Heukarya contained in EcoSystem ,depth :: Int -- ^depth of Heukaryas' tree structure ,maxWinProb :: Double -- ^probability of Eukarya who has bigger fitness win the game ,mutateProb :: Double -- ^probability of mutating ,crossProb :: Double -- ^probability of pairing crossover ,outType :: Text -- ^Heukaryas' root's type, represented by Text } deriving (Show, Read) -- |storing the data which are not writable to file data EcoUnWritable g d = EcoUnWritable { rndGen :: g -- ^Random Generator ,genes :: [d] -- ^genes for constructing Heukarya } defaultEcoConfig = EcoConfig{num=2000, depth=20, maxWinProb=0.6, mutateProb=0.4, crossProb=0.8, outType="Double"} -- |EcoSystem consists of ecosystem's configuration and Jungle. -- `Tree rep` is sometimes used for repsentation of Heukarya by `Tree String` data EcoSystem g d rep = EcoSystem { ecoUnW :: EcoUnWritable g d ,ecoConfig :: EcoConfig, ecoJungle :: Seq (Tree rep) } -- |initial a EcoSystem initGeneration unW cfg = (genJungle g2 (depth cfg) (genes unW) (outType cfg) (num cfg) ) >>= \z -> return $ EcoSystem unW{rndGen = g1} cfg z where (g1,g2) = split (rndGen unW) -- |evolve a EcoSystem one step -- Parameters: EcoSystem , fitness function nextGeneration ecoSys@(EcoSystem unW cfg jg) fitness = do mtJg <- mutatedJg return $ EcoSystem unW{rndGen = g1} cfg mtJg where (g1,g2) = split (rndGen unW) (g3,g4) = split g2 (g5,g6) = split g4 choicedJg = choiceJungle g3 fitness jg (maxWinProb cfg) crossedJg = crossJungle g5 (depth cfg) choicedJg (crossProb cfg) mutatedJg = crossedJg >>= \z->mutateJungle g6 (depth cfg) (genes unW) z (mutateProb cfg) -- |evolving until condiction suffered or max number of Generations hitted -- Parameters : max number of generations, EcoSystem, stop evolving's Condiction , -- fitness function, generation counter(placed by zero when used) evolveGeneration maxGeneration ecoSys@(EcoSystem unW cfg jg) stopCondict fitnessFunc cnt = if stopCondict jg || cnt >= maxGeneration then return ecoSys else (nextGeneration ecoSys $ smap fitnessFunc jg) >>= \z -> evolveGeneration maxGeneration z stopCondict fitnessFunc cnt -- |evolving until condiction suffered or max number of Generations hitted -- save checkpoint per period -- Parameters : max number of generations, checkpoint's file path, -- save checkpoint per x generations, -- EcoSystem, stop evolving's Condiction , -- fitness function, generation counter(placed by zero when used) evolveCheckGeneration maxGeneration filepath checksPer ecoSys@(EcoSystem unW cfg jg) stopCondict fitnessFunc cnt = do if cnt `rem` checksPer == 0 then liftIO (writeEcoSystem filepath ecoSys) else return () if stopCondict jg || cnt >= maxGeneration then liftIO (writeEcoSystem filepath ecoSys) >> return ecoSys else (nextGeneration ecoSys $ smap fitnessFunc jg) >>= \z -> evolveCheckGeneration maxGeneration filepath checksPer z stopCondict fitnessFunc cnt -- |read a EcoSystem from file and addon UnWritable data -- Parameters : filepath for reading, UnWritable data readEcoSystem filepath unW@(EcoUnWritable g geneList) = do (cfg,strJg) <- readFile filepath >>= (return.read) :: IO (EcoConfig,Seq (Tree String)) jg <- return $ smap (fmap (\x->head $ filter (\s -> show s == x) geneList)) strJg return (EcoSystem unW cfg jg) -- |write a EcoSystem into file without UnWritable data -- Parameters : filepath for saving, EcoSystem saved writeEcoSystem filepath (EcoSystem unW cfg jg) = writeFile filepath (show $ (cfg,smap (fmap show) jg))