fixed merge
This commit is contained in:
commit
4ef4b82e82
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
concurrency/flags/img/*.gif
|
concurrency/flags/img/*.gif
|
||||||
concurrency/charfinder/charfinder_index.pickle
|
concurrency/charfinder/charfinder_index.pickle
|
||||||
|
18-asyncio/charfinder/charfinder_index.pickle
|
||||||
metaprog/oscon-schedule/data/schedule?_db
|
metaprog/oscon-schedule/data/schedule?_db
|
||||||
concurrency/wikipedia/fixture/docroot/
|
concurrency/wikipedia/fixture/docroot/
|
||||||
|
|
||||||
|
@ -1,203 +0,0 @@
|
|||||||
|
|
||||||
"""
|
|
||||||
Taxi simulator
|
|
||||||
==============
|
|
||||||
|
|
||||||
Driving a taxi from the console::
|
|
||||||
|
|
||||||
>>> from taxi_sim import taxi_process
|
|
||||||
>>> taxi = taxi_process(ident=13, trips=2, start_time=0)
|
|
||||||
>>> next(taxi)
|
|
||||||
Event(time=0, proc=13, action='leave garage')
|
|
||||||
>>> taxi.send(_.time + 7)
|
|
||||||
Event(time=7, proc=13, action='pick up passenger')
|
|
||||||
>>> taxi.send(_.time + 23)
|
|
||||||
Event(time=30, proc=13, action='drop off passenger')
|
|
||||||
>>> taxi.send(_.time + 5)
|
|
||||||
Event(time=35, proc=13, action='pick up passenger')
|
|
||||||
>>> taxi.send(_.time + 48)
|
|
||||||
Event(time=83, proc=13, action='drop off passenger')
|
|
||||||
>>> taxi.send(_.time + 1)
|
|
||||||
Event(time=84, proc=13, action='going home')
|
|
||||||
>>> taxi.send(_.time + 10)
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "<stdin>", line 1, in <module>
|
|
||||||
StopIteration
|
|
||||||
|
|
||||||
Sample run with two cars, random seed 10. This is a valid doctest::
|
|
||||||
|
|
||||||
>>> main(num_taxis=2, seed=10)
|
|
||||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
|
||||||
taxi: 0 Event(time=5, proc=0, action='pick up passenger')
|
|
||||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
|
||||||
taxi: 1 Event(time=10, proc=1, action='pick up passenger')
|
|
||||||
taxi: 1 Event(time=15, proc=1, action='drop off passenger')
|
|
||||||
taxi: 0 Event(time=17, proc=0, action='drop off passenger')
|
|
||||||
taxi: 1 Event(time=24, proc=1, action='pick up passenger')
|
|
||||||
taxi: 0 Event(time=26, proc=0, action='pick up passenger')
|
|
||||||
taxi: 0 Event(time=30, proc=0, action='drop off passenger')
|
|
||||||
taxi: 0 Event(time=34, proc=0, action='going home')
|
|
||||||
taxi: 1 Event(time=46, proc=1, action='drop off passenger')
|
|
||||||
taxi: 1 Event(time=48, proc=1, action='pick up passenger')
|
|
||||||
taxi: 1 Event(time=110, proc=1, action='drop off passenger')
|
|
||||||
taxi: 1 Event(time=139, proc=1, action='pick up passenger')
|
|
||||||
taxi: 1 Event(time=140, proc=1, action='drop off passenger')
|
|
||||||
taxi: 1 Event(time=150, proc=1, action='going home')
|
|
||||||
*** end of events ***
|
|
||||||
|
|
||||||
See longer sample run at the end of this module.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import random
|
|
||||||
import collections
|
|
||||||
import queue
|
|
||||||
import argparse
|
|
||||||
import time
|
|
||||||
|
|
||||||
DEFAULT_NUMBER_OF_TAXIS = 3
|
|
||||||
DEFAULT_END_TIME = 180
|
|
||||||
SEARCH_DURATION = 5
|
|
||||||
TRIP_DURATION = 20
|
|
||||||
DEPARTURE_INTERVAL = 5
|
|
||||||
|
|
||||||
Event = collections.namedtuple('Event', 'time proc action')
|
|
||||||
|
|
||||||
|
|
||||||
# BEGIN TAXI_PROCESS
|
|
||||||
def taxi_process(ident, trips, start_time=0): # <1>
|
|
||||||
"""Yield to simulator issuing event at each state change"""
|
|
||||||
time = yield Event(start_time, ident, 'leave garage') # <2>
|
|
||||||
for i in range(trips): # <3>
|
|
||||||
time = yield Event(time, ident, 'pick up passenger') # <4>
|
|
||||||
time = yield Event(time, ident, 'drop off passenger') # <5>
|
|
||||||
|
|
||||||
yield Event(time, ident, 'going home') # <6>
|
|
||||||
# end of taxi process # <7>
|
|
||||||
# END TAXI_PROCESS
|
|
||||||
|
|
||||||
|
|
||||||
# BEGIN TAXI_SIMULATOR
|
|
||||||
class Simulator:
|
|
||||||
|
|
||||||
def __init__(self, procs_map):
|
|
||||||
self.events = queue.PriorityQueue()
|
|
||||||
self.procs = dict(procs_map)
|
|
||||||
|
|
||||||
def run(self, end_time): # <1>
|
|
||||||
"""Schedule and display events until time is up"""
|
|
||||||
# schedule the first event for each cab
|
|
||||||
for _, proc in sorted(self.procs.items()): # <2>
|
|
||||||
first_event = next(proc) # <3>
|
|
||||||
self.events.put(first_event) # <4>
|
|
||||||
|
|
||||||
# main loop of the simulation
|
|
||||||
sim_time = 0 # <5>
|
|
||||||
while sim_time < end_time: # <6>
|
|
||||||
if self.events.empty(): # <7>
|
|
||||||
print('*** end of events ***')
|
|
||||||
break
|
|
||||||
|
|
||||||
current_event = self.events.get() # <8>
|
|
||||||
sim_time, proc_id, previous_action = current_event # <9>
|
|
||||||
print('taxi:', proc_id, proc_id * ' ', current_event) # <10>
|
|
||||||
active_proc = self.procs[proc_id] # <11>
|
|
||||||
next_time = sim_time + compute_duration(previous_action) # <12>
|
|
||||||
try:
|
|
||||||
next_event = active_proc.send(next_time) # <13>
|
|
||||||
except StopIteration:
|
|
||||||
del self.procs[proc_id] # <14>
|
|
||||||
else:
|
|
||||||
self.events.put(next_event) # <15>
|
|
||||||
else: # <16>
|
|
||||||
msg = '*** end of simulation time: {} events pending ***'
|
|
||||||
print(msg.format(self.events.qsize()))
|
|
||||||
# END TAXI_SIMULATOR
|
|
||||||
|
|
||||||
|
|
||||||
def compute_duration(previous_action):
|
|
||||||
"""Compute action duration using exponential distribution"""
|
|
||||||
if previous_action in ['leave garage', 'drop off passenger']:
|
|
||||||
# new state is prowling
|
|
||||||
interval = SEARCH_DURATION
|
|
||||||
elif previous_action == 'pick up passenger':
|
|
||||||
# new state is trip
|
|
||||||
interval = TRIP_DURATION
|
|
||||||
elif previous_action == 'going home':
|
|
||||||
interval = 1
|
|
||||||
else:
|
|
||||||
raise ValueError('Unknown previous_action: %s' % previous_action)
|
|
||||||
return int(random.expovariate(1/interval)) + 1
|
|
||||||
|
|
||||||
|
|
||||||
def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS,
|
|
||||||
seed=None):
|
|
||||||
"""Initialize random generator, build procs and run simulation"""
|
|
||||||
if seed is not None:
|
|
||||||
random.seed(seed) # get reproducible results
|
|
||||||
|
|
||||||
taxis = {i: taxi_process(i, (i+1)*2, i*DEPARTURE_INTERVAL)
|
|
||||||
for i in range(num_taxis)}
|
|
||||||
sim = Simulator(taxis)
|
|
||||||
sim.run(end_time)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description='Taxi fleet simulator.')
|
|
||||||
parser.add_argument('-e', '--end-time', type=int,
|
|
||||||
default=DEFAULT_END_TIME,
|
|
||||||
help='simulation end time; default = %s'
|
|
||||||
% DEFAULT_END_TIME)
|
|
||||||
parser.add_argument('-t', '--taxis', type=int,
|
|
||||||
default=DEFAULT_NUMBER_OF_TAXIS,
|
|
||||||
help='number of taxis running; default = %s'
|
|
||||||
% DEFAULT_NUMBER_OF_TAXIS)
|
|
||||||
parser.add_argument('-s', '--seed', type=int, default=None,
|
|
||||||
help='random generator seed (for testing)')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
main(args.end_time, args.taxis, args.seed)
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
Sample run from the command line, seed=3, maximum elapsed time=120::
|
|
||||||
|
|
||||||
# BEGIN TAXI_SAMPLE_RUN
|
|
||||||
$ python3 taxi_sim.py -s 3 -e 120
|
|
||||||
taxi: 0 Event(time=0, proc=0, action='leave garage')
|
|
||||||
taxi: 0 Event(time=2, proc=0, action='pick up passenger')
|
|
||||||
taxi: 1 Event(time=5, proc=1, action='leave garage')
|
|
||||||
taxi: 1 Event(time=8, proc=1, action='pick up passenger')
|
|
||||||
taxi: 2 Event(time=10, proc=2, action='leave garage')
|
|
||||||
taxi: 2 Event(time=15, proc=2, action='pick up passenger')
|
|
||||||
taxi: 2 Event(time=17, proc=2, action='drop off passenger')
|
|
||||||
taxi: 0 Event(time=18, proc=0, action='drop off passenger')
|
|
||||||
taxi: 2 Event(time=18, proc=2, action='pick up passenger')
|
|
||||||
taxi: 2 Event(time=25, proc=2, action='drop off passenger')
|
|
||||||
taxi: 1 Event(time=27, proc=1, action='drop off passenger')
|
|
||||||
taxi: 2 Event(time=27, proc=2, action='pick up passenger')
|
|
||||||
taxi: 0 Event(time=28, proc=0, action='pick up passenger')
|
|
||||||
taxi: 2 Event(time=40, proc=2, action='drop off passenger')
|
|
||||||
taxi: 2 Event(time=44, proc=2, action='pick up passenger')
|
|
||||||
taxi: 1 Event(time=55, proc=1, action='pick up passenger')
|
|
||||||
taxi: 1 Event(time=59, proc=1, action='drop off passenger')
|
|
||||||
taxi: 0 Event(time=65, proc=0, action='drop off passenger')
|
|
||||||
taxi: 1 Event(time=65, proc=1, action='pick up passenger')
|
|
||||||
taxi: 2 Event(time=65, proc=2, action='drop off passenger')
|
|
||||||
taxi: 2 Event(time=72, proc=2, action='pick up passenger')
|
|
||||||
taxi: 0 Event(time=76, proc=0, action='going home')
|
|
||||||
taxi: 1 Event(time=80, proc=1, action='drop off passenger')
|
|
||||||
taxi: 1 Event(time=88, proc=1, action='pick up passenger')
|
|
||||||
taxi: 2 Event(time=95, proc=2, action='drop off passenger')
|
|
||||||
taxi: 2 Event(time=97, proc=2, action='pick up passenger')
|
|
||||||
taxi: 2 Event(time=98, proc=2, action='drop off passenger')
|
|
||||||
taxi: 1 Event(time=106, proc=1, action='drop off passenger')
|
|
||||||
taxi: 2 Event(time=109, proc=2, action='going home')
|
|
||||||
taxi: 1 Event(time=110, proc=1, action='going home')
|
|
||||||
*** end of events ***
|
|
||||||
# END TAXI_SAMPLE_RUN
|
|
||||||
|
|
||||||
"""
|
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
Taxi simulator
|
Taxi simulator
|
||||||
|
|
||||||
@ -27,40 +26,59 @@ See explanation and longer sample run at the end of this module.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
|
||||||
import random
|
import random
|
||||||
import collections
|
import collections
|
||||||
import queue
|
import queue
|
||||||
import argparse
|
import argparse
|
||||||
|
import time
|
||||||
|
|
||||||
DEFAULT_NUMBER_OF_TAXIS = 3
|
DEFAULT_NUMBER_OF_TAXIS = 3
|
||||||
DEFAULT_END_TIME = 80
|
DEFAULT_END_TIME = 180
|
||||||
SEARCH_DURATION = 4
|
SEARCH_DURATION = 5
|
||||||
TRIP_DURATION = 10
|
TRIP_DURATION = 20
|
||||||
DEPARTURE_INTERVAL = 5
|
DEPARTURE_INTERVAL = 5
|
||||||
|
|
||||||
Event = collections.namedtuple('Event', 'time proc action')
|
Event = collections.namedtuple('Event', 'time proc action')
|
||||||
|
|
||||||
|
Actitivy = collections.namedtuple('Actitivy', 'name distr_param')
|
||||||
|
|
||||||
def compute_delay(interval):
|
START = Actitivy('start shift', TRIP_DURATION)
|
||||||
"""Compute action delay using exponential distribution"""
|
SEARCH_PAX = Actitivy('searching for passenger', SEARCH_DURATION)
|
||||||
|
DRIVE_PAX = Actitivy('driving passenger', TRIP_DURATION)
|
||||||
|
|
||||||
|
TRANSITIONS = {
|
||||||
|
START : SEARCH_PAX;
|
||||||
|
SEARCH_PAX : DRIVE_PAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
def compute_duration(previous_action):
|
||||||
|
"""Compute action duration using exponential distribution"""
|
||||||
|
if previous_action in ['leave garage', 'drop off passenger']:
|
||||||
|
# state is prowling
|
||||||
|
interval = SEARCH_DURATION
|
||||||
|
elif previous_action == 'pick up passenger':
|
||||||
|
# state is trip
|
||||||
|
interval = TRIP_DURATION
|
||||||
|
elif previous_action == 'going home':
|
||||||
|
interval = 1
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
return int(random.expovariate(1/interval)) + 1
|
return int(random.expovariate(1/interval)) + 1
|
||||||
|
|
||||||
|
|
||||||
# BEGIN TAXI_PROCESS
|
# BEGIN TAXI_PROCESS
|
||||||
def taxi_process(ident, trips, start_time=0): # <1>
|
def taxi_process(ident, trips, start_time=0): # <1>
|
||||||
"""Yield to simulator issuing event at each state change"""
|
"""Yield to simulator issuing event at each state change"""
|
||||||
time = yield Event(start_time, ident, 'leave garage') # <2>
|
time = yield Event(start_time, ident, 'leave garage') # <2>
|
||||||
for i in range(trips): # <3>
|
for i in range(trips): # <3>
|
||||||
prowling_ends = time + compute_delay(SEARCH_DURATION) # <4>
|
time = yield Event(time, ident, 'pick up passenger') # <4>
|
||||||
time = yield Event(prowling_ends, ident, 'pick up passenger') # <5>
|
time = yield Event(time, ident, 'drop off passenger') # <5>
|
||||||
|
|
||||||
trip_ends = time + compute_delay(TRIP_DURATION) # <6>
|
yield Event(time, ident, 'going home') # <6>
|
||||||
time = yield Event(trip_ends, ident, 'drop off passenger') # <7>
|
# end of taxi process # <7>
|
||||||
|
|
||||||
yield Event(time + 1, ident, 'going home') # <8>
|
|
||||||
# end of taxi process # <9>
|
|
||||||
# END TAXI_PROCESS
|
# END TAXI_PROCESS
|
||||||
|
|
||||||
|
|
||||||
# BEGIN TAXI_SIMULATOR
|
# BEGIN TAXI_SIMULATOR
|
||||||
class Simulator:
|
class Simulator:
|
||||||
|
|
||||||
@ -68,8 +86,7 @@ class Simulator:
|
|||||||
self.events = queue.PriorityQueue()
|
self.events = queue.PriorityQueue()
|
||||||
self.procs = dict(procs_map)
|
self.procs = dict(procs_map)
|
||||||
|
|
||||||
|
def run(self, end_time, delay=False): # <1>
|
||||||
def run(self, end_time): # <1>
|
|
||||||
"""Schedule and display events until time is up"""
|
"""Schedule and display events until time is up"""
|
||||||
# schedule the first event for each cab
|
# schedule the first event for each cab
|
||||||
for _, proc in sorted(self.procs.items()): # <2>
|
for _, proc in sorted(self.procs.items()): # <2>
|
||||||
@ -77,33 +94,38 @@ class Simulator:
|
|||||||
self.events.put(first_event) # <4>
|
self.events.put(first_event) # <4>
|
||||||
|
|
||||||
# main loop of the simulation
|
# main loop of the simulation
|
||||||
time = 0
|
sim_time = 0 # <5>
|
||||||
while time < end_time: # <5>
|
while sim_time < end_time: # <6>
|
||||||
if self.events.empty(): # <6>
|
if self.events.empty(): # <7>
|
||||||
print('*** end of events ***')
|
print('*** end of events ***')
|
||||||
break
|
break
|
||||||
|
|
||||||
# get and display current event
|
# get and display current event
|
||||||
current_event = self.events.get() # <7>
|
current_event = self.events.get() # <8>
|
||||||
print('taxi:', current_event.proc, # <8>
|
if delay:
|
||||||
current_event.proc * ' ', current_event)
|
time.sleep((current_event.time - sim_time) / 2)
|
||||||
|
# update the simulation time
|
||||||
|
sim_time, proc_id, previous_action = current_event
|
||||||
|
print('taxi:', proc_id, proc_id * ' ', current_event)
|
||||||
|
active_proc = self.procs[proc_id]
|
||||||
# schedule next action for current proc
|
# schedule next action for current proc
|
||||||
time = current_event.time # <9>
|
next_time = sim_time + compute_duration(previous_action)
|
||||||
proc = self.procs[current_event.proc] # <10>
|
|
||||||
try:
|
try:
|
||||||
next_event = proc.send(time) # <11>
|
next_event = active_proc.send(next_time) # <12>
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
del self.procs[current_event.proc] # <12>
|
del self.procs[proc_id] # <13>
|
||||||
else:
|
else:
|
||||||
self.events.put(next_event) # <13>
|
self.events.put(next_event) # <14>
|
||||||
else: # <14>
|
else: # <15>
|
||||||
msg = '*** end of simulation time: {} events pending ***'
|
msg = '*** end of simulation time: {} events pending ***'
|
||||||
print(msg.format(self.events.qsize()))
|
print(msg.format(self.events.qsize()))
|
||||||
# END TAXI_SIMULATOR
|
# END TAXI_SIMULATOR
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS,
|
def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS,
|
||||||
seed=None):
|
seed=None, delay=False):
|
||||||
"""Initialize random generator, build procs and run simulation"""
|
"""Initialize random generator, build procs and run simulation"""
|
||||||
if seed is not None:
|
if seed is not None:
|
||||||
random.seed(seed) # get reproducible results
|
random.seed(seed) # get reproducible results
|
||||||
@ -111,7 +133,7 @@ def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS,
|
|||||||
taxis = {i: taxi_process(i, (i+1)*2, i*DEPARTURE_INTERVAL)
|
taxis = {i: taxi_process(i, (i+1)*2, i*DEPARTURE_INTERVAL)
|
||||||
for i in range(num_taxis)}
|
for i in range(num_taxis)}
|
||||||
sim = Simulator(taxis)
|
sim = Simulator(taxis)
|
||||||
sim.run(end_time)
|
sim.run(end_time, delay)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
@ -128,9 +150,11 @@ if __name__ == '__main__':
|
|||||||
% DEFAULT_NUMBER_OF_TAXIS)
|
% DEFAULT_NUMBER_OF_TAXIS)
|
||||||
parser.add_argument('-s', '--seed', type=int, default=None,
|
parser.add_argument('-s', '--seed', type=int, default=None,
|
||||||
help='random generator seed (for testing)')
|
help='random generator seed (for testing)')
|
||||||
|
parser.add_argument('-d', '--delay', action='store_true',
|
||||||
|
help='introduce delay proportional to simulation time')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
main(args.end_time, args.taxis, args.seed)
|
main(args.end_time, args.taxis, args.seed, args.delay)
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
Loading…
Reference in New Issue
Block a user