module Epidemic.BirthDeathSamplingOccurrence
( configuration
, allEvents
, observedEvents
) where
import Epidemic.Types.Population
import Epidemic.Types.Events
import Epidemic.Types.Parameter
import Data.Maybe (fromJust)
import qualified Data.Vector as V
import System.Random.MWC
import System.Random.MWC.Distributions (categorical, exponential)
import Epidemic
import Epidemic.Utility
data BDSORates =
BDSORates Rate Rate Rate Rate
instance ModelParameters BDSORates where
rNaught (BDSORates birthRate deathRate samplingRate occurrenceRate) _ =
Just $ birthRate / (deathRate + samplingRate + occurrenceRate)
eventRate (BDSORates birthRate deathRate samplingRate occurrenceRate) _ =
Just $ birthRate + deathRate + samplingRate + occurrenceRate
birthProb (BDSORates birthRate deathRate samplingRate occurrenceRate) _ =
Just $ birthRate / (birthRate + deathRate + samplingRate + occurrenceRate)
newtype BDSOPopulation =
BDSOPopulation People
deriving (Show)
instance Population BDSOPopulation where
susceptiblePeople _ = Nothing
infectiousPeople (BDSOPopulation people) = Just people
removedPeople _ = Nothing
isInfected (BDSOPopulation (People people)) = not $ V.null people
birthDeathSamplingOccurrenceRates :: Rate -> Rate -> Rate -> Rate -> BDSORates
birthDeathSamplingOccurrenceRates = BDSORates
configuration :: Time
-> (Rate,Rate,Rate,Rate)
-> SimulationConfiguration BDSORates BDSOPopulation
configuration maxTime (birthRate, deathRate, samplingRate, occurrenceRate) =
let bdsoRates =
birthDeathSamplingOccurrenceRates
birthRate
deathRate
samplingRate
occurrenceRate
(seedPerson, newId) = newPerson initialIdentifier
bdsoPop = BDSOPopulation (People $ V.singleton seedPerson)
in SimulationConfiguration bdsoRates bdsoPop newId maxTime
randomBirthDeathSamplingOccurrenceEvent ::
BDSORates
-> Time
-> BDSOPopulation
-> Integer
-> GenIO
-> IO (Time, EpidemicEvent, BDSOPopulation, Integer)
randomBirthDeathSamplingOccurrenceEvent rates@(BDSORates br dr sr ocr) currTime (BDSOPopulation (People currPeople)) currId gen =
let netEventRate = fromJust $ eventRate rates currTime
eventWeights = V.fromList [br,dr,sr,ocr]
in
do delay <- exponential (fromIntegral (V.length currPeople) * netEventRate) gen
eventIx <- categorical eventWeights gen
(selectedPerson, unselectedPeople) <- randomPerson currPeople gen
return $ case eventIx of
0 -> let newTime = currTime + delay
(birthedPerson, newId) = newPerson currId
event = Infection newTime selectedPerson birthedPerson
in ( newTime
, event
, BDSOPopulation (People $ V.cons birthedPerson currPeople)
, newId)
1 -> let newTime = currTime + delay
event = Removal newTime selectedPerson
in (newTime, event, BDSOPopulation (People unselectedPeople), currId)
2 -> let newTime = currTime + delay
event = Sampling newTime selectedPerson
in (newTime, event, BDSOPopulation (People unselectedPeople), currId)
3 -> let newTime = currTime + delay
event = Occurrence newTime selectedPerson
in (newTime, event, BDSOPopulation (People unselectedPeople), currId)
_ -> error "no birth-death-sampling-occurrence event selected."
allEvents ::
BDSORates
-> Time
-> (Time, [EpidemicEvent], BDSOPopulation, Integer)
-> GenIO
-> IO (Time, [EpidemicEvent], BDSOPopulation, Integer)
allEvents rates maxTime currState@(currTime, currEvents, currPop, currId) gen =
if isInfected currPop
then do
(newTime, event, newPop, newId) <-
randomBirthDeathSamplingOccurrenceEvent rates currTime currPop currId gen
if newTime < maxTime
then allEvents
rates
maxTime
(newTime, event : currEvents, newPop, newId)
gen
else return currState
else return currState
observedEvents :: [EpidemicEvent]
-> [EpidemicEvent]
observedEvents events =
sort $ occurrenceEvents ++ sampleTreeEvents''
where
occurrenceEvents = filter isNonReconTreeObservation events
sampleTreeEvents'' =
sampleTreeEvents . sampleTree $ transmissionTree events (Person 1)