Toll Lanes: Simulation
Please Log In for full access to the web site.
Note that this link will take you to an external site (https://shimmer.mit.edu) to authenticate, and then you will be redirected back to this page.
1) Toll Simulator
As a toll company, we need to decide on how many toll lanes to have. Therefore, we're interested in predicting how many cars there will be waiting at the tolls on average given a certain number of toll lanes - and we'll do this via a Monte Carlo simulation. We'll repeatedly run random trials and then average them to get a more robust estimate. We'll use those estimates to optimize the number of lanes to build.
Based on years of traffic data, our company knows the probabilities of different numbers of cars arriving at this section of road, which they refer to as arrival_probs. It is represented as a dictionary mapping a number of cars to the probability that each minute, that many cars will arrive. For instance, {0: 0.5, 1: 0.3, 3: 0.2} means that for any given minute, there is a 50% chance of 0 cars arriving, a 30% chance of 1 car coming, and a 20% chance of 3 cars. Additionally, if there is only one lane, all the arriving cars go to that lane. But if there are multiple lanes, then the cars will randomly and uniformly choose a lane regardless of how many cars are already in that lane. (This is different from the hypothesis mentioned in the previous exercise.)
2) Simulating Arrivals
First, we will start by simulating the arrival of cars in a single minute. Your task for this section is to make a function simulate_minute(arrival_probs, num_lanes) which takes in arrival_probs and num_lanes (defined in the previous section) and returns a random list which represents the number of cars that are arriving in each lane. Since numpy operations generally run faster than generic Python operations, we will practice using numpy here as well!
How many different lists could simulate_minute({3: 1.0}, 2) randomly generate? How likely is each list?
Because arrival_prob is {3: 1.0}, 3 cars are guaranteed to arrive each time. This simplifies the problem down to randomly sorting three cars into two lanes.
This can be thought of as similar to flipping a coin three times and then counting the number of heads and tails that appear. Flipping a coin three times in a row is equally likely to result in the following outcomes: HHH, HHT, HTH, THH, HTT, THT, TTH, TTT.
In the eight possible outcomes, [3 H, 0 T] appears once, [2 H, 1 T] appears 3 times, [1 H, 2 T] appears 3 times, and [0 H, 3 T] appears once.
simulate_minute({0: 0.5, 1: 0.3, 3: 0.2, 4: 0}, 3) could potentially generate?
Explanation to above question:
Since we are using random functions, the code checker is very lenient and accepts any reasonable response. To that end, it's pretty straightforward to get 100% on this exercise, but for your own edification please work through the problem responsibly.
Try to attempt this problem using numpy as a means of practice, but since this is a lot of new syntax, please feel free to look at the more in-depth guide below where we break down the steps of the function and offer tips:
-
Initializing a numpy array can be done using syntax from this reading such as
numpy.array([0, 0, 0]). A slightly more general form is to use the functionnumpy.zeros(3)which also makes a 3 long array of zeros. -
In order to randomly choose a number of cars, we could use something like
numpy.random.choice([0, 1, 2, 3], p=[0.7, 0.2, 0.05, 0.05])from the reading. This will return an integer randomly chosen based on the arrival probabilities{0: 0.7, 1: 0.2, 2: 0.05, 3: 0.05}. -
In order to randomly sort 5 cars into 3 lanes (numbered 0, 1, 2), we could use something like
numpy.random.randint(3, size=5)which will return a numpy array of length 5 with the lane numbers the cars were assigned. For example, a list like[1, 0, 0, 2, 0]could be generated, which would mean 3 cars were added to lane 0, 1 car was added to lane 1, and 1 car was added to lane 2. This should result in a final list of[3, 1, 1]being returned.
3) Simulating Trials
Now that we can generate arrivals for a single minute, we can simulate a single trial for a set of toll lanes over time. Your task for this section is to make a function simulate_lanes(arrival_probs, num_lanes, num_minutes) which takes in arrival_probs, num_lanes and num_minutes (an integer representing how long to run the simulation.) This function will randomly generate a lanes_list that represents the number of cars waiting in each lane each minute according to the process described below. Since numpy operations generally run faster than generic Python operations, we will practice using numpy here as well!
To make data for a single trial, we will start with a numpy array representing the number of cars in each lane initialized to zero. Then for each minute, we will deduct one car from any lane with a positive number of cars. Next, we randomly generate the number of cars arriving to the lanes and add that to the number of waiting cars. If we repeat this process and keep track of the number of cars in each lane in each minute, we can create a list of lists of the number of cars per lane in each minute (the same lane_lines format used as inputs in previous questions.)
For example, if we call simulate_lanes({0: 0.5, 1: 0.3, 3: 0.2}, 2, 3), one possible outcome is as follows:
- Minute 0: the lane_list starts with containing one list of cars
[0, 0](0 cars in each lane.) - Minute 1: we randomly sample the number of arrivals and get 1 car, then randomly assign that car to the lane at index 1, resulting in
[0, 1]. Then, since there were no waiting cars from minute 0 we append[0, 1]to the lane_list. - Minute 2: we deduct a car from any positive lane, and get
[0, 0]. Then a random sampling generates 3 arrival cars and randomly distributes them into the lanes resulting in[2, 1]to add on to the waiting cars[0, 0]for a result of[2, 1]being added to the end of the lane_list. - Minute 3: deduct cars from minute 2 to get
[1, 0].Randomly generate 1 car which is sorted into lanes[0, 1]. Add list of arriving cars to list of previously waiting cars[1, 0]for a final list of[1, 1]being added to the lane_list. - Finally, the function returns the completed lane_list
[[0, 0], [0, 1], [2, 1], [1, 1]]
Your code might result in different numbers of arrivals due to different random number generation, but a reasonable implementation should never produce impossible results. For example, [[0, 0], [3, 3]] is not possible because 6 total cars arriving in one minute isn't possible according to the arrival_prob {0: 0.5, 1: 0.3, 3: 0.2}. However, [[1, 0], [1, 0]] is possible because 1 car could leave lane 0 and 1 car could also arrive in one minute.
Since we are using random functions, the code checker is very lenient and accepts any reasonable response. To that end, it's pretty straightforward to get 100% on this exercise, but for your own edification please work through the problem responsibly.
Try to attempt this problem using numpy as a means of practice, but since this is a lot of new syntax, please feel free to look at the more in-depth guide below where we break down the steps of the function and offer tips:
-
Initializing a numpy array can be done using syntax from this reading such as
numpy.array([0, 0, 0]). A slightly more general form is to use the functionnumpy.zeros(3)which also makes a 3 long array of zeros. -
As for repeating the process for each minute in
num_minutes, we expect a for loop to be handy. -
For deducting a car from lanes with positive numbers, try running this code snippet to see what happens:
a = numpy.array([0, 5, 2])
print(a > 3)
print(a - (a > 3))
-
The simulate_minute function you wrote in the previous section should be helpful for generating the cars that are arriving to the lanes in the current minute.
-
Note that once you randomly generate the number of arrivals by lane, you can add the values in numpy arrays together using the
+sign.
3.1) Simulations for Stats
Now that we can simulate the toll lane process, we can use this to answer some analytical questions. For example:
How many distinct cars arrive in a 20 minute simulation given arrival_probs of {0: 0.5, 1: 0.3, 3: 0.2} and 2 lanes?
We can estimate this using the Monte Carlo method by finding the average number of cars that arrived across a large number (at least 100) of 20-minute simulations with the given arrival_probs and lanes. How you decide to calculate these estimates is up to you (you may use previously defined functions or create new functions / use additional packages.)
arrival_probs of {2: 1.0} and 2 lanes? Enter your answer below as a Python float:
arrival_probs of {0: 0.5, 1: 0.3, 3: 0.2} and 2 lanes? Enter your answer below as a Python float:
arrival_probs of {1: 0.1, 5: 0.9} and 2 toll lanes, how many total cars are waiting at the tolls at any given minute during a simulation of 20 minutes? (Note: make sure to take the average over the 20 minutes.) Enter your answer below as a Python float:
arrival_probs of {1: 0.1, 5: 0.9}, what is the minimum number of lanes so that on average over 20 minutes we have an average of 1 or fewer car in each lane? Enter your answer below as a Python integer:
Next Exercise: Toll Lanes: Design Reflection
6.s090