From f4cdee24471f4b11dfcda4b2248323f60c67a642 Mon Sep 17 00:00:00 2001 From: Luciano Ramalho Date: Thu, 9 Apr 2015 00:51:55 -0300 Subject: [PATCH] update from Atlas --- {iterables => 14-it-generator}/aritprog.rst | 0 .../aritprog_float_error.py | 0 .../aritprog_runner.py | 0 {iterables => 14-it-generator}/aritprog_v0.py | 0 {iterables => 14-it-generator}/aritprog_v1.py | 0 {iterables => 14-it-generator}/aritprog_v2.py | 0 {iterables => 14-it-generator}/aritprog_v3.py | 0 {iterables => 14-it-generator}/aritprog_v4.py | 0 {iterables => 14-it-generator}/aritprog_v5.py | 0 .../fibo_by_hand.py | 0 .../sequences => 14-it-generator}/sentence.py | 0 {iterables => 14-it-generator}/sentence.rst | 0 .../sentence_gen.py | 0 .../sentence_gen2.py | 0 .../sentence_genexp.py | 0 .../sentence_iter.py | 0 .../sentence_iter2.py | 0 .../sentence_runner.py | 0 .../yield_delegate_fail.py | 0 .../yield_delegate_fix.py | 0 .../iterables}/CACM/citation.txt | 0 .../iterables}/CACM/closed_file.py | 0 {iterables => attic/iterables}/CACM/haha.py | 0 .../iterables}/CACM/less_more.py | 0 .../iterables}/CACM/zero_div.py | 0 .../iterables}/almost_aritprog_v0.py | 0 .../iterables}/almost_aritprog_v6.py | 0 {iterables => attic/iterables}/paragraph.py | 0 .../iterables}/simplest_generators.doctest | 0 {iterables => attic/iterables}/vector.py | 0 .../iterables}/vector_flex_init.py | 0 control/taxi_sim2.py | 270 ++++++++++++++++++ 32 files changed, 270 insertions(+) rename {iterables => 14-it-generator}/aritprog.rst (100%) rename {iterables => 14-it-generator}/aritprog_float_error.py (100%) rename {iterables => 14-it-generator}/aritprog_runner.py (100%) rename {iterables => 14-it-generator}/aritprog_v0.py (100%) rename {iterables => 14-it-generator}/aritprog_v1.py (100%) rename {iterables => 14-it-generator}/aritprog_v2.py (100%) rename {iterables => 14-it-generator}/aritprog_v3.py (100%) rename {iterables => 14-it-generator}/aritprog_v4.py (100%) rename {iterables => 14-it-generator}/aritprog_v5.py (100%) rename {iterables => 14-it-generator}/fibo_by_hand.py (100%) rename {attic/sequences => 14-it-generator}/sentence.py (100%) rename {iterables => 14-it-generator}/sentence.rst (100%) rename {iterables => 14-it-generator}/sentence_gen.py (100%) rename {iterables => 14-it-generator}/sentence_gen2.py (100%) rename {iterables => 14-it-generator}/sentence_genexp.py (100%) rename {iterables => 14-it-generator}/sentence_iter.py (100%) rename {iterables => 14-it-generator}/sentence_iter2.py (100%) rename {iterables => 14-it-generator}/sentence_runner.py (100%) rename {iterables => 14-it-generator}/yield_delegate_fail.py (100%) rename {iterables => 14-it-generator}/yield_delegate_fix.py (100%) rename {iterables => attic/iterables}/CACM/citation.txt (100%) rename {iterables => attic/iterables}/CACM/closed_file.py (100%) rename {iterables => attic/iterables}/CACM/haha.py (100%) rename {iterables => attic/iterables}/CACM/less_more.py (100%) rename {iterables => attic/iterables}/CACM/zero_div.py (100%) rename {iterables => attic/iterables}/almost_aritprog_v0.py (100%) rename {iterables => attic/iterables}/almost_aritprog_v6.py (100%) rename {iterables => attic/iterables}/paragraph.py (100%) rename {iterables => attic/iterables}/simplest_generators.doctest (100%) rename {iterables => attic/iterables}/vector.py (100%) rename {iterables => attic/iterables}/vector_flex_init.py (100%) create mode 100644 control/taxi_sim2.py diff --git a/iterables/aritprog.rst b/14-it-generator/aritprog.rst similarity index 100% rename from iterables/aritprog.rst rename to 14-it-generator/aritprog.rst diff --git a/iterables/aritprog_float_error.py b/14-it-generator/aritprog_float_error.py similarity index 100% rename from iterables/aritprog_float_error.py rename to 14-it-generator/aritprog_float_error.py diff --git a/iterables/aritprog_runner.py b/14-it-generator/aritprog_runner.py similarity index 100% rename from iterables/aritprog_runner.py rename to 14-it-generator/aritprog_runner.py diff --git a/iterables/aritprog_v0.py b/14-it-generator/aritprog_v0.py similarity index 100% rename from iterables/aritprog_v0.py rename to 14-it-generator/aritprog_v0.py diff --git a/iterables/aritprog_v1.py b/14-it-generator/aritprog_v1.py similarity index 100% rename from iterables/aritprog_v1.py rename to 14-it-generator/aritprog_v1.py diff --git a/iterables/aritprog_v2.py b/14-it-generator/aritprog_v2.py similarity index 100% rename from iterables/aritprog_v2.py rename to 14-it-generator/aritprog_v2.py diff --git a/iterables/aritprog_v3.py b/14-it-generator/aritprog_v3.py similarity index 100% rename from iterables/aritprog_v3.py rename to 14-it-generator/aritprog_v3.py diff --git a/iterables/aritprog_v4.py b/14-it-generator/aritprog_v4.py similarity index 100% rename from iterables/aritprog_v4.py rename to 14-it-generator/aritprog_v4.py diff --git a/iterables/aritprog_v5.py b/14-it-generator/aritprog_v5.py similarity index 100% rename from iterables/aritprog_v5.py rename to 14-it-generator/aritprog_v5.py diff --git a/iterables/fibo_by_hand.py b/14-it-generator/fibo_by_hand.py similarity index 100% rename from iterables/fibo_by_hand.py rename to 14-it-generator/fibo_by_hand.py diff --git a/attic/sequences/sentence.py b/14-it-generator/sentence.py similarity index 100% rename from attic/sequences/sentence.py rename to 14-it-generator/sentence.py diff --git a/iterables/sentence.rst b/14-it-generator/sentence.rst similarity index 100% rename from iterables/sentence.rst rename to 14-it-generator/sentence.rst diff --git a/iterables/sentence_gen.py b/14-it-generator/sentence_gen.py similarity index 100% rename from iterables/sentence_gen.py rename to 14-it-generator/sentence_gen.py diff --git a/iterables/sentence_gen2.py b/14-it-generator/sentence_gen2.py similarity index 100% rename from iterables/sentence_gen2.py rename to 14-it-generator/sentence_gen2.py diff --git a/iterables/sentence_genexp.py b/14-it-generator/sentence_genexp.py similarity index 100% rename from iterables/sentence_genexp.py rename to 14-it-generator/sentence_genexp.py diff --git a/iterables/sentence_iter.py b/14-it-generator/sentence_iter.py similarity index 100% rename from iterables/sentence_iter.py rename to 14-it-generator/sentence_iter.py diff --git a/iterables/sentence_iter2.py b/14-it-generator/sentence_iter2.py similarity index 100% rename from iterables/sentence_iter2.py rename to 14-it-generator/sentence_iter2.py diff --git a/iterables/sentence_runner.py b/14-it-generator/sentence_runner.py similarity index 100% rename from iterables/sentence_runner.py rename to 14-it-generator/sentence_runner.py diff --git a/iterables/yield_delegate_fail.py b/14-it-generator/yield_delegate_fail.py similarity index 100% rename from iterables/yield_delegate_fail.py rename to 14-it-generator/yield_delegate_fail.py diff --git a/iterables/yield_delegate_fix.py b/14-it-generator/yield_delegate_fix.py similarity index 100% rename from iterables/yield_delegate_fix.py rename to 14-it-generator/yield_delegate_fix.py diff --git a/iterables/CACM/citation.txt b/attic/iterables/CACM/citation.txt similarity index 100% rename from iterables/CACM/citation.txt rename to attic/iterables/CACM/citation.txt diff --git a/iterables/CACM/closed_file.py b/attic/iterables/CACM/closed_file.py similarity index 100% rename from iterables/CACM/closed_file.py rename to attic/iterables/CACM/closed_file.py diff --git a/iterables/CACM/haha.py b/attic/iterables/CACM/haha.py similarity index 100% rename from iterables/CACM/haha.py rename to attic/iterables/CACM/haha.py diff --git a/iterables/CACM/less_more.py b/attic/iterables/CACM/less_more.py similarity index 100% rename from iterables/CACM/less_more.py rename to attic/iterables/CACM/less_more.py diff --git a/iterables/CACM/zero_div.py b/attic/iterables/CACM/zero_div.py similarity index 100% rename from iterables/CACM/zero_div.py rename to attic/iterables/CACM/zero_div.py diff --git a/iterables/almost_aritprog_v0.py b/attic/iterables/almost_aritprog_v0.py similarity index 100% rename from iterables/almost_aritprog_v0.py rename to attic/iterables/almost_aritprog_v0.py diff --git a/iterables/almost_aritprog_v6.py b/attic/iterables/almost_aritprog_v6.py similarity index 100% rename from iterables/almost_aritprog_v6.py rename to attic/iterables/almost_aritprog_v6.py diff --git a/iterables/paragraph.py b/attic/iterables/paragraph.py similarity index 100% rename from iterables/paragraph.py rename to attic/iterables/paragraph.py diff --git a/iterables/simplest_generators.doctest b/attic/iterables/simplest_generators.doctest similarity index 100% rename from iterables/simplest_generators.doctest rename to attic/iterables/simplest_generators.doctest diff --git a/iterables/vector.py b/attic/iterables/vector.py similarity index 100% rename from iterables/vector.py rename to attic/iterables/vector.py diff --git a/iterables/vector_flex_init.py b/attic/iterables/vector_flex_init.py similarity index 100% rename from iterables/vector_flex_init.py rename to attic/iterables/vector_flex_init.py diff --git a/control/taxi_sim2.py b/control/taxi_sim2.py new file mode 100644 index 0000000..e42f6bf --- /dev/null +++ b/control/taxi_sim2.py @@ -0,0 +1,270 @@ + +""" +Taxi simulator + +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=4, proc=0, action='pick up passenger') + taxi: 1 Event(time=5, proc=1, action='leave garage') + taxi: 1 Event(time=9, proc=1, action='pick up passenger') + taxi: 0 Event(time=10, proc=0, action='drop off passenger') + taxi: 1 Event(time=12, proc=1, action='drop off passenger') + taxi: 0 Event(time=17, proc=0, action='pick up passenger') + taxi: 1 Event(time=19, proc=1, action='pick up passenger') + taxi: 1 Event(time=21, proc=1, action='drop off passenger') + taxi: 1 Event(time=24, proc=1, action='pick up passenger') + taxi: 0 Event(time=28, proc=0, action='drop off passenger') + taxi: 1 Event(time=28, proc=1, action='drop off passenger') + taxi: 0 Event(time=29, proc=0, action='going home') + taxi: 1 Event(time=30, proc=1, action='pick up passenger') + taxi: 1 Event(time=61, proc=1, action='drop off passenger') + taxi: 1 Event(time=62, proc=1, action='going home') + *** end of events *** + +See explanation and 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, delay=False): # <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 + + # get and display current event + current_event = self.events.get() # <8> + if delay: + 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 + next_time = sim_time + compute_duration(previous_action) + try: + next_event = active_proc.send(next_time) # <12> + except StopIteration: + del self.procs[proc_id] # <13> + else: + self.events.put(next_event) # <14> + else: # <15> + 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']: + # 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 + + +def main(end_time=DEFAULT_END_TIME, num_taxis=DEFAULT_NUMBER_OF_TAXIS, + seed=None, delay=False): + """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, delay) + + +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)') + parser.add_argument('-d', '--delay', action='store_true', + help='introduce delay proportional to simulation time') + + args = parser.parse_args() + main(args.end_time, args.taxis, args.seed, args.delay) + + +""" +Notes for the ``taxi_process`` coroutine:: + +<1> `taxi_process` will be called once per taxi, creating a generator + object to represent its operations. `ident` is the number of the taxi + (eg. 0, 1, 2 in the sample run); `trips` is the number of trips this + taxi will make before going home; `start_time` is when the taxi + leaves the garage. + +<2> The first `Event` yielded is `'leave garage'`. This suspends the + coroutine, and lets the simulation main loop proceed to the next + scheduled event. When it's time to reactivate this process, the main + loop will `send` the current simulation time, which is assigned to + `time`. + +<3> This block will be repeated once for each trip. + +<4> The ending time of the search for a passenger is computed. + +<5> An `Event` signaling passenger pick up is yielded. The coroutine + pauses here. When the time comes to reactivate this coroutine, + the main loop will again `send` the current time. + +<6> The ending time of the trip is computed, taking into account the + current `time`. + +<7> An `Event` signaling passenger drop off is yielded. Coroutine + suspended again, waiting for the main loop to send the time of when + it's time to continue. + +<8> The `for` loop ends after the given number of trips, and a final + `'going home'` event is yielded, to happen 1 minute after the current + time. The coroutine will suspend for the last time. When reactivated, + it will be sent the time from the simulation main loop, but here I + don't assign it to any variable because it will not be useful. + +<9> When the coroutine falls off the end, the coroutine object raises + `StopIteration`. + + +Notes for the ``Simulator.run`` method:: + +<1> The simulation `end_time` is the only required argument for `run`. + +<2> Use `sorted` to retrieve the `self.procs` items ordered by the + integer key; we don't care about the key, so assign it to `_`. + +<3> `next(proc)` primes each coroutine by advancing it to the first + yield, so it's ready to be sent data. An `Event` is yielded. + +<4> Add each event to the `self.events` `PriorityQueue`. The first + event for each taxi is `'leave garage'`, as seen in the sample run + (ex_taxi_process>>). + +<5> Main loop of the simulation: run until the current `time` equals + or exceeds the `end_time`. + +<6> The main loop may also exit if there are no pending events in the + queue. + +<7> Get `Event` with the smallest `time` in the queue; this is the + `current_event`. + +<8> Display the `Event`, identifying the taxi and adding indentation + according to the taxi id. + +<9> Update the simulation time with the time of the `current_event`. + +<10> Retrieve the coroutine for this taxi from the `self.procs` + dictionary. + +<11> Send the `time` to the coroutine. The coroutine will yield the + `next_event` or raise `StopIteration` it's finished. + +<12> If `StopIteration` was raised, delete the coroutine from the + `self.procs` dictionary. + +<13> Otherwise, put the `next_event` in the queue. + +<14> If the loop exits because the simulation time passed, display the + number of events pending (which may be zero by coincidence, + sometimes). + + +Sample run from the command line, seed=24, total elapsed time=160:: + +# BEGIN TAXI_SAMPLE_RUN +$ python3 taxi_sim.py -s 24 -e 160 +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=6, proc=1, action='pick up passenger') +taxi: 2 Event(time=10, proc=2, action='leave garage') +taxi: 2 Event(time=11, proc=2, action='pick up passenger') +taxi: 2 Event(time=23, proc=2, action='drop off passenger') +taxi: 0 Event(time=24, proc=0, action='drop off passenger') +taxi: 2 Event(time=24, proc=2, action='pick up passenger') +taxi: 2 Event(time=26, proc=2, action='drop off passenger') +taxi: 0 Event(time=30, proc=0, action='pick up passenger') +taxi: 2 Event(time=31, proc=2, action='pick up passenger') +taxi: 0 Event(time=43, proc=0, action='drop off passenger') +taxi: 0 Event(time=44, proc=0, action='going home') +taxi: 2 Event(time=46, proc=2, action='drop off passenger') +taxi: 2 Event(time=49, proc=2, action='pick up passenger') +taxi: 1 Event(time=70, proc=1, action='drop off passenger') +taxi: 2 Event(time=70, proc=2, action='drop off passenger') +taxi: 2 Event(time=71, proc=2, action='pick up passenger') +taxi: 2 Event(time=79, proc=2, action='drop off passenger') +taxi: 1 Event(time=88, proc=1, action='pick up passenger') +taxi: 2 Event(time=92, proc=2, action='pick up passenger') +taxi: 2 Event(time=98, proc=2, action='drop off passenger') +taxi: 2 Event(time=99, proc=2, action='going home') +taxi: 1 Event(time=102, proc=1, action='drop off passenger') +taxi: 1 Event(time=104, proc=1, action='pick up passenger') +taxi: 1 Event(time=135, proc=1, action='drop off passenger') +taxi: 1 Event(time=136, proc=1, action='pick up passenger') +taxi: 1 Event(time=151, proc=1, action='drop off passenger') +taxi: 1 Event(time=152, proc=1, action='going home') +*** end of events *** +# END TAXI_SAMPLE_RUN + +"""