summaryrefslogtreecommitdiff
path: root/src/Genome.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Genome.hs')
-rw-r--r--src/Genome.hs89
1 files changed, 75 insertions, 14 deletions
diff --git a/src/Genome.hs b/src/Genome.hs
index c3fc361..500512c 100644
--- a/src/Genome.hs
+++ b/src/Genome.hs
@@ -7,11 +7,13 @@ module Genome
, mutateGene
, mutateGenomeAddInternal
+ , mutateGenomeRemoveInternal
) where
import Mind (NeuronIndex (..))
import System.Random
+import Data.Ix
data Gene = Gene { source :: NeuronIndex, sink :: NeuronIndex, weight :: Float } deriving (Eq, Show)
@@ -21,8 +23,8 @@ data Genome = Genome { numInput :: Int, numInternal :: Int, numOutput :: Int, ge
-- choose a random list element
randomChoice :: RandomGen a => [b] -> a -> (b, a)
randomChoice xs r =
- let (index, r') = randomR (0, length xs - 1) r
- in (xs !! index, r')
+ let (idx, r') = randomR (0, length xs - 1) r
+ in (xs !! idx, r')
-- pick a new random source for the gene
@@ -31,12 +33,12 @@ mutateGeneSource genome g r =
let
nInput = numInput genome
nInternal = numInternal genome
- index :: Int
- (index, r') = randomR (0, nInput+nInternal-1) r
+ idx :: Int
+ (idx, r') = randomR (0, nInput+nInternal-1) r
source' =
- if index < nInput
- then Input index
- else Internal $ index - nInput
+ if idx < nInput
+ then Input idx
+ else Internal $ idx - nInput
in ( g { source = source' }, r')
@@ -46,11 +48,11 @@ mutateGeneSink genome g r =
let
nInternal = numInternal genome
nOutput = numOutput genome
- index :: Int
- (index, r') = randomR (0, nInternal+nOutput-1) r
- sink' = if index < nInternal
- then Internal index
- else Output $ index - nInternal
+ idx :: Int
+ (idx, r') = randomR (0, nInternal+nOutput-1) r
+ sink' = if idx < nInternal
+ then Internal idx
+ else Output $ idx - nInternal
in ( g { sink = sink' }, r' )
@@ -61,7 +63,7 @@ mutateGeneWeight _ g r =
let
w = 2 * (abs $ weight g)
(weight', r') = randomR (negate w, w) r
- in ( g { weight = weight' }, r' )
+ in ( g { weight = weight' }, r' )
-- randomly mutate gene (modify source, sink, or weight
@@ -77,4 +79,63 @@ mutateGenomeAddInternal genome r = (genome { numInternal = 1 + numInternal genom
-- remove an internal neuron, decrementing sources and incrementing sinks
mutateGenomeRemoveInternal :: RandomGen a => Genome -> a -> (Genome, a)
-mutateGenomeRemoveInternal = undefined
+mutateGenomeRemoveInternal g r =
+ let
+ (idx, r') = randomR (0, numInternal g - 1) r
+ remove = Internal idx
+ genes' = map
+ (\(Gene so si w) ->
+ let
+ so' = if (isInternal so) && (so >= remove)
+ then decrementNeuron g so else so
+ si' = if (si < remove) || (not $ isInternal si) then si
+ else if si == remove
+ then
+ let si'' = incrementNeuron g si
+ in if isInternal si'' then si else si''
+ else decrementNeuron g si
+ in Gene {source=so', sink=si', weight=w}
+ )
+ (genes g)
+ in
+ (g { numInternal = (numInternal g - 1), genes = genes' }, r')
+
+validn :: Genome -> NeuronIndex -> NeuronIndex
+validn g (Input x)
+ | (inRange (0, numInput g - 1) x) = Input x
+ | otherwise = error "out of range Input!"
+validn g (Internal x)
+ | (inRange (0, numInternal g - 1) x) = Internal x
+ | otherwise = error "out of range Internal!"
+validn g (Output x)
+ | (inRange (0, numOutput g - 1) x) = Output x
+ | otherwise = error "out of range Output!"
+
+
+
+incrementNeuron :: Genome -> NeuronIndex -> NeuronIndex
+incrementNeuron g (Input x)
+ | (x >= numInput g - 1) = validn g (Internal 0)
+ | otherwise = validn g (Input $ x+1)
+incrementNeuron g (Internal x)
+ | (x >= numInternal g - 1) = validn g (Output 0)
+ | otherwise = validn g (Internal $ x+1)
+incrementNeuron g (Output x)
+ | (x >= numOutput g - 1) = error "cannot increment past the end of outputs!"
+ | otherwise = validn g (Output $ x+1)
+
+
+decrementNeuron :: Genome -> NeuronIndex -> NeuronIndex
+decrementNeuron g (Input x)
+ | (x <= 0) = error "cannot decrement past the first Input!"
+ | otherwise = validn g (Input $ x-1)
+decrementNeuron g (Internal x)
+ | (x <= 0) = validn g (Input $ numInput g - 1)
+ | otherwise = validn g (Internal $ x-1)
+decrementNeuron g (Output x)
+ | (x <= 0) = validn g (Internal $ numInternal g - 1)
+ | otherwise = validn g (Output $ x-1)
+
+isInternal :: NeuronIndex -> Bool
+isInternal (Internal _) = True
+isInternal _ = False