Title: | Fast and Flexible Compartmental Modelling |
---|---|
Description: | Fast and flexible compartmental modelling with Template Model Builder. |
Authors: | Steve Walker [cre, aut], Weiguang Guan [aut], Jen Freeman [aut], Ben Bolker [aut], Darren Flynn-Primrose [aut], Irena Papst [ctb], Michael Li [ctb], Kevin Zhao [ctb] |
Maintainer: | Steve Walker <[email protected]> |
License: | GPL-3 |
Version: | 1.16.7 |
Built: | 2025-03-24 03:08:55 UTC |
Source: | https://github.com/canmod/macpan2 |
Convert a function that represents an elementwise binary
operator into one that is consistent with the C++
engine. This function is intended to clarify how macpan2
treats binary operators, which is a little different from
base R. The difference is clarified in
vignette("elementwise_binary_operators")
, and BinaryOperator
is
primarily used as a resource for that vignette.
BinaryOperator(operator) mp_binary_operator(operator)
BinaryOperator(operator) mp_binary_operator(operator)
operator |
A binary operator. Valid binary operations have the following characteristics. |
A binary operator consistent with the C++
engine.
BinaryOperator()
: Synonym of mp_binary_operator
.
set.seed(1L) A = matrix(abs(rnorm(6)), 3, 2) # 3 by 2 matrix x = matrix(abs(rnorm(3))) # 3 by 1 matrix y = t(abs(rnorm(2))) # 1 by 2 matrix times = BinaryOperator(`*`) pow = BinaryOperator(`^`) identical(times(A, x), times(x, A)) ## TRUE identical(pow(A, y), pow(y, A)) ## FALSE
set.seed(1L) A = matrix(abs(rnorm(6)), 3, 2) # 3 by 2 matrix x = matrix(abs(rnorm(3))) # 3 by 1 matrix y = t(abs(rnorm(2))) # 1 by 2 matrix times = BinaryOperator(`*`) pow = BinaryOperator(`^`) identical(times(A, x), times(x, A)) ## TRUE identical(pow(A, y), pow(y, A)) ## FALSE
Comparison Functions
all_equal(x, y) all_consistent(x, y) not_all_equal(x, y) all_not_equal(x, y)
all_equal(x, y) all_consistent(x, y) not_all_equal(x, y) all_not_equal(x, y)
x |
|
y |
|
all_equal()
: Is it true that all corresponding elements of x
and y
are equal, have the same shape, and have no missing values?
all_consistent()
: Is it true that all corresponding elements of x
and y
are either equal or at least one is a blank string, have the
same shape, and have no missing values?
not_all_equal()
: Complement of all_equal
.
all_not_equal()
: Do not know yet. Currently unused; should we remove?
Distributions which can be used to specify prior or likelihood components in model calibration.
Uniform Distribution (Improper), only appropriate for prior
components - mp_uniform
Normal Distribution - mp_normal
Log-Normal Distribution - mp_log_normal
Logit-Normal Distribution - mp_logit_normal
Poisson Distribution - mp_poisson
Negative Binomial Distribution - mp_neg_bin
mp_uniform(trans_distr_param = list()) mp_normal( location = mp_distr_param_null("location"), sd, trans_distr_param = list(location = mp_identity, sd = mp_log) ) mp_log_normal( location = mp_distr_param_null("location"), sd, trans_distr_param = list(location = mp_identity, sd = mp_identity) ) mp_logit_normal( location = mp_distr_param_null("location"), sd, trans_distr_param = list(location = mp_identity, sd = mp_identity) ) mp_poisson( location = mp_distr_param_null("location"), trans_distr_param = list(location = mp_identity) ) mp_neg_bin( location = mp_distr_param_null("location"), disp, trans_distr_param = list(location = mp_identity, disp = mp_log) )
mp_uniform(trans_distr_param = list()) mp_normal( location = mp_distr_param_null("location"), sd, trans_distr_param = list(location = mp_identity, sd = mp_log) ) mp_log_normal( location = mp_distr_param_null("location"), sd, trans_distr_param = list(location = mp_identity, sd = mp_identity) ) mp_logit_normal( location = mp_distr_param_null("location"), sd, trans_distr_param = list(location = mp_identity, sd = mp_identity) ) mp_poisson( location = mp_distr_param_null("location"), trans_distr_param = list(location = mp_identity) ) mp_neg_bin( location = mp_distr_param_null("location"), disp, trans_distr_param = list(location = mp_identity, disp = mp_log) )
trans_distr_param |
Named list of transformations for each
distributional parameter. See |
location |
Location parameter.
Specifying the |
sd |
Standard deviation parameter. |
disp |
Dispersion parameter. |
All distributional parameter arguments can be specified either as
a numeric value, a character string giving the parameter name, or a
distributional parameter object (See fit_distr_params
).
Convert a model specification into a graph (using the graph
package) that can be plotted with Rgraphviz
: see ?Rgraphviz::plot.graphNEL
and https://graphviz.org/doc/info/attrs.html for information on customizing the plot.
dot_layout(spec, include_inout = FALSE)
dot_layout(spec, include_inout = FALSE)
spec |
a model specification |
include_inout |
(logical) include nodes defined by |
In order to plot the graph, you need to have loaded the Rgraphviz
package (library("Rgraphviz")
).
if (require(Rgraphviz)) { macpan_base = mp_tmb_library("starter_models", "macpan_base", package = "macpan2") ## plot with left-to-right layout, rectangles instead of default circles dot_layout(macpan_base) |> plot(attrs = list(graph = list(rankdir = "LR"), node = list(shape = "rectangle"))) }
if (require(Rgraphviz)) { macpan_base = mp_tmb_library("starter_models", "macpan_base", package = "macpan2") ## plot with left-to-right layout, rectangles instead of default circles dot_layout(macpan_base) |> plot(attrs = list(graph = list(rankdir = "LR"), node = list(shape = "rectangle"))) }
Empty matrices are useful when defining matrices that do not need to be initialized because they will get computed before they are required by other expressions. They can also provide a useful placeholder for matrices that should only have a value after a certain phase in the simulation.
empty_matrix
empty_matrix
A numeric
matrix
with zero rows
and zero columns.
spec = mp_tmb_model_spec(during = list(x ~ time_step(0))) identical(spec$empty_matrices()$x, empty_matrix) ## TRUE
spec = mp_tmb_model_spec(during = list(x ~ time_step(0))) identical(spec$empty_matrices()$x, empty_matrix) ## TRUE
Output of mp_trajectory
if nothing is simulated.
empty_trajectory
empty_trajectory
A data frame with zero rows and the following columns: matrix
,
time
, row
, col
, value
.
Evaluate an expression in the TMB-based C++ simulation and objective
function engine. This function is useful for trying out the
engine_functions
that can be used to define macpan2
models.
engine_eval( .expr, ..., .matrix_to_return, .tmb_cpp = getOption("macpan2_dll"), .structure_labels = NullLabels() )
engine_eval( .expr, ..., .matrix_to_return, .tmb_cpp = getOption("macpan2_dll"), .structure_labels = NullLabels() )
.expr |
Expression as a one-sided formula, the right-hand-side of which is treated as the expression to be evaluated. |
... |
Named objects that can be coerced into numeric matrices. |
.matrix_to_return |
Optional name of one of the matrices given
in |
.tmb_cpp |
Name of a |
.structure_labels |
Deprecated. |
Matrix being produced on the right-hand-side or matrix given in
.matrix_to_return
if it is provided.
engine_eval(~ exp(y), y = pi) # ~ 23.14069 # It is not currently possible to assign values to a subset of # a matrix in a natural way (e.g. you cannot do things like x[1] = exp(y)), # but you can achieve this functionality using the assign function. engine_eval(~ assign(x, 1, 0, exp(y)) , x = rep(0, 2) , y = pi , .matrix_to_return = "x" )
engine_eval(~ exp(y), y = pi) # ~ 23.14069 # It is not currently possible to assign values to a subset of # a matrix in a natural way (e.g. you cannot do things like x[1] = exp(y)), # but you can achieve this functionality using the assign function. engine_eval(~ assign(x, 1, 0, exp(y)) , x = rep(0, 2) , y = pi , .matrix_to_return = "x" )
Functions currently supported by the C++ TMB engine for constructing expressions for defining model simulations.
The quickest way to experiment with these functions is
to use the engine_eval
function, as in the
following example that calculates a force of infection.
engine_eval(~ beta * I / N , beta = 0.25 , I = 1e3 , N = 1e7 )
To produce a simulation using these engine functions, one may
use simple_sims
.
simple_sims( iteration_exprs = list(x ~ x - 0.9 * x), time_steps = 5, mats = list(x = 1) )
Elementwise binary operators take two matrix-valued
arguments and apply a binary operator (e.g. +
, *
)
to each set of corresponding elements, and return the
corresponding matrix-valued output containing the
resulting elements. What does 'corresponding' mean? If
the two matrix-valued arguments have the same shape
(same number of rows and columns), then two elements
correspond if they occur in the same row and column
position in the two matrices. If the two matrices are
not of the same shape but there is one row and/or
one column in either matrix, then the singleton rows
and columns are recycled sufficiently many times
so that they match the shape of the other matrix. If
after recycling singleton rows and columns the
matrices are still of different shape, then an error
is thrown and the matrices are said to be incompatible.
x + y
x - y
x * y
x / y
x ^ y
x
– Any matrix with dimensions compatible with y
.
y
– Any matrix with dimensions compatible with x
.
A matrix with the binary operator applied elementwise after any necessary recycling of rows and/or columns.
engine_eval(~ 1 + 2) engine_eval(~ y * z, y = 1:3, z = matrix(1:6, 3, 2)) engine_eval(~ 1 / (1 - y), y = 1/4)
log(x)
– Natural logarithm
exp(x)
– Exponential function
cos(x)
– Cosine function
proportions(x, limit, eps)
– matrix of x / sum(x)
or rep(limit, length(x))
if sum(x) < eps
x
– Any matrix
limit
– numeric value to return elementwise from proportions
if sum(x) < eps
eps
– numeric tolerance for sum(x)
A matrix with the same dimensions as x
, with the
unary function applied elementwise.
engine_eval(~ log(y), y = c(2, 0.5))
from:to
– Inclusive and ordered sequence of
integers between two bounds.
seq(from, length, by)
– Ordered sequence of
integers with equal spacing between adjacent
values.
from
– Scalar integer giving the first integer
in the sequence.
to
– Scalar integer giving the last integer in
the sequence.
length
– Number of integers in the sequence.
by
– Scalar giving the difference
between adjacent values in the sequence.
Column vector with a sequence of integers.
The colon operator works much like the base R version
:
. It takes two scalar-valued integers
and returns a column vector with all integers between
the two inputs.
The seq
function is a little different from the
base R default, seq
, in that it
allows the user precise control over the length of
the output through the length
argument. The
base R function gives the user this option, but not
as the default.
engine_eval(~ 1:10) engine_eval(~ seq(1, 10, 2))
Replicate Elements
rep(x, times)
– Replicate a column vector a
number of times, by repeatedly stacking it on top of
itself.
x
– A scalar-valued variable to repeat.
times
– A scalar-valued integer variable giving
the number of times to repeat x
.
Column vector with times
copies of x
stacked
on top of each other.
engine_eval(~ rep(1, 10))
x %*% y
– Standard matrix multiplication.
x %x% y
– Kronecker product
x
– A matrix. For the standard product, x
must have as many columns as y
has rows.
y
– A matrix. For standard product, y
must have as many rows as x
has columns.
The matrix product of x
and y
.
engine_eval(~ (1:10) %*% t(1:10)) engine_eval(~ (1:10) %x% t(1:10))
The order of operations can be enforced in the usual
way with round parentheses, (
.
c(...)
– Stack columns of arguments into a
single column vector.
cbind(...)
– Create a matrix containing all of
the columns of a group of matrices with the same
number of rows.
rbind(...)
– Create a matrix containing all of
the rows of a group of matrices with the same number
of columns.
matrix(x, rows, cols)
– Reshape a matrix to have
rows
rows and cols
columns. The input x
must
have rows * cols
elements.
t(x)
– Standard matrix transpose.
...
– Any number of dimensionally consistent
matrices. The definition of dimensionally consistent
depends on the function.
x
– Can be any matrix for t
, but for matrix
it must have rows * cols
elements.
rows
– Scalar integer giving the number of
rows in the output.
cols
– Scalar integer giving the number of
columns in the output.
A combined or reshaped matrix.
Any number of column vectors can be combined into a bigger column vector.
Column and row vectors of the same length can be
combined using the cbind
and
rbind
functions respectively
The matrix
function can be used to redefine the
numbers of rows and columns to use for arranging
the values of a matrix. It works similarly to
the base R matrix
function in that it
takes the same arguments.
On the other hand, this function differs substantially
from the base R version in that it must be filled
by column and there is no byrow
option.
Matrices can be transposed with the usual
function, t
.
engine_eval(~ c(a, b, c), a = 1, b = 10:13, c = matrix(20:25, 3, 2)) engine_eval(~ cbind(a, 10 + a), a = 0:3) engine_eval(~ rbind(a, 10 + a), a = t(0:3)) engine_eval(~ matrix(1:12, 4, 3)) engine_eval(~ t(1:3))
to_diag(x)
– Create a diagonal matrix by setting
the diagonal to a column vector, x
.
from_diag(x)
– Extract the diagonal from a
matrix, x
, and return the diagonal as a column
vector.
x
– Any matrix (for from_diag
) or a
column vector (for to_diag
). It is common to assume
that x
is square for from_diag
but this is
not required.
to_diag(x)
– Diagonal matrix with x
on the
diagonal.
from_diag(x)
– Column vector containing the
diagonal of x
. A value is considered to be on
the diagonal if it has a row index equal to
the column index.
The to_diag
function can be used to produce a
diagonal matrix by setting a column vector equal
to the desired diagonal. The from_diag
does
(almost) the opposite, which is to get a column vector
containing the diagonal of an existing matrix.
engine_eval(~from_diag(matrix(1:9, 3, 3))) engine_eval(~to_diag(from_diag(matrix(1:9, 3, 3)))) engine_eval(~from_diag(to_diag(from_diag(matrix(1:9, 3, 3)))))
sum(...)
– Sum all of the elements of all of the
matrices passed to ...
.
col_sums(x)
– Row vector containing the sums
of each column.
row_sums(x)
– Column vector containing the sums
of each row.
group_sums(x, f, n)
– Column vector containing the
sums of groups of elements in x
. The groups are
determined by the integers in f
and the order of
the sums in the output is determined by these
integers.
mean(x)
– Arthmetic average of all elements in matrix
x
.
sd(x)
– Sample standard deviation of all elements in
matrix x
.
...
– Any number of matrices of any shape.
x
– A matrix of any dimensions, except for
group_sums
that expects x
to be a column vector.
f
– A column vector the same length as x
containing integers between 0
and m-1
, given m
unique groups. Elements of f
refer to the indices
of x
that will be grouped and summed.
n
– A column vector of length m
. If f
does
not contain group k
in [0, m-1]
, group_sums
skips
this group and the output at index k+1
is n[k+1]
.
A matrix containing sums of subsets of the inputs.
The row_sums
and col_sums
are similar to the base R
rowSums
and colSums
functions,
but with slightly different behaviour. In particular, the
row_sums
function returns a column vector and the
col_sums
function returns a row vector. If a specific shape
is required then the transpose t
function must
be explicitly used.
x = 1 y = 1:3 A = matrix(1:12, 4, 3) engine_eval(~ sum(y), y = y) engine_eval(~ sum(x, y, A), x = x, y = y, A = A) engine_eval(~ col_sums(A), A = A) engine_eval(~ row_sums(A), A = A) engine_eval(~ group_sums(x, f, n), x = 1:10, f = rep(0:3, 1:4), n = c(1:4))
x[i,j]
– Matrix containing a subset
of the rows and columns of x
.
block(x,i,j,n,m)
– Matrix containing a
contiguous subset of rows and columns of x
https://eigen.tuxfamily.org/dox/group__TutorialBlockOperations.html
x
– Any matrix.
i
– An integer column vector (for [
) or
integer scalar (for block
) containing the indices
of the rows to extract (for [
) or the index of the
first row to extract (for block
).
j
– An integer column vector (for [
) or
integer scalar (for block
) containing the indices
of the columns to extract (for [
) or the index of
the first column to extract (for block
).
n
– Number of rows in the block to return.
m
– Number of columns in the block to return.
A matrix containing a subset of the rows and columns
in x
.
Note that zero-based indexing is used
so the first row/column gets index, 0
, etc.
engine_eval(~ A[c(3, 1, 2), 2], A = matrix(1:12, 4, 3)) engine_eval(~ block(x,i,j,n,m), x = matrix(1:12, 4, 3), i=1, j=1, n=2, m=2)
For matrices with their simulation history saved, it is possible to bind the rows or columns of past versions of such matrices into a single matrix.
rbind_lag(x, lag, t_min)
– Bind the rows of versions of
x
that were recorded at the end of all
simulation iterations corresponding to time lags given
by integers in lag
.
rbind_time(x, t, t_min)
– Bind the rows of versions of
x
that were recorded at the end of all
simulation iterations corresponding to integers in
t
.
cbind_lag(x, lag, t_min)
– Bind the columns of versions of
x
that were recorded at the end of all
simulation iterations corresponding to time lags given
by integers in lag
. (TODO – cbind_lag is not developed yet)
cbind_time(x, t, t_min)
– Bind the columns of versions of
x
that were recorded at the end of all
simulation iterations corresponding to integers in
t
. (TODO – cbind_lag is not developed yet)
x
– Any matrix with saved history such that the
number of columns (for rbind_*
) or rows (for
cbind_*
) does not change throughout the simulation.
lag
– Integer vector giving numbers
of time steps before the current step to obtain
past values of x
.
t
– Integer vector giving time steps
at which to obtain past values of x
.
t_min
– Integer giving the minimum time step
that is allowed to be accessed. All time-steps in t
or implied by lag
that are before t_min
are ignored.
A matrix containing values of x
from past times.
Get or update the index of the current or lagged time step or the index of the current time group. A time group is a contiguous set of time steps defined by two change points.
time_step(lag)
: Get the time-step associated
with a particular lag from the current time-step.
If the lagged time-step is less than zero, the
function returns zero.
time_group(index, change_points)
: Update the
index
associated with the current time group.
The current group is defined by the minimum
of all elements of change_points
that are
greater than the current time step. The time group
index
is the index associated with this element.
Please see the examples below, they are easier
to understand than this explanation.
time_var(x, change_points)
: An improvement
to time_group
. Returns values in x
at time steps in change_points
, return value
remains constant between change_points
.
x
: Column vector representing a time series.
time_var
will return the value of x
corresponding
to element in change_points
that contains the
current time.
lag
: Number of time-steps to look back for
the time-step to return.
change_points
: Increasing column vector of
time steps giving the lower bound of each time
group.
A 1-by-1 matrix with the time-step lag
steps
ago, or with zero if t+1 < lag
simple_sims( iteration_exprs = list(x ~ time_step(0)), time_steps = 10, mats = list(x = empty_matrix) ) sims = simple_sims( iteration_exprs = list( j ~ time_group(j, change_points), time_varying_parameter ~ time_variation_schedule[j] ), mats = list( j = 0, change_points = c(0, 4, 7), time_variation_schedule = c(42, pi, sqrt(2)), time_varying_parameter = empty_matrix ), time_steps = 10, ) set.seed(1L) change_points = c(0,2,5) x_val = rnorm(length(change_points)) simple_sims( iteration_exprs = list(x ~ time_var(x_val,change_points)) , int_vecs = list(change_points = change_points) , mats = list(x = empty_matrix, x_val=x_val) , time_steps = 10 )
One may take the convolution of each element in a matrix, x, over simulation time using a kernel, k. There are two arguments of this function.
convolution(x, k)
x
– The matrix containing elements to be
convolved.
k
– A column vector giving the convolution kernel.
A matrix the same size as x
but with the
convolutions, , of each element,
, given by the following.
unless , in which case,
where is the convolution,
is the value of
at time step,
,
is the value of the kernel at lag,
,
and
is the length of the kernel.
If any empty matrices are encountered when looking
back in time, they are treated as matrices with all
zeros. Similarly, any matrices encounte
of x
Smoothly clamp the elements of a matrix so that they
do not get closer to 0 than a tolerance, eps
, with
a default of 1e-12. The output of the clamp
function is as follows.
clamp(x, eps)
x
: A matrix with elements that should remain positive.
eps
: A small positive number giving the
theoretical minimum of the elements in the returned
matrix.
All probability densities have the same first two arguments.
observed
simulated
The simulated
argument gives a matrix of means for
the observed
values at which the densities are
being evaluated. Additional arguments are other
distributional parameters such as the standard
deviation or dispersion parameter. All densities
are given as log-densities, so if you would like
the density itself you must pass the result through
the exp
function.
If the simulated
matrix or the additional parameter
matrices have either a single row or
single column, these singleton rows and columns are
repeated to match the number of rows and columns in
the observed
matrix. This feature allows one
to do things like specify a single common mean for
several values.
dpois(observed, simulated)
– Log of the Poisson density
based on this dpois
TMB function.
dnbinom(observed, simulated, over_dispersion)
–
Log of the negative binomial density based on this dnbinom
TMB function. To get the variance that this function
requires we use this expression, simulated + simulated^2/over_dispersion
,
following p.165 in this book
dnorm(observed, simulated, standard_deviation)
–
Log of the normal density based on this dnorm
TMB function.
observed
– Matrix of observed values
at which the density is being evaluated.
simulated
– Matrix of distributional means,
with singleton rows and columns recycled to match
the numbers of rows and columns in observed
.
over_dispersion
– Over-dispersion parameter
given by (simulated/standard_deviation)^2 - simulated)
.
standard_deviation
– Standard deviation parameter.
All random number generator functions have mean
as the first argument. Subsequent arguments give
additional distributional parameters.
Singleton rows and columns in the matrices passed to
the additional distributional parameters are recycled
so that all arguments have the same number of rows
and columns. All functions return a matrix the same
shape as mean
but with pseudo-random numbers
deviating from each mean in the mean
matrix.
rpois(mean)
– Pseudo-random Poisson distributed
values.
rnbinom(mean, over_dispersion)
– Pseudo-random
negative binomially distributed values.
rnorm(mean, standard_deviation)
– Pseudo-random
normal values.
mean
– Matrix of means about which to simulate
pseudo-random variation.
over_dispersion
– Matrix of over-dispersion parameters
given by (simulated/standard_deviation)^2 - simulated)
.
standard_deviation
– Matrix of standard deviation parameters.
Assign values to a subset of the elements in a matrix.
assign(x, i, j, v)
x
– Matrix with elements that are to be updated
by the values in v
.
i
– Column vector of row indices pointing to
the elements of x
to be updated. These indices are
paired with those in v
. If the length of
i
does not equal that of v
, then it must have a
single index that gets paired with every element of
v
. Indices are zero-based, i=0
corresponds to
the first row.
j
– Column vector of column indices pointing to
the elements of x
to be updated. These indices are
paired with those in v
. If the length of
j
does not equal that of v
, then it must have a
single index that gets paired with every element of
v
. Indices are zero-based, j=0
corresponds to
the first column.
v
– Column vector of values to replace elements
of x
at locations given by i
and j
.
The assign
function is not called for its return
value, which is an empty_matrix
, but
rather to modify x
but replacing some of its
components with those in v
.
x = matrix(1:12, 3, 4) engine_eval(~ x + 1, x = x) engine_eval(~ x + 1, x = x, .matrix_to_return = "x") engine_eval(~ assign(x, 2, 1, 100), x = x, .matrix_to_return = "x") engine_eval(~ assign(x , c(2, 1, 0) , 0 , c(100, 1000, 10000) ), x = x, .matrix_to_return = "x")
Unpack elements of a matrix into smaller matrices.
unpack(x, ...)
x
– Matrix with elements to be distributed to
the matrices passed through ...
.
...
– Matrices with elements to be replaced by
the values of elements in x
in column-major order.
These matrices must be named matrices and not
computed on the fly using expressions. Note that even
subsetting (e.g. unpack(x, y[0], y[3])
) counts as
an expression. This use-case would require the
assign
function
assign(y, c(0, 3), 0, x)
.
The unpack
function is not called for its return
value, which is an empty_matrix
, but
rather to modify the matrices in ...
by replacing
at least some of its components with those in x
.
Here we fill a matrix with integers from 1
to 12
and then unpack them one-at-a-time into two
column vectors, x
and y
. By returning y
we see the integers after the first three were
used up by x
.
engine_eval(~unpack(matrix(1:12, 3, 4), x, y) , x = rep(0, 3) , y = rep(1, 5) , .matrix_to_return = "y" )
Print out the value of a matrix.
print(x)
x
– Name of a matrix in the model.
An empty_matrix
.
simple_sims( list(dummy ~ print(x), x ~ x / 2) , time_steps = 10 , mats = list(x = 2) )
Finalizers
finalizer_char(x) finalizer_index(x)
finalizer_char(x) finalizer_index(x)
x |
Raw parsed expression. |
finalizer_char()
: Finalize parsed expression so that the parse table is
a little more human readable.
finalizer_index()
: Finalize parsed expression so that the parse table can
be passed to the C++ engine.
Find all paths through a compartmental model.
find_all_paths(edges_df, start_node_guesses = character(0L))
find_all_paths(edges_df, start_node_guesses = character(0L))
edges_df |
A data frame with a |
start_node_guesses |
Optional guesses for nodes that start paths. This is useful for models that are not directed acyclic graphs (DAGs). |
List of character vectors of state variable names, each vector describing a path through the model.
spec = mp_tmb_library("starter_models", "macpan_base", package = "macpan2") spec |> mp_flow_frame() |> find_all_paths()
spec = mp_tmb_library("starter_models", "macpan_base", package = "macpan2") spec |> mp_flow_frame() |> find_all_paths()
Distributional parameters can be added to the list of parameters that are fit
during calibration. By default, distributional parameters in priors and
likelihoods are not fit. Use mp_nofit
to exclude distributional parameters
from being fit and mp_fit
to fit them.
mp_fit(x, trans = DistrParamTransDefault()) mp_nofit(x, trans = DistrParamTransDefault())
mp_fit(x, trans = DistrParamTransDefault()) mp_nofit(x, trans = DistrParamTransDefault())
x |
numeric starting value of the distributional parameter to fit, or character name of an existing variable in the model with a default starting value to use. |
trans |
transformation to apply to the distributional parameter.
By default, distributional parameters inherit a default transformation from
the associated distribution. For example, the standard deviation parameter
|
A distributional parameter object.
# First we call the SIR model spec, and generate some data for calibration. spec = mp_tmb_library("starter_models", "sir", package = "macpan2") data = mp_simulator(spec, 50, "infection") |> mp_trajectory() # Suppose we want to specify a Normal prior on the transmission parameter # beta, and we are interested in estimating the prior standard deviation. # Here we use `mp_fit` to estimate the standard deviation, `sd`, and we # provide a numeric starting value for `sd` in the optimization. cal = mp_tmb_calibrator( spec , data , traj = "infection" , par = list(beta = mp_normal(location = 0.35, sd = mp_fit(0.1))) , default = list(beta = 0.25) ) # When viewing the calibration objective function we can see the additional # prior density term added for beta. The standard deviation parameter has # been automatically named 'distr_params_log_sd_beta'. cal$simulator$tmb_model$obj_fn$obj_fn_expr # Next we optimize and view the fitted parameters. We can see the # distributional parameter in the coefficient table with a default value # equal to the numeric value we provided to `mp_fit` above. mp_optimize(cal) mp_tmb_coef(cal) # If instead we want control over the name of the new fitted distributional # parameter, we can add a new variable to our model specification with the # default value set to the desired optimization starting value. updated_spec = spec |> mp_tmb_insert(default = list(sd_var = 0.1)) # In the calibrator, we use the name of this newly added variable, "sd_var", # as input to `mp_fit`. cal = mp_tmb_calibrator( updated_spec , data , traj = "infection" , par = list(beta = mp_normal(location = 0.35, sd = mp_fit("sd_var"))) , default = list(beta = 0.25) ) # We can see this distributional parameter get propogated to the objective # function and the fitted parameter table. cal$simulator$tmb_model$obj_fn$obj_fn_expr mp_optimize(cal) mp_tmb_coef(cal)
# First we call the SIR model spec, and generate some data for calibration. spec = mp_tmb_library("starter_models", "sir", package = "macpan2") data = mp_simulator(spec, 50, "infection") |> mp_trajectory() # Suppose we want to specify a Normal prior on the transmission parameter # beta, and we are interested in estimating the prior standard deviation. # Here we use `mp_fit` to estimate the standard deviation, `sd`, and we # provide a numeric starting value for `sd` in the optimization. cal = mp_tmb_calibrator( spec , data , traj = "infection" , par = list(beta = mp_normal(location = 0.35, sd = mp_fit(0.1))) , default = list(beta = 0.25) ) # When viewing the calibration objective function we can see the additional # prior density term added for beta. The standard deviation parameter has # been automatically named 'distr_params_log_sd_beta'. cal$simulator$tmb_model$obj_fn$obj_fn_expr # Next we optimize and view the fitted parameters. We can see the # distributional parameter in the coefficient table with a default value # equal to the numeric value we provided to `mp_fit` above. mp_optimize(cal) mp_tmb_coef(cal) # If instead we want control over the name of the new fitted distributional # parameter, we can add a new variable to our model specification with the # default value set to the desired optimization starting value. updated_spec = spec |> mp_tmb_insert(default = list(sd_var = 0.1)) # In the calibrator, we use the name of this newly added variable, "sd_var", # as input to `mp_fit`. cal = mp_tmb_calibrator( updated_spec , data , traj = "infection" , par = list(beta = mp_normal(location = 0.35, sd = mp_fit("sd_var"))) , default = list(beta = 0.25) ) # We can see this distributional parameter get propogated to the objective # function and the fitted parameter table. cal$simulator$tmb_model$obj_fn$obj_fn_expr mp_optimize(cal) mp_tmb_coef(cal)
Initial Valid Variables
initial_valid_vars(valid_var_names)
initial_valid_vars(valid_var_names)
valid_var_names |
Character vector of variable names. |
A ledger is a table with rows that identify specific instances of a
functional form used to define a mp_dynamic_model
. Ledgers
are most commonly created using the mp_join
function as in the
following example.
age = mp_index(Age = c("young", "old")) state = mp_cartesian( mp_index(Epi = c("S", "I", "R")), age ) mp_join( from = mp_subset(state, Epi = "S"), to = mp_subset(state, Epi = "I"), by = list(from.to = "Age") ) #> from to #> S.young I.young #> S.old I.old
Generate an Arithmetic Expression Parser
make_expr_parser(parser_name = NULL, finalizer = force)
make_expr_parser(parser_name = NULL, finalizer = force)
parser_name |
Name of the parsing function as a character string. No longer used, but still present for back-compatibility. |
finalizer |
Function used to post-process a parsed formula.
The default is the identity finalizer, which returns the parsed
formula itself. Other good choices are The result of this function is another function that takes a single
argument,
|
parser = make_expr_parser(finalizer = finalizer_char) foi = ~ beta * I / 100 valid_funcs = setNames( list(`*`, `/`), c("*", "/") ) valid_vars = list(beta = 0.1, I = 30) parser(foi)
parser = make_expr_parser(finalizer = finalizer_char) foi = ~ beta * I / 100 valid_funcs = setNames( list(`*`, `/`), c("*", "/") ) valid_vars = list(beta = 0.1, I = 30) parser(foi)
An experimental alternative to mp_per_capita_flow
that
allows users to specify flows using absolute rates instead of
per-capita rates.
mp_absolute_flow(from, to, rate, rate_name = NULL)
mp_absolute_flow(from, to, rate, rate_name = NULL)
from |
String giving the name of the compartment from which the flow originates. |
to |
String giving the name of the compartment to which the flow is going. |
rate |
String giving the expression for the absolute flow rate per time-step. |
rate_name |
String giving the name for the variable that
will store the |
Create a one-column ledger (see LedgerDefinition
) with rows
identifying instances of an aggregation.
mp_aggregate(index, by = "Group", ledger_column = "group")
mp_aggregate(index, by = "Group", ledger_column = "group")
index |
An index to aggregate over. |
by |
A column set label to group by. By default a dummy
and constant |
ledger_column |
Name of the column in the output ledger that describes the groups. |
Other functions that return ledgers
mp_join()
Produce a new index table by taking all possible pairwise combinations of the input tables. This is useful for producing product models that expand model components through stratification.
mp_cartesian(...)
mp_cartesian(...)
... |
Index tables (see |
Other functions that return index tables
mp_index()
,
mp_rename()
,
mp_subset()
,
mp_union()
Other functions that take products of index tables and return one index tables
mp_linear()
,
mp_square()
,
mp_symmetric()
,
mp_triangle()
mp_cartesian( mp_index(Epi = c("S", "I")), mp_index(Age = c("young", "old")) ) si = mp_index(Epi = c("S", "I")) age = mp_index(Age = c("young", "old")) loc = mp_index(City = c("hamilton", "toronto")) vax = mp_index(Vax = c("unvax", "vax")) (si |> mp_cartesian(age) |> mp_cartesian(loc) |> mp_cartesian(vax) ) flow_rates = mp_index(Epi = c("infection", "recovery")) mp_union( mp_cartesian( mp_subset(flow_rates, Epi = "infection"), age ), mp_subset(flow_rates, Epi = "recovery") )
mp_cartesian( mp_index(Epi = c("S", "I")), mp_index(Age = c("young", "old")) ) si = mp_index(Epi = c("S", "I")) age = mp_index(Age = c("young", "old")) loc = mp_index(City = c("hamilton", "toronto")) vax = mp_index(Vax = c("unvax", "vax")) (si |> mp_cartesian(age) |> mp_cartesian(loc) |> mp_cartesian(vax) ) flow_rates = mp_index(Epi = c("infection", "recovery")) mp_union( mp_cartesian( mp_subset(flow_rates, Epi = "infection"), age ), mp_subset(flow_rates, Epi = "recovery") )
Get a data frame with one row for each change made to each state variable at each time step.
mp_change_frame(spec)
mp_change_frame(spec)
spec |
Model specification ( |
Data frame with two columns: state
and change
. Each row
describes one change.
("starter_models" |> mp_tmb_library("sir", package = "macpan2") |> mp_change_frame() )
("starter_models" |> mp_tmb_library("sir", package = "macpan2") |> mp_change_frame() )
Default Values
mp_default(model, include_all = FALSE) mp_default_list(model, include_all = FALSE)
mp_default(model, include_all = FALSE) mp_default_list(model, include_all = FALSE)
model |
A model object from which to extract default values. If
|
include_all |
Include all default variables, even those that are not
used in the |
A long-format data frame with default values for matrices required
as input to model objects. The columns of this output are matrix
, row
,
col
, and value
. Scalar matrices do not have any entries in the row
or
col
columns.
mp_default_list()
: List of the default variables as matrices.
This is an 'old' model specification function that was tested out
at a workshop. Currently it still drives the engine-agnostic-grammar
vignette, but we plan to replace this function with
mp_tmb_model_spec
and other model specification
functions.
mp_dynamic_model( expr_list = ExprList(), ledgers = list(), init_vecs = list(), unstruc_mats = list() )
mp_dynamic_model( expr_list = ExprList(), ledgers = list(), init_vecs = list(), unstruc_mats = list() )
expr_list |
Expression list. |
ledgers |
Ledgers. |
init_vecs |
Initial structured vectors. |
unstruc_mats |
Initial unstructured matrices. |
This is an 'old' function that was tested out at a workshop.
Currently it still drives the engine-agnostic-grammar vignette,
but we plan to replace this function with mp_simulator
.
mp_dynamic_simulator( dynamic_model, time_steps = 0L, vectors = NULL, unstruc_mats = NULL, mats_to_save = NULL, mats_to_return = NULL, params = OptParamsList(0), random = OptParamsList(), obj_fn = ObjectiveFunction(~0), log_file = LogFile(), do_pred_sdreport = TRUE, tmb_cpp = "macpan2", initialize_ad_fun = TRUE, ... )
mp_dynamic_simulator( dynamic_model, time_steps = 0L, vectors = NULL, unstruc_mats = NULL, mats_to_save = NULL, mats_to_return = NULL, params = OptParamsList(0), random = OptParamsList(), obj_fn = ObjectiveFunction(~0), log_file = LogFile(), do_pred_sdreport = TRUE, tmb_cpp = "macpan2", initialize_ad_fun = TRUE, ... )
dynamic_model |
Object product by |
time_steps |
Number of time steps to simulate. |
vectors |
Named list of named vectors as initial values for the simulations that are referenced in the expression list in the dynamic model. |
unstruc_mats |
= Named list of objects that can be coerced to numerical matrices that are used in the expression list of the dynamic model. |
mats_to_save |
TODO |
mats_to_return |
TODO |
params |
TODO |
random |
TODO |
obj_fn |
TODO |
log_file |
TODO |
do_pred_sdreport |
TODO |
tmb_cpp |
TODO |
initialize_ad_fun |
TODO |
... |
TODO |
Additional information that can be joined to the output of
the tidy.TMB
or tidy.stanfit
functions in the broom.mixed
package.
mp_effects_descr(model) mp_add_effects_descr(coef_table, model)
mp_effects_descr(model) mp_add_effects_descr(coef_table, model)
model |
A model in the TMB engine that can be used to compute tables of statistical effects. |
coef_table |
Coefficient table that was probably generated using
|
mp_add_effects_descr()
: Convenience function for adding coefficient
descriptions from a calibrated model to coef_table
s generated by
mp_tmb_coef
or mp_tmbstan_coef
.
Expand a structured model so that it is represented in an unstructured
format requiring a more verbose description. Currently,
this is only applicable for mp_tmb_model_spec
objects
that have explicit flows
(e.g. mp_per_capita_flow
). For such models, mp_expand
produces a model with expression lists composed entirely of plain R
formulas.
mp_expand(model) mp_reduce(model)
mp_expand(model) mp_reduce(model)
model |
A model object. |
mp_reduce()
: Confusingly, mp_reduce
and mp_expand
are synonyms.
Please use mp_expand
in new projects, as mp_reduce
is available for
back-compatibility only.
sir = mp_tmb_library("starter_models", "sir", package = "macpan2") print(sir) print(mp_expand(sir))
sir = mp_tmb_library("starter_models", "sir", package = "macpan2") print(sir) print(mp_expand(sir))
Extract the index for a particular dimension in a ledger from a ledger or from an object containing one or more ledgers.
mp_extract(x, dimension_name)
mp_extract(x, dimension_name)
x |
Object |
dimension_name |
Name of a dimension used in a ledger. |
Factor an Index
mp_factors(index, unpack = c("no", "maybe", "yes"))
mp_factors(index, unpack = c("no", "maybe", "yes"))
index |
An index to be factored. |
unpack |
Place factors in the global environment? |
Return the values of variables after the simulation loop has finished
and the final
set of expressions have been evaluated.
mp_final(model) mp_final_list(model)
mp_final(model) mp_final_list(model)
model |
Object that can be used to simulate. |
mp_final_list()
: Final values formatted as a list of matrices.
Get a data frame where each row represents a flow in a model specification.
mp_flow_frame(spec, topological_sort = TRUE, loops = "^$")
mp_flow_frame(spec, topological_sort = TRUE, loops = "^$")
spec |
|
topological_sort |
Should the states be topologically sorted to respect the main direction of flow? |
loops |
Pattern for matching the names of flows that make
the flow model not a DAG, which is a critical assumption when topologically
sorting the order of states and flows in the output. This is only relevant if
|
A data frame that gives information provided in calls to
mp_per_capita_flow
and mp_per_capita_inflow
.
A forecaster is an object that can make forecasts. It is constructed from
mp_tmb_calibrator
, which is an object that can be used to
calibrate the parameters of a model – typically by fitting the model to
data. The main difference between a calibrator and a forecaster is that
the latter runs for more time steps, past the last time step of the
calibrator. A forecaster object can be used to generate different types of
forecasts using the mp_trajectory
family of functions.
mp_forecaster( calibrator, forecast_period_time_steps, outputs = NULL, data = NULL, tv = NULL, default = list() )
mp_forecaster( calibrator, forecast_period_time_steps, outputs = NULL, data = NULL, tv = NULL, default = list() )
calibrator |
Object made using |
forecast_period_time_steps |
The number of time steps to project beyond the period with data. |
outputs |
An optional character vector of variables in the model
to forecast. If this argument is omited, then the forecaster will inherit
the outputs of the |
data |
An optional data frame containing the data that were fitted to.
Typically this argument will be unused, because by default the data are
stored in the |
tv |
An optional replacement for the |
default |
An optional list of default model variables (e.g., parameters initial values of state variables) to override calibrated values. |
Functions Used by an Object for Communicating with a Computational Engine
mp_functions_used(object) mp_generates_randomness(object)
mp_functions_used(object) mp_generates_randomness(object)
object |
An object for communicating with a computational engine. |
Character vector of names of functions that are used by object
.
mp_generates_randomness()
: Does the object use functions that generate
randomness?
Create a new index with fewer columns to create names for an aggregated vector that is labelled by the input index.
mp_group(index, by)
mp_group(index, by)
index |
Index to group rows. |
by |
Column set label to group by. |
Make an index table to enumerate model quantity labels by category. These
objects generalize and wrap data.frame
s, where each column is a
label category and each row is an index. Indices must contain
only letters, numbers, and underscores. Blank empty string entries are
allowed, but missing values (NA
s) are not.
mp_index(..., labelling_column_names) ## S3 method for class 'Index' print(x, ...) ## S3 method for class 'Index' names(x) ## S3 method for class 'Index' labelling_column_names(x) ## S3 method for class 'Index' labels(object, ...)
mp_index(..., labelling_column_names) ## S3 method for class 'Index' print(x, ...) ## S3 method for class 'Index' names(x) ## S3 method for class 'Index' labelling_column_names(x) ## S3 method for class 'Index' labels(object, ...)
... |
Character vectors to combine to produce an index. Alternatively, any number of data frames of character-valued columns. If data frames are supplied, their rows will be bound and the result converted to an index if possible. |
labelling_column_names |
A |
x |
An index. |
object |
An index. |
For example, the following index table describes the state variables of the model:
sir = mp_index(Epi = c("S", "I", "R")) print(sir) #> Epi #> S #> I #> R
Here, the column Epi
denotes that the category of these labels is
epidemiological. There is nothing special about this specific choice of
category name; we could have also used another name like Compartment
.
However, in more complicated models, it is good to think carefully about
choosing descriptive category names. For example, in an age-structured SIR
model, we could add an Age
column to generate an index table as follows:
sir_age = mp_index( Epi = rep(c("S", "I", "R"), 2), Age = rep(c("young", "old"), each = 3) ) print(sir_age) #> Epi Age #> S young #> I young #> R young #> S old #> I old #> R old
Here, having the first column in the index table labeled Compartment
would
be somewhat misleading, as the compartments aren't actually just "S", "I",
and "R", they are each of the epidemiological states stratified by the age
groups "young" and "old".
This index table could also be generated by first specifying individual index
tables for the Epi
and Age
columns, and then using a macpan2
product
function that combines the tables into a single index table:
sir = mp_index(Epi = c("S", "I", "R")) age = mp_index(Age = c("young", "old")) prod = mp_cartesian(sir, age) prod #> Epi Age #> S young #> I young #> R young #> S old #> I old #> R old
The mp_cartesian()
function will produce a table with entries that are all
possible combinations of the individual index tables. The "See Also" section
of the mp_cartesian()
help page catalogues all available product functions.
We can produce the full labels of model quantities, which are simply
dot-concatenated indices, one for each entry in the index table, using the
labels()
function:
#> [1] "S.young" "I.young" "R.young" "S.old" "I.old" "R.old"
Dots are not allowed in indices so that the labels can be inverted to reproduce the original index table (provided that the column names can be retrieved).
It is recommended to use UpperCamelCase for the columns of index tables and single uppercase characters ("S", "I"), all lowercase character strings ("gamma"), and/or snake_case strings ("aging_rate") for indices. This convention helps when reading code that contains references to both column names and indices.
print(Index)
: Print an index.
names(Index)
: Get the names of the columns of an index.
labelling_column_names(Index)
: Retrieve the labelling_column_names
of
an index. These are the names of the columns that are used to label
the model components.
labels(Index)
: Convert an index into
a character vector giving labels associated with each model component
(i.e. row) being described.
Other functions that return index tables
mp_cartesian()
,
mp_rename()
,
mp_subset()
,
mp_union()
state = mp_index( Epi = c("S", "I", "S", "I"), Age = c("young", "young", "old", "old") ) print(state) labels(state) mp_cartesian(state, mp_index(City = c("hamilton", "toronto")))
state = mp_index( Epi = c("S", "I", "S", "I"), Age = c("young", "young", "old", "old") ) print(state) labels(state) mp_cartesian(state, mp_index(City = c("hamilton", "toronto")))
Return a data frame containing the values of variables at the end of the
before
phase, right before the simulation loop begins (i.e. right before
the during
phase).
mp_initial(model) mp_initial_list(model)
mp_initial(model) mp_initial_list(model)
model |
A model specification object or model simulator object from which to extract initial values. |
A long-format data frame with initial values for matrices.
The columns of this output are matrix
, time
, row
, col
, and value
.
Scalar matrices do not have any entries in the row
or col
columns. The
before
phase corresponds to a time
value of 0.
mp_initial_list()
: List of the initial variables as matrices.
Join two or more index tables (see mp_index
) to produce a
ledger (see LedgerDefinition
).
mp_join(..., by = empty_named_list())
mp_join(..., by = empty_named_list())
... |
Named arguments giving indexes created by
|
by |
What columns to use to join the indexes. See below on how to specify this argument. |
When two index tables are passed to ...
, mp_join
behaves very much like
an ordinary inner join.
When more than two tables are passed to ...
, mp_join
iteratively joins
pairs of tables to produce a final ledger. For example, if index tables A
B
, and C
are passed to mp_join
, an inner join of A
and B
is
performed and the result is joined with C
. In each of these successive
internal joins. The properties of inner
joins ensures that the order of tables does not affect the set of rows in
the final table (SW states without proof!).
When two index tables are passed to ...
, the by
argument is just a
character vector of column names on which to join (as in standard R functions
for joining data frames), or the dot-concatenation of these column names.
For example,
state = mp_index( Epi = c("S", "I", "S", "I"), Age = c("young", "young", "old", "old") ) mp_join( from = mp_subset(state, Epi = "S"), to = mp_subset(state, Epi = "I"), by = "Age" ) #> from to #> S.young I.young #> S.old I.old
If there are more than two tables then the by
argument must be a named
list of character vectors, each describing how to join the columns of
a pair of tables in ...
. The names of this list are dot-concatenations
of the names of pairs of tables in ...
. For example,
rates = mp_index( Epi = c("lambda", "lambda"), Age = c("young", "old") ) mp_join( from = mp_subset(state, Epi = "S"), to = mp_subset(state, Epi = "I"), rate = mp_subset(rates, Epi = "lambda"), by = list( from.to = "Age", from.rate = "Age" ) ) #> from to rate #> S.young I.young lambda.young #> S.old I.old lambda.old
If the by
columns have different names in two tables, then you can
specify these using formula notation where the left-hand-side
is a dot-concatenation of columns in the first table and the
right-hand-side is a dot-concatenation of the columns in the second
table. For example,
contact = mp_index( AgeSusceptible = c("young", "young", "old", "old"), AgeInfectious = c("young", "old", "young", "old") ) mp_join( sus = mp_subset(state, Epi = "S"), inf = mp_subset(state, Epi = "I"), con = contact, by = list( sus.con = "Age" ~ "AgeSusceptible", inf.con = "Age" ~ "AgeInfectious" ) ) #> sus inf con #> S.young I.young young.young #> S.old I.young old.young #> S.young I.old young.old #> S.old I.old old.old
Other functions that return ledgers
mp_aggregate()
Return a character vector of labels for each row of an index (or a ledger?? FIXME: what does this mean for ledgers??).
mp_labels(x, labelling_column_names)
mp_labels(x, labelling_column_names)
x |
Object |
labelling_column_names |
What index columns should be used for generating the labels. If missing then defaults will be used. (FIXME: clarify how the defaults are used.) |
Create a grid on which to layout the flow diagram of a model specification.
mp_layout_grid( spec, east = "", south = "^$", north = "^$", west = "^$", loops = north, x_gap = 0.3, y_gap = 0.3, north_south_sep = 0, east_west_sep = 0, trim_states = character() )
mp_layout_grid( spec, east = "", south = "^$", north = "^$", west = "^$", loops = north, x_gap = 0.3, y_gap = 0.3, north_south_sep = 0, east_west_sep = 0, trim_states = character() )
spec |
A model specification made with |
east |
Regular expression for matching the names of flows that will be connected eastward in the layout. |
south |
Regular expression for matching the names of flows that will be connected southward in the layout. |
north |
Regular expression for matching the names of flows that will be connected northward in the layout. |
west |
Regular expression for matching the names of flows that will be connected westward in the layout. |
loops |
Regular expression for matching the names of flows that cause loops in the flow model, and so should be ignored when building the layout. |
x_gap |
Size of the gap to the left and right of the 1-by-1 space provided for a node. |
y_gap |
Size of the gap above and below the 1-by-1 space provided for a node. |
north_south_sep |
Horizontal separation between north and south flow arrows. |
east_west_sep |
Vertical separation between east and west flow arrows. |
trim_states |
List of states to remove from the diagram |
Layout the flow diagram of a model specification so that each row is one of the paths through the model (ignoring loops).
mp_layout_paths( spec, sort_paths = TRUE, combine_columns = TRUE, deduplicate_edges = TRUE, loops = "^$", ignore = "^$", x_gap = 0.3, y_gap = 0.3, north_south_sep = 0, east_west_sep = 0, trim_states = character() )
mp_layout_paths( spec, sort_paths = TRUE, combine_columns = TRUE, deduplicate_edges = TRUE, loops = "^$", ignore = "^$", x_gap = 0.3, y_gap = 0.3, north_south_sep = 0, east_west_sep = 0, trim_states = character() )
spec |
A model specification made with |
sort_paths |
Should the paths/rows be sorted to minimize the number times an edge must go through a node that it is not connected with? |
combine_columns |
Should each state/node get its own column in the
layout ( |
deduplicate_edges |
Should each row have all of the edges in the path or should duplicate edges be removed? |
loops |
Regular expression for matching the names of flows that cause loops in the flow model, and so should be ignored when building the layout. |
ignore |
Regular expression for matching the names of flows that should be removed from the layout analysis entirely. These will be isolated in a data frame for custom drawing of 'difficult' edges. |
x_gap |
Size of the gap to the left and right of the 1-by-1 space provided for a node. |
y_gap |
Size of the gap above and below the 1-by-1 space provided for a node. |
north_south_sep |
Horizontal separation between north and south flow arrows. |
east_west_sep |
Vertical separation between east and west flow arrows. |
trim_states |
List of states to remove from the diagram |
Bundle up several ledgers (see LedgerDefinition
) to pass
to mp_dynamic_model
.
mp_ledgers(...)
mp_ledgers(...)
... |
Ledgers to bundle up. |
TODO: what does this mean?
mp_linear(x, y_labelling_column_names)
mp_linear(x, y_labelling_column_names)
x |
An index. |
y_labelling_column_names |
TODO |
Other functions that take products of index tables and return one index tables
mp_cartesian()
,
mp_square()
,
mp_symmetric()
,
mp_triangle()
Lookup a subset or factor index associated with a symbol, and return the index associated with that symbol.
mp_lookup(index, symbol)
mp_lookup(index, symbol)
index |
Index table (see |
symbol |
Character string that could possibly be associated with a
subset or factor of |
Open a browser at the current version of a particular model in an
online macpan2
model library.
mp_model_docs(model_name, macpan_library = "starter_models")
mp_model_docs(model_name, macpan_library = "starter_models")
model_name |
Name of a model in the |
macpan_library |
Name of a library. Currently, the default value of
|
This function returns the URL of the library model, but the main purpose is the side-effect of automatically opening a web browser at this URL.
Create a directory with a template model definition.
mp_model_starter(starter_name, dir)
mp_model_starter(starter_name, dir)
starter_name |
Currently can only be |
dir |
String giving the path to a directory for copying the template model definition. |
Calibrate a model that has been parameterized, typically by using
mp_tmb_calibrator
to produce such a model.
mp_optimize(model, optimizer, ...) ## S3 method for class 'TMBCalibrator' mp_optimize( model, optimizer = c("nlminb", "optim", "DEoptim", "optimize", "optimise"), ... )
mp_optimize(model, optimizer, ...) ## S3 method for class 'TMBCalibrator' mp_optimize( model, optimizer = c("nlminb", "optim", "DEoptim", "optimize", "optimise"), ... )
model |
A model object capable of being optimized. Typically
this object will be produced using |
optimizer |
Name of an implemented optimizer. See below for the options and details on using each option. |
... |
Arguments to pass to the |
The mp_tmb_calibrator
models that get passed to
mp_optimize
will remember both their original default parameters
set at the time the model was created, and their currently best
parameters that get the updated when mp_optimize
is run. The
optimization is started from the currently best parameter set.
Therefore, if you find yourself in a local minimum you might need
to either recreate the model using mp_tmb_calibrator
or use optimizer = "DEoptim"
, which is more robust to objective
functions with multiple optima.
The output of the optimizer
. The model
object is modified
and saves the history of optimization outputs. These outputs can be
obtained using mp_optimizer_output
.
mp_optimize(TMBCalibrator)
: Optimize a TMB calibrator.
nlminb
The default optimizer is nlminb
. This optimizer uses
gradients computed by the
Template Model Builder
engine of macpan2
. This optimizer is efficient at local optimization
by exploiting the gradient information computed by automatic differentiation.
However, like many nonlinear optimizers, it can struggle if the objective function has multiple optima.
To set control parameters (e.g., maximum number of iterations), you
can use the control
argument:
mp_optimize(model, "nlminb", control = list(iter.max = 800))
See the nlminb
help page for the complete list of
control parameters and what the output means.
optim
The optim
optimizer lets you choose from a variety
of optimization algorithms. The default, method = "Nelder-Mead"
,
does not use second derivatives
(compare with the description of nlminb
), and so
could be less efficient at taking each step. However, we
find that it can be somewhat better at getting out of local optima,
although the "DEoptim"
optimizer is designed for objective functions
with multiple optima (see description below).
To set control parameters (e.g., maximum number of iterations), one may use the following.
mp_optimize(model, "nlminb", control = list(maxit = 800))
See the optim
help page for the complete list of
control parameters and what the output means.
If your model is parameterized by only a single parameter, you'll get a warning asking you to use 'method = "Brent"' or optimizer = 'optimize()'. You can ignore this warning if you are happy with your answer, or can do either of the suggested options as follows.
mp_optimize(model, "optim", method = "Brent", lower = 0, upper = 1.2) mp_optimize(model, "optimize", interval = c(0, 1.2))
In this case you have to specify lower and upper bounds for the optimization.
DEoptim
The DEoptim
optimizer comes from the DEoptim
package;
you'll need to have that package installed to use this option.
It is designed for objective functions with multiple optima. Use
this method if you do not believe the fit you get by other methods.
The downsides of this method are that it doesn't use gradient
information and evaluates the objective function at many different
points, so is likely to be much slower than gradient-based optimizers
such as the default nlminb
optimizer, or optim
with method = "BFGS"
.
Because this optimizer starts from multiple points in the parameter space, you need to specify lower and upper bounds for each parameter in the parameter vector.
mp_optimize(model, "DEoptim", lower = c(0, 0), upper = c(1.2, 1.2))
In this example we have two parameters, and therefore need
to specify two values each for lower
and upper
optimize
and optimise
This optimizer can only be used for models parameterized with a single parameter. You need to specify lower and upper bounds, e.g.
mp_optimize(model, "optimize", c(0, 1.2))
spec = ("starter_models" |> mp_tmb_library("seir", package = "macpan2") |> mp_tmb_update(default = list(beta = 0.6)) ) sim = mp_simulator(spec, 50, "infection") ## simulate data to fit to, but remove the start of the ## simulated epidemic in order to make it more difficult ## to fit. data = mp_trajectory(sim) data = data[data$time > 24, ] data$time = data$time - 24 ## time scale object that accounts for the true starting time ## of the epidemic (in this example we are not trying to estimate ## the initial number infected, so the starting time strongly ## affects the fitting procedure) time = mp_sim_offset(24, 0, "steps") ## model calibrator, estimating only the transmission parameter cal = mp_tmb_calibrator(spec , data = data , traj = "infection" , par = "beta" , default = list(beta = 1) , time = time ) ## From the starting point at beta = 1 this takes us into a ## local optimum at beta = 0.13, far from the true value of beta = 0.6. mp_optimize(cal) ## In this case, one-dimensional optimization finds the true value. mp_optimize(cal, "optimize", c(0, 1.2))
spec = ("starter_models" |> mp_tmb_library("seir", package = "macpan2") |> mp_tmb_update(default = list(beta = 0.6)) ) sim = mp_simulator(spec, 50, "infection") ## simulate data to fit to, but remove the start of the ## simulated epidemic in order to make it more difficult ## to fit. data = mp_trajectory(sim) data = data[data$time > 24, ] data$time = data$time - 24 ## time scale object that accounts for the true starting time ## of the epidemic (in this example we are not trying to estimate ## the initial number infected, so the starting time strongly ## affects the fitting procedure) time = mp_sim_offset(24, 0, "steps") ## model calibrator, estimating only the transmission parameter cal = mp_tmb_calibrator(spec , data = data , traj = "infection" , par = "beta" , default = list(beta = 1) , time = time ) ## From the starting point at beta = 1 this takes us into a ## local optimum at beta = 0.13, far from the true value of beta = 0.6. mp_optimize(cal) ## In this case, one-dimensional optimization finds the true value. mp_optimize(cal, "optimize", c(0, 1.2))
Create a new model specification using parameter values that have been optimized.
mp_optimized_spec(model, spec_structure = c("original", "modified"))
mp_optimized_spec(model, spec_structure = c("original", "modified"))
model |
A model object that can be optimized/calibrated. Currently,
only models produced by |
spec_structure |
A character string identifying the structure of the
returned model specification. Use |
The following is a list of additional model specification structure that was
or could have been added to the "modified"
specification by
mp_tmb_calibrator
for the purposes of fitting to data.
Observed data in a format that can be compared with simulated data.
Expressions preparing simulated data so that they can be compared with the observed data.
Distributional parameters for likelihood and prior components of the objective function (e.g., a dispersion parameter for a negatively binomial likelihood component, or a prior standard deviation for a transmission rate parameter).
Data, parameters, and expressions for modelling time-variation of parameters (e.g., basis functions and weights for a spline determining the time-variation of transmission rate).
A copy of the model specification used to produce the calibrator model, with calibrated default values.
Get the output from an optimizer used in model calibration.
mp_optimizer_output(model, what = c("latest", "all"))
mp_optimizer_output(model, what = c("latest", "all"))
model |
An object that has been optimized. |
what |
A string indicating whether to return the results of the
|
When objects created by mp_tmb_calibrator
are successfully
passed to mp_optimize
, they build up an
optimization history. This history is recorded as a list of the output
produced by the underlying optimizer (e.g. nlminb
). This
mp_optimizer_output
function returns the latest output by default
or the entire history list.
Define the prior distributions for parameters and random effects to be
passed to par
argument of the mp_tmb_calibrator
function.
mp_par(params, random)
mp_par(params, random)
params |
Named list of distributional specifications for the fixed effects. |
random |
Named list of distributional specifications for the random effects. |
Description of Model Parameterization
mp_parameterization(model, types = c("fixed", "random"))
mp_parameterization(model, types = c("fixed", "random"))
model |
Parameterized model, probably produced using
|
types |
Vector indicating what kinds of parameters should be
included, |
Specify different kinds of flows between compartments.
mp_per_capita_flow(from, to, rate, abs_rate = NULL) mp_per_capita_inflow(from, to, rate, abs_rate = NULL) mp_per_capita_outflow(from, rate, abs_rate = NULL)
mp_per_capita_flow(from, to, rate, abs_rate = NULL) mp_per_capita_inflow(from, to, rate, abs_rate = NULL) mp_per_capita_outflow(from, rate, abs_rate = NULL)
from |
String giving the name of the compartment from which the flow originates. |
to |
String giving the name of the compartment to which the flow is going. |
rate |
String giving the expression for the per-capita
flow rate. Alternatively, and for back compatibility,
a two-sided formula with the left-hand-side giving the name of the absolute
flow rate per time-step and the right-hand-side giving an expression for
the per-capita rate of flow from |
abs_rate |
String giving the name for the absolute flow rate per
time-step. By default, during simulations, the absolute flow rate will be
computed as |
The examples below can be mixed and matched in mp_tmb_model_spec()
to produce compartmental models. The symbols used below must
be used in an appropriate context (e.g., if N
is used for total population
size, then there must be an expression like N ~ S + I + R
somewhere in
the model or for models with constant population size there must be a
default variable, N
, with a numerical value).
mp_per_capita_inflow()
: Only flow into the to
compartment, and
do not flow out of the from
compartment. The from
compartment can even
be a function of a set of compartments, because it will not be updated. A
common construction is mp_per_capita_inflow("N", "S", "birth_rate", "birth")
for adding a birth process, which involves the total population size, N
,
rather than a single compartment.
mp_per_capita_outflow()
: Only flow out of the from
compartment,
without going anywhere. This is useful for removing individuals from the
system (e.g., death). To keep track of the total number of dead individuals
one can use mp_per_capita_flow
and set to
to be a compartment for
these individuals (e.g., to = "D"
).
# infection by mass action # https://github.com/canmod/macpan2/blob/main/inst/starter_models/si mp_per_capita_flow("S", "I", "beta * I / N", "infection") # recovery # https://github.com/canmod/macpan2/blob/main/inst/starter_models/sir mp_per_capita_flow("I", "R", "gamma", "recovery") # disease progression with different severity # https://github.com/canmod/macpan2/blob/main/inst/starter_models/macpan_base mp_per_capita_flow("E", "I_mild", "alpha * phi" , "progression_mild") mp_per_capita_flow("E", "I_sev" , "alpha * (1 - phi)", "progression_sev") # birth # https://github.com/canmod/macpan2/blob/main/inst/starter_models/sir_demog mp_per_capita_inflow("N", "S", "nu", "birth") # death # https://github.com/canmod/macpan2/blob/main/inst/starter_models/sir_demog mp_per_capita_outflow("S", "mu", "death_S") mp_per_capita_outflow("I", "mu", "death_I") mp_per_capita_outflow("R", "mu", "death_R") # vaccination # https://github.com/canmod/macpan2/blob/main/inst/starter_models/shiver mp_per_capita_flow("S", "V", "((a * S)/(b + S))/S", "vaccination") # importation (experimental) # mp_absolute_inflow("I", "delta", "importation")
# infection by mass action # https://github.com/canmod/macpan2/blob/main/inst/starter_models/si mp_per_capita_flow("S", "I", "beta * I / N", "infection") # recovery # https://github.com/canmod/macpan2/blob/main/inst/starter_models/sir mp_per_capita_flow("I", "R", "gamma", "recovery") # disease progression with different severity # https://github.com/canmod/macpan2/blob/main/inst/starter_models/macpan_base mp_per_capita_flow("E", "I_mild", "alpha * phi" , "progression_mild") mp_per_capita_flow("E", "I_sev" , "alpha * (1 - phi)", "progression_sev") # birth # https://github.com/canmod/macpan2/blob/main/inst/starter_models/sir_demog mp_per_capita_inflow("N", "S", "nu", "birth") # death # https://github.com/canmod/macpan2/blob/main/inst/starter_models/sir_demog mp_per_capita_outflow("S", "mu", "death_S") mp_per_capita_outflow("I", "mu", "death_I") mp_per_capita_outflow("R", "mu", "death_R") # vaccination # https://github.com/canmod/macpan2/blob/main/inst/starter_models/shiver mp_per_capita_flow("S", "V", "((a * S)/(b + S))/S", "vaccination") # importation (experimental) # mp_absolute_inflow("I", "delta", "importation")
Return an integer vector of positions of x
in
table
. Currently this is a simple wrapper around
match
.
mp_positions(x, table, zero_based = TRUE)
mp_positions(x, table, zero_based = TRUE)
x |
Character vector |
table |
Character vector |
zero_based |
Use zero-based indexing? Defaults to |
Print Model Specification
mp_print_spec(model) mp_print_before(model) mp_print_during(model) mp_print_after(model)
mp_print_spec(model) mp_print_before(model) mp_print_during(model) mp_print_after(model)
model |
A model produced by |
mp_print_before()
: Print just the expressions executed before the
simulation loop.
mp_print_during()
: Print just the expressions executed during each
iteration of the simulation loop.
mp_print_after()
: Print just the expressions executed after the
simulation loop.
Pass the output of this function to the tv
argument of
mp_tmb_calibrator
to model time variation of
a parameter with flexible radial basis functions.
mp_rbf( tv, dimension, initial_weights, seed, prior_sd = 1, fit_prior_sd = TRUE, sparse_tol = 0.01 )
mp_rbf( tv, dimension, initial_weights, seed, prior_sd = 1, fit_prior_sd = TRUE, sparse_tol = 0.01 )
tv |
String giving the name of the parameter. |
dimension |
Number of bases. |
initial_weights |
Optional vector with |
seed |
Optional random seed to use to generate the |
prior_sd |
Prior standard deviation default value for radial basis function coefficients, defaults to 1. |
fit_prior_sd |
Should the prior sd be be fitted. |
sparse_tol |
Tolerance below which radial basis function outputs are set exactly to zero. Small values are more accurate but slower. Lack of accuracy can be visually apparent as jumps in graphs of the time-varying parameter. |
Extract the index used as a reference for generating position vectors.
mp_reference(x, dimension_name)
mp_reference(x, dimension_name)
x |
Object |
dimension_name |
Name of a dimension used in a ledger if applicable. |
Rename Index Columns
mp_rename(x, ...)
mp_rename(x, ...)
x |
An index with columns to be renamed. |
... |
Name-value pairs. The name gives the new name and the value is a character vector giving the old name. |
Other functions that return index tables
mp_cartesian()
,
mp_index()
,
mp_subset()
,
mp_union()
Collects information from the headers of the README files in model directories and returns the results as a data frame
mp_show_models( dir = system.file("starter_models", package = "macpan2"), show_missing = FALSE, for_markdown = FALSE ) show_models( dir = system.file("starter_models", package = "macpan2"), show_missing = FALSE, for_markdown = FALSE ) mp_list_models(dir = system.file("starter_models", package = "macpan2"))
mp_show_models( dir = system.file("starter_models", package = "macpan2"), show_missing = FALSE, for_markdown = FALSE ) show_models( dir = system.file("starter_models", package = "macpan2"), show_missing = FALSE, for_markdown = FALSE ) mp_list_models(dir = system.file("starter_models", package = "macpan2"))
dir |
directory to list |
show_missing |
(logical) include entries for models with no README information? |
for_markdown |
(logical) format for rendering the table with markdown-formatted links to model readme files? |
a data frame containing entries Directory
(model directory), Title
(model title), Description
(short description)
show_models()
: Synonym for mp_show_models
, which is
preferred. Present for back-compatibility.
mp_list_models()
: Return a character vector containing model
names, instead of a data frame with more information about each model.
mp_show_models(show_missing = TRUE)
mp_show_models(show_missing = TRUE)
Set the simulation bounds (start time and end time) for a
calibration. This is used to override the default simulation
bounds taken from the observed data passed to
mp_tmb_calibrator
.
mp_sim_bounds(sim_start, sim_end, time_scale = "steps", time_column = "time")
mp_sim_bounds(sim_start, sim_end, time_scale = "steps", time_column = "time")
sim_start |
Start time of each simulation. |
sim_end |
End time of each simulation. |
time_scale |
Qualitative description of the size of a time step.
The only valid values are 'steps' and 'daily'. If you would like each time
step in the model to represent one day, then you should consider using
'daily'. Note that using 'daily' will require that your data represent
time using a (1) |
time_column |
Name of the column that will identify the time at which particular values were observed. |
An object to be passed to the time
argument of
mp_tmb_calibrator
.
Offset the starting and ending times of the simulation, from the
start and end time of the data used in calibration. This is used to
override the default offsets of zero taken from the observed data passed to
mp_tmb_calibrator
.
mp_sim_offset( sim_start_offset, sim_end_offset, time_scale = "steps", time_column = "time" )
mp_sim_offset( sim_start_offset, sim_end_offset, time_scale = "steps", time_column = "time" )
sim_start_offset |
Number of time steps before the first data point to start each simulation. |
sim_end_offset |
Number of time steps after the last data point to end each simulation. |
time_scale |
Qualitative description of the size of a time step.
The only valid values are 'steps' and 'daily'. If you would like each time
step in the model to represent one day, then you should consider using
'daily'. Note that using 'daily' will require that your data represent
time using a (1) |
time_column |
Name of the column that will identify the time at which particular values were observed. |
An object to be passed to the time
argument of
mp_tmb_calibrator
.
Construct a simulator from a model specification object.
mp_simulator(model, time_steps, outputs, default = list())
mp_simulator(model, time_steps, outputs, default = list())
model |
A model specification object. |
time_steps |
How many time steps should be simulated when simulations are requested? |
outputs |
Character vector of names of model quantities that will be outputted when simulations are requested. |
default |
Named list of numerical objects that will update the default values defined in the model specification object. Any number of objects can be updated or not. |
Slice an index
mp_slices(index, unpack = c("no", "maybe", "yes"))
mp_slices(index, unpack = c("no", "maybe", "yes"))
index |
Index to slice up. |
unpack |
Place factors in the global environment? |
Self Cartesian Product
mp_square(x, suffixes = c("A", "B"))
mp_square(x, suffixes = c("A", "B"))
x |
An index. |
suffixes |
Length-2 character vector giving suffixes that disambiguate the column names in the output. |
Other functions that take products of index tables and return one index tables
mp_cartesian()
,
mp_linear()
,
mp_symmetric()
,
mp_triangle()
Data frame giving states that per-capita flow rates directly depend on. This is intended for plotting diagrams and not for mathematical analysis, in that it does not describe indirect dependence for flow rates on state variables.
mp_state_dependence_frame(spec)
mp_state_dependence_frame(spec)
spec |
Model specification from |
This documentation was originally in mp_index()
and should be cleaned up
See issue #131. Also this is an experimental feature.
mp_structured_vector(x, ...) mp_set_numbers(vector, ...)
mp_structured_vector(x, ...) mp_set_numbers(vector, ...)
x |
An index. |
... |
Passed on to S3 methods. |
vector |
An index. |
mp_set_numbers()
: Update numerical values of a structured
vector. TODO: details on syntax.
state = mp_index( Epi = c("S", "I", "S", "I"), Age = c("young", "young", "old", "old") ) state_vector = (state |> mp_structured_vector() |> mp_set_numbers(Epi = c(S = 1000)) |> mp_set_numbers(Epi = c(I = 1), Age = "old") ) print(state_vector)
state = mp_index( Epi = c("S", "I", "S", "I"), Age = c("young", "young", "old", "old") ) state_vector = (state |> mp_structured_vector() |> mp_set_numbers(Epi = c(S = 1000)) |> mp_set_numbers(Epi = c(I = 1), Age = "old") ) print(state_vector)
Take a subset of the rows of an index table (see mp_index
)
to produce another index table. The mp_subset
function gives rows that
match a certain criterion and mp_setdiff
gives rows that do not match.
mp_subset(x, ...) mp_setdiff(x, ...)
mp_subset(x, ...) mp_setdiff(x, ...)
x |
Model index. |
... |
Name-value pairs. The names are columns (or sets of columns
using dot-concatenation) in |
Other functions that return index tables
mp_cartesian()
,
mp_index()
,
mp_rename()
,
mp_union()
Symmetric Self Cartesian Product
mp_symmetric(x, y_labelling_column_names, exclude_diag = TRUE)
mp_symmetric(x, y_labelling_column_names, exclude_diag = TRUE)
x |
An index. |
y_labelling_column_names |
TODO |
exclude_diag |
Should 'diagonal' commponents be excluded from the output. |
Other functions that take products of index tables and return one index tables
mp_cartesian()
,
mp_linear()
,
mp_square()
,
mp_triangle()
Time Scale
mp_time_scale(start, end, time_step_scale = c("steps", "daily", "weekly"), ...)
mp_time_scale(start, end, time_step_scale = c("steps", "daily", "weekly"), ...)
start |
First date or time in the first time step |
end |
Last date or time in the last time step |
time_step_scale |
TODO |
... |
TODO |
Get the result of TMB::MakeADFun
underlying a TMB-based
model in macpan2
.
mp_tmb(model)
mp_tmb(model)
model |
An object based on TMB. |
Construct an object that can get used to calibrate an object produced by
mp_tmb_model_spec
or mp_tmb_library
,
and possibly modified by mp_tmb_insert
or
mp_tmb_update
. Note that the output of this function is
not a model that has been calibrated to data, but rather an object that
contains a model that can be calibrated. To actually attempt a
calibration one needs the mp_optimize
function (see
examples below).
mp_tmb_calibrator( spec, data = empty_trajectory, traj = character(), par = character(), tv = character(), outputs = traj, default = list(), time = NULL, save_data = TRUE )
mp_tmb_calibrator( spec, data = empty_trajectory, traj = character(), par = character(), tv = character(), outputs = traj, default = list(), time = NULL, save_data = TRUE )
spec |
An TMB model spec to fit to data. Such specs can be produced by
|
data |
A data frame containing trajectories to fit to and possibly
time-varying parameters. The data must be of the same format as that
produced by |
traj |
A character vector giving the names of trajectories to fit
to data, or a named list of likelihood distributions specified with
|
par |
A character vector giving the names of parameters, either time-varying or not, to fit using trajectory match. |
tv |
A character vector giving the names of parameters to make
time-varying according to the values in |
outputs |
A character vector of outputs that will be generated
when |
default |
A list of default values to use to update the defaults
in the |
time |
Specify the start and end time of the simulated trajectories,
and the time period associated with each time step. The default is |
save_data |
Save a copy of the data in the calibrator object that is
returned, so that you do not need to pass the data manually to downstream
functions like |
spec = mp_tmb_library("starter_models", "sir", package = "macpan2") sim = mp_simulator(spec, 50, "infection") data = mp_trajectory(sim) cal = mp_tmb_calibrator( spec , data , traj = "infection" , par = "beta" , default = list(beta = 0.25) ) mp_optimize(cal) mp_tmb_coef(cal) ## requires broom.mixed package
spec = mp_tmb_library("starter_models", "sir", package = "macpan2") sim = mp_simulator(spec, 50, "infection") data = mp_trajectory(sim) cal = mp_tmb_calibrator( spec , data , traj = "infection" , par = "beta" , default = list(beta = 0.25) ) mp_optimize(cal) mp_tmb_coef(cal) ## requires broom.mixed package
TMB Model Coefficient Table
mp_tmb_coef(model, back_transform = TRUE, ...)
mp_tmb_coef(model, back_transform = TRUE, ...)
model |
Object that contains information about model coefficients. |
back_transform |
A boolean to indicate if model coefficients should be
back transformed to display their defaults, estimates, and confidence
intervals on the original scale. Coefficient names are also stripped of their
transformation identifier. Currently, this back transformation only
applies to log transformed coefficients that have been named with "log_"
prefix or logit transformed coefficients that have been named with "logit_"
prefix. Back transformation also applies to time varying parameters and
distributional parameters that get automatic prefixes when used. |
... |
Arguments to pass onto the |
A data frame that describes the fitted coefficients.
Create a list of expressions for defining a compartmental model in TMB.
mp_tmb_expr_list( before = list(), during = list(), after = list(), .simulate_exprs = character(0L) )
mp_tmb_expr_list( before = list(), during = list(), after = list(), .simulate_exprs = character(0L) )
before |
List of formulas to be evaluated in the order provided before
the simulation loop begins. Each |
during |
List of formulas to be evaluated at every iteration of the
simulation loop, with the same rules as |
after |
List of formulas to be evaluated after the simulation loop,
with the same rules as |
.simulate_exprs |
Character vector of names of expressions to be evaluated within TMB simulate blocks. This is useful when an expression cannot be evaluated during the computation of the objective function and its gradients (e.g. if the expression contains randomness or other discontinuities that will break the automatic differentiation machinery of TMB). |
Object of class ExprList
with the following methods.
$data_arg(...)
: Return the following components of the data structure
to pass to C++.
expr_output_id
– Indices into the list of matrices identifying the
matrix being produced.
expr_sim_block
– Identified whether or not the expression should be
evaluated inside a simulate macro within TMB.
expr_num_p_table_rows
– Number of rows associated with each
expression in the parse table (p_table_*
)
eval_schedule
– Vector giving the number of expressions to evaluate
in each phase (before, during, or after) of the simulation.
p_table_x
– Parse table column giving an index for looking up either
function, matrix, or literal.
p_table_n
– Parse table column giving the number of arguments in
functions.
p_table_i
– Parse table column giving indices for looking up the
rows in the parse table corresponding with the first argument of the
function.
...
: Character vector containing the names of the matrices in the model.
Covariance of Fixed Effect Estimates
mp_tmb_fixef_cov(model)
mp_tmb_fixef_cov(model)
model |
Object that contains information about fitted model parameters. |
A covariance matrix.
Insert, update, or delete elements of a TMB model spec, produced using
mp_tmb_library
or mp_tmb_model_spec
. The
only difference between mp_tmb_insert
and mp_tmb_update
is that
the former shifts the positions of existing expressions to make room
for the new expressions, whereas the latter overwrites existing expressions
using the new expressions. The treatment of new default
values and
integers
is the same. The examples below clarify this difference.
Note that mp_tmb_delete
does not contain an expressions
argument,
because it is not necessary to specify new expressions in the case
of deletion.
mp_tmb_insert( model, phase = "during", at = 1L, expressions = list(), default = list(), integers = list(), must_save = character(), must_not_save = character(), sim_exprs = character() ) mp_tmb_update( model, phase = "during", at = 1L, expressions = list(), default = list(), integers = list(), must_save = character(), must_not_save = character(), sim_exprs = character() ) mp_tmb_delete( model, phase, at, default = character(), integers = character(), must_save = character(), must_not_save = character(), sim_exprs = character() )
mp_tmb_insert( model, phase = "during", at = 1L, expressions = list(), default = list(), integers = list(), must_save = character(), must_not_save = character(), sim_exprs = character() ) mp_tmb_update( model, phase = "during", at = 1L, expressions = list(), default = list(), integers = list(), must_save = character(), must_not_save = character(), sim_exprs = character() ) mp_tmb_delete( model, phase, at, default = character(), integers = character(), must_save = character(), must_not_save = character(), sim_exprs = character() )
model |
TMB model spec object produced using
|
phase |
At what phase should |
at |
Expression number, which can be identified by printing out
|
expressions |
Expressions to insert into the model spec or to replace existing expressions. |
default |
Named list of objects, each of which can be coerced into
a |
integers |
Named list of vectors that can be coerced to integer
vectors. These integer vectors can be used by name in model formulas to
provide indexing of matrices and as grouping factors in
|
must_save |
Character vector of the names of variables that must have their values stored at every iteration of the simulation loop. For example, a variable that you do not want to be returned, but that impacts dynamics with a time lag, must be saved and therefore must be in this list. |
must_not_save |
Character vector of the names of variables that must not have their values stored at every iteration of the simulation loop. For example, the user may ask to return a very large matrix that would create performance issues if stored at each iteration. The creator of the model can mark such variables making it impossible for the user of the model to save their full simulation history. |
sim_exprs |
Character vector of the names of |
These modifications do not update the model specification in-place. Instead
the output of mp_tmb_insert
, mp_tmb_update
, and mp_tmb_delete
define
a new model specification and should be saved if you want to use the new
model (e.g., new_model = mp_tmb_insert(model, ...)
).
A new model spec object with updated and/or inserted information.
si = mp_tmb_library("starter_models", "si", package = "macpan2") print(si) ## Update the mixing process to include ## optional phenomenological heterogeneity. ## We need mp_tmb_update here so that ## the previous infection expression is ## overwritten. mp_tmb_update(si, phase = "during" , at = 1 , expressions = list(infection ~ beta * I * (S/N)^zeta) , default = list(zeta = 1) ) ## Parameterize with log_beta in place of beta. ## We need mp_tmb_insert here so that the ## existing expression for computing the initial ## number of susceptible indiviudals is not ## overwritten. mp_tmb_insert(si, phase = "before" , at = 1 , expressions = list(beta ~ exp(log_beta)) , default = list(log_beta = log(0.5)) )
si = mp_tmb_library("starter_models", "si", package = "macpan2") print(si) ## Update the mixing process to include ## optional phenomenological heterogeneity. ## We need mp_tmb_update here so that ## the previous infection expression is ## overwritten. mp_tmb_update(si, phase = "during" , at = 1 , expressions = list(infection ~ beta * I * (S/N)^zeta) , default = list(zeta = 1) ) ## Parameterize with log_beta in place of beta. ## We need mp_tmb_insert here so that the ## existing expression for computing the initial ## number of susceptible indiviudals is not ## overwritten. mp_tmb_insert(si, phase = "before" , at = 1 , expressions = list(beta ~ exp(log_beta)) , default = list(log_beta = log(0.5)) )
Insert Back Transformations of Model Parameters
mp_tmb_insert_backtrans( model, variables = character(), transformation = mp_log )
mp_tmb_insert_backtrans( model, variables = character(), transformation = mp_log )
model |
TMB model spec object produced using
|
variables |
Character vector of parameters to back transform. |
transformation |
A transformation object such as |
A new model specification object with expressions for the
untransformed (or back transformed) parameters at the beginning of the
before
phase. The transformed version of the parameter is also
added to the defaults and are identified with a prefixed name (e.g.,
log_beta
if beta
is log transformed).
Insert Log Linear Model of Time Variation (Experimental)
mp_tmb_insert_log_linear( model, parameter_name, design_matrices, time_var_parameters, window_names = names(time_var_parameters), baseline_functions = c(list(macpan2:::TimeVarBaselineParameter()), rep(list(macpan2:::TimeVarBaselineNumeric(0)), length(design_matrices) - 1)), link_functions = rep(list(mp_identity), length(design_matrices)), full_series_name = sprintf("time_var_output_%s", parameter_name), baseline_names = sprintf("baseline_%s", window_names), matrix_coef_names = sprintf("matrix_coef_%s", window_names), matrix_row_names = sprintf("matrix_row_%s", window_names), matrix_col_names = sprintf("matrix_col_%s", window_names), linear_pred_names = sprintf("linear_pred_%s", window_names), time_var_names = sprintf("time_var_%s", window_names), time_index_name = sprintf("time_index_%s", parameter_name), sparsity_tolerance = 0 )
mp_tmb_insert_log_linear( model, parameter_name, design_matrices, time_var_parameters, window_names = names(time_var_parameters), baseline_functions = c(list(macpan2:::TimeVarBaselineParameter()), rep(list(macpan2:::TimeVarBaselineNumeric(0)), length(design_matrices) - 1)), link_functions = rep(list(mp_identity), length(design_matrices)), full_series_name = sprintf("time_var_output_%s", parameter_name), baseline_names = sprintf("baseline_%s", window_names), matrix_coef_names = sprintf("matrix_coef_%s", window_names), matrix_row_names = sprintf("matrix_row_%s", window_names), matrix_col_names = sprintf("matrix_col_%s", window_names), linear_pred_names = sprintf("linear_pred_%s", window_names), time_var_names = sprintf("time_var_%s", window_names), time_index_name = sprintf("time_index_%s", parameter_name), sparsity_tolerance = 0 )
model |
A model specification (see |
parameter_name |
Character string giving the name of the parameter to make time-varying. |
design_matrices |
List of matrices, one for each time window, describing the model of time variation. |
time_var_parameters |
Named list of parameter vectors for each window, with names giving the window names. |
window_names |
Names for each window. |
baseline_functions |
It is complicated – this is a joke – I'm tired. |
link_functions |
List of objects representing link functions. |
full_series_name |
Name of variable storing the full time series. |
baseline_names |
Names of variables containing the baseline in each window. |
matrix_coef_names |
Names of vectors containing values of the non-zero elements of the design matrices. |
matrix_row_names |
Names of the vectors containing row indices of the non-zero elements of the design matrices. |
matrix_col_names |
Names of the vectors containing column indices of the non-zero elements of the design matrices. |
linear_pred_names |
Names of the vectors containing the linear predictors in each window. |
time_var_names |
Names of the time-varying parameter in each window. |
time_index_name |
Name of the index at which the time varying parameter changes. |
sparsity_tolerance |
Make design matrix coefficients exactly zero when they are below this tolerance. |
A version of mp_tmb_insert
making it more convenient to
transform an incidence variable into a reports variable, which accounts
for reporting delays and under-reporting. This new reports variable is
a convolution of the simulation history of an incidence variable with
a kernel that is proportional to a Gamma distribution of reporting
delay times.
mp_tmb_insert_reports( model, incidence_name, report_prob, mean_delay, cv_delay, reports_name = sprintf("reported_%s", incidence_name), report_prob_name = sprintf("%s_report_prob", incidence_name), mean_delay_name = sprintf("%s_mean_delay", incidence_name), cv_delay_name = sprintf("%s_cv_delay", incidence_name) )
mp_tmb_insert_reports( model, incidence_name, report_prob, mean_delay, cv_delay, reports_name = sprintf("reported_%s", incidence_name), report_prob_name = sprintf("%s_report_prob", incidence_name), mean_delay_name = sprintf("%s_mean_delay", incidence_name), cv_delay_name = sprintf("%s_cv_delay", incidence_name) )
model |
A model produced by |
incidence_name |
Name of the incidence variable to be transformed. |
report_prob |
Value to use for the reporting probability; the proportion of cases that get reported. |
mean_delay |
Mean of the Gamma distribution of reporting delay times. |
cv_delay |
Coefficient of variation of the Gamma distribution of reporting delay times. |
reports_name |
Name of the new reports variable. |
report_prob_name |
Name of the variable containing |
mean_delay_name |
Name of the variable containing |
cv_delay_name |
Name of the variable containing |
Insert Basic Transformations of Model Variables
mp_tmb_insert_trans(model, variables = character(), transformation = mp_log)
mp_tmb_insert_trans(model, variables = character(), transformation = mp_log)
model |
TMB model spec object produced using
|
variables |
Character vector of variables to transform. |
transformation |
A transformation object such as |
A new model specification object with expressions for the transformed
variables at the end of the simulation loop. The transformed variables
are identified with a prefixed name (e.g., log_incidence
if incidence
is log transformed).
Get a TMB model specification from a model library.
mp_tmb_library(..., package = NULL, alternative_specs = FALSE) mp_tmb_entire_library()
mp_tmb_library(..., package = NULL, alternative_specs = FALSE) mp_tmb_entire_library()
... |
File path components pointing to a directory that
contains an R script that creates an object called |
package |
If |
alternative_specs |
If |
mp_tmb_entire_library()
: List of one model specification for each model
in the library.
mp_tmb_library( "starter_models" , "si" , package = "macpan2" )
mp_tmb_library( "starter_models" , "si" , package = "macpan2" )
Specify a simulation model in the TMB engine. A detailed explanation of this
function is covered in vignette("quickstart")
.
mp_tmb_model_spec( before = list(), during = list(), after = list(), default = list(), integers = list(), must_save = character(), must_not_save = character(), sim_exprs = character(), state_update = c("euler", "rk4", "discrete_stoch", "hazard", "rk4_old", "euler_multinomial") )
mp_tmb_model_spec( before = list(), during = list(), after = list(), default = list(), integers = list(), must_save = character(), must_not_save = character(), sim_exprs = character(), state_update = c("euler", "rk4", "discrete_stoch", "hazard", "rk4_old", "euler_multinomial") )
before |
List of formulas to be evaluated (in the order provided)
before the simulation loop begins. These formulas must be standard
two-sided R |
during |
List of formulas or calls to flow functions (e.g.,
|
after |
List of formulas to be evaluated (in the order provided)
before the simulation loop begins. These formulas must be standard
two-sided R |
default |
Named list of objects, each of which can be coerced into
a |
integers |
Named list of vectors that can be coerced to integer
vectors. These integer vectors can be used by name in model formulas to
provide indexing of matrices and as grouping factors in
|
must_save |
Character vector of the names of variables that must have their values stored at every iteration of the simulation loop. For example, a variable that you do not want to be returned, but that impacts dynamics with a time lag, must be saved and therefore must be in this list. |
must_not_save |
Character vector of the names of variables that must not have their values stored at every iteration of the simulation loop. For example, the user may ask to return a very large matrix that would create performance issues if stored at each iteration. The creator of the model can mark such variables making it impossible for the user of the model to save their full simulation history. |
sim_exprs |
Character vector of the names of |
state_update |
Optional character vector for how to update the state
variables when it is relevant. Options include |
Expressions in the before
, during
, and after
lists can be standard
R formula
objects for defining variables in the model. These
formulas must have a left hand side that gives the name of the (possibly
matrix-valued) variable being updated, and a right hand side giving an
expression containing only (1) the names of quantities in the model, (2)
numerical literals (e.g., 3.14
), or (3) functions defined in the TMB
engine (described in engine_functions
). For example, the
expression N ~ S + I + R
updates the value of N
to be the sum of the
variables S
, I
, and R
.
Names can be provided for the components of the before
, during
, and
after
lists, and these names do not have to be unique. These names are
used by the sim_exprs
argument.
## A simple SI model. spec = mp_tmb_model_spec( during = mp_per_capita_flow("S", "I", "beta * I / N", "infection") , default = list(N = 100, S = 99, I = 1, beta = 0.2) ) (spec |> mp_simulator(time_steps = 5L, output = "infection") |> mp_trajectory() ) ## The `~` can be used for flexibly defining dynamical variables. spec2 = mp_tmb_model_spec( during = list( force_of_infection ~ beta * I / N , mp_per_capita_flow("S", "I", "force_of_infection", "infection") ) , default = list(N = 100, S = 99, I = 1, beta = 0.2) ) (spec2 |> mp_simulator(time_steps = 5L, output = "force_of_infection") |> mp_trajectory() ) ## The `before` argument can be used to pre-compute quantities before ## the simulation loop begins. Here we compute `S` from `N` and `I`, ## instead of specifying `S` in the `default` list. The potential ## benefit here is that one could make `I` a parameter to be fitted, ## while ensuring consistent values for `S`. spec3 = mp_tmb_model_spec( before = S ~ N - I , during = mp_per_capita_flow("S", "I", "beta * I / N", "infection") , default = list(N = 100, I = 1, beta = 0.2) ) (spec3 |> mp_simulator(time_steps = 5L, output = "infection") |> mp_trajectory() )
## A simple SI model. spec = mp_tmb_model_spec( during = mp_per_capita_flow("S", "I", "beta * I / N", "infection") , default = list(N = 100, S = 99, I = 1, beta = 0.2) ) (spec |> mp_simulator(time_steps = 5L, output = "infection") |> mp_trajectory() ) ## The `~` can be used for flexibly defining dynamical variables. spec2 = mp_tmb_model_spec( during = list( force_of_infection ~ beta * I / N , mp_per_capita_flow("S", "I", "force_of_infection", "infection") ) , default = list(N = 100, S = 99, I = 1, beta = 0.2) ) (spec2 |> mp_simulator(time_steps = 5L, output = "force_of_infection") |> mp_trajectory() ) ## The `before` argument can be used to pre-compute quantities before ## the simulation loop begins. Here we compute `S` from `N` and `I`, ## instead of specifying `S` in the `default` list. The potential ## benefit here is that one could make `I` a parameter to be fitted, ## while ensuring consistent values for `S`. spec3 = mp_tmb_model_spec( before = S ~ N - I , during = mp_per_capita_flow("S", "I", "beta * I / N", "infection") , default = list(N = 100, I = 1, beta = 0.2) ) (spec3 |> mp_simulator(time_steps = 5L, output = "infection") |> mp_trajectory() )
Value of the Objective Function of a Model
mp_tmb_objective( model, parameter_updates = list(), baseline = c("recommended", "default", "optimized") )
mp_tmb_objective( model, parameter_updates = list(), baseline = c("recommended", "default", "optimized") )
model |
A model with an objective function, probably one produced using
|
parameter_updates |
Named list of a subset of model variables with
the values to use when simulating the trajectory using the
|
baseline |
Models can contain several alternative sets of
parameters, and this |
Leverages the tmbstan
and broom.mixed
packages to generate
MCMC-based coefficient tables.
mp_tmbstan_coef(model, tmbstan_args = list(), ...)
mp_tmbstan_coef(model, tmbstan_args = list(), ...)
model |
Object that contains information about model coefficients. |
tmbstan_args |
Arguments to pass on to |
... |
Arguments to pass onto the |
Specify a set of trajectories to fit. The output of this function
is intended to be passed to the traj
argument of
mp_tmb_calibrator
.
mp_traj(likelihood = empty_named_list(), condensation = empty_named_list())
mp_traj(likelihood = empty_named_list(), condensation = empty_named_list())
likelihood |
List of likelihood components. The names of the list identify the trajectory associated with each likelihood component. |
condensation |
List of condensation methods. The names of the list identify the trajectories produced by each condensation method. |
Return simulations of the trajectory of the output
variables of a dynamical model simulator. To see this functionality
in context, please see vignette("quickstart")
.
mp_trajectory(model, include_initial = FALSE) mp_trajectory_par( model, parameter_updates = list(), include_initial = FALSE, include_final = FALSE, baseline = c("recommended", "default", "optimized") ) mp_trajectory_sd( model, conf.int = FALSE, conf.level = 0.95, include_initial = FALSE, back_transform = TRUE ) mp_trajectory_ensemble(model, n, probs = c(0.025, 0.975)) mp_trajectory_sim(model, n, probs = c(0.025, 0.25, 0.5, 0.75, 0.975)) mp_trajectory_replicate( model, n, parameter_updates = list(), include_initial = FALSE, include_final = FALSE, baseline = c("recommended", "default", "optimized") )
mp_trajectory(model, include_initial = FALSE) mp_trajectory_par( model, parameter_updates = list(), include_initial = FALSE, include_final = FALSE, baseline = c("recommended", "default", "optimized") ) mp_trajectory_sd( model, conf.int = FALSE, conf.level = 0.95, include_initial = FALSE, back_transform = TRUE ) mp_trajectory_ensemble(model, n, probs = c(0.025, 0.975)) mp_trajectory_sim(model, n, probs = c(0.025, 0.25, 0.5, 0.75, 0.975)) mp_trajectory_replicate( model, n, parameter_updates = list(), include_initial = FALSE, include_final = FALSE, baseline = c("recommended", "default", "optimized") )
model |
A dynamical model simulator produced by
|
include_initial |
Should the initial values of the simulation be
included in the output? If |
parameter_updates |
Named list of a subset of model variables with
the values to use when simulating the trajectory using the
|
include_final |
Should the final values of the simulation, after the
post-simulation processing steps in the |
baseline |
Models can contain several alternative sets of
parameters, and this |
conf.int |
Should confidence intervals be produced? |
conf.level |
If |
back_transform |
A boolean to indicate if trajectories, standard
deviations, and confidence intervals should be back transformed to
the original scale. Variable names are also stripped of their
transformation identifier. Currently, this back transformation only
applies to log transformed coefficients that have been named with "log_"
prefix or logit transformed coefficients that have been named with "logit_"
prefix. Back transformation also applies to time varying parameters and
distributional parameters that get automatic prefixes when used.
|
n |
Number of random trajectories to simulate. |
probs |
Numeric vector of probabilities corresponding to quantiles for summarizing the results over the random realizations. |
A data frame with one row for each simulated value and the following columns.
Name of the variable in the model. All variables are matrix-valued
in macpan2
(scalars are technically 1-by-1 matrices), which explains
the name of this field. In hindsight I would have called it variable
.
Time index of the simulated value, with time = 0
indicating initial
values.
The 0-based index of the row of the matrix, or the name of the row of the matrix if row names (or names for column vectors) are supplied for the default value of the matrix.
The 0-based index of the column of the matrix, or the name of the column of the matrix if column names are supplied for the default value of the matrix. It is also possible that this column is blank if everything is either a scalar or column vector (a common case).
(mp_trajectory
and mp_trajectory_sd
) Simulation values.
(for mp_trajectory_sd
only)
The standard deviations of the simulated values accounting for parameter
estimation uncertainty.
(for mp_trajectory_sd
only)
The lower bounds of the confidence interval for the simulated values.
(for mp_trajectory_sd
only)
The upper bounds of the confidence interval for the simulated values.
(for mp_trajectory_[ensemble|sim]
)
The n-th quantiles of the simulation values over repeated simulations.
mp_trajectory_par()
: Produce a trajectory, after updating the baseline
set of parameters with values in parameter_updates
.
mp_trajectory_sd()
: Simulate a trajectory that includes uncertainty
information provided by the sdreport
function in TMB
with default
settings.
mp_trajectory_ensemble()
: Simulate a trajectory that includes uncertainty
information provided by repeatedly sampling from a normal approximation to the
distribution of the fitted parameters, and generating one trajectory for
each of these samples. The quantiles of the empirical distribution of these
trajectories can be used to produce a confidence interval for the
fitted trajectory.
mp_trajectory_sim()
: Generate quantiles over n
realizations of
the trajectory. Instead of a value
column in the output data frame, there
is one column for each of the quantiles defined in probs
.
mp_trajectory_replicate()
: Generate a list of n
simulation results.
spec = mp_tmb_library("starter_models" , "si" , package = "macpan2" ) simulator = mp_simulator(spec , time_steps = 10L , outputs = c("infection", "I") ) trajectory = mp_trajectory(simulator) print(trajectory)
spec = mp_tmb_library("starter_models" , "si" , package = "macpan2" ) simulator = mp_simulator(spec , time_steps = 10L , outputs = c("infection", "I") ) trajectory = mp_trajectory(simulator) print(trajectory)
Self Cartesian Product Excluding One Off-Diagonal Side
mp_triangle( x, y_labelling_column_names, exclude_diag = TRUE, lower_tri = FALSE )
mp_triangle( x, y_labelling_column_names, exclude_diag = TRUE, lower_tri = FALSE )
x |
An index. |
y_labelling_column_names |
TODO |
exclude_diag |
Should 'diagonal' commponents be excluded from the output. |
lower_tri |
Should the lower triangular components be include from the
output. If |
Other functions that take products of index tables and return one index tables
mp_cartesian()
,
mp_linear()
,
mp_square()
,
mp_symmetric()
Union of Indexes
mp_union(...)
mp_union(...)
... |
Indexes. |
Other functions that return index tables
mp_cartesian()
,
mp_index()
,
mp_rename()
,
mp_subset()
Get the state and/or flow variables in a model specification.
mp_state_vars(spec, topological_sort = FALSE, loops = "^$", trans = "") mp_flow_vars(spec, topological_sort = FALSE, loops = "^$", trans = "") mp_state_flow_vars(spec, topological_sort = FALSE, loops = "^$", trans = "")
mp_state_vars(spec, topological_sort = FALSE, loops = "^$", trans = "") mp_flow_vars(spec, topological_sort = FALSE, loops = "^$", trans = "") mp_state_flow_vars(spec, topological_sort = FALSE, loops = "^$", trans = "")
spec |
Model specification ( |
topological_sort |
Should the states and flows be
topologically sorted to
respect the main direction of flow? The default is no topological sorting,
which differs from |
loops |
Pattern for matching the names of flows that make
the flow model not a DAG, which is a critical assumption when topologically
sorting the order of states and flows in the output. This is only relevant if
|
trans |
Add a prefix to the names for indicating if a transformed version of the variables is preferred. |
Character vector of names of all state and/or flow variables that
have been explicitly represented in the model using functions like
mp_per_capita_flow
.
mp_state_vars()
: Return character vector of all state variables.
mp_flow_vars()
: Return the names of all variables that contain
the absolute flow between compartments.
The absolute flow is the magnitude of a flow per time step.
mp_state_flow_vars()
: Union of mp_state_vars()
and mp_flow_vars()
.
si = mp_tmb_library("starter_models", "si", package = "macpan2") (si |> mp_simulator(time_steps = 5L, mp_state_vars(si)) |> mp_trajectory() )
si = mp_tmb_library("starter_models", "si", package = "macpan2") (si |> mp_simulator(time_steps = 5L, mp_state_vars(si)) |> mp_trajectory() )
Create a numeric
vector of all zeros with names
given by x
mp_zero_vector(x, ...)
mp_zero_vector(x, ...)
x |
Object representing the names of the output vector. Most
commonly this will be a |
... |
Passed on to S3 methods. |
This page describes functions for giving names and labels to entities in structured models.
to_labels(x) to_names(x) to_name(x) to_name_pairs(x) to_values(x)
to_labels(x) to_names(x) to_name(x) to_name_pairs(x) to_values(x)
x |
Object from which to extract its name, names, labels, name-pairs, or values. Not all types of objects will work for all functions. |
Character vector (or numeric vector in the case of to_values
)
that describes x
.
to_labels()
: Extract a vector for describing the rows
of a data frame or values of a numeric vector.
to_names()
: Extract a character vector for describing the
character-valued columns in a data frame or the flattened structure of
a numeric vector.
Names obey the following restrictions: (1) they cannot have dots, (2) all
values must start with a letter, (3) all characters must be letters,
numbers, or underscore.
to_name()
: Extract a string (i.e. length-1 character
vector) for describing the character-valued columns in a data frame or the
flattened structure of a numeric vector. The name of an object is the
dot-concatenation of its names.
to_name_pairs()
: A character
vector with all possible pairwise dot-concatenations of a set of names.
to_values()
: Extract the numeric
column from a
data frame with only a single numerical column. This data frame might have
more than one column, but only one of them can be numeric. This function
will also turn numeric matrix
and array
objects
with dimnames
into a flattened numeric vector with labels
produced by appropriately dot-concatenating the dimnames
.
A goal of macpan2
is to provide a mechanism for representing structured
compartmental models. An example of such a model is to have each compartment
in an SEIR model split into a set of spatial locations and into a set of
age groups. It is crucial but difficult to assign meaningful and consistent
names to the compartments, flow rates, transmission rates, contact rates,
sub-population sizes, and other parameters determining these quantities.
Such names should convey how the different quantities relate to one another.
For example, the names should make clear that the rate of flow between two
compartments is specific to, say, the age group and location of those
compartments. The naming system should facilitate identifying model
quantities and sets of quantities. For example, in a spatially structured
model we might want to refer to all states in a particular location
(e.g. Toronto) and a specific state within that location (e.g. susceptible
individuals in Toronto).
Model entities (e.g. states, flow rates, transmission rates), can be described using a data frame of string-valued columns. The rows of these data frames represent the entities being represented. The columns of the data frame represent different ways to describe the rows.
EpiSympVax = data.frame( Epi = c(rep(c("S", "E", "I", "I", "R", "beta"), 2), "alpha", "gamma", "gamma", "infectiousness", "infectiousness", ""), Symp = c(rep(c("", "", "mild", "severe", "", ""), 2), "", "mild", "severe", "mild", "severe", ""), Vax = c(rep(c("unvax", "vax"), each = 6), "", "", "", "", "", "dose_rate") ) EpiSympVax #> Epi Symp Vax #> 1 S unvax #> 2 E unvax #> 3 I mild unvax #> 4 I severe unvax #> 5 R unvax #> 6 beta unvax #> 7 S vax #> 8 E vax #> 9 I mild vax #> 10 I severe vax #> 11 R vax #> 12 beta vax #> 13 alpha #> 14 gamma mild #> 15 gamma severe #> 16 infectiousness mild #> 17 infectiousness severe #> 18 dose_rate
Non-empty values in each cell must contain only letters, numbers, underscores, and must start with a letter. Empty values are zero-length strings that can be used to indicate that some partitions are not applicable to some variables. The purpose for these restrictions is to facilitate the construction of strings and character vectors that summarize different aspects of the data frame. When taken together, these summaries can be inverted to restore the full labelled partition and so they represent zero information loss. This equivalence allows us to go back-and-forth between the two representations without loosing information, but perhaps gaining convenience.
There are three types of summaries: the names, the name, and the labels. The names of a data frame are the names of the string-valued columns.
to_names(EpiSympVax) #> [1] "Epi" "Symp" "Vax"
The name of a data frame is the dot-concatenation of the names.
to_name(EpiSympVax) #> [1] "Epi.Symp.Vax"
The labels of a data frame is the row-wise dot-concatenation of the string-valued columns.
to_labels(EpiSympVax) #> [1] "S..unvax" "E..unvax" "I.mild.unvax" #> [4] "I.severe.unvax" "R..unvax" "beta..unvax" #> [7] "S..vax" "E..vax" "I.mild.vax" #> [10] "I.severe.vax" "R..vax" "beta..vax" #> [13] "alpha.." "gamma.mild." "gamma.severe." #> [16] "infectiousness.mild." "infectiousness.severe." "..dose_rate"
These labels give a unique single character string for referring to each
variable. With only the labels and one of either the names or the name, one may
recover the labelled partition. The labels provide convenient names for the
variables – i.e. rownames.
By convention we use UpperCamelCase
for partition names and a modified form of
snake_case for variable labels. Our
modification of snake case allows for single uppercase letters in order to
accommodate the convention in epidemiology for using single uppercase letters to
refer to state variables. For example, S
, I
, and R
, as well as I_mild
and I_severe
, would be consistent with our modified snake case style.
Self Naming List
nlist(...)
nlist(...)
... |
Objects to put into the list |
Compute a set of radial basis functions (dimension
of them).
rbf(time_steps, dimension, scale = time_steps/dimension)
rbf(time_steps, dimension, scale = time_steps/dimension)
time_steps |
number of time steps in the model |
dimension |
number of gaussians in the basis |
scale |
width of the gaussians |
matplot(rbf(100, 5), type = "l")
matplot(rbf(100, 5), type = "l")
Construct objects for reading data.
Reader(...) CSVReader(...) JSONReader(...) TXTReader(...) RReader(...) NULLReader(...)
Reader(...) CSVReader(...) JSONReader(...) TXTReader(...) RReader(...) NULLReader(...)
... |
Character vectors giving path components to the file to be read. |
CSVReader()
: Read CSV files.
JSONReader()
: Read JSON files.
TXTReader()
: Read TXT files.
RReader()
: Read R files.
NULLReader()
: Placeholder reader that always returns NULL
.
Simple Iterated Simulation
simple_sims(iteration_exprs, time_steps, int_vecs = list(), mats = list())
simple_sims(iteration_exprs, time_steps, int_vecs = list(), mats = list())
iteration_exprs |
List of expressions to pass to the
engine. The expressions
are only allowed to use valid |
time_steps |
Number of time steps to iterate. |
int_vecs |
Named list of integer vectors. |
mats |
Named list of matrices. |
A data frame with the simulation results.
These functions return a modified version of a model specification, such that the state variables are updated each time step according to different numerical methods.
mp_euler(model) mp_rk4(model) mp_rk4_old(model) mp_euler_multinomial(model) mp_discrete_stoch(model) mp_hazard(model)
mp_euler(model) mp_rk4(model) mp_rk4_old(model) mp_euler_multinomial(model) mp_discrete_stoch(model) mp_hazard(model)
model |
Object with quantities that have been explicitly marked as state variables. |
By choosing one of these functions, one is able to convert
To see the computations that update the state variables under these
modified specifications, one may use the
mp_expand
function (see examples).
The default update method for model specifications produced using
mp_tmb_model_spec
is mp_euler
. This update method
yields a difference-equation model where the state is updated once
per time-step using the absolute flow rate as the difference between
steps.
mp_euler()
: ODE solver using the Euler method, which is
equivalent to treating the model as a set of discrete-time difference
equations. This is the default method used by
mp_tmb_model_spec
, but this default can be changed using
the functions described below.
mp_rk4()
: ODE solver using Runge-Kutta 4. Any formulas that
appear before model flows in the during
list will only be updated
with RK4 if they do contain functions in
getOption("macpan2_non_iterable_funcs")
and if they do not make any
state variable assignments (i.e., the left-hand-side does not contain
state variables). Each formula that does not meet these conditions will
be evaluated only once at each time-step before the other three RK4
iterations are taken. By default, the time_var
function and functions
that generate random numbers (e.g., rbinom
) are not iterable. Functions
that generate random numbers will only be called once with state update
methods that do not repeat expressions more than once per time-step
(e.g., mp_euler
), and so repeating these functions with RK4
could make it difficult to compare methods. If you really do want to
regenerate random numbers at each RK4 iteration, you can do so by setting
the above option appropriately. The time_var
function assumes that it
will only be called once per time-step, and so it should never be removed
from the list of non-iterable functions. Although in principle it could
make sense to update state variables manually, it currently causes us to
be confused. We therefore require that all state variable updates are set
explicitly (e.g., with mp_per_capita_flow
).
mp_rk4_old()
: Old version of mp_rk4
that doesn't keep track
of absolute flows through each time-step. As a result this version is
more efficient but makes it more difficult to compute things like
incidence over a time scale.
mp_euler_multinomial()
: Original and deprecated name for
mp_discrete_stoch
. In all new projects please use mp_discrete_stoch
.
mp_discrete_stoch()
: Update state such that the probability of moving
from box i
to box j
in one time step is given by
(1 - exp(-sum(r_i))) * (r_ij / r_i)
,
where r_ij
is the per-capita rate of flow from box i
to box j
, and
r_i
is the sum of all r_ij
for a particular i
.
These probabilities from box i
are used together in a multinomial
distribution that determines how many individuals go to each j
box and
how many stay in i
.
mp_hazard()
: Update state with hazard steps, which is equivalent
to taking the step given by the expected value of the Euler-multinomial
distribution.
sir = mp_tmb_library("starter_models", "sir", package = "macpan2") sir sir |> mp_euler() |> mp_expand() sir |> mp_rk4() |> mp_expand() sir |> mp_discrete_stoch() |> mp_expand()
sir = mp_tmb_library("starter_models", "sir", package = "macpan2") sir sir |> mp_euler() |> mp_expand() sir |> mp_rk4() |> mp_expand() sir |> mp_discrete_stoch() |> mp_expand()
Create objects for representing names and labels in a dynamical model.
StringDataFromFrame(data) StringDataFromDotted(labels, name) ## S3 method for class 'StringData' print(x, ...)
StringDataFromFrame(data) StringDataFromDotted(labels, name) ## S3 method for class 'StringData' print(x, ...)
data |
Data frame with names given by column names and labels by the elements of the columns. |
labels |
Character vector with (dot-separated) partition labels. |
name |
Character scalar with (dot-separated) partition name. |
x |
|
... |
Not used but present for S3 method consistency. |
print(StringData)
: Print out a StringData
object.
StringDataFromFrame()
: Construct object from a data frame without any
dots in either the names or the values.
StringDataFromDotted()
: Construct object from a character scalar with
(dot-separated) partition names and a character vector with (dot-separated)
partition labels.
vars = (mp_cartesian( mp_index(Epi = c("S", "I", "R")) , mp_index(Age = c("young", "old")) ) |> as.data.frame() |> StringDataFromFrame() ) vars vars$dot()
vars = (mp_cartesian( mp_index(Epi = c("S", "I", "R")) , mp_index(Age = c("young", "old")) ) |> as.data.frame() |> StringDataFromFrame() ) vars vars$dot()
Return position vector of indices corresponding to the input object.
to_positions(x)
to_positions(x)
x |
An object of a class that can be converted to a position vector. |
Convert an object to a string.
to_string(x)
to_string(x)
x |
Object to convert to a string. |
A length-1 character vector.
Transform
Transform(variable, default = NULL, trans_variable = variable) Identity(variable, default = NULL, trans_variable = variable) Log(variable, default = NULL, trans_variable = sprintf("log_%s", variable)) Logit( variable, default = NULL, trans_variable = sprintf("logit_%s", variable) )
Transform(variable, default = NULL, trans_variable = variable) Identity(variable, default = NULL, trans_variable = variable) Log(variable, default = NULL, trans_variable = sprintf("log_%s", variable)) Logit( variable, default = NULL, trans_variable = sprintf("logit_%s", variable) )
variable |
Character string giving the name of a variable in the model. |
default |
Default value for the untransformed variable. If |
trans_variable |
Character string to use as the name of the transformed
version of the |
Identity()
: Identity transformation.
Log()
: Log transformation.
Logit()
: Logit transformation.
mp_identity
- Identity transformation
mp_log
- Log transformation
mp_logit
- Logit transformation
mp_sqrt
- Square-root transformation
mp_identity mp_log mp_logit mp_sqrt
mp_identity mp_log mp_logit mp_sqrt