Aorus
Aorus

Reputation: 138

Resetting R simmer environment for Monte Carlo replications

I would like to run Monte Carlo replications of my simmer simulation and was wondering if there is a way to do this without calling simmer::simmer() within the replication loop while still ensuring that new simmer::timeout() values are randomly generated for each iteration.

At a high level, my setup is as follows:

env <- setup_sim(input_params)
results <- run_sim(env, n_mc = 100)

where setup_sim() is a function that initializes the simmer environment and adds resources and trajectories. I would like to separate environment creation from executing the simulation, since I am defining the environment programmatically and it takes a nonsignificant amount of time to set up.

I then call run_sim() to execute the simulation, resetting the simmer environment each time:

run_sim <- function(.env, run_until = Inf, n_mc = 1, use_parallel = FALSE) {
  # Run simulation
  start_time <- Sys.time()

  print('Simulating...')
  if (use_parallel == TRUE & n_mc > 1) {
    envs <- parallel::mclapply(1:n_mc, function(i) {
      .env |>
        simmer::reset() |>
        simmer::run(until = run_until) |>
        simmer::wrap()
      })
    } else {
      envs <- purrr::map(
        seq.int(1, n_mc),
        function(i) {
          .env |>
            simmer::reset() |>
            simmer::run(
              until = run_until,
              progress = simmer_progress
              )
        },
        .progress = pb_bar_options
        )
      }

  duration <- Sys.time() - start_time
  print('Simulation complete. ')
  print(duration)

  envs
}

However, I noticed that the random number generated for timeouts do not change across replications, even though they are generated from function calls:

... |>
    simmer::timeout(
        \() {
          step_nbr <- simmer::get_attribute(env, keys = 'step_nbr')
          cycle_time <- get_cycle_time_wrapper(
            step_nbr,
            simmer::get_selected(env),
            rand_seed = sample.int(100000, 1)
            ) *
            simmer::get_attribute(env, keys = 'TimeMultiplier')

          cycle_time
        }
        ) |> 
...

where get_cycle_time_wrapper() is a function that randomly samples values from a lookup table.

Is there a way to ensure a new random sample for each replication given my setup, or do I have to recreate the simmer environment each time?

Thanks!

Upvotes: 1

Views: 50

Answers (0)

Related Questions