Specifying Recruitment
03_recruitment_functions.Rmd
As part of the model_options
list that is a required input to the MSE function, users must specify a recruitment function as well as relevant parameter values for the OM to project future recruitment. Some simple recruitment functions are prepackaged with the model – a Beverton-Holt stock recruit function, a function that resamples from the historical recruitment timeseries, and two different functions that specify distinct recruitment regimes – but users are also able to specify their own custom recruitment functions, as necesarry.
A simple example of specifying a recruitment function for the MSE is as follows:
resample_recruits <- function(hist_recruits, nyears, seed){
set.seed(seed)
return(sample(hist_recruits, size=nyears, replace=TRUE))
}
om$recruitment$func <- resample_recruits
om$recruitment$pars <- list(
hist_recruits = rnorm(100, mean=25, sd=2),
nyears = 100
)
The om$recruitment$func
list element is a reference to the recruitment function that should be used to project recruitment in the future, while om$recruitment$pars
is a named list of parameter values spcific to the provided recruitment function. Note that the final required parameter in resample_recruits
, “seed”, is not povided in the recruitment$pars
list. Instead, this parameter is dynmically passed to the recruitment function within the MSE loop, thus ensuring that recruitment timeseries remain reproducible across multiple simpulations.
Working with Existing Recruitment functions
Four recruitment functions come pre-packaged with the repository:
-
resample_recruits
- randomly resample from a known recruitment timeseries -
resample_regime_recruits
- randomly resample recruits form a known recruitment timeseries with pre-defined regimes -
regime_recruits
- randonly draw recruitment from regime-specific distributions -
beverton_holt
- a Beverton-Holt stock recruit relationships, parameterized with steepness
The first three functions all function in the same way as in the example above, where users simple provide the function name, and a named parameter list (without the final seed
parameter).
The beverton_holt
function works differently however, due to it specifying a state-dependent recruitment function. This function is an R function factory (a funtion that returns another function), that accepts the standard Beverton-Holt parameters – h, R0, and S0 – and returns back a new function to which SSB is provided an input (see the example below).
beverton_holt <- function(h, R0, S0, sigR, seed){
# note that the set.seed() call needs to happen
# outside of the returned function, or else there
# will be no random variability in recruitment draws
set.seed(seed)
function(ssb){
bh <- (4*R0*h*ssb)/((1-h)*R0*(S0/R0) + (5*h - 1)*ssb)
return(
bh + exp(rnorm(1, mean=0, sd=sigR)) # lognormal deviates
)
}
}
bevholt <- beverton_holt(h=0.7, R0=25, S0=300, sigR=1, seed=1120)
bevholt(ssb=50) # 16.65
## [1] 17.74222
This function factory can be used in nearly exactly the same way as the previous three recruitment functions:
om$recruitment$func <- beverton_holt
om$recruitment$pars <- list(
h=0.70,
R0=25,
S0=300,
sigR=1
)
Like with the other recruitment functions, the final “seed” parameter is not provided as input in the recruitmemt$pars
list. The MSE will internally handle computing SSB at the beginning of each year and using the defined SRR to generate an annual recruitment level.
Defining Custom Recruitment Functions
Users can, optionally, define their own recruitment functions beyond what comes pre-packaged with the MSE.
There are two types of recruitment functions that can be developed: those which are state-dependent (such as the Beverton-Holt), and those that are not state-dependent (such as the recruitment regime functions). State-independent recruitment functions have the useful property that the entire recruitment timeseries can be defined before the MSE simulation starts (which is helpful for guaranteeing reproducability between model runs), while state-depenedent functions are only realized at the start of each simulation year. Where possible, we recommend defining state-independent recruitment functions.
The R function that defines a custom recruitment function, regardless of type, can take any form it needs too with the important caveat that the final function pararmeter must be called “seed” and represent a random seed (this holds even if the custom recruitment functions is completely deterministic). Below is an example of a recruitment function that random pulls recruitment from a lognormal distribution:
random_lognormal <- function(log_mean_rec, sigR, nyears, seed){
set.seed(seed)
return(exp(log_mean_rec + rnorm(nyears, 0, sigR) - 0.5*sigR^2))
}
random_lognormal(log_mean_rec = log(25), sigR = 1.04, nyears = 5, seed = 1007) # 25.022 19.746 55.721 14.737 5.858
This is an example of a “state-independent” recruitment function. The function takes a mean recruitment level (in log space) and a recruitment variation and computes nyears
random recruitment levels. Nearly all such state-independent recruitment functions will need to accept an nyears
parameter in order to generate the correct number of recruitment events. Similarly, like all recruitment functions, the final parameter defines a random seed.