Concept Review — Discrete Event Simulation
So what will it take to simulate a theme park on my laptop? And will it look anything like Game Central Station from Wreck-it-Ralph?
I’m afraid not … the code written in R will use Discrete Event Simulation or DES, which really just shows what could happen in a process over time. The major use case of DES is to optimize processes which is why it is commonly used in operations research. Simulations allow decision-makers to view a typical process after many iterations and see how it could be improved. For example, would adding extra machines to a factory line reduce bottlenecks in producing a product?
This article will apply DES to a hypothetical Disney World. This version of the park will be a bit simpler and will have some extra assumptions to make the modelling easier.
As this blog is focussed more on the application, there will be lots of code examples over theory, but this concept review of the components involved should help get us up to speed.
There are some basic components that are required for DES to work. Each one is something we will create using simmer but let’s review them here before the coding begins:
- Trajectory: A trajectory is a path that a guest will take through the simulation. For example, when a guest arrives, they may queue up for a ride, go on a ride and then leave. This would be their trajectory.
- Resource: A resource is a thing that is used during the trajectory. In the example above, the ride would be a resource.
- Generator: A generator is an item we use to generate the guests, and generators will typically generate many guests over the course of a simulation. The generator also needs a trajectory to know where generated guests should go.
- Environment: The environment is where this whole simulation runs, in our case this is the Theme Park itself. It encapsulates all of our resources, generators and trajectories. With simmer there is an added advantage that the environment will also track and report our resource use, which makes the analysis of the simulation much simpler.
With that review completed, let’s get hands-on! The simulations below build on one another and increase in complexity as they go on. For illustrative purposes, the code is not refactored until the final simulation which takes advantage of some extra R functions and features to clean up the simulation.
Simulation One: Meeting Lilo and Stitch
The first simulation will serve as an introduction. In this simulation, guests arrive and start to queue to see Lilo and Stitch. Before coding, it’s helpful to review what the components will be:
- Trajectory: Arrive at the park, queue, use character resource (Lilo or Stitch), release character resource and leave the park.
- Resource: Character that guests can meet. Either Lilo or Stitch, therefore, capacity is set to two for this resource, meaning it can be seized by two guests at once.
- Generator: Will generate guests periodically arriving at the park.
- Environment: The park itself.
Now let’s think about the code for each element. R allows us to take advantage of other packages like dplyr to organize the code we write. This makes trajectory building much simpler:
First, the guest seizes a character locking them from use by any other guest. Then they time out with that resource. Time out simply means they cannot do anything else. The length of time out in most simulations will be based on a real process. However, in this made-up scenario, the length of the timeout is sampled from a normal distribution. Finally, the guest releases the resource and it can once again be used by another guest in the queue.
The trajectory is the most complicated concept. The environment, resources and generator are all defined together in one block of code:
This set of components is again very basic. The important notes are that the resource has a capacity of two, as per the specification. The guests arrive according to an exponential function and are given the trajectory defined above. The arrival of guests would also typically be modeled after a real event but for the purpose of the example, the exponential will work just fine!
The last step is running the simulation and doing some analysis. Running the simulation is as simple as typing run and providing a number of timesteps to run for. In this case, the park will open for 15 hours. For analysis, we will use simmer.plot an extension of the simmer library that builds some simple visualizations for us to use:
The first plot below shows the resource utilization. For this simulation, our utilization sits at just 20%. This percentage represents the proportion of the simulation time that the resource was in use.
The 20% utilization value is fairly low and ideally, we would have a higher utilization as this means more happy guests! The next visualization represents wait times, with no guests waiting for more than 5-time steps. This makes sense as our resource time out is based on a sample from a normal distribution around 5 steps. The average wait time, though, is much lower, represented by the blue line.
Simulation Two: Meeting Lilo and Stitch with fast passes
Now let’s add some complexity, starting slowly. The simulation will remain the same as above. However, we will add priority customers. These will mimic the ‘FastPass’ system in Disney Parks. Really all we do is generate a new customer who has priority:
Note that this customer has a priority of one, as opposed to the default customer which defaults to 0. A higher priority value means that this customer will skip the queue and ride before all customers of lower priority. The other addition is that these customers arrive every 50-time steps. In reality, they would have pre-booked a pass for a certain evenly spaced out time.