--- 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 = GenericComponent Int > | PP > | FPP > deriving (Show, 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 Synthesis = Synthesis [(Compound, Amount)] (Compound,Amount) > 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 > , synthesis :: [Synthesis] > -- ^ 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 = [Synthesis [(Substrate Phosphor, 1)] (PP, 1)] > > fpps :: Enzyme > fpps = Enzyme "FPPS" [] syn Nothing > where > syn = [Synthesis [(PP, 1)] (FPP, 1)] --- 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 -> [(Component,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 _) = (\(a,b) -> (Substrate a,b)) > . 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 -> [(Compound, 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 ""