summaryrefslogtreecommitdiffstats
path: root/Evolve.hs
diff options
context:
space:
mode:
authorRay Hogenson <rhogenson@posteo.net>2019-09-07 16:36:01 -0700
committerRay Hogenson <rhogenson@posteo.net>2019-09-07 16:36:01 -0700
commit440dd38f24d1df150fb5b4c7965bb6e792c929fe (patch)
tree4d9da56e839f85949dbde1f3b3b0413f3f52b753 /Evolve.hs
downloadevolution-main.tar.zst
Write a little guyHEADmain
This program is in a weird state right now, but I'm checking it in to git so that I can back it up, since I want to reinstall again.
Diffstat (limited to 'Evolve.hs')
-rw-r--r--Evolve.hs45
1 files changed, 45 insertions, 0 deletions
diff --git a/Evolve.hs b/Evolve.hs
new file mode 100644
index 0000000..a34a382
--- /dev/null
+++ b/Evolve.hs
@@ -0,0 +1,45 @@
+module Evolve (Evolvable, evolve, mutate, score, mutateProbability) where
+
+import qualified System.Random as Random
+import Data.List (maximumBy)
+import qualified Par
+import qualified Control.Monad.State as State
+import RandomState (splits)
+import Data.Function (on)
+import qualified Control.Concurrent.Chan as Chan
+import System.Timeout (timeout)
+import Control.Exception (evaluate)
+
+class Evolvable e where
+ mutate :: Random.RandomGen g => e -> State.State g e
+ score :: e -> Double
+
+numChildren :: Int
+numChildren = 100
+
+printModCount :: Int
+printModCount = 100
+
+scoreTimeout :: Int
+scoreTimeout = 1000
+
+mutateProbability :: Double
+mutateProbability = 0.005
+
+evolve :: (Evolvable e, Show e) => Chan.Chan e -> e -> IO ()
+evolve c e = evolve' 0 c e 0
+
+timeoutScore :: Evolvable e => e -> IO Double
+timeoutScore e = maybe (-1) id <$> timeout scoreTimeout (evaluate (score e))
+
+evolve' :: (Evolvable e, Show e) => Int -> Chan.Chan e -> e -> Double -> IO ()
+evolve' generation chan startState myScore = do gs <- take numChildren . State.evalState splits <$> Random.newStdGen
+ childrenScores <- ((myScore, startState) :) <$> Par.mapIO scoreChild gs
+ let (bestScore, bestChild) = maximumBy (compare `on` fst) childrenScores
+ if generation `mod` printModCount == 0
+ then Chan.writeChan chan bestChild
+ else return ()
+ evolve' (succ generation) chan bestChild bestScore
+ where scoreChild g = do let myChild = State.evalState (mutate startState) g
+ realScore <- timeoutScore myChild
+ return (realScore, myChild)