such progress, much wow.
This commit is contained in:
parent
8befc7c94d
commit
f2ca0b1834
66
app/Main.hs
66
app/Main.hs
@ -1,4 +1,5 @@
|
|||||||
{-# LANGUAGE BangPatterns #-}
|
{-# LANGUAGE BangPatterns #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
@ -8,8 +9,12 @@ import Data.List
|
|||||||
import System.Random
|
import System.Random
|
||||||
import Control.Concurrent
|
import Control.Concurrent
|
||||||
import Control.Parallel.Strategies
|
import Control.Parallel.Strategies
|
||||||
|
import Control.Monad.Writer
|
||||||
import qualified Debug.Trace as Debug
|
import qualified Debug.Trace as Debug
|
||||||
|
import qualified Control.Foldl as F
|
||||||
import System.IO
|
import System.IO
|
||||||
|
import Data.Aeson
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
|
||||||
import ArbitraryEnzymeTree
|
import ArbitraryEnzymeTree
|
||||||
import Environment
|
import Environment
|
||||||
@ -38,9 +43,9 @@ exampleEnvironment addedC es pred tox =
|
|||||||
, maxCompound = maxCompoundWithoutGeneric + addedC
|
, maxCompound = maxCompoundWithoutGeneric + addedC
|
||||||
, toxicCompounds = tox --[(Produced FPP,0.1)] ++ tox
|
, toxicCompounds = tox --[(Produced FPP,0.1)] ++ tox
|
||||||
, possibleEnzymes = es -- [pps,fpps] ++ es
|
, possibleEnzymes = es -- [pps,fpps] ++ es
|
||||||
, settings = Settings { automimicry = True
|
, settings = Settings { automimicry = False
|
||||||
, predatorsRandom = False
|
, predatorsRandom = False
|
||||||
, numPlants = 150
|
, numPlants = 50
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +68,7 @@ exampleEnvironment addedC es pred tox =
|
|||||||
-- defaultAbsorption = fmap ( limit Phosphor 2
|
-- defaultAbsorption = fmap ( limit Phosphor 2
|
||||||
-- . limit Nitrate 1
|
-- . limit Nitrate 1
|
||||||
-- . limit Sulfur 0
|
-- . limit Sulfur 0
|
||||||
-- ) <$> asks soil
|
-- ) <$> fromEnv soil
|
||||||
-- -- custom absorbtion with helper-function:
|
-- -- custom absorbtion with helper-function:
|
||||||
-- limit :: Nutrient -> Amount -> (Nutrient, Amount) -> (Nutrient, Amount)
|
-- limit :: Nutrient -> Amount -> (Nutrient, Amount) -> (Nutrient, Amount)
|
||||||
-- limit n a (n', a')
|
-- limit n a (n', a')
|
||||||
@ -73,7 +78,7 @@ exampleEnvironment addedC es pred tox =
|
|||||||
-- Running the simulation
|
-- Running the simulation
|
||||||
-- ----------------------
|
-- ----------------------
|
||||||
|
|
||||||
loop :: Int -> [Plant] -> Environment -> IO ()
|
loop :: Int -> [Plant] -> Simulation -> IO ()
|
||||||
loop loopAmount ps env = loop' loopAmount 0 ps env
|
loop loopAmount ps env = loop' loopAmount 0 ps env
|
||||||
|
|
||||||
where
|
where
|
||||||
@ -83,30 +88,39 @@ loop loopAmount ps env = loop' loopAmount 0 ps env
|
|||||||
Just (_,toxicity) -> (e,"\ESC[38;5;" ++ show (16 + 36*5 + 6*floor (5*(1-toxicity)) + 0) ++ "m" -- yellow -> red rainbow for tocixity 0 -> 1
|
Just (_,toxicity) -> (e,"\ESC[38;5;" ++ show (16 + 36*5 + 6*floor (5*(1-toxicity)) + 0) ++ "m" -- yellow -> red rainbow for tocixity 0 -> 1
|
||||||
++ padded 50 (show (enzymeName e)) ++ "\ESC[0m")
|
++ padded 50 (show (enzymeName e)) ++ "\ESC[0m")
|
||||||
Nothing -> (e, padded 50 (show (enzymeName e)))
|
Nothing -> (e, padded 50 (show (enzymeName e)))
|
||||||
) <$> possibleEnzymes env
|
) <$> possibleEnzymes (snd env)
|
||||||
toxins :: [(Compound, Amount)]
|
toxins :: [(Compound, Amount)]
|
||||||
toxins = toxicCompounds env
|
toxins = toxicCompounds (snd env)
|
||||||
padded i str = take i $ str ++ repeat ' '
|
padded i str = take i $ str ++ repeat ' '
|
||||||
printEvery = 10
|
printEvery = 10
|
||||||
loop' :: Int -> Int -> [Plant] -> Environment -> IO ()
|
loop' :: Int -> Int -> [Plant] -> Simulation -> IO ()
|
||||||
loop' loopAmount curLoop plants e = unless (loopAmount+1 == curLoop) $ do
|
loop' loopAmount curLoop plants s = unless (loopAmount+1 == curLoop) $ do
|
||||||
when (curLoop `mod` printEvery == 0) $ do
|
when (curLoop `mod` printEvery == 0) $ do
|
||||||
putStr "\ESC[2J\ESC[H"
|
putStr "\ESC[2J\ESC[H"
|
||||||
printEnvironment e
|
printEnvironment (snd env)
|
||||||
putStrLn ""
|
putStrLn ""
|
||||||
putStrLn $ "Generation " ++ show curLoop ++ " of " ++ show loopAmount ++ ":"
|
putStrLn $ "Generation " ++ show curLoop ++ " of " ++ show loopAmount ++ ":"
|
||||||
newPlants <- flip runReaderT e $ do
|
newPlants <- simulate s $ do
|
||||||
(!fs,cs) <- unzip <$> fitness plants
|
(!fs,cs) <- unzip <$> fitness plants
|
||||||
let fps = zip plants fs -- gives us plants & their fitness in a tuple
|
let fps = zip plants fs -- gives us plants & their fitness in a tuple
|
||||||
sumFitness = sum fs
|
sumFitness = sum fs
|
||||||
|
spc = meanAndVar `from` sumProducedCompounds $ cs
|
||||||
|
ndc = meanAndVar `from` numDistinctCompounds $ cs
|
||||||
|
fns = meanAndVar `from` id $ fs
|
||||||
when (curLoop `mod` printEvery == 0) $ liftIO $ do
|
when (curLoop `mod` printEvery == 0) $ liftIO $ do
|
||||||
printPopulation stringe (zip3 plants fs cs)
|
printPopulation stringe (zip3 plants fs cs)
|
||||||
putStrLn $ "Population statistics: VarC = " ++ (padded 50 . show . varianceOfProducedCompounds $ cs)
|
putStrLn $ "Population statistics (mean,variance):"
|
||||||
++ " DistC = " ++ (padded 50 . show . meanOfDistinctCompounds $ cs)
|
putStrLn $ "Amount of Components produced = " ++ (padded 50 . show $ spc)
|
||||||
|
putStrLn $ "Number of distinct Components = " ++ (padded 50 . show $ ndc)
|
||||||
|
putStrLn $ "Fitness = " ++ (padded 50 . show $ fns)
|
||||||
hFlush stdout
|
hFlush stdout
|
||||||
threadDelay $ 100*1000 -- sleep x*1000ns (=x ~ ms)
|
threadDelay $ 10*1000 -- sleep x*1000ns (=x ~ ms)
|
||||||
|
tell $ show curLoop
|
||||||
|
++ "," ++ show (fst spc) ++ "," ++ show (snd spc)
|
||||||
|
++ "," ++ show (fst ndc) ++ "," ++ show (snd ndc)
|
||||||
|
++ "," ++ show (fst fns) ++ "," ++ show (snd fns)
|
||||||
-- generate x new plants.
|
-- generate x new plants.
|
||||||
np <- asks (numPlants . settings)
|
np <- fromEnv (numPlants . settings)
|
||||||
sequence . flip fmap [1..np] $ \_ -> do
|
sequence . flip fmap [1..np] $ \_ -> do
|
||||||
parent' <- liftIO $ randomRIO (0,sumFitness)
|
parent' <- liftIO $ randomRIO (0,sumFitness)
|
||||||
let
|
let
|
||||||
@ -119,26 +133,29 @@ loop loopAmount ps env = loop' loopAmount 0 ps env
|
|||||||
| otherwise = findParent (x-f) ps
|
| otherwise = findParent (x-f) ps
|
||||||
parent = findParent parent' fps
|
parent = findParent parent' fps
|
||||||
haploMate parent
|
haploMate parent
|
||||||
loop' loopAmount (curLoop+1) newPlants e
|
loop' loopAmount (curLoop+1) newPlants s
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
hSetBuffering stdin NoBuffering
|
hSetBuffering stdin NoBuffering
|
||||||
--hSetBuffering stdout NoBuffering
|
--hSetBuffering stdout NoBuffering
|
||||||
randomCompounds <- makeHead (Substrate PPM) <$> generateTreeFromList 40 (toEnum <$> [(maxCompoundWithoutGeneric+1)..] :: [Compound]) -- generate roughly x compounds
|
randomCompounds <- makeHead (Substrate PPM) <$> generateTreeFromList 30 (toEnum <$> [(maxCompoundWithoutGeneric+1)..] :: [Compound]) -- generate roughly x compounds
|
||||||
ds <- randoms <$> newStdGen
|
ds <- randoms <$> newStdGen
|
||||||
probs <- randomRs (0.2,0.7) <$> newStdGen
|
--probs <- randomRs (0.2,0.7) <$> newStdGen
|
||||||
let poisonedTree = poisonTree ds randomCompounds
|
let poisonedTree = poisonTree ds randomCompounds
|
||||||
poisonCompounds = foldMap (\(a,b) -> [(b,a) | a > 0.5]) poisonedTree
|
poisonCompounds = foldMap (\(a,b) -> [(b,a) | a > 0.5]) poisonedTree
|
||||||
predators <- generatePredators 0.5 poisonedTree
|
predators <- generatePredators 0.5 poisonedTree
|
||||||
let env = exampleEnvironment (getTreeSize randomCompounds) (generateEnzymeFromTree randomCompounds) (zip predators probs) poisonCompounds
|
--let env = exampleEnvironment (getTreeSize randomCompounds) (generateEnzymeFromTree randomCompounds) (zip predators probs) poisonCompounds
|
||||||
emptyPlants = replicate (numPlants . settings $ env) emptyPlant
|
(Just env) <- decodeStrict' <$> BS.readFile "environment2.json"
|
||||||
|
let emptyPlants = replicate (numPlants . settings $ env) emptyPlant
|
||||||
enzs <- randomRs (0,length (possibleEnzymes env) - 1) <$> newStdGen
|
enzs <- randomRs (0,length (possibleEnzymes env) - 1) <$> newStdGen
|
||||||
let startPlants = randomGenome 1 enzs (possibleEnzymes env) emptyPlants
|
let startPlants = randomGenome 1 enzs (possibleEnzymes env) emptyPlants
|
||||||
printEnvironment env
|
printEnvironment env
|
||||||
writeFile "poison.twopi" $ generateDotFromPoisonTree "poison" 0.5 poisonedTree
|
writeFile "poison.twopi" $ generateDotFromPoisonTree "poison" 0.5 poisonedTree
|
||||||
|
--writeFile "environment.json" . encode $ env
|
||||||
putStr "\ESC[?1049h"
|
putStr "\ESC[?1049h"
|
||||||
loop 2000 startPlants env
|
logfile <- openFile "simulation.log" WriteMode
|
||||||
|
loop 2000 startPlants (logfile,env)
|
||||||
putStrLn "Simulation ended. Press key to exit."
|
putStrLn "Simulation ended. Press key to exit."
|
||||||
_ <- getChar
|
_ <- getChar
|
||||||
putStr "\ESC[?1049l"
|
putStr "\ESC[?1049l"
|
||||||
@ -182,8 +199,12 @@ printEnvironment (Environment soil pred metaIter maxComp toxic possEnz settings)
|
|||||||
printPopulation :: [(Enzyme,String)] -> [(Plant,Double,Vector Amount)] -> IO ()
|
printPopulation :: [(Enzyme,String)] -> [(Plant,Double,Vector Amount)] -> IO ()
|
||||||
printPopulation es ps = do
|
printPopulation es ps = do
|
||||||
let padded i str = take i $ str ++ repeat ' '
|
let padded i str = take i $ str ++ repeat ' '
|
||||||
putStr $ padded 50 "Population:"
|
n = length ps
|
||||||
forM_ ps $ \(_,f,_) -> putStr (printColor f '█')
|
fitnesses = (\(_,f,_) -> f) <$> ps
|
||||||
|
meanFitness = sum fitnesses / fromIntegral n
|
||||||
|
maxFitness = maximum fitnesses
|
||||||
|
putStr $ padded 50 ("Population: (fitness: mean " ++ padded 5 (show meanFitness) ++ ", max: " ++ padded 5 (show maxFitness) ++ ")")
|
||||||
|
forM_ ps $ \(_,f,_) -> putStr (printColor (f/maxFitness) '█')
|
||||||
putStrLn colorOff
|
putStrLn colorOff
|
||||||
forM_ es $ \(e,s) -> do
|
forM_ es $ \(e,s) -> do
|
||||||
putStr s
|
putStr s
|
||||||
@ -204,6 +225,7 @@ printPopulation es ps = do
|
|||||||
|
|
||||||
printColor :: Double -> Char -> String
|
printColor :: Double -> Char -> String
|
||||||
printColor x c
|
printColor x c
|
||||||
|
| x > 1 = "Error: " ++ show x
|
||||||
| x*x < 0.5 = "\ESC[38;5;" ++ show (16 + 36*5 + 6*floor (5*2*x') + 0) ++ "m" ++ [c] ++ ""
|
| x*x < 0.5 = "\ESC[38;5;" ++ show (16 + 36*5 + 6*floor (5*2*x') + 0) ++ "m" ++ [c] ++ ""
|
||||||
| otherwise = "\ESC[38;5;" ++ show (16 + 36*floor (5*2*(1-x')) + 6*5 + 0) ++ "m" ++ [c] ++ ""
|
| otherwise = "\ESC[38;5;" ++ show (16 + 36*floor (5*2*(1-x')) + 6*5 + 0) ++ "m" ++ [c] ++ ""
|
||||||
-- 32 bit
|
-- 32 bit
|
||||||
|
@ -28,6 +28,8 @@ dependencies:
|
|||||||
- pretty-simple
|
- pretty-simple
|
||||||
- parallel
|
- parallel
|
||||||
- foldl
|
- foldl
|
||||||
|
- aeson
|
||||||
|
- bytestring
|
||||||
|
|
||||||
library:
|
library:
|
||||||
source-dirs: src
|
source-dirs: src
|
||||||
|
@ -1,14 +1,24 @@
|
|||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-# LANGUAGE TypeSynonymInstances #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
module Environment where
|
module Environment where
|
||||||
|
|
||||||
import Data.Functor ((<$>))
|
import Data.Functor ((<$>))
|
||||||
import Control.Applicative ((<*>))
|
import Control.Applicative ((<*>))
|
||||||
import Control.Monad (forM_)
|
import Control.Monad (forM_)
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
|
import Control.Monad.Writer.Strict
|
||||||
import Control.Parallel.Strategies
|
import Control.Parallel.Strategies
|
||||||
import Data.List (permutations, subsequences)
|
import Data.List (permutations, subsequences)
|
||||||
import Numeric.LinearAlgebra
|
import Numeric.LinearAlgebra
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
import System.Random
|
import System.Random
|
||||||
|
import System.IO
|
||||||
|
import Data.Aeson
|
||||||
|
import GHC.Generics
|
||||||
|
|
||||||
|
import WriterIO
|
||||||
|
|
||||||
type Probability = Double
|
type Probability = Double
|
||||||
type Quantity = Int
|
type Quantity = Int
|
||||||
@ -17,18 +27,27 @@ type Amount = Double
|
|||||||
|
|
||||||
-- | Nutrients are the basis for any reaction and are found in the environment of the plant.
|
-- | Nutrients are the basis for any reaction and are found in the environment of the plant.
|
||||||
data Nutrient = PPM
|
data Nutrient = PPM
|
||||||
deriving (Show, Enum, Bounded, Eq)
|
deriving (Show, Enum, Bounded, Eq, Generic)
|
||||||
|
|
||||||
|
instance FromJSON Nutrient
|
||||||
|
instance ToJSON Nutrient
|
||||||
|
|
||||||
-- | Fixed, non-generic Components
|
-- | Fixed, non-generic Components
|
||||||
data Component = PP
|
data Component = PP
|
||||||
| FPP
|
| FPP
|
||||||
deriving (Show, Enum, Bounded, Eq)
|
deriving (Show, Enum, Bounded, Eq, Generic)
|
||||||
|
|
||||||
|
instance FromJSON Component
|
||||||
|
instance ToJSON Component
|
||||||
|
|
||||||
-- | Compounds are either direct nutrients, already processed components or GenericCompound
|
-- | Compounds are either direct nutrients, already processed components or GenericCompound
|
||||||
data Compound = Substrate Nutrient
|
data Compound = Substrate Nutrient
|
||||||
| Produced Component
|
| Produced Component
|
||||||
| GenericCompound Int
|
| GenericCompound Int
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq, Generic)
|
||||||
|
|
||||||
|
instance FromJSON Compound
|
||||||
|
instance ToJSON Compound
|
||||||
|
|
||||||
instance Enum Compound where
|
instance Enum Compound where
|
||||||
toEnum x
|
toEnum x
|
||||||
@ -64,7 +83,10 @@ data Enzyme = Enzyme
|
|||||||
-- ^ in case of competition for nutrients this denotes the priority
|
-- ^ in case of competition for nutrients this denotes the priority
|
||||||
-- Nothing = max possible
|
-- Nothing = max possible
|
||||||
}
|
}
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq, Generic)
|
||||||
|
|
||||||
|
instance FromJSON Enzyme
|
||||||
|
instance ToJSON Enzyme
|
||||||
|
|
||||||
-- | conviniently make an Enzyme using 1 of the first compund to produce 1 of the second
|
-- | conviniently make an Enzyme using 1 of the first compund to produce 1 of the second
|
||||||
makeSimpleEnzyme :: Compound -> Compound -> Enzyme
|
makeSimpleEnzyme :: Compound -> Compound -> Enzyme
|
||||||
@ -84,14 +106,20 @@ data Predator = Predator { irresistance :: [Compound]
|
|||||||
, numAttacks :: Amount
|
, numAttacks :: Amount
|
||||||
-- ^ Avarage number of attacks in a generation of appearance
|
-- ^ Avarage number of attacks in a generation of appearance
|
||||||
-- (~ mean of poisson-distribution)
|
-- (~ mean of poisson-distribution)
|
||||||
} deriving (Show, Eq)
|
} deriving (Show, Eq, Generic)
|
||||||
|
|
||||||
|
instance FromJSON Predator
|
||||||
|
instance ToJSON Predator
|
||||||
|
|
||||||
-- | Settings to enable/disable parts of the simulation
|
-- | Settings to enable/disable parts of the simulation
|
||||||
data Settings = Settings { automimicry :: Bool -- ^ do we have automimicry-protection?
|
data Settings = Settings { automimicry :: Bool -- ^ do we have automimicry-protection?
|
||||||
, predatorsRandom :: Bool -- ^ do predators always appear or according to their random distribution?
|
, predatorsRandom :: Bool -- ^ do predators always appear or according to their random distribution?
|
||||||
, numPlants :: Int -- ^ number of plants in starting population
|
, numPlants :: Int -- ^ number of plants in starting population
|
||||||
}
|
}
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq, Generic)
|
||||||
|
|
||||||
|
instance FromJSON Settings
|
||||||
|
instance ToJSON Settings
|
||||||
|
|
||||||
-- | The environment itself.
|
-- | The environment itself.
|
||||||
|
|
||||||
@ -116,13 +144,26 @@ data Environment =
|
|||||||
, possibleEnzymes :: [Enzyme]
|
, possibleEnzymes :: [Enzyme]
|
||||||
-- ^ All enzymes that can be created by genetic manipulation in this setting.
|
-- ^ All enzymes that can be created by genetic manipulation in this setting.
|
||||||
, settings :: Settings
|
, settings :: Settings
|
||||||
} deriving (Show, Eq)
|
} deriving (Show, Eq, Generic)
|
||||||
|
|
||||||
|
instance FromJSON Environment
|
||||||
|
instance ToJSON Environment
|
||||||
|
|
||||||
-- helper function. Allows for [0..maxCompoundWithoutGeneric] :: [Compound] with all non-generic Compounds
|
-- helper function. Allows for [0..maxCompoundWithoutGeneric] :: [Compound] with all non-generic Compounds
|
||||||
maxCompoundWithoutGeneric :: Int
|
maxCompoundWithoutGeneric :: Int
|
||||||
maxCompoundWithoutGeneric = fromEnum (maxBound :: Nutrient) + fromEnum (maxBound :: Component) + 1
|
maxCompoundWithoutGeneric = fromEnum (maxBound :: Nutrient) + fromEnum (maxBound :: Component) + 1
|
||||||
|
|
||||||
type World a = ReaderT Environment IO a
|
type Simulation = (Handle, Environment)
|
||||||
|
type World a = WriterIOT (ReaderT Simulation IO) a
|
||||||
|
|
||||||
|
instance HasHandle (WriterIOT (ReaderT Simulation IO)) where
|
||||||
|
getHandle = asks fst
|
||||||
|
|
||||||
|
fromEnv :: (Environment -> a) -> World a
|
||||||
|
fromEnv f = asks $ f . snd
|
||||||
|
|
||||||
|
simulate :: Simulation -> World a -> IO a
|
||||||
|
simulate (log, e) = fmap fst . flip runReaderT (log,e) . runWriterT . getWriterT
|
||||||
|
|
||||||
-- Plants
|
-- Plants
|
||||||
-- ------
|
-- ------
|
||||||
@ -158,15 +199,15 @@ fitness ps = do
|
|||||||
nutrients <- mapM absorbNutrients ps -- absorb soil
|
nutrients <- mapM absorbNutrients ps -- absorb soil
|
||||||
products <- sequenceA $ zipWith produceCompounds ps nutrients -- produce compounds
|
products <- sequenceA $ zipWith produceCompounds ps nutrients -- produce compounds
|
||||||
ds <- liftIO $ randoms <$> newStdGen
|
ds <- liftIO $ randoms <$> newStdGen
|
||||||
preds <- asks predators
|
preds <- fromEnv predators
|
||||||
randPred <- asks (predatorsRandom . settings)
|
randPred <- fromEnv (predatorsRandom . settings)
|
||||||
let
|
let
|
||||||
appearingPredators = if randPred then
|
appearingPredators = if randPred then
|
||||||
fmap (fst . fst) . filter (\((_,p),r) -> p > r) $ zip preds ds -- assign one probability to each predator, filter those who appear, throw random data away again.
|
fmap (fst . fst) . filter (\((_,p),r) -> p > r) $ zip preds ds -- assign one probability to each predator, filter those who appear, throw random data away again.
|
||||||
-- appearingPredators is now a sublist of preds without the probability.
|
-- appearingPredators is now a sublist of preds without the probability.
|
||||||
else
|
else
|
||||||
fst <$> preds -- else just forget about probabilities
|
fst <$> preds -- else just forget about probabilities
|
||||||
automimicry <- asks (automimicry . settings)
|
automimicry <- fromEnv (automimicry . settings)
|
||||||
popDefense <- if automimicry then
|
popDefense <- if automimicry then
|
||||||
forM appearingPredators $ \p -> do
|
forM appearingPredators $ \p -> do
|
||||||
as <- mapM (dieToPredator p) products -- how good can an individual deter p
|
as <- mapM (dieToPredator p) products -- how good can an individual deter p
|
||||||
@ -176,7 +217,7 @@ fitness ps = do
|
|||||||
dieRate <- mapM (dieToPredators (zip appearingPredators popDefense)) products -- defeat predators with produced compounds
|
dieRate <- mapM (dieToPredators (zip appearingPredators popDefense)) products -- defeat predators with produced compounds
|
||||||
let sumEnzymes = sum . fmap (\(_,q,a) -> fromIntegral q*a) . genome <$> ps -- amount of enzymes * activation = resources "wasted"
|
let sumEnzymes = sum . fmap (\(_,q,a) -> fromIntegral q*a) . genome <$> ps -- amount of enzymes * activation = resources "wasted"
|
||||||
staticCostOfEnzymes = (\x -> 1 - 0.02*x) <$> sumEnzymes -- static cost of creating enzymes
|
staticCostOfEnzymes = (\x -> 1 - 0.02*x) <$> sumEnzymes -- static cost of creating enzymes
|
||||||
nutrientsAvailable <- fmap snd <$> asks soil
|
nutrientsAvailable <- fmap snd <$> fromEnv soil
|
||||||
let nutrientsLeft = (\p -> [p ! i | i <- [0..fromEnum (maxBound :: Nutrient)]]) <$> products
|
let nutrientsLeft = (\p -> [p ! i | i <- [0..fromEnum (maxBound :: Nutrient)]]) <$> products
|
||||||
nutrientRatio = minimum . zipWith (flip (/)) nutrientsAvailable <$> nutrientsLeft
|
nutrientRatio = minimum . zipWith (flip (/)) nutrientsAvailable <$> nutrientsLeft
|
||||||
costOfEnzymes = max 0 <$> zipWith (\s n -> s-n*0.1) staticCostOfEnzymes nutrientRatio -- cost to keep enzymes are static costs + amount of nutrient sucked out of the primary cycle
|
costOfEnzymes = max 0 <$> zipWith (\s n -> s-n*0.1) staticCostOfEnzymes nutrientRatio -- cost to keep enzymes are static costs + amount of nutrient sucked out of the primary cycle
|
||||||
@ -186,8 +227,8 @@ fitness ps = do
|
|||||||
|
|
||||||
produceCompounds :: Plant -> [(Nutrient, Amount)] -> World (Vector Amount)
|
produceCompounds :: Plant -> [(Nutrient, Amount)] -> World (Vector Amount)
|
||||||
produceCompounds (Plant genes _) substrate = do
|
produceCompounds (Plant genes _) substrate = do
|
||||||
numIter <- asks metabolismIteration
|
numIter <- fromEnv metabolismIteration
|
||||||
numCompounds <- asks maxCompound
|
numCompounds <- fromEnv maxCompound
|
||||||
let
|
let
|
||||||
initialAmount = assoc (numCompounds+1) 0 ((\(n,a) -> (fromEnum $ Substrate n,a)) <$> substrate) :: Vector Amount
|
initialAmount = assoc (numCompounds+1) 0 ((\(n,a) -> (fromEnum $ Substrate n,a)) <$> substrate) :: Vector Amount
|
||||||
enzymes = (\(e,q,a) -> (synthesis e,fromIntegral q*a)) <$> genes -- [(((Component,Amount),(Component,Amount)),q*a)], Amount got * by quantity & activation
|
enzymes = (\(e,q,a) -> (synthesis e,fromIntegral q*a)) <$> genes -- [(((Component,Amount),(Component,Amount)),q*a)], Amount got * by quantity & activation
|
||||||
@ -218,7 +259,7 @@ dieToPredators appearingPredators compounds = do
|
|||||||
|
|
||||||
dieToPredator :: Predator -> Vector Amount -> World Double
|
dieToPredator :: Predator -> Vector Amount -> World Double
|
||||||
dieToPredator p comps = do
|
dieToPredator p comps = do
|
||||||
toxins <- asks toxicCompounds
|
toxins <- fromEnv toxicCompounds
|
||||||
return $ product [1 - min 1 (comps ! fromEnum t * l) | (t,l) <- toxins, t `elem` irresistance p]
|
return $ product [1 - min 1 (comps ! fromEnum t * l) | (t,l) <- toxins, t `elem` irresistance p]
|
||||||
|
|
||||||
-- Mating & Creation of diversity
|
-- Mating & Creation of diversity
|
||||||
@ -239,7 +280,7 @@ haploMate (Plant genes abs) = do
|
|||||||
r3 <- liftIO ((randoms <$> newStdGen) :: IO [Double])
|
r3 <- liftIO ((randoms <$> newStdGen) :: IO [Double])
|
||||||
r4 <- liftIO digen
|
r4 <- liftIO digen
|
||||||
r5 <- liftIO digen
|
r5 <- liftIO digen
|
||||||
enzymes <- asks possibleEnzymes
|
enzymes <- fromEnv possibleEnzymes
|
||||||
re1 <- liftIO ((randomRs (0,length enzymes - 1) <$> newStdGen) :: IO [Int])
|
re1 <- liftIO ((randomRs (0,length enzymes - 1) <$> newStdGen) :: IO [Int])
|
||||||
re2 <- liftIO ((randomRs (0,length enzymes - 1) <$> newStdGen) :: IO [Int])
|
re2 <- liftIO ((randomRs (0,length enzymes - 1) <$> newStdGen) :: IO [Int])
|
||||||
let
|
let
|
||||||
@ -288,7 +329,7 @@ haploMate (Plant genes abs) = do
|
|||||||
|
|
||||||
-- | Plant with no secondary metabolism with unlimited extraction from environment.
|
-- | Plant with no secondary metabolism with unlimited extraction from environment.
|
||||||
emptyPlant :: Plant
|
emptyPlant :: Plant
|
||||||
emptyPlant = Plant [] (asks soil)
|
emptyPlant = Plant [] (fromEnv soil)
|
||||||
|
|
||||||
getAmountOf :: Compound -> [(Compound, Amount)] -> Amount
|
getAmountOf :: Compound -> [(Compound, Amount)] -> Amount
|
||||||
getAmountOf c = sum . fmap snd . filter ((== c) . fst)
|
getAmountOf c = sum . fmap snd . filter ((== c) . fst)
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
module Evaluation ( varianceOfProducedCompounds
|
module Evaluation
|
||||||
, meanOfDistinctCompounds
|
( sumProducedCompounds
|
||||||
) where
|
, numDistinctCompounds
|
||||||
|
, sumCompounds
|
||||||
|
, from
|
||||||
|
, meanAndVar
|
||||||
|
) where
|
||||||
|
|
||||||
import Control.Foldl as F
|
import Control.Foldl as F
|
||||||
import Numeric.LinearAlgebra as LA
|
import Numeric.LinearAlgebra as LA
|
||||||
@ -10,11 +14,31 @@ import Environment
|
|||||||
eps :: Amount
|
eps :: Amount
|
||||||
eps = 0.01
|
eps = 0.01
|
||||||
|
|
||||||
varianceOfProducedCompounds :: [LA.Vector Amount] -> Double
|
-- | sum of produced compounds ignoring everything defined as 'Nutrient'.
|
||||||
varianceOfProducedCompounds comps = F.fold F.variance $ sumElements <$> comps
|
sumProducedCompounds :: Functor f => f (LA.Vector Amount) -> f Amount
|
||||||
|
-- sumProducedCompounds :: [LA.Vector Amount] -> [Amount]
|
||||||
|
-- cut off numNutrients from the start of the vector and then sum.
|
||||||
|
sumProducedCompounds = fmap $ (\v -> sumElements . LA.subVector numNutrients (size v - numNutrients) $ v)
|
||||||
|
where
|
||||||
|
numNutrients = fromEnum (maxBound :: Nutrient) + 1 --enum starts at 0, subVector-indexing at 1
|
||||||
|
|
||||||
|
-- | sum of all compounds
|
||||||
|
sumCompounds :: Functor f => f (LA.Vector Amount) -> f Amount
|
||||||
|
--sumCompounds :: [LA.Vector Amount] -> [Amount]
|
||||||
|
sumCompounds = fmap sumElements
|
||||||
|
|
||||||
-- | count compound as active if it is over eps.
|
-- | count compound as active if it is over eps.
|
||||||
meanOfDistinctCompounds :: [LA.Vector Amount] -> Double
|
numDistinctCompounds :: Functor f => f (LA.Vector Amount) -> f Amount
|
||||||
meanOfDistinctCompounds comps = F.fold F.mean $ sumElements . LA.cmap (\x -> if abs x < eps then 0 else 1) <$> comps
|
--numDistinctCompounds :: [LA.Vector Amount] -> [Amount]
|
||||||
|
numDistinctCompounds comps = sumElements . LA.cmap (\x -> if abs x < eps then 0 else 1) <$> comps
|
||||||
|
|
||||||
-- TODO: Mean enzyme-activity?
|
-- | helper function for Foldl-Package.
|
||||||
|
--
|
||||||
|
-- Usage: @F.mean `from` sumCompounds $ v@ where v is a Set/List/Vector/... of Vector of Compounds.
|
||||||
|
infixr 9 `from`
|
||||||
|
from :: Foldable f => F.Fold a b -> (c -> f a) -> c -> b
|
||||||
|
from f w b = F.fold f (w b)
|
||||||
|
|
||||||
|
-- | helper to get mean and variance in a single pass.
|
||||||
|
meanAndVar :: F.Fold Amount (Amount,Amount)
|
||||||
|
meanAndVar = (,) <$> F.mean <*> F.variance
|
||||||
|
27
src/WriterIO.hs
Normal file
27
src/WriterIO.hs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
module WriterIO (
|
||||||
|
WriterIOT(..)
|
||||||
|
, HasHandle(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad.Reader
|
||||||
|
import Control.Monad.State
|
||||||
|
import Control.Monad.Writer.Strict
|
||||||
|
import System.IO
|
||||||
|
|
||||||
|
newtype WriterIOT m a = WriterIOT { getWriterT :: WriterT () m a }
|
||||||
|
deriving (Functor, Applicative, Monad, MonadIO, MonadTrans, MonadReader r, MonadState s)
|
||||||
|
|
||||||
|
class HasHandle m where
|
||||||
|
getHandle :: m Handle
|
||||||
|
|
||||||
|
instance (MonadIO m, HasHandle (WriterIOT m)) => MonadWriter String (WriterIOT m) where
|
||||||
|
tell w = do
|
||||||
|
h <- getHandle
|
||||||
|
liftIO $ hPutStrLn h w
|
||||||
|
listen = fmap (\a -> (a,error "cannot read from already written stuff"))
|
||||||
|
pass = fmap fst
|
Loading…
Reference in New Issue
Block a user