Skip to contents

Run an ensemble simulation of a stock-and-flow model, varying initial conditions and/or parameters in the range specified in range. The ensemble can be run in parallel using multiple threads by first setting use_threads(). The results are returned as a dataframe with summary statistics and optionally individual simulations.

Usage

ensemble(
  sfm,
  n = 10,
  return_sims = FALSE,
  range = NULL,
  cross = TRUE,
  quantiles = c(0.025, 0.975),
  only_stocks = TRUE,
  keep_nonnegative_flow = TRUE,
  keep_nonnegative_stock = FALSE,
  keep_unit = TRUE,
  verbose = TRUE
)

Arguments

sfm

Stock-and-flow model, object of class sdbuildR_xmile.

n

Number of simulations to run in the ensemble. When range is specified, n defines the number of simulations to run per condition. If each condition only needs to be run once, set n = 1. Defaults to 10.

return_sims

If TRUE, return the individual simulations in the ensemble. Set to FALSE to save memory. Defaults to FALSE.

range

List of ranges to vary parameters in the ensemble. Only stocks and constants can be specified. All ranges have to be of the same length if cross = FALSE. Defaults to NULL.

cross

If TRUE, cross the parameters in the range list to generate all possible combinations of parameters. Defaults to TRUE.

quantiles

Quantiles to calculate in the summary, e.g. c(0.025, 0.975).

only_stocks

If TRUE, only save stocks. If FALSE, auxiliaries and flows are saved using a callback function. Only applies if language is set to "Julia" in sim_specs() and no delay functions are used. Defaults to FALSE.

keep_nonnegative_flow

If TRUE, keeps original non-negativity setting of flows. Defaults to TRUE.

keep_nonnegative_stock

If TRUE, keeps original non-negativity setting of stocks Defaults to FALSE.

keep_unit

If TRUE, keeps units of variables. Defaults to TRUE.

verbose

If TRUE, update on progress. Defaults to FALSE.

Value

Object of class sdbuildR_ensemble, which is a list containing:

success

If TRUE, simulation was successful. If FALSE, simulation failed.

error_message

If success is FALSE, contains the error message.

df

Dataframe with simulation results in long format, if return_sims is TRUE. The iteration number is indicated by column "i". If range was specified, the condition is indicated by column "j".

summary

Dataframe with summary statistics of the ensemble, including quantiles specified in quantiles. If range was specified, summary statistics are calculated for each condition (j) in the ensemble.

n

Number of simulations run in the ensemble (per condition j if range is specified).

n_total

Total number of simulations run in the ensemble (across all conditions if range is specified).

n_conditions

Total number of conditions.

conditions

Dataframe with the conditions used in the ensemble, if range is specified.

init

List with df (if return_sims = TRUE) and summary, containing dataframe with the initial values of the stocks used in the ensemble.

constants

List with df (if return_sims = TRUE) and summary, containing dataframe with the constant parameters used in the ensemble.

script

Julia script used for the ensemble simulation.

duration

Duration of the simulation in seconds.

...

Other parameters passed to ensemble

Details

To run large simulations, it is recommended to limit the output size by saving fewer values. To create a reproducible ensemble simulation, set a seed using sim_specs().

If you do not see any variation within a condition of the ensemble (i.e. the confidence bands are virtually non-existent), there are likely no random elements in your model. Without these, there can be no variability in the model. Try specifying a random initial condition or adding randomness to other model elements.

Examples


if (FALSE)  # requires Julia setup
if (JuliaConnectoR::juliaSetupOk()) {
  # Load example and set simulation language to Julia
  sfm <- xmile("predator_prey") |> sim_specs(language = "Julia")

  # Set random initial conditions
  sfm <- build(sfm, c("predator", "prey"), eqn = "runif(1, min = 20, max = 80)")

  # For ensemble simulations, it is highly recommended to reduce the
  # returned output. For example, to save only every 1 time units and discard
  # the first 100 time units, use:
  sfm <- sim_specs(sfm, save_at = 1, save_from = 100)

  # Run ensemble simulation with 100 simulations
  sims <- ensemble(sfm, n = 100)
  plot(sims)

  # Plot individual trajectories
  sims <- ensemble(sfm, n = 10, return_sims = TRUE)
  plot(sims, type = "sims")

  # Specify which trajectories to plot
  plot(sims, type = "sims", i = 1)

  # Plot the median with lighter individual trajectories
  plot(sims, central_tendency = "median", type = "sims", alpha = 0.1)

  # Ensembles can also be run with exact values for the initial conditions
  # and parameters. Below, we vary the initial values of the predator and the
  # birth rate of the predators (delta). We generate a hunderd samples per
  # condition. By default, the parameters are crossed, meaning that all
  # combinations of the parameters are run.
  sims <- ensemble(sfm,
    n = 50,
    range = list("predator" = c(10, 50), "delta" = c(.025, .05))
  )

  plot(sims)

  # By default, a maximum of nine conditions is plotted.
  # Plot specific conditions:
  plot(sims, j = c(1, 3), nrows = 1)

  # Generate a non-crossed design, where the length of each range needs to be
  # equal:
  sims <- ensemble(sfm,
    n = 10, cross = FALSE,
    range = list(
      "predator" = c(10, 20, 30),
      "delta" = c(.020, .025, .03)
    )
  )
  plot(sims, nrows = 3)

  # Run simulation in parallel
  use_threads(4)
  sims <- ensemble(sfm, n = 10)

  # Stop using threads
  use_threads(stop = TRUE)

  # Close Julia
  use_julia(stop = TRUE)
}
 # \dontrun{}