packages feed

hevolisa-0.0: Hevolisa/Evolution.hs

--
-- Module      : Evolution
-- Copyright   : (c) Daniel Neun 2008
-- License     : BSD-style
-- Maintainer  : daniel.neun@gmx.de
-- Stability   : experimental
-- Portability : portable

module Hevolisa.Evolution where

import Prelude hiding (error)
import Hevolisa.Shapes.DnaDrawing
import Hevolisa.Tools
import Hevolisa.Renderer ( drawingError,drawingToFile,withImageFromPNG)
import Debug.Trace

-- |Context contains the current drawing and the source image for comparison
data EvolutionContext = EvolutionContext {
      drawing :: DnaDrawing,
      image   :: [Integer]
} deriving (Show, Eq)

type Error = Integer

-- |Init the context with image and initial drawing
initContext :: [Integer]  -> IO EvolutionContext
initContext image = randomInit >>= \drawing ->
                    return $ EvolutionContext drawing image

-- |Number of mutations between image writes
imageInterval = 100

-- |Start the evolution process
start :: FilePath -> IO (EvolutionContext,Error)
start fp = do c <- withImageFromPNG fp initContext 
              e <- error c
              iter 0 (c,e)

-- |Recursive function combines mutation and writing files
iter :: Int -> (EvolutionContext,Error) -> IO (EvolutionContext,Error)
iter n (c1,e1) = do trace (show e1) $ maybeWriteToFile c1
                    c2 <- mutate c1
                    e2 <- error c2
                    iter (n + 1) $ minError (c1,e1)(c2,e2)
    where maybeWriteToFile
              | isTimeToWrite = \ec -> drawingToFile (drawing ec) n >> return ec
              | otherwise     = return
          isTimeToWrite = n `mod` imageInterval == 0
          minError (c1,e1)(c2,e2) | e1 < e2   = (c1,e1)
                                  | otherwise = (c2,e2)

-- |Color error, smaller is better
error :: EvolutionContext -> IO Integer
error (EvolutionContext drawing source) = drawingError drawing source

-- |EvolutionContext mutates minimizing the error
instance Mutable EvolutionContext where
    mutate = mutateEvolutionContext

-- |Mutate the drawing in the EvolutionContext
mutateEvolutionContext :: EvolutionContext -> IO EvolutionContext
mutateEvolutionContext (EvolutionContext d s) = do m <- mutate d
                                                   return (EvolutionContext m s)