The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
Modelers may encounter many situations where individuals can transition from one compartment to multiple others, such as the SIRD model. There are 2 main approaches to handle this:
Model transitions as competing risks
Model as multinomial transition (outgoing population is split by a fixed proportion to transition to new compartments).
denim
allows users to model both situations, while
requiring minimal change to the code base to switch between 2 methods of
modeling.
To specify the proportion that goes to each outgoing compartment, define the transition using the following syntax in model definition:
"proportion * compartment -> out_compartment" = [transition]
Note that the proportion
here is the proportion of
compartment
that will end up in
out_compartment
at equilibrium.
Example: An SIRD model where 90% of infected can recover while the remaining 10% will die.
transitions <- list(
"S -> I" = "beta * S * (I / N) * timeStep",
"0.9 * I -> R" = d_gamma(1/3, 2),
"0.1 * I -> D" = d_exponential(0.1)
)
\[ \begin{cases} dS = -\beta S \frac{I}{N} \\ dIR_1 = 0.9 *\beta S \frac{I}{N} -\frac{1}{3}IR_1 \\ dIR_2 = \frac{1}{3}IR_1 - \frac{1}{3}IR_2 \\ dID = 0.1*\beta S \frac{I}{N} - 0.1*ID \\ dR = \frac{1}{3}IR_2 \\ dD = 0.1*ID \end{cases} \]
denim
will automatically normalize the proportions if
they don’t sum up to 1.
Example 2: The following model definition is equivalent to the one in Example 1
To further demonstrate the implementation of multinomial in
denim
, we provide the equivalent model implemented in
deSolve
and compare the output of 2 implementations.
# model in deSolve
transition_func <- function(t, state, param){
with(as.list( c(state, param) ), {
dS = - beta * S * (IR1 + IR2 + ID)/N
# apply linear chain trick for I -> R transition
# 0.9 * to specify prop of I that goes to I->R transition
dIR1 = 0.9 * beta * S * (IR1 + IR2 + ID)/N - rate*IR1
dIR2 = rate*IR1 - rate*IR2
dR = rate*IR2
# handle I -> D transition
# 0.1 * to specify prop of I that goes to I->D transition
dID = 0.1 * beta * S * (IR1 + IR2 + ID)/N - exp_rate*ID
dD = exp_rate*ID
list(c(dS, dIR1, dIR2, dID, dR, dD))
})
}
desolveInitialValues <- c(
S = 999,
# note that internally, denim also allocate initial value based on specified proportion
IR1 = 0.9,
IR2 = 0,
ID = 0.1,
R = 0,
D = 0
)
# --- run denim model ----
mod <- sim(transitions = transitions,
initialValues = denimInitialValues,
parameters = parameters,
simulationDuration = simulationDuration,
timeStep = timeStep)
# run deSolve model
times <- seq(0, simulationDuration)
ode_mod <- ode(y = desolveInitialValues, times = times, parms = parameters, func = transition_func)
ode_mod <- as.data.frame(ode_mod)
ode_mod$I<- rowSums(ode_mod[, c("IR1", "IR2", "ID")])
Output Comparison
When there are multiple transitions from one compartment and no proportions are specified, denim will automatically treat these transitions as competing risks.
Example: the following model definition
will treat I->R
and I->D
as competing
risks.
To further demonstrate the implementation of competing risks in
denim
, we provide the equivalent model implemented in
deSolve
and compare the output of 2 implementations.
transition_func <- function(t, state, param){
with(as.list( c(state, param) ), {
dS = - beta * S * (I1 + I2 + IR + ID)/N
dI1 = beta * S * (I1 + I2 + IR + ID)/N - (rate+d_rate)*I1
dIR = rate*I1 - (d_rate + rate)*IR
dID = d_rate*I1 - (d_rate + rate)*ID
dI2 = d_rate*IR + rate*ID - (d_rate + rate)*I2
dR = rate*IR + rate*I2
dD = d_rate*ID + d_rate*I2
list(c(dS, dI1, dIR, dID, dI2, dR, dD))
})
}
desolveInitialValues <- c(
S = 950,
I1 = 50,
IR = 0,
ID = 0,
I2 = 0,
R = 0,
D = 0
)
# run denim model
mod <- sim(transitions = transitions,
initialValues = denimInitialValues,
parameters = parameters,
simulationDuration = simulationDuration,
timeStep = timeStep)
# run deSolve model
times <- seq(0, simulationDuration)
ode_mod <- ode(y = desolveInitialValues, times = times, parms = parameters, func = transition_func)
ode_mod <- as.data.frame(ode_mod)
ode_mod$I <- rowSums(ode_mod[,c("I1", "ID", "IR", "I2")])
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.