chemodiversity/sketch.md.lhs

406 lines
12 KiB
Plaintext

---
title: Sketch for simulating chemodiversity
author: Stefan Dresselhaus
date: \today
format: markdown+lhs
papersize: a4
fontsize: 10pt
documentclass: scrartcl
width: 1920
height: 1080
margin: 0.2
theme: solarized
slideNumber: true
...
(rough) sketch components responsible for chemodiversity
========================================================
---
Genes
-----
- define which enzymes are produced in which quantities
- list in fig. 1 in [[1](git@github.com:hakimel/reveal.js.git)]
- can be scaled down/inactivated (i.e. when predators leave for generations)
- easy to ramp up production as long as the genes are still there
- plants can survive without problems with inactive PSM-cycles when no
adversaries are present.
---
=== Inheritance & Mutation
- via whole-genome and local-genome duplication
- copies accumulate mutations that lead to neofunctionalization
- e.g. subtle differences in terpene synthases can yield vastly different products
- i.e. these changes can appear easily
- need to classify products by "chemical distance" for simulation
- **TODO**: Map/Markov-Chain of mutations that may occur here?
---
=== Evolutional strategies
- "Bet-hedging": reduce variations of fitness over time
- **TODO**: understand
- different effects of intra-cohort-variation vs. inter-cohort-variation
- Plants with inactive PSM can survive if predators are deterred by other
individuals due to automimicry-effect which *could* foster wider genetic
variance
- the more of those individuals are present in a population, the less their
overall fitness becomes.
- **TODO**: fitness must also be able to depend on relative appearance of
adversarial traits in the population
- Keyword: Frequency-dependent-selection (FDS)
---
Pathways to produce chemical compounds
--------------------------------------
- 40k+ compounds just stem from compounds of the calvin-cycle taking the
MEP-pathway or from the krebs-cycle taking the MVA-pathway
- both yield the same intermediate product that forms the basis.
- 10k+ compounds are amino-acid-derivatives
- Chapter VI in [[1](git@github.com:hakimel/reveal.js.git)] exemplary describes 4 complete different pathways that yield
compounds.
- similar compounds/pathways should be found in the simulation
---
=== Consequences of producing compounds
- taking away parts of the calvin/krebs cycle puts pressure on those
- **TODO**: find out what they do and on what they depend.
- **TODO**: where do amino-acids come from? How much impact has the diversion of
these components?
---
Maintaining chemical diversity
------------------------------
=== + screening hypothesis
- many PSM found have no *known* biological activity
- plants "keep them around" in case another mutation needs them to produce
something "useful"
- creating things without use increase the need for photosynthesis and/or
nutrient uptake.
=== - screening hypothesis
- it is suggested that local abiotic & biotic selection pressures are the main
driver
- inactive molecules are not maintained long
- it was observed that some plants "rediscovered" some compounds in their
evolution suggesting they got rid of them when no pressure to maintain them
was applied
---
=== questions resulting from this that should be answered in the simulation
- details in chapter VIII of [[1](git@github.com:hakimel/reveal.js.git)]
- how quick can lost diversity be restored?
- how expensive is it to keep producing many inactive substances while also
producing active deterrents? Does this lead to a single point-of-failure due
to overspecialisation? What must be done to prevent this?
- strong selection pressure *should* decrease quantity of compounds due to
costs, but plants do not seem to care.
- is this diversity needed in presence of multiple different adversaries?
- does the simulation specialize when only presented with one adversary?
What about adaptive adversaries?
- adaptation in the qualitative & quantitative evolution in response to
changed pressure? (i.e. those who cannot adapt quick enough die?)
---
Scenario
========
As this is literate Haskell first a bit of throat-clearing:
> {-# LANGUAGE RecordWildCards #-}
>
> import Data.Functor ((<$>))
> import Control.Applicative ((<*>))
> import Control.Monad (forM_)
> import Data.List (permutations, subsequences)
Then some general aliases to make everything more readable:
> type Probability = Float
> type Quantity = Int
> type Activation = Float
> type Amount = Float
---
Nutrients & Compounds
---------------------
Nutrients are the basis for any reaction and are found in the environment of the
plant.
> data Nutrient = Sulfur
> | Phosphor
> | Nitrate
> | Photosynthesis
> deriving (Show, Enum, Bounded, Eq)
>
> data Component = PP
> | FPP
> deriving (Show, Enum, Bounded, Eq)
Compounds are either direct nutrients or already processed components
> data Compound = Substrate Nutrient
> | Produced Component
> deriving (Show, Eq)
This simple definition is only a brief sketch.
---
Enzymes
-------
Enzymes are the main reaction-driver behind synthesis of intricate compounds.
> data Enzyme = Enzyme
> { enzymeName :: String
> -- ^ Name of the Enzyme. Enzymes with the same name are supposed
> -- to be identical.
> , substrateRequirements :: [(Nutrient,Amount)]
> -- ^ needed for reaction to take place
> , substrateIntolerance :: [(Nutrient,Amount)]
> -- ^ inhibits reaction if given nutrients are above the given concentration
> , synthesis :: [(Compound,Amount)] -> [(Compound,Amount)]
> -- ^ given x in amount a, this will produce y in amount b
> , dominance :: Maybe Amount
> -- ^ in case of competition for nutrients this denotes the priority
> -- Nothing = max possible
> }
>
> instance Show Enzyme where
> show (Enzyme{..}) = enzymeName
>
> instance Eq Enzyme where
> a == b = enzymeName a == enzymeName b
---
Example "enzymes" could be:
> pps :: Enzyme -- uses Phosphor from Substrate to produce PP
> pps = Enzyme "PPS" [(Phosphor,1)] [] syn Nothing
> where
> syn compAvailable = [(Substrate Phosphor,i*(-1)),(Produced PP,i)]
> where
> i = getAmountOf (Substrate Phosphor) compAvailable
>
> fpps :: Enzyme -- PP -> FPP
> fpps = Enzyme "FPPS" [] [] syn Nothing
> where
> syn compAvailable = [(Produced PP,i*(-1)),(Produced FPP,i*0.5)]
> where
> i = getAmountOf (Produced PP) compAvailable
---
Environment
-----------
In the environment we have predators that impact the fitness of our plants and
may be resistant to some compounds the plant produces. They can also differ in
their intensity.
> data Predator = Predator { resistance :: [Component]
> -- ^ list of components this predator is resistant to
> , fitnessImpact :: Amount
> -- ^ impact on the fitness of a plant
> -- (~ agressiveness of the herbivore)
> } deriving (Show, Eq)
Exemplatory:
> greenfly :: Predator -- 20% of plants die to greenfly, but the fly is
> greenfly = Predator [PP] 0.2 -- killed by any Component not being PP
---
The environment itself is just the soil and the predators. Extensions would be
possible.
> data Environment =
> Environment
> { soil :: [(Nutrient, Amount)]
> -- ^ soil is a list of nutrients available to the plant.
> , predators :: [(Predator, Probability)]
> -- ^ Predators with the probability of appearance in this generation.
> } deriving (Show, Eq)
Example:
> exampleEnvironment :: Environment
> exampleEnvironment =
> Environment
> { soil = [ (Nitrate, 2)
> , (Phosphor, 3)
> , (Photosynthesis, 10)
> ]
> , predators = [ (greenfly, 0.1) ]
> }
---
Plants
------
Plants consist of a Genome responsible for creation of the PSM and also an
internal state how many nutrients and compounds are currently inside the plant.
> type Genome = [(Enzyme, Quantity, Activation)]
>
> data Plant = Plant
> { genome :: Genome
> -- ^ the genetic characteristic of the plant
> , absorbNutrients :: Environment -> [(Nutrient,Amount)]
> -- ^ the capability to absorb nutrients given an environment
> }
> instance Show Plant where
> show p = "Plant with Genome " ++ show (genome p)
> instance Eq Plant where
> a == b = genome a == genome b
---
The following example yields in the example-environment this population:
*Main> printPopulation [pps, fpps] plants
Population:
PPS ______oöö+++______oöö+++____________oöö+++oöö+++
FPPS ____________oöö+++oöö+++______oöö+++______oöö+++
> plants :: [Plant]
> plants = (\g -> Plant g defaultAbsorption) <$> genomes
> where
> enzymes = [pps, fpps]
> quantity = [1,2] :: [Quantity]
> activation = [0.7, 0.9, 1]
>
> genomes = do
> e <- permutations enzymes
> e' <- subsequences e
> q <- quantity
> a <- activation
> return $ (,,) <$> e' <*> [q] <*> [a]
>
> defaultAbsorption (Environment s _) = limit Phosphor 2
> . limit Nitrate 1
> . limit Sulfur 0
> <$> s
> -- custom absorbtion with helper-function:
> limit :: Nutrient -> Amount -> (Nutrient, Amount) -> (Nutrient, Amount)
> limit n a (n', a')
> | n == n' = (n, min a a') -- if we should limit, then we do ;)
> | otherwise = (n', a')
---
Fitness
-------
The fitness-measure is central for the generation of offspring and the
simulation. It evaluates the probability for passing on genes given a plant in
an environment.
> type Fitness = Float
>
> fitness :: Environment -> Plant -> Fitness
> fitness e p = survivalRate
> where
> nutrients = absorbNutrients p e
> products = produceCompounds p nutrients
> survivalRate = deterPredators (predators e) products
---
> produceCompounds :: Plant -> [(Nutrient, Amount)] -> [Compound]
> produceCompounds (Plant genes _) = undefined
> -- this will take some constrained linear algebra-solving
> deterPredators :: [(Predator, Probability)] -> [Compound] -> Probability
> deterPredators ps cs = sum $ do
> c <- cs -- for every compound
> (p,prob) <- ps -- and every predator
> return (if c `notin` (resistance p) -- if the plant cannot deter the predator
> then prob * fitnessImpact p -- impact it weighted by probability
> else 0)
> where
> (Produced a) `notin` b = all (/=a) b
> _ `notin`_ = False
Mating & Creation of diversity
------------------------------
TODO
---
Running the simulation
----------------------
> main = do
> putStrLn "Environment:"
> print exampleEnvironment
> putStrLn "Example population:"
> printPopulation [pps, fpps] plants
runhaskell sketch.md.lhs
Environment:
Environment { soil = [(Nitrate,2.0),(Phosphor,3.0),(Photosynthesis,10.0)]
, predators = [(Predator {resistance = [PP], fitnessImpact = 0.2},0.1)]}
Example population:
Population:
PPS ______oöö+++______oöö+++____________oöö+++oöö+++
FPPS ____________oöö+++oöö+++______oöö+++______oöö+++
---
Utility Functions
-----------------
> getAmountOf :: Compound -> [(Compound, Amount)] -> Amount
> getAmountOf c = sum . fmap snd . filter ((== c) . fst)
>
> printPopulation :: [Enzyme] -> [Plant] -> IO ()
> printPopulation es ps = do
> let padded i str = take i $ str ++ repeat ' '
> putStrLn "Population:"
> forM_ es $ \e -> do
> putStr $ padded 8 (show e)
> forM_ ps $ \(Plant g _) -> do
> let curE = sum $ map (\(_,q,a) -> (fromIntegral q)*a)
> . filter (\(e',_,_) -> e == e')
> $ g
> plot x
> | x > 2 = "O"
> | x > 1 = "+"
> | x > 0.7 = "ö"
> | x > 0.5 = "o"
> | x > 0 = "."
> | otherwise = "_"
> putStr (plot curE)
> putStrLn ""