Commit af372d32 authored by Bentriou Mahmoud's avatar Bentriou Mahmoud

new notebook examples: creation of a ContinuousTimeModel, ABC-SMC with ContinuousTimeModel

parent 2f893aa0
This diff is collapsed.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Create a model\n",
"\n",
"In this package, probabilistic models are represented by `ContinuousTimeModel` objects. There are several ways to create these kind of objects."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"using MarkovProcesses"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. With load_model()\n",
"\n",
"A bunch of models are already available in the package. If `str_model::String` is the name of an implemented model, then `load_model(str_model)` creates a variable with name `str_model`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Poisson process\n",
"load_model(\"poisson\")\n",
"poisson"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Repressilator model\n",
"load_model(\"repressilator\")\n",
"repressilator"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. With @network_model\n",
"\n",
"A useful feature is avaiable for CTMCs induced by a Chemical Reaction Network. Let's consider the Chemical Reaction Network of the SIR model:\n",
"\n",
"$$\n",
"Infection: S + I \\xrightarrow{k_i} 2I \\\\\n",
"Recovery: I \\xrightarrow{k_r} R\n",
"$$\n",
"\n",
"The macro `@network_model` creates easily a CTMC stored in a `ContinuousTimeModel` variable based on this formalism."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"easy_sir = @network_model begin\n",
" Infection: (S + I => 2I, ki*I*S)\n",
" Recovery: (I => R, kr*I)\n",
"end \"My awesome SIR\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the first reaction, `ki*I*S` is the reaction rate of the reaction `Infection`. This model is almost ready to use, we have to set the initial state and the parameters."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"set_param!(easy_sir, [0.0012, 0.05])\n",
"set_x0!(easy_sir, [95, 5, 0])\n",
"using Plots\n",
"σ = simulate(easy_sir)\n",
"plot(times(σ), σ.I, linetype = :steppost)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Manually (advanced)\n",
"\n",
"When the above cases don't fit your application one can create manually a `ContinuousTimeModel`. Let's take a look about the signature of the constructor method:\n",
"\n",
"```julia\n",
"function ContinuousTimeModel(dim_state::Int, dim_params::Int, map_var_idx::Dict{VariableModel,Int}, \n",
" map_param_idx::Dict{ParameterModel,Int}, transitions::Vector{<:Transition},\n",
" p::Vector{Float64}, x0::Vector{Int}, t0::Float64, \n",
" f!::Function, isabsorbing::Function; kwargs)\n",
"```\n",
"\n",
"First, one has to specify the dimensions of the state space and the parameter space."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dim_state_sir, dim_params_sir = 3, 2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`map_var_idx` is a dictionary that maps each model variable (represented by a `Symbol`) to an index in the state space."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"map_var_idx_sir = Dict(:S => 1, :I => 2, :R => 3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`map_var_params` is the equivalent of `map_var_idx` for parameters."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"map_params_idx_sir = Dict(:ki => 1, :kr => 2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`transitions` are the transitions/reactions of the model (vector of `Symbol`), `p`, `x0` and `t0` are respectively the parameters, the initial state and initial time of the model."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"transitions_sir = [:Infection, :Recovery]\n",
"p_sir = [0.0012, 0.05]\n",
"x0_sir = [95, 5, 0]\n",
"t0_sir = 0.0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The two last arguments are functions, the first one, called `f!` must have the signature:\n",
"\n",
"```julia\n",
"function f!(xnplus1::Vector{Int}, ptr_t::Vector{Float64}, ptr_tr::Vector{Transition},\n",
" xn::Vector{Int}, tn::Float64, p::Vector{Float64})\n",
"\n",
"```\n",
"\n",
"It should return nothing. `xnplus1`, `ptr_t` and `ptr_tr` are vectors where the next values are stored. `ptr_t` is of length 1 and stores the next time value (`ptr_t[1] = tn + delta_t`) whereas `ptr_tr` stores the name of the next transition/reaction (`ptr_tr[1] = :Infection` for example). This function is implemented in the package as:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"@everywhere function sir_f!(xnplus1::Vector{Int}, l_t::Vector{Float64}, l_tr::Vector{Transition},\n",
" xn::Vector{Int}, tn::Float64, p::Vector{Float64})\n",
" @inbounds a1 = p[1] * xn[1] * xn[2]\n",
" @inbounds a2 = p[2] * xn[2]\n",
" l_a = (a1, a2)\n",
" asum = sum(l_a)\n",
" if asum == 0.0\n",
" copyto!(xnplus1, xn)\n",
" return nothing\n",
" end\n",
" nu_1 = (-1, 1, 0)\n",
" nu_2 = (0, -1, 1)\n",
" l_nu = (nu_1, nu_2)\n",
" l_str_R = (:Infection, :Recovery)\n",
"\n",
" u1 = rand()\n",
" u2 = rand()\n",
" tau = - log(u1) / asum\n",
" b_inf = 0.0\n",
" b_sup = a1\n",
" reaction = 0\n",
" for i = 1:2 \n",
" if b_inf < asum*u2 < b_sup\n",
" reaction = i\n",
" break\n",
" end\n",
" @inbounds b_inf += l_a[i]\n",
" @inbounds b_sup += l_a[i+1]\n",
" end\n",
" \n",
" nu = l_nu[reaction]\n",
" for i = 1:3\n",
" @inbounds xnplus1[i] = xn[i]+nu[i]\n",
" end\n",
" @inbounds l_t[1] = tn + tau\n",
" @inbounds l_tr[1] = l_str_R[reaction]\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The second function called `isaborbing` must have the signature:\n",
"\n",
"```julia\n",
"isabsorbing(p::Vector{Float64}, xn::Vector{Int})\n",
"```\n",
"\n",
"This function checks if the state `xn` is an absorbing state according to the model parametrised by `p`. It has to return true or false.\n",
"\n",
"For a CTMC, a state is an absorbing state if the total exit rate is zero. In the case of the SIR model:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"@everywhere sir_isabsorbing(p::Vector{Float64}, xn::Vector{Int}) = (p[1]*xn[1]*xn[2] + p[2]*xn[2]) === 0.0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally one sets the observed variables and the model can be created."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"g_sir = [:I]\n",
"tryhard_sir = ContinuousTimeModel(dim_state_sir, dim_params_sir, \n",
" map_var_idx_sir, map_params_idx_sir, \n",
" transitions_sir, p_sir, x0_sir, t0_sir, \n",
" getfield(Main, :sir_f!), getfield(Main, :sir_isabsorbing); g = g_sir, name = \"Handmade SIR\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"using Plots\n",
"σ = simulate(tryhard_sir)\n",
"plot(times(σ), σ.I, linetype = :steppost)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 1.5.3",
"language": "julia",
"name": "julia-1.5"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.5.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ABC-SMC with ContinuousTimeModel\n",
"\n",
"The package allows the run of ABC-SMC algorithm with models defined by the package."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"using MarkovProcesses\n",
"using Distributions\n",
"\n",
"load_model(\"SIR\")\n",
"set_time_bound!(SIR, 100.0)\n",
"parametric_SIR = ParametricModel(SIR, (:ki, Uniform(0.001, 0.0015)))\n",
"\n",
"vec_observations = [simulate(SIR)]\n",
"function dist_obs(vec_sim::Vector{Trajectory}, vec_observations::Vector{Trajectory})\n",
" return dist_lp(vec_sim[1], vec_observations[1]; p=2)\n",
"end\n",
"\n",
"epsilon = 0.5 * dist_obs([simulate(SIR)], vec_observations)\n",
"@show epsilon\n",
"\n",
"res_abc = abc_smc(parametric_SIR, vec_observations, dist_obs, nbr_particles = 100, tolerance = epsilon)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"using Plots\n",
"histogram(res_abc.mat_p_end, weights = res_abc.weights_end)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 1.5.3",
"language": "julia",
"name": "julia-1.5"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.5.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment