---
title: "Getting started with odin2"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting started with odin2}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

`odin2` implements a high-level language for describing and implementing ordinary differential equations and difference equations in R.  It provides a "[domain specific language](https://en.wikipedia.org/wiki/Domain-specific_language)" (DSL) which _looks_ like R but is compiled directly to C++, using [`dust2`](https://mrc-ide.github.io/dust2/) to solve your system and to provide an interface to particle filters.  You can then use [`monty`](https://mrc-ide.github.io/monty/) to fit your models using MCMC.

This vignette jumps through a few of the core features of `odin2` and ways that you might use it with `dust2` and `monty`.  Other vignettes (when written!) will expand on topics covered here in more detail.

# Discrete time stochastic SIR model

A simple definition of the SIR model is:

$$\begin{align*}
\frac{dS}{dt} &= -\beta \frac{SI}{N} \\
\frac{dI}{dt} &= \beta \frac{SI}{N} - \gamma I \\
\frac{dR}{dt} &= \gamma I \\
\end{align*}$$

where $S$ is the number of susceptibles, $I$ is the number of infected and $R$ is the number recovered; the total population size $N = S + I + R$ is constant. $\beta$ is the infection rate, $\gamma$ is the recovery rate.

Discretising this model in time steps of width $dt$ gives the following update equations for each time step:

$$\begin{align*}
S_{t+1} &= S_t - n_{SI} \\
I_{t+1} &= I_t + n_{SI} - n_{IR} \\
R_{t+1} &= R_t + n_{IR}
\end{align*}$$

where

$$\begin{align*}
n_{SI} &\sim \mathrm{Binomial}(S, 1 - e^{-\beta \frac{I}{N} \cdot dt}) \\
n_{IR} &\sim \mathrm{Binomial}(I, 1 - e^{-\gamma \cdot dt})
\end{align*}$$

Here is this system, as a stochastic compartmental model:

```{r}
gen <- odin2::odin({
  p_IR <- 1 - exp(-gamma * dt)
  N <- parameter(1000)

  p_SI <- 1 - exp(-(beta * I / N * dt))
  n_SI <- Binomial(S, p_SI)
  n_IR <- Binomial(I, p_IR)

  update(S) <- S - n_SI
  update(I) <- I + n_SI - n_IR
  update(R) <- R + n_IR

  initial(S) <- N - I0
  initial(I) <- I0
  initial(R) <- 0

  beta <- parameter(0.2)
  gamma <- parameter(0.1)
  I0 <- parameter(10)
})
```

This step generates C++ code for the model and compiles it; it will take a few seconds.

Once we have our system, we can pass it to [`dust2::dust_system_create`] to create and start simulating it.  Our system above has defaults for its parameters (`N`, `beta`, `gamma`, and `I0`) so we can initialise with almost no arguments:

```{r}
pars <- list(beta = 0.2, gamma = 0.1, I0 = 10, N = 1000)
sys <- dust2::dust_system_create(gen(), pars, n_particles = 10)
```

By default the system will start at time `0` and with `dt = 1`.  We can simulate 10 random epidemics starting from our initial conditions:

```{r}
dust2::dust_system_set_state_initial(sys)
time <- 0:100
y <- dust2::dust_system_simulate(sys, time)
matplot(time, t(y[2, , ]), col = "#00000055", lty = 1, type = "l",
        xlab = "Time", ylab = "Number of infecteds")
```

as this system is stochastic, each trajectory will be different.
