• Traces its origins to developments in the 1990s
  • The current incarnation of gadget, gadget3, is based on a new codebase with linkages to TMB
  • It is a environment to build MICE models entirely from R
  • Easy to adapt existing processes and/or define new with R code
  • Flexible observation data aggregation
    • Can derive aggregation from data.frames, rather than interdependent setup options
  • Direct mapping of gadget2 concepts to gadget3
  • Superset of gadget2 abilities; random effects, sparse sampling likelihood, weight loss
  • Many more avenues for model customisation




Key concepts

  • Stocks represent a homogenous group, not necessarily whole stock
    • e.g. substocks for maturity stages, sex
    • Defines the dimensions for stock arrays that g3 will use internally
    • Fleets are special instances of stocks
  • Actions act on stock objects, defining biological process
    • Growth, migration, aging and stock interations (fishing and predation)
    • No restrictions to number of actions, bar RAM & time
    • Actions’ behaviour customised by composing functions
stock <-
  g3_stock(
    var_name = c(species = 'her', maturity = 'imm'),
    lengthgroups = seq(3, 28, 1)
  ) |>
  g3s_age(minage = 0, maxage = 5)

fleet <-
  g3_fleet(
    var_name = c(type = 'comm', country = 'fi')
  )


actions <- list(
  g3a_time(1990, 2025, step_length = rep(3, 4)),
  g3a_initialconditions_normalcv(stock),
  g3a_renewal_normalparam(stock),
  g3a_age(stocks),
  g3a_naturalmortality(stock),
  g3a_growmature(
    stock,
    g3a_grow_impl_bbinom(maxlengthgroupgrowth = 4),
  ),
  ...
)

Incorporating data

  • Likelihood actions allow model to be compared to real-world data
  • Nature of comparison based on columns in data
actions_lik <- list(
  g3l_catchdistribution(
    "aldist_comm",
    obs_data = aldist_comm,
    fleets = fleet,
    stocks = stock,
    function_f = g3l_distribution_sumofsquares()
  ),
  g3l_catchdistribution(
    "ldist_comm",
    obs_data = ldist_comm,
    fleets = fleet,
    stocks = stock,
    function_f = g3l_distribution_sumofsquares()
  ),
  g3l_abundancedistribution(
    "acoustic",
    obs_data = acoustic_abund,
    stocks = stocks_her,
    function_f = g3l_distribution_surveyindices_log()
  )
)

Length updates in Gadget

  • When growth is implemented in Gadget it depends on length, and modelled in terms of \(\Delta l_i\). The length transition from \(t\) to \(t+1\) follows: \[ N_{c,a(t+1),t+1} = X_{c,t} S_{c,t} N_{c,a(t),t}, \qquad N_{c,0,t_{0_c}} = \phi_c R_{c,t_{0_c}} \]

where \(X_{c,t}\) is the cohort (\(c\)) specific growth transition matrix, \(S_.\) cohort specific survial and \(R_.\) the recruitment to cohort \(c\) at time \(t_{0_c}\).

  • Following the results of Stefansson (2005) the elements of \(X\) are parametrised based on the Beta-Binomial distribution: \[ \frac{\Gamma(\alpha + \beta)}{\Gamma(\alpha)\Gamma{\beta}}\frac{\Gamma(n+1)}{\Gamma(n-x+1)\Gamma(x+1)}\frac{\Gamma(n-x+\beta)\Gamma(x+\alpha)}{\Gamma(n+\alpha + \beta)} \]
    • \(x\) is the length group update and \(n\) is the maximum length group growth
    • The mean is \(\overline{\Delta l_i} = \frac{n\alpha}{\alpha + \beta}\), and rewriting \(\alpha = \frac{\beta\Delta l_i}{n-\overline{\Delta l_i}}\)

Length updates in Gadget (cont.)

  • This formulation is fairly flexible, depends on \(\overline{\Delta l}\), \(\beta\) and \(n\).
  • Multiple options available for \(\overline{\Delta l}\) including
    • g3a_grow_lengthvbsimple: \(\overline{\Delta l_i} = (l_\infty - l_i)(1 - e^{-k\Delta t})\)
    • g3a_grow_length_multspec: \(\overline{\Delta l_i} = \Delta t p_0 l_i^{p_1} \psi_i (p_2 T + p_3)\)
    • and a number others (including user defined functions)
    • \(\beta\) is estimated and \(n\) is typically fixed to a reasonable value
  • The effects of fishing are accounted for by tracking abundances by age–length cell

