## Warning: package 'deSolve' was built under R version 4.3.1
The model used for demonstrating the process of migrating code from
deSolve
to denim
is as followed
# --- Model definition in deSolve
transition_func <- function(t, state, param){
with(as.list( c(state, param) ), {
gamma_rate = 1/scale
dS = -beta*S*I/N
dI1 = beta*S*I/N - gamma_rate*I1
dI2 = gamma_rate*I1 - gamma_rate*I2
dI = dI1 + dI2
dR = gamma_rate*I2
list(c(dS, dI, dI1, dI2, dR))
})
}
# ---- Model configuration
parameters <- c(beta = 0.3, scale = 3, N = 1000)
initialValues <- c(S = 999, I = 1, I1 = 1, I2=0, R=0)
# ---- Run simulation
times <- seq(0, 100) # simulation duration
ode_mod <- ode(y = initialValues, times = times, parms = parameters, func = transition_func)
# --- show output
ode_mod <- as.data.frame(ode_mod)
head(ode_mod[-1, c("time", "S", "I", "R")])
## time S I R
## 2 1 998.6561 1.294182 0.04969647
## 3 2 998.2239 1.594547 0.18152864
## 4 3 997.6985 1.921416 0.38010527
## 5 4 997.0695 2.290735 0.63971843
## 6 5 996.3225 2.716551 0.96093694
## 7 6 995.4387 3.212577 1.34869352
Unlike deSolve
where transitions between compartments
are defined by a system of ODEs, transitions in denim
must
be defined by (i) a distribution of dwell-time, (ii) a mathematical
expression, (iii) a fixed number or proportion.
User must first identify the transitions that best describe the ones
in their deSolve
model.
# --- Model definition in deSolve
transition_func <- function(t, state, param){
with(as.list( c(state, param) ), {
gamma_rate = 1/scale
# For S -> I transition, since it involves parameters (beta, N),
# the best transition to describe this is using a mathematical formula
dS = -beta*S*I/N
# For I -> R transition, linear chain trick is applied --> implies Erlang distributed dwell time
# Hence, we can use d_gamma from denim
dI1 = beta*S*I/N - gamma_rate*I1
dI2 = gamma_rate*I1 - gamma_rate*I2
dI = dI1 + dI2
dR = gamma_rate*I2
list(c(dS, dI, dI1, dI2, dR))
})
}
With the transitions identified, user can then define the model in
denim
.
When using denim
, the model structure is given as a
list
of key-value pairs where
key is a string showing the transition direction between compartments
value is the built-in distribution function that describe the transition
# --- Transition def for denim
transitions <- list(
"S -> I" = "beta * S * I/N * timestepDur",
"I -> R" = d_gamma(3, 2) # shape is 2 from number of I sub compartments
)
Note that when converting an ODE to a math expression, we must
multiply the original expression with time step duration (variable
timestepDur
in the model definition code). This is because
we are essentially using Euler’s method to estimate the solution for the
ODE.
Similar to deSolve
, denim
also ask users to
provide the initial values and any additional parameters
in the form of named vectors.
For the example deSolve
code, while users can use the
initalValues
from the deSolve
code as is
(denim
will ignore unused I1
, I2
compartments as these sub-compartments will be automatically computed
internally), it is recommended to remove redundant compartments (in this
example, I1
and I2
).
For parameters, since rate
and scale
are
already defined in the distribution functions, users only need to keep
beta
and N
from the initial parameters vector.
We also need to specify the value for timestepDur
here.
# remove I1, I2 compartments
denim_initialValues <- c(S = 999, I = 1, R=0)
denim_parameters <- c(beta = 0.3, N = 1000, timestepDur=0.01)
Initialization of sub-compartments: when
there are multiple sub-compartments (e.g., compartment I
consist of I1
and I2
sub-compartments), the
initial population is always assigned to the first sub-compartment. In
our example, since I = 1
, denim will assign
I1 = 1
and I2 = 0
.
Lastly, users need to define the simulation duration and time step
for denim
to run. Unlike deSolve
which takes a
time sequence, denim
only require the simulation
duration and time step.
Since denim
is a discrete time model, time step must be
set to a small value for the result to closely follow that of
deSolve
(in this example, 0.01).
The following plots show output from denim
and
deSolve