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 TRUE.

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

# 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)
#> Running a total of 100 simulations
#> Starting Julia ...
#> Connecting to Julia TCP server at localhost:11980 ...
#> Package "Tables.jl" (version >= 1.0) is required. Installing ...
#> Starting Julia ...
#> Setting up Julia environment for sdbuildR...
#> Simulation took 7.1842 seconds
plot(sims)
# Plot individual trajectories sims <- ensemble(sfm, n = 10, return_sims = TRUE) #> Running a total of 10 simulations #> Simulation took 0.6144 seconds 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)) ) #> Running a total of 200 simulations for 4 conditions (50 simulations per condition) #> Simulation took 1.6544 seconds 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) ) ) #> Running a total of 30 simulations for 3 conditions (10 simulations per condition) #> Simulation took 0.458 seconds plot(sims, nrows = 3)
# Run simulation in parallel use_threads(4) #> Warning: n is set to 4, which is higher than the number of available cores minus 1. Setting it to 3. sims <- ensemble(sfm, n = 10) #> Running a total of 10 simulations #> Simulation took 1.3759 seconds # Stop using threads use_threads(stop = TRUE) # Close Julia use_julia(stop = TRUE)