Customising growth

g3a_growmature(
  stock,
  impl_f = g3a_grow_impl_bbinom(
    delta_len_f = g3a_grow_lengthvbsimple(
      linf_f = g3_parameterized("Linf"),
      kappa_f = g3_parameterized("K")
    ),
    delta_wgt_f = g3a_grow_weightsimple(),
    beta_f = g3_parameterized('bbin'),
    maxlengthgroupgrowth = 15
  ),
  maturity_f = ~0,
)
g3a_grow_lengthvbsimple <-
  function(
    linf_f,
    kappa_f,
    by_stock = TRUE
  ) {
    f_substitute(
      ~ avoid_zero(
        (linf_f - stock__midlen) *
          (1 - exp(-(kappa_f) * cur_step_size))
      ),
      list(
        linf_f = linf_f,
        kappa_f = kappa_f
      )
    )
  }
  • The growth action is implemented in combination with optional maturation
  • The user supplies functions for
    • impl_f growth update (beta - binomial)
    • delta_len_f mean growth rate
    • delta_wgt_f mean weight update
    • beta_f \(\beta\) parameter
    • maturity_f the maturity function
  • User defined functions can replace individual parts of growth update

Modifying parameters

  • All parameters can be made time and area varying:
kappa_f =
  g3_parameterized(
    "K",
    by_year = TRUE,
    by_area = TRUE,
    by_stock = TRUE
  )

params.in <-
  params.in |>
  g3_init_val("*.K.#.*", 0.5 * runif(48))

Modifying parameters

  • Depend on external data \(K = \alpha T + \beta\)
kappa_f =
  g3_formula(
    Ka * cur_temp + Kb,
    Ka = g3_parameterized('Ka'),
    Kb = g3_parameterized('Kb'),
    cur_temp = g3_timeareadata(
      'temperature',
      temperature_df,
      value_field = "temp",
      areas = areas
    )
  )

params.in <-
  params.in |>
  g3_init_val('*.Ka', 0.01) |>
  g3_init_val('*.Kb', 0.1)

Modifying parameters

  • Depend on abundance: \(K = \alpha f(N_t) + \beta\)
kappa_f =
  g3_formula(
    Ka *
      sum(stock_ss(
        stock__num,
        area = default,
        vec = 'area'
      )) +
      Kb,
    Ka = g3_parameterized('Ka'),
    Kb = g3_parameterized('Kb'),
  )


params.in <-
  params.in |>
  g3_init_val('Ka', -0.1 * 1e-8) |>
  g3_init_val('Kb', 0.2)

Modifying parameters

  • Random effect: \(K = \alpha T + \beta + \epsilon_t\)
kappa_f =
  g3_formula(
    Ka * cur_temp + Kb + eps,
    Ka = g3_parameterized('Ka'),
    Kb = g3_parameterized('Kb'),
    eps = g3_param_project(
      "eps",
      by_step = FALSE,
      g3_param_project_dnorm()
    ),
    cur_temp = g3_timeareadata(
      'temperature',
      temperature_df,
      value_field = "temp",
      areas = areas
    )
  )

params.in <-
  params.in |>
  g3_init_val('*.Ka', 0.01) |>
  g3_init_val('*.Kb', 0.1) |>
  g3_init_val('*.dnorm.mean', 0) |>
  g3_init_val('*.dnorm.mean', 0.01)

Blue ling

  • Long lived, deep water, data poor, bad age data
  • Low recruitment period in recent times but has picked up
  • Available von B parameters from a related stock
  • When parameters were estimated freely the stability of the model estimates suffered

Concluding remarks

  • The beta-binomial length update allows for a fairly flexible parametrisation of the growth transition matrix
  • In gadget it is fairly straightforward to either create your own growth functions or modify existing functions through model parameters
  • Computationally expensive (order of magnitude), growth is applied to each age–length cell
    • Typical implementation has 50 length- and 15 agegroups on quarterly timesteps
    • Expect optimisation times w/o random effects around 15 mins with very basic models on recent hardware
    • Reducing the number of age and lengthgroups can reduce run times
    • Random effects require substantially more resources
  • It is possible to fit models without age data, but some information on growth is helpful
  • Alternative formulations are being investigated

References

Stefansson, Gunnar. 2005. Growth models in population simulations.” Final Report DST2: Development of Structurally Detailed Statistically Testable Models of Marine Populations, Technical Report 118: 73–80.