Skip to content

Add informative error if user specifies multiple state variables for a simple_*_* #73

@wpetry

Description

@wpetry

Defining kernels with >1 state variable should throw an informative error recommending the user to check their state definitions for typos or set sim_gen = "general".

Relates to #69.

Reprex

library(ipmr)

p_list <- list(
  surv_int = -6,
  surv_z = 1.68,
  grow_int = 1.27,
  grow_z = 0.612,
  grow_sd = 0.0787,
  flow_int = -7.88,
  flow_z = 2.11,
  seed_int = 2.6204,
  seed_z = 0.01256,
  bank_int = -0.91,
  est = 0.1,
  recr_mu = 0,
  recr_sd = 0.1
)

Scenario 1: Modification requires general IPM

User decides to add a discrete seed bank to a simple IPM, but doesn't change sim_gen = "general". The error message is difficult to parse, in part because of how late it arises. Desired behavior would be to error as soon as the SBin kernel is defined with a new state variable that does not match the previous kernels.

ipm <- init_ipm(sim_gen = "simple", di_dd = "di", det_stoch = "det",
                    uses_age = FALSE) |>
  define_kernel(
    name          = "P",
    family        = "CC",
    formula       = (s * g) * d_z,
    s             = plogis(surv_int + surv_z * z_1),  # size-specific survival
    g             = dnorm(z_2, mu_g, grow_sd),        # size-specific growth
    mu_g          = grow_int + grow_z * z_1,
    data_list     = p_list,
    states        = list(c("z")),
    uses_par_sets = FALSE,
    evict_cor     = FALSE
  ) |>
  define_kernel(
    name          = "F",
    family        = "CC",
    formula       = r_r * r_s * est * r_d * d_z,
    r_r           = plogis(flow_int + flow_z * z_1),  # Pr(flowering|size)
    r_s           = exp(seed_int + seed_z * z_1),     # seed production | size & flowering = 1
    r_d           = dnorm(z_2, recr_mu, recr_sd),
    data_list     = p_list,
    states        = list(c("z")),
    uses_par_sets = FALSE,
    evict_cor     = FALSE
  ) |>
  define_kernel(
    name          = "SBin",
    family        = "CD",
    formula       = r_r * r_s * (1 - est) * d_z,
    r_r           = plogis(flow_int + flow_z * z_1),  # Pr(flowering|size)
    r_s           = exp(seed_int + seed_z * z_1),     # seed production | size & flowering = 1
    data_list     = p_list,
    states        = list(c("z", "b")),
    uses_par_sets = FALSE,
    evict_cor     = FALSE
  ) |>
  define_kernel(
    name          = "SBout",
    formula       = est * r_d,
    r_d           = dnorm(z_2, recr_mu, recr_sd),
    family        = "DC",
    data_list     = p_list,
    states        = list(c("b", "z")),
    uses_par_sets = FALSE,
    evict_cor     = FALSE
  ) |>
  define_impl(
    make_impl_args_list(
      kernel_names = c("P", "F", "SBin", "SBout"),
      int_rule     = rep("midpoint", 4),
      state_start  = c("z", "z", "z", "b"),
      state_end    = c("z", "z", "b", "z")
    )
  ) |>
  define_domains(
    z = c(-1, 6, 100)
  ) |>
  define_pop_state(
    n_z = runif(100),
    n_b = 100,
  )

## Throws error only at the make_ipm() stage
ipm |>
  make_ipm(
    iterate = TRUE,
    iterations = 100
  )

Scenario 2: Typo in state variable

User makes a typo in one of the kernel definitions. The error message is difficult to parse, in part because of how late it arises. Desired behavior would be to error as soon as the F kernel is defined with a new state variable that does not match the previous kernels.

ipm2 <- init_ipm(sim_gen = "simple", di_dd = "di", det_stoch = "det",
                    uses_age = FALSE) |>
  define_kernel(
    name          = "P",
    family        = "CC",
    formula       = (s * g) * d_z,
    s             = plogis(surv_int + surv_z * z_1),  # size-specific survival
    g             = dnorm(z_2, mu_g, grow_sd),        # size-specific growth
    mu_g          = grow_int + grow_z * z_1,
    data_list     = p_list,
    states        = list(c("z")),
    uses_par_sets = FALSE,
    evict_cor     = FALSE
  ) |>
  define_kernel(
    name          = "F",
    family        = "CC",
    formula       = r_r * r_s * est * r_d * d_z,
    r_r           = plogis(flow_int + flow_z * z_1),  # Pr(flowering|size)
    r_s           = exp(seed_int + seed_z * z_1),     # seed production | size & flowering = 1
    r_d           = dnorm(z_2, recr_mu, recr_sd),
    data_list     = p_list,
    states        = list(c("x")),  # TYPO IN STATE VARIABLE
    uses_par_sets = FALSE,
    evict_cor     = FALSE
  ) |>
  define_impl(
    make_impl_args_list(
      kernel_names = c("P", "F"),
      int_rule     = rep("midpoint", 2),
      state_start  = c("z", "z"),
      state_end    = c("z", "z")
    )
  ) |>
  define_domains(
    z = c(-1, 6, 100)
  ) |>
  define_pop_state(
    n_z = runif(100)
  )

## Throws error only at the make_ipm() stage
ipm2 |>
  make_ipm(
    iterate = TRUE,
    iterations = 100
  )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions