Skip to content

Commit 5774e57

Browse files
committed
update from Atlas
1 parent 4ef4b82 commit 5774e57

File tree

3 files changed

+461
-0
lines changed

3 files changed

+461
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ concurrency/charfinder/charfinder_index.pickle
33
18-asyncio/charfinder/charfinder_index.pickle
44
metaprog/oscon-schedule/data/schedule?_db
55
concurrency/wikipedia/fixture/docroot/
6+
17-futures/countries/flags/
67

78
# Byte-compiled / optimized / DLL files
89
__pycache__/

16-coroutine/taxi_sim.py

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
2+
"""
3+
Taxi simulator
4+
==============
5+
6+
Driving a taxi from the console::
7+
8+
>>> from taxi_sim import taxi_process
9+
>>> taxi = taxi_process(ident=13, trips=2, start_time=0)
10+
>>> next(taxi)
11+
Event(time=0, proc=13, action='leave garage')
12+
>>> taxi.send(_.time + 7)
13+
Event(time=7, proc=13, action='pick up passenger')
14+
>>> taxi.send(_.time + 23)
15+
Event(time=30, proc=13, action='drop off passenger')
16+
>>> taxi.send(_.time + 5)
17+
Event(time=35, proc=13, action='pick up passenger')
18+
>>> taxi.send(_.time + 48)
19+
Event(time=83, proc=13, action='drop off passenger')
20+
>>> taxi.send(_.time + 1)
21+
Event(time=84, proc=13, action='going home')
22+
>>> taxi.send(_.time + 10)
23+
Traceback (most recent call last):
24+
File "<stdin>", line 1, in <module>
25+
StopIteration
26+
27+
Sample run with two cars, random seed 10. This is a valid doctest::
28+
29+
>>> main(num_taxis=2, seed=10)
30+
taxi: 0 Event(time=0, proc=0, action='leave garage')
31+
taxi: 0 Event(time=5, proc=0, action='pick up passenger')
32+
taxi: 1 Event(time=5, proc=1, action='leave garage')
33+
taxi: 1 Event(time=10, proc=1, action='pick up passenger')
34+
taxi: 1 Event(time=15, proc=1, action='drop off passenger')
35+
taxi: 0 Event(time=17, proc=0, action='drop off passenger')
36+
taxi: 1 Event(time=24, proc=1, action='pick up passenger')
37+
taxi: 0 Event(time=26, proc=0, action='pick up passenger')
38+
taxi: 0 Event(time=30, proc=0, action='drop off passenger')
39+
taxi: 0 Event(time=34, proc=0, action='going home')
40+
taxi: 1 Event(time=46, proc=1, action='drop off passenger')
41+
taxi: 1 Event(time=48, proc=1, action='pick up passenger')
42+
taxi: 1 Event(time=110, proc=1, action='drop off passenger')
43+
taxi: 1 Event(time=139, proc=1, action='pick up passenger')
44+
taxi: 1 Event(time=140, proc=1, action='drop off passenger')
45+
taxi: 1 Event(time=150, proc=1, action='going home')
46+
*** end of events ***
47+
48+
See longer sample run at the end of this module.
49+
50+
"""
51+
52+
import random
53+
import collections
54+
import queue
55+
import argparse
56+
import time
57+
58+
DEFAULT_NUMBER_OF_TAXIS = 3
59+
DEFAULT_END_TIME = 180
60+
SEARCH_DURATION = 5
61+
TRIP_DURATION = 20
62+
DEPARTURE_INTERVAL = 5
63+
64+
Event = collections.namedtuple('Event', 'time proc action')
65+
66+
67+
# BEGIN TAXI_PROCESS
68+
def taxi_process(ident, trips, start_time=0): # <1>
69+
"""Yield to simulator issuing event at each state change"""
70+
time = yield Event(start_time, ident, 'leave garage') # <2>
71+
for i in range(trips): # <3>
72+
time = yield Event(time, ident, 'pick up passenger') # <4>
73+
time = yield Event(time, ident, 'drop off passenger') # <5>
74+
75+
yield Event(time, ident, 'going home') # <6>
76+
# end of taxi process # <7>
77+
# END TAXI_PROCESS
78+
79+
80+
# BEGIN TAXI_SIMULATOR
81+
class Simulator:
82+
83+
def __init__(self, procs_map):
84+
self.events = queue.PriorityQueue()
85+
self.procs = dict(procs_map)
86+
87+
def run(self, end_time): # <1>
88+
"""Schedule and display events until time is up"""
89+
# schedule the first event for each cab
90+
for _, proc in sorted(self.procs.items()): # <2>
91+
first_event = next(proc) # <3>
92+
self.events.put(first_event) # <4>
93+
94+
# main loop of the simulation
95+
sim_time = 0 # <5>
96+
while sim_time < end_time: # <6>
97+
if self.events.empty(): # <7>
98+
print('*** end of events ***')
99+
break
100+
101+
current_event = self.events.get() # <8>
102+
sim_time, proc_id, previous_action = current_event # <9>
103+
print('taxi:', proc_id, proc_id * ' ', current_event) # <10>
104+
active_proc = self.procs[proc_id] # <11>
105+
next_time = sim_time + compute_duration(previous_action) # <12>
106+
try:
107+
next_event = active_proc.send(next_time) # <13>
108+
except StopIteration:
109+
del self.procs[proc_id] # <14>
110+
else:
111+
self.events.put(next_event) # <15>
112+
else: # <16>
113+
msg = '*** end of simulation time: {} events pending ***'
114+
print(msg.format(self.events.qsize()))
115+
# END TAXI_SIMULATOR
116+
117+
118+
def compute_duration(previous_action):
119+
"""Compute action duration using exponential distribution"""
120+
if previous_action in ['leave garage', 'drop off passenger']:
121+
# new state is prowling
122+
interval = SEARCH_DURATION
123+
elif previous_action == 'pick up passenger':
124+
# new state is trip
125+
interval = TRIP_DURATION
126+
elif previous_action == 'going home':
127+
interval = 1
128+
else:
129+
raise ValueError('Unknown previous_action: %s' % previous_action)
130+
return int(random.expovariate(1/interval)) + 1
131+
132+
133+
def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS,
134+
seed=None):
135+
"""Initialize random generator, build procs and run simulation"""
136+
if seed is not None:
137+
random.seed(seed) # get reproducible results
138+
139+
taxis = {i: taxi_process(i, (i+1)*2, i*DEPARTURE_INTERVAL)
140+
for i in range(num_taxis)}
141+
sim = Simulator(taxis)
142+
sim.run(end_time)
143+
144+
145+
if __name__ == '__main__':
146+
147+
parser = argparse.ArgumentParser(
148+
description='Taxi fleet simulator.')
149+
parser.add_argument('-e', '--end-time', type=int,
150+
default=DEFAULT_END_TIME,
151+
help='simulation end time; default = %s'
152+
% DEFAULT_END_TIME)
153+
parser.add_argument('-t', '--taxis', type=int,
154+
default=DEFAULT_NUMBER_OF_TAXIS,
155+
help='number of taxis running; default = %s'
156+
% DEFAULT_NUMBER_OF_TAXIS)
157+
parser.add_argument('-s', '--seed', type=int, default=None,
158+
help='random generator seed (for testing)')
159+
160+
args = parser.parse_args()
161+
main(args.end_time, args.taxis, args.seed)
162+
163+
164+
"""
165+
166+
Sample run from the command line, seed=3, maximum elapsed time=120::
167+
168+
# BEGIN TAXI_SAMPLE_RUN
169+
$ python3 taxi_sim.py -s 3 -e 120
170+
taxi: 0 Event(time=0, proc=0, action='leave garage')
171+
taxi: 0 Event(time=2, proc=0, action='pick up passenger')
172+
taxi: 1 Event(time=5, proc=1, action='leave garage')
173+
taxi: 1 Event(time=8, proc=1, action='pick up passenger')
174+
taxi: 2 Event(time=10, proc=2, action='leave garage')
175+
taxi: 2 Event(time=15, proc=2, action='pick up passenger')
176+
taxi: 2 Event(time=17, proc=2, action='drop off passenger')
177+
taxi: 0 Event(time=18, proc=0, action='drop off passenger')
178+
taxi: 2 Event(time=18, proc=2, action='pick up passenger')
179+
taxi: 2 Event(time=25, proc=2, action='drop off passenger')
180+
taxi: 1 Event(time=27, proc=1, action='drop off passenger')
181+
taxi: 2 Event(time=27, proc=2, action='pick up passenger')
182+
taxi: 0 Event(time=28, proc=0, action='pick up passenger')
183+
taxi: 2 Event(time=40, proc=2, action='drop off passenger')
184+
taxi: 2 Event(time=44, proc=2, action='pick up passenger')
185+
taxi: 1 Event(time=55, proc=1, action='pick up passenger')
186+
taxi: 1 Event(time=59, proc=1, action='drop off passenger')
187+
taxi: 0 Event(time=65, proc=0, action='drop off passenger')
188+
taxi: 1 Event(time=65, proc=1, action='pick up passenger')
189+
taxi: 2 Event(time=65, proc=2, action='drop off passenger')
190+
taxi: 2 Event(time=72, proc=2, action='pick up passenger')
191+
taxi: 0 Event(time=76, proc=0, action='going home')
192+
taxi: 1 Event(time=80, proc=1, action='drop off passenger')
193+
taxi: 1 Event(time=88, proc=1, action='pick up passenger')
194+
taxi: 2 Event(time=95, proc=2, action='drop off passenger')
195+
taxi: 2 Event(time=97, proc=2, action='pick up passenger')
196+
taxi: 2 Event(time=98, proc=2, action='drop off passenger')
197+
taxi: 1 Event(time=106, proc=1, action='drop off passenger')
198+
taxi: 2 Event(time=109, proc=2, action='going home')
199+
taxi: 1 Event(time=110, proc=1, action='going home')
200+
*** end of events ***
201+
# END TAXI_SAMPLE_RUN
202+
203+
"""

0 commit comments

Comments
 (0)