Skip to content

Instantly share code, notes, and snippets.

@Lambdanaut
Created September 5, 2011 06:03
Show Gist options
  • Save Lambdanaut/1194199 to your computer and use it in GitHub Desktop.
Save Lambdanaut/1194199 to your computer and use it in GitHub Desktop.
I've got a pain fetish so I decided to wrestle a program making heavy use of System.Random WITHOUT a State Monad. When I got to the point where I needed to add a mutation rate I decided it works fine enough as it is without one, so here you go! (Technical
module GE where
import System.Random
import Data.List (elemIndex)
import Control.Monad (foldM)
type Aminal = [Int]
type Population = [Aminal]
gen = 10 {- GENERATIONS -}
pop = 10 {- POPULATION NUMBER -}
chr = 10 {- CHROMOSOMAL LENGTH -}
maxi = 9 {- MAXIMUM VALUE OF CHROMOSOME -}
{- GENERATES A LIST OF RANDOM ANIMALS -}
initPop :: (RandomGen g) => Int -> g -> (Population,g)
initPop x rando = foldl (\(l,r) _ -> ( (fst $ randRange (0,maxi) r chr):l, snd $ randRange (0,maxi) r chr) ) ([],rando) [1..x]
where randRange (x,y) rando range = foldl (\(l,r) _ -> ( (fst $ randomR (x,y) r):l,snd $ randomR (x,y) r ) ) ([],rando) [1..range]
{- Breeds Two Animals Together splitting their genes randomly -}
breed :: StdGen -> Aminal -> Aminal -> (Aminal,StdGen)
breed rando a1 a2 = foldl (\(l,r) (g1,g2) -> (l++[fst $ randChoice r g1 g2],snd $ randChoice r g1 g2) ) ([],rando) $ zip a1 a2
where randChoice r g1 g2 = case random r :: (Bool,StdGen) of
(True,newRando) -> (g1,newRando)
(False,newRando) -> (g2,newRando)
generation :: Population -> StdGen -> IO (Population,StdGen)
generation curPop rando = do
{- Get Greatest Fit -}
let fittestIndex = elemIndex (foldl max 0 $ map sum curPop) $ map sum curPop
case fittestIndex of
Nothing -> error "There is not a \"most fit\" creature in the population. "
Just i -> do
{- Breed Most Fit with All Others -}
return $ foldl (\(l,r) aminal -> (l++[fst $ breed r (curPop !! i) aminal],snd $ breed r (curPop !! i) aminal) ) ([],rando) curPop
main :: IO ()
main = do
rando1 <- getStdGen
let (initialPop,rando2) = initPop pop rando1
aminals <- foldM (\(p,r) _ -> generation p r) (initialPop,rando2) [1..gen]
mapM_ (putStrLn.show) $ fst aminals
module GE where
import System.Random
import Data.List (elemIndex)
import Control.Monad (foldM)
type Aminal = [Int]
type Population = [Aminal]
gen = 10 {- GENERATIONS -}
pop = 10 {- POPULATION NUMBER -}
chr = 10 {- CHROMOSOMAL LENGTH -}
maxi = 9 {- MAXIMUM VALUE OF CHROMOSOME -}
{- GENERATES A LIST OF RANDOM ANIMALS -}
initPop :: (RandomGen g) => Int -> g -> (Population,g)
initPop x rando = foldl (\(l,r) _ -> ( (fst $ randRange (0,maxi) r chr):l, snd $ randRange (0,maxi) r chr) ) ([],rando) [1..x]
where randRange (x,y) rando range = foldl (\(l,r) _ -> ( (fst $ randomR (x,y) r):l,snd $ randomR (x,y) r ) ) ([],rando) [1..range]
{- Breeds Two Animals Together splitting their genes randomly -}
breed :: StdGen -> Aminal -> Aminal -> (Aminal,StdGen)
breed rando a1 a2 = foldl (\(l,r) (g1,g2) -> (l++[fst $ randChoice r g1 g2],snd $ randChoice r g1 g2) ) ([],rando) $ zip a1 a2
where randChoice r g1 g2 = case random r of
(True,newRando) -> (g1,newRando)
(False,newRando) -> (g2,newRando)
generation :: Population -> StdGen -> IO (Population,StdGen)
generation curPop rando = do
{- Get Greatest Fit -}
let fittestIndex = elemIndex (foldl max 0 $ map sum curPop) $ map sum curPop
case fittestIndex of
Nothing -> error "There is not a \"most fit\" creature in the population. "
Just i -> do
{- Breed Most Fit with All Others -}
return $ foldl (\(l,r) aminal -> (l++[fst $ breed r (curPop !! i) aminal],snd $ breed r (curPop !! i) aminal) ) ([],rando) curPop
main :: IO ()
main = do
rando1 <- getStdGen
let (initialPop,rando2) = initPop pop rando1
aminals <- foldM (\(p,r) _ -> generation p r) (initialPop,rando2) [1..gen]
mapM_ (putStrLn.show) $ fst aminals
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment