Created
April 4, 2012 06:30
-
-
Save blackwithwhite666/2298992 to your computer and use it in GitHub Desktop.
Revisions
-
Lipin Dmitriy revised this gist
Jan 7, 2014 . 1 changed file with 25 additions and 25 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,12 +1,12 @@ -- gen.hs -- http://habrahabr.ru/post/128704/ import qualified Control.Monad as Monad import qualified Control.Monad.Random as Random import qualified Control.Monad.Trans as Trans import qualified Control.Monad.Maybe as Maybe import Data.List (nub) import System.Random (RandomGen, newStdGen) import Data.Maybe (isNothing) -- Common invert :: (Integral a, Fractional b) => [a] -> [b] @@ -24,10 +24,10 @@ genUnique (x:xs) = if (fst x) == (snd x) randInt :: Int -> Int -> IO Int randInt start end = do value <- Random.evalRandIO range return value where range = Random.getRandomR (start, end) -- Solution definition data Solution = Solution Int Int Int Int @@ -47,7 +47,7 @@ instance Equation Solution where equationDiff a = abs (equationResult a - 30) randomSolution = do params <- Monad.replicateM 4 $ randInt (-30) 30 return $ createSolution params createSolution params = (Solution (params!!0) (params!!1) (params!!2) (params!!3)) @@ -128,11 +128,11 @@ class GeneUtils a where produceParents :: [a] -> IO [(Genome, Genome)] instance GeneUtils Gene where selectRandom gen genes = Random.evalRand m gen where toTuple (Gene g l) = (g, l) weights = map toTuple genes m = sequence . repeat . Random.fromList $ weights produceParents genes = do gen <- newStdGen @@ -145,10 +145,10 @@ data GenePool = GenePool class GenePoolUtils a where computeGenes :: a -> Maybe [Gene] generateParents :: a -> Maybe.MaybeT IO [(Genome, Genome)] generateChilds :: a -> Maybe.MaybeT IO [Genome] findResults :: a -> [Genome] runEvolution :: a -> Maybe.MaybeT IO [Genome] instance GenePoolUtils GenePool where computeGenes (GenePool gs) = do @@ -161,36 +161,36 @@ instance GenePoolUtils GenePool where return $ (map createGene) $ (zip gs) $ likelihoods generateParents pool = do genes <- Maybe.MaybeT $ do return $ computeGenes pool pairs <- Trans.lift $ produceParents genes return $ pairs generateChilds pool = do parents <- generateParents pool childs <- Trans.lift . sequence $ take l (breedChilds parents) return $ take l $ nub childs where l = length $ genomes pool findResults pool = nub $ do (genome, fitness) <- zip gs $ map computeFitness gs Monad.guard $ isNothing fitness return genome where gs = genomes pool runEvolution pool = do newPool <- Trans.lift $ evolve pool return $ findResults newPool where evolveOne :: GenePool -> Maybe.MaybeT IO GenePool evolveOne pool = do Trans.lift $ print pool childs <- generateChilds pool return (GenePool childs) evolve :: GenePool -> IO GenePool evolve pool = do maybeNextPool <- Maybe.runMaybeT $ evolveOne pool case maybeNextPool of Nothing -> return pool Just nextPool -> do @@ -200,8 +200,8 @@ instance GenePoolUtils GenePool where -- run solver main = do gs <- Monad.replicateM populationSize generateGenome results <- Maybe.runMaybeT $ runEvolution (GenePool gs) print $ results where populationSize = 128 -
Lipin Dmitriy revised this gist
Jan 7, 2014 . 2 changed files with 152 additions and 137 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,12 @@ dist cabal-dev *.o *.hi *.chi *.chs.h .virthualenv .hsenv .cabal-sandbox/ cabal.sandbox.config cabal.config gen This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,7 +6,7 @@ import Control.Monad.Trans import Control.Monad.Maybe import Data.List import System.Random import Data.Maybe -- Common invert :: (Integral a, Fractional b) => [a] -> [b] @@ -19,186 +19,189 @@ tupleGen (a:b:xs) = (a,b): tupleGen xs genUnique :: (Eq a) => [(a, a)] -> [(a, a)] genUnique [] = [] genUnique (x:xs) = if (fst x) == (snd x) then genUnique xs else x : genUnique xs randInt :: Int -> Int -> IO Int randInt start end = do value <- evalRandIO range return value where range = getRandomR (start, end) -- Solution definition data Solution = Solution Int Int Int Int deriving (Eq, Show) class Equation a where equationResult :: a -> Int equationDiff :: a -> Int randomSolution :: IO a createSolution :: [Int] -> a solutionToList :: a -> [Int] mutateSolution :: a -> IO a instance Equation Solution where equationResult (Solution a b c d) = a + b * 2 + c * 3 + d * 4 equationDiff a = abs (equationResult a - 30) randomSolution = do params <- replicateM 4 $ randInt (-30) 30 return $ createSolution params createSolution params = (Solution (params!!0) (params!!1) (params!!2) (params!!3)) solutionToList (Solution a b c d) = [a, b, c, d] mutateSolution s = do mutatedParams <- mutate $ solutionToList s return $ createSolution mutatedParams where mutateValue :: Int -> IO Int mutateValue param = do chance <- randInt 0 1 value <- randInt (-30) 30 return $ if chance == 1 then value else param mutate :: [Int] -> IO [Int] mutate params = sequence $ do param <- params return $ mutateValue param -- Genome definition data Genome = Genome { solution :: Solution } deriving (Eq, Show) class GenomeUtils a where computeFitness :: a -> Maybe Int createChild :: (a, a) -> IO a breedChilds :: [(a, a)] -> [IO a] generateGenome :: IO a mutateGenome :: a -> IO a instance GenomeUtils Genome where computeFitness (Genome s) | diff == 0 = Nothing | otherwise = Just diff where diff = equationDiff s createChild (p1, p2) = do crossover <- randInt 0 3 first <- randInt 0 1 let child = flippedCombine first p1 p2 crossover mutatedChild <- mutateGenome child return child where combine :: Genome -> Genome -> Int -> Genome combine (Genome s1) (Genome s2) crossover = (Genome (createSolution $ concat [start, end])) where start = fst $ splitAt crossover $ solutionToList s1 end = snd $ splitAt crossover $ solutionToList s2 flippedCombine first p1 p2 crossover | first == 0 = combine p1 p2 crossover | otherwise = combine p2 p1 crossover breedChilds parents = convert parents where convert :: [(Genome, Genome)] -> [IO Genome] convert [] = [] convert (x:xs) = createChild x : convert xs generateGenome = do solution <- randomSolution return (Genome solution) mutateGenome (Genome s) = do mutated <- mutateSolution s return (Genome mutated) -- Gene definition data Gene = Gene { genome :: Genome , likelihood :: Rational } deriving (Eq, Show) class GeneUtils a where selectRandom :: RandomGen g => g -> [a] -> [Genome] produceParents :: [a] -> IO [(Genome, Genome)] instance GeneUtils Gene where selectRandom gen genes = evalRand m gen where toTuple (Gene g l) = (g, l) weights = map toTuple genes m = sequence . repeat . fromList $ weights produceParents genes = do gen <- newStdGen return $ genUnique $ tupleGen $ selectRandom gen genes -- GenePool definition data GenePool = GenePool { genomes :: [Genome] } deriving (Show) class GenePoolUtils a where computeGenes :: a -> Maybe [Gene] generateParents :: a -> MaybeT IO [(Genome, Genome)] generateChilds :: a -> MaybeT IO [Genome] findResults :: a -> [Genome] runEvolution :: a -> MaybeT IO [Genome] instance GenePoolUtils GenePool where computeGenes (GenePool gs) = do fitnesses <- sequence $ map computeFitness gs let invertedFitnesses = invert fitnesses mult = ((100/) . sum) invertedFitnesses likelihoods = map (*mult) invertedFitnesses createGene (g, l) = Gene g l return $ (map createGene) $ (zip gs) $ likelihoods generateParents pool = do genes <- MaybeT $ do return $ computeGenes pool pairs <- lift $ produceParents genes return $ pairs generateChilds pool = do parents <- generateParents pool childs <- lift . sequence $ take l (breedChilds parents) return $ take l $ nub childs where l = length $ genomes pool findResults pool = nub $ do (genome, fitness) <- zip gs $ map computeFitness gs guard $ isNothing fitness return genome where gs = genomes pool runEvolution pool = do newPool <- lift $ evolve pool return $ findResults newPool where evolveOne :: GenePool -> MaybeT IO GenePool evolveOne pool = do lift $ print pool childs <- generateChilds pool return (GenePool childs) evolve :: GenePool -> IO GenePool evolve pool = do maybeNextPool <- runMaybeT $ evolveOne pool case maybeNextPool of Nothing -> return pool Just nextPool -> do pool <- evolve nextPool return pool -- run solver main = do gs <- replicateM populationSize generateGenome results <- runMaybeT $ runEvolution (GenePool gs) print $ results where populationSize = 128 -
blackwithwhite666 created this gist
Apr 4, 2012 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,204 @@ -- gen.hs -- http://habrahabr.ru/post/128704/ import Control.Monad import Control.Monad.Random import Control.Monad.Trans import Control.Monad.Maybe import Data.List import System.Random import Maybe -- Common invert :: (Integral a, Fractional b) => [a] -> [b] invert xs = map (\x -> 1 / fromIntegral x) xs tupleGen :: [a] -> [(a, a)] tupleGen [] = [] tupleGen (a:b:xs) = (a,b): tupleGen xs genUnique :: (Eq a) => [(a, a)] -> [(a, a)] genUnique [] = [] genUnique (x:xs) = if (fst x) == (snd x) then genUnique xs else x : genUnique xs randInt :: Int -> Int -> IO Int randInt start end = do value <- evalRandIO range return value where range = getRandomR (start, end) -- Solution definition data Solution = Solution Int Int Int Int deriving (Eq, Show) class Equation a where equationResult :: a -> Int equationDiff :: a -> Int randomSolution :: IO a createSolution :: [Int] -> a solutionToList :: a -> [Int] mutateSolution :: a -> IO a instance Equation Solution where equationResult (Solution a b c d) = a + b * 2 + c * 3 + d * 4 equationDiff a = abs (equationResult a - 30) randomSolution = do params <- replicateM 4 $ randInt (-30) 30 return $ createSolution params createSolution params = (Solution (params!!0) (params!!1) (params!!2) (params!!3)) solutionToList (Solution a b c d) = [a, b, c, d] mutateSolution s = do mutatedParams <- mutate $ solutionToList s return $ createSolution mutatedParams where mutateValue :: Int -> IO Int mutateValue param = do chance <- randInt 0 1 value <- randInt (-30) 30 return $ if chance == 1 then value else param mutate :: [Int] -> IO [Int] mutate params = sequence $ do param <- params return $ mutateValue param -- Genome definition data Genome = Genome { solution :: Solution } deriving (Eq, Show) class GenomeUtils a where computeFitness :: a -> Maybe Int createChild :: (a, a) -> IO a breedChilds :: [(a, a)] -> [IO a] generateGenome :: IO a mutateGenome :: a -> IO a instance GenomeUtils Genome where computeFitness (Genome s) | diff == 0 = Nothing | otherwise = Just diff where diff = equationDiff s createChild (p1, p2) = do crossover <- randInt 0 3 first <- randInt 0 1 let child = case first of 0 -> combine p1 p2 crossover 1 -> combine p2 p1 crossover mutatedChild <- mutateGenome child return child where combine :: Genome -> Genome -> Int -> Genome combine (Genome s1) (Genome s2) crossover = (Genome (createSolution $ concat [start, end])) where start = fst $ splitAt crossover $ solutionToList s1 end = snd $ splitAt crossover $ solutionToList s2 breedChilds parents = convert parents where convert :: [(Genome, Genome)] -> [IO Genome] convert [] = [] convert (x:xs) = createChild x : convert xs generateGenome = do solution <- randomSolution return (Genome solution) mutateGenome (Genome s) = do mutated <- mutateSolution s return (Genome mutated) -- Gene definition data Gene = Gene { genome :: Genome, likelihood :: Rational } deriving (Eq, Show) class GeneUtils a where selectRandom :: RandomGen g => g -> [a] -> [Genome] produceParents :: [a] -> IO [(Genome, Genome)] instance GeneUtils Gene where selectRandom gen genes = evalRand m gen where toTuple (Gene g l) = (g, l) weights = map toTuple genes m = sequence . repeat . fromList $ weights produceParents genes = do gen <- newStdGen return $ genUnique $ tupleGen $ selectRandom gen genes -- GenePool definition data GenePool = GenePool { genomes :: [Genome] } deriving (Show) class GenePoolUtils a where computeGenes :: a -> Maybe [Gene] generateParents :: a -> MaybeT IO [(Genome, Genome)] generateChilds :: a -> MaybeT IO [Genome] findResults :: a -> [Genome] runEvolution :: a -> MaybeT IO [Genome] instance GenePoolUtils GenePool where computeGenes (GenePool gs) = do fitnesses <- sequence $ map computeFitness gs let invertedFitnesses = invert fitnesses mult = ((100/) . sum) invertedFitnesses likelihoods = map (*mult) invertedFitnesses createGene (g, l) = Gene g l return $ (map createGene) $ (zip gs) $ likelihoods generateParents pool = do genes <- MaybeT $ do return $ computeGenes pool pairs <- lift $ produceParents genes return $ pairs generateChilds pool = do parents <- generateParents pool childs <- lift . sequence $ take l (breedChilds parents) return $ take l $ nub childs where l = length $ genomes pool findResults pool = nub $ do (genome, fitness) <- zip gs $ map computeFitness gs guard $ isNothing fitness return genome where gs = genomes pool runEvolution pool = do newPool <- lift $ evolve pool return $ findResults newPool where evolveOne :: GenePool -> MaybeT IO GenePool evolveOne pool = do lift $ print pool childs <- generateChilds pool return (GenePool childs) evolve :: GenePool -> IO GenePool evolve pool = do maybeNextPool <- runMaybeT $ evolveOne pool case maybeNextPool of Nothing -> return pool Just nextPool -> do pool <- evolve nextPool return pool -- run solver main = do gs <- replicateM populationSize generateGenome results <- runMaybeT $ runEvolution (GenePool gs) print $ results where populationSize = 5