[Haskell-beginners] Randomness woes
Gökhan San
gsan at stillpsycho.net
Sun Jan 10 15:58:02 EST 2010
Erlend Hamberg <ehamberg at gmail.com> writes:
> g <- getSplit
> let genome' = evalRand (mutate genome) g
>
> Handling the random generator explicitly like this feels a bit ugly. Or is
> this okay?
I was working on a very similar problem and I used 'split' of RandomGen
all the way down. It behaved well as far as I can tell, and if I recall
correctly, 'split' was faster than 'next' for StdGen.
So, I'd also appreciate any comment on the elegance issue myself. :-)
Though, I didn't quite get why you are explicitly calling 'evalRand'
instead of utilizing MonadRandom.
Here's an example:
> makePopulation :: (RandomGen g) => [(Genome, Fitness)] -> Rand g [Genome]
> makePopulation chms = do
> g <- getSplit
> return $ makePopulation' chms g []
> where size = length chms
> makePopulation' c g' a =
> if length a == size
> -- if we have ‘size’ members, we are done
> then a
> -- if not, find two new parents and append a child
> else makePopulation' c g' newPop
> where parent1 = evalRand (rouletteSelect chms) g'
> parent2 = evalRand (rouletteSelect chms) g'
> c1 = evalRand (reproduce (parent1, parent2) mutationRate) g'
> newPop = c1:a
Here, you're generating both parents using the same random generator,
hence, parents are always identical. Here's a variation that works
within MonadRandom:
> makePopulation :: (RandomGen g) => [(Genome, Fitness)] -> Rand g [Genome]
> makePopulation chms = makePopulation' []
> where size = length chms
> makePopulation' a =
> if length a == size
> -- if we have ‘size’ members, we are done
> then return a
> -- if not, find two new parents and append a child
> else do parent1 <- rouletteSelect chms
> parent2 <- rouletteSelect chms
> c1 <- reproduce (parent1, parent2) mutationRate
> let newPop = c1:a
> makePopulation' newPop
I didn't check for bugs in the algorithm but now both parents and the
offspring are generated independently, and resulting fitness values
won't be identical.
I think the idea is that you should be able to reduce the number of
'evalRand's in your module to one.
--
Gökhan San
More information about the Beginners
mailing list