no diversity. needs static tests.

This commit is contained in:
Stefan Dresselhaus
2018-06-04 01:37:58 +02:00
parent 69895ffaab
commit cc6fac6533
3 changed files with 112 additions and 86 deletions

View File

@ -16,10 +16,7 @@ type Activation = Double
type Amount = Double
-- | Nutrients are the basis for any reaction and are found in the environment of the plant.
data Nutrient = Sulfur
| Phosphor
| Nitrate
| Photosynthesis
data Nutrient = PPM
deriving (Show, Enum, Bounded, Eq)
-- | Fixed, non-generic Components
@ -156,7 +153,7 @@ instance Eq Plant where
type Fitness = Double
fitness :: [Plant] -> World [Fitness]
fitness :: [Plant] -> World [(Fitness, Vector Amount)]
fitness ps = do
nutrients <- mapM absorbNutrients ps -- absorb soil
products <- sequenceA $ zipWith produceCompounds ps nutrients -- produce compounds
@ -172,18 +169,20 @@ fitness ps = do
automimicry <- asks (automimicry . settings)
popDefense <- if automimicry then
forM appearingPredators $ \p -> do
as <- mapM (deterPredator p) products -- how good can an individual deter p
as <- mapM (dieToPredator p) products -- how good can an individual deter p
return $ sum as / fromIntegral (length as) -- how good can the population deter p on average
else
return $ repeat 1
survivalRate <- mapM (deterPredators (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"
staticCostOfEnzymes = (\x -> 1 - 0.01*x) <$> sumEnzymes -- static cost of creating enzymes
nutrientsAvailable <- fmap snd <$> asks soil
let nutrientsLeft = (\p -> [p ! i | i <- [0..fromEnum (maxBound :: Nutrient)]]) <$> products
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
return $ zipWith (*) survivalRate costOfEnzymes
costOfEnzymes = max 0 <$> zipWith (\s n -> s-n*0.01) staticCostOfEnzymes nutrientRatio -- cost to keep enzymes are static costs + amount of nutrient sucked out of the primary cycle
survivalRate = (1-) <$> dieRate
return $ (,) <$> zipWith (*) survivalRate costOfEnzymes
<*> products
produceCompounds :: Plant -> [(Nutrient, Amount)] -> World (Vector Amount)
produceCompounds (Plant genes _) substrate = do
@ -207,16 +206,17 @@ produceCompounds (Plant genes _) substrate = do
-- so F(D) is omitted
-- A(d_hat) is ahat * numAttacks p, because ahat is only deterrence of the population
-- and does not incorporate the number of attacks, which A(d_hat) in the paper does.
deterPredators :: [(Predator, Double)] -> Vector Amount -> World Probability
deterPredators appearingPredators compounds = do
dieToPredators :: [(Predator, Double)] -> Vector Amount -> World Probability
dieToPredators [] _ = return 0 -- if no predator, no dying.
dieToPredators appearingPredators compounds = do
deters <- forM appearingPredators $ \(p,ahat) -> do
myDeter <- deterPredator p compounds
return $ exp $ negate $ numAttacks p * ahat * myDeter -- exp due to assumption that number of attacks are poisson-distributed.
myDeter <- dieToPredator p compounds
return $ ahat * myDeter -- exp due to assumption that number of attacks are poisson-distributed.
return $ product deters
deterPredator :: Predator -> Vector Amount -> World Double
deterPredator p comps = do
dieToPredator :: Predator -> Vector Amount -> World Double
dieToPredator p comps = do
toxins <- asks toxicCompounds
return $ product [1 - min 1 (comps ! fromEnum t * l) | (t,l) <- toxins, t `elem` irresistance p]
@ -227,12 +227,17 @@ deterPredator p comps = do
-- | mate haploid
haploMate :: Plant -> World Plant
haploMate (Plant genes abs) = do
let digen :: IO [(Double, Int)]
digen = do
ds <- randoms <$> newStdGen
is <- randoms <$> newStdGen
return $ zip ds is
--generate some random infinite uniform distributed lists of doubles in [0,1)
r1 <- liftIO ((randoms <$> newStdGen) :: IO [Double])
r1 <- liftIO digen
r2 <- liftIO ((randoms <$> newStdGen) :: IO [Double])
r3 <- liftIO ((randoms <$> newStdGen) :: IO [Double])
r4 <- liftIO ((randoms <$> newStdGen) :: IO [Double])
r5 <- liftIO ((randoms <$> newStdGen) :: IO [Double])
r4 <- liftIO digen
r5 <- liftIO digen
enzymes <- asks possibleEnzymes
re1 <- liftIO ((randomRs (0,length enzymes - 1) <$> newStdGen) :: IO [Int])
re2 <- liftIO ((randomRs (0,length enzymes - 1) <$> newStdGen) :: IO [Int])
@ -243,29 +248,36 @@ haploMate (Plant genes abs) = do
. duplicateGene r4
. deleteGene r5
$ genes
deleteGene :: [Double] -> Genome -> Genome
deleteGene (r:rs) ((e,1,a):gs) = if r < 0.1 then deleteGene rs gs else (e,1,a):deleteGene rs gs
deleteGene (r:rs) ((e,q,a):gs) = if r < 0.1 then (e,q-1,a):deleteGene rs gs else (e,q,a):deleteGene rs gs
deleteGene :: [(Double,Int)] -> Genome -> Genome
deleteGene _ [] = []
deleteGene ((r,i):rs) g = if r < 0.05 then deleteGene rs (stay ++ go' ++ stay') else g
where
(stay, go:stay') = splitAt (i `mod` length g - 2) g
go' = case go of
(e,1,a) -> []
(e,q,a) -> [(e,q-1,a)]
duplicateGene :: [Double] -> Genome -> Genome
duplicateGene (r:rs) ((e,q,a):gs) = if r < 0.1 then (e,1,a):(e,q,a):duplicateGene rs gs else (e,q,a):duplicateGene rs gs
duplicateGene :: [(Double,Int)] -> Genome -> Genome
duplicateGene _ [] = []
duplicateGene ((r,i):rs) g = if r < 0.05 then duplicateGene rs (stay ++ (e,q+1,a):stay') else g
where
(stay, (e,q,a):stay') = splitAt (i `mod` length g - 2) g
addGene :: [Double] -> [Int] -> Genome -> Genome
addGene (r:rs) (s:ss) g = if r < 0.05 then (enzymes !! s,1,1):g else g
addGene (r:rs) (s:ss) g = if r < 0.005 then (enzymes !! s,1,1):g else g
noiseActivation :: [Double] -> Genome -> Genome
noiseActivation (r:rs) ((e,q,a):gs) = (e,q,max 0 $ min 1 $ a-0.01+0.02*r):noiseActivation rs gs
noiseActivation _ [] = []
mutateGene :: [Double] -> [Int] -> Genome -> Genome
mutateGene (r:rs) (s:ss) ((e,1,a):gs) = if r < 0.01 then ((enzymes !! s),1,a):mutateGene rs ss gs
else (e,1,a):mutateGene rs ss gs
mutateGene (r:rs) (s:ss) ((e,q,a):gs) = if r < 0.01 then (e,q-1,a):((enzymes !! s),1,a):mutateGene rs ss gs
else (e,q,a):mutateGene rs ss gs
mutateGene (r:rs) (s:ss) [] = []
mutateGene :: [(Double,Int)] -> [Int] -> Genome -> Genome
mutateGene _ _ [] = []
mutateGene ((r,i):rs) (s:ss) g = if r < 0.25 then mutateGene rs ss (stay ++ go' ++ stay') else g
where
(stay, go:stay') = splitAt (i `mod` length g - 2) g
go' = case go of
(e,1,a) -> [(enzymes !! s,1,a)]
(e,q,a) -> [(e,q-1,a),(enzymes !! s,1,a)]
return $ Plant genes' abs