fixed merge

This commit is contained in:
Luciano Ramalho 2015-04-15 04:51:38 -03:00
commit 4ef4b82e82
3 changed files with 57 additions and 235 deletions

1
.gitignore vendored
View File

@ -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/

View File

@ -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
"""

View File

@ -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)
""" """