Skip to content

Commit d2cd714

Browse files
authored
Merge pull request #74 from realpython/simpy
Simpy
2 parents 2c70a60 + 96328bc commit d2cd714

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

simulation-with-simpy/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Simulating Real-World Processes With SimPy
2+
3+
Corresponding code for ["Simulating Real-World Processes With SimPy."](https://realpython.com/simulation-with-simpy/)
4+
5+
## Running the Script
6+
7+
The file `simulate.py` contains the script that mimics the tutorial code. You can execute the code by running `python3 simulate.py` from the directory that contains the file.
8+
9+
Here is some sample output:
10+
11+
```console
12+
$ python3 simulate.py
13+
Input # of cashiers working: 1
14+
Input # of servers working: 1
15+
Input # of ushers working: 1
16+
Running simulation...
17+
The average wait time is 42 minutes and 26 seconds.
18+
```

simulation-with-simpy/simulate.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
"""Companion code to https://realpython.com/simulation-with-simpy/
2+
3+
'Simulating Real-World Processes With SimPy'
4+
5+
Python version: 3.7.3
6+
SimPy version: 3.0.11
7+
"""
8+
9+
import simpy
10+
import random
11+
import statistics
12+
13+
wait_times = []
14+
15+
16+
class Theater(object):
17+
def __init__(self, env, num_cashiers, num_servers, num_ushers):
18+
self.env = env
19+
self.cashier = simpy.Resource(env, num_cashiers)
20+
self.server = simpy.Resource(env, num_servers)
21+
self.usher = simpy.Resource(env, num_ushers)
22+
23+
def purchase_ticket(self, moviegoer):
24+
yield self.env.timeout(random.randint(1, 3))
25+
26+
def check_ticket(self, moviegoer):
27+
yield self.env.timeout(3 / 60)
28+
29+
def sell_food(self, moviegoer):
30+
yield self.env.timeout(random.randint(1, 5))
31+
32+
33+
def go_to_movies(env, moviegoer, theater):
34+
# Moviegoer arrives at the theater
35+
arrival_time = env.now
36+
37+
with theater.cashier.request() as request:
38+
yield request
39+
yield env.process(theater.purchase_ticket(moviegoer))
40+
41+
with theater.usher.request() as request:
42+
yield request
43+
yield env.process(theater.check_ticket(moviegoer))
44+
45+
if random.choice([True, False]):
46+
with theater.server.request() as request:
47+
yield request
48+
yield env.process(theater.sell_food(moviegoer))
49+
50+
# Moviegoer heads into the theater
51+
wait_times.append(env.now - arrival_time)
52+
53+
54+
def run_theater(env, num_cashiers, num_servers, num_ushers):
55+
theater = Theater(env, num_cashiers, num_servers, num_ushers)
56+
57+
for moviegoer in range(3):
58+
env.process(go_to_movies(env, moviegoer, theater))
59+
60+
while True:
61+
yield env.timeout(0.20) # Wait a bit before generating a new person
62+
63+
moviegoer += 1
64+
env.process(go_to_movies(env, moviegoer, theater))
65+
66+
67+
def get_average_wait_time(wait_times):
68+
average_wait = statistics.mean(wait_times)
69+
# Pretty print the results
70+
minutes, frac_minutes = divmod(average_wait, 1)
71+
seconds = frac_minutes * 60
72+
return round(minutes), round(seconds)
73+
74+
75+
def get_user_input():
76+
num_cashiers = input("Input # of cashiers working: ")
77+
num_servers = input("Input # of servers working: ")
78+
num_ushers = input("Input # of ushers working: ")
79+
params = [num_cashiers, num_servers, num_ushers]
80+
if all(str(i).isdigit() for i in params): # Check input is valid
81+
params = [int(x) for x in params]
82+
else:
83+
print(
84+
"Could not parse input. Simulation will use default values:",
85+
"\n1 cashier, 1 server, 1 usher.",
86+
)
87+
params = [1, 1, 1]
88+
return params
89+
90+
91+
def main():
92+
# Setup
93+
random.seed(42)
94+
num_cashiers, num_servers, num_ushers = get_user_input()
95+
96+
# Run the simulation
97+
env = simpy.Environment()
98+
env.process(run_theater(env, num_cashiers, num_servers, num_ushers))
99+
env.run(until=90)
100+
101+
# View the results
102+
mins, secs = get_average_wait_time(wait_times)
103+
print(
104+
"Running simulation...",
105+
f"\nThe average wait time is {mins} minutes and {secs} seconds.",
106+
)
107+
108+
109+
if __name__ == "__main__":
110+
main()

0 commit comments

Comments
 (0)