|
3 | 3 | import collections |
4 | 4 | import queue |
5 | 5 |
|
6 | | -FIND_CUSTOMER_INTERVAL = 4 |
| 6 | +FIND_PASSENGER_INTERVAL = 4 |
7 | 7 | TRIP_DURATION = 10 |
8 | 8 |
|
9 | 9 | Event = collections.namedtuple('Event', 'time actor description') |
10 | 10 |
|
| 11 | + |
11 | 12 | def compute_delay(interval): |
12 | 13 | return int(random.expovariate(1/interval)) + 1 |
13 | 14 |
|
14 | 15 |
|
15 | | -def taxi_process(sim, ident): |
16 | | - trips = 3 |
| 16 | +def taxi_process(ident, trips): |
| 17 | + trip_ends = 0 |
17 | 18 | for i in range(trips): |
18 | | - prowling_time = compute_delay(FIND_CUSTOMER_INTERVAL) |
19 | | - yield Event(sim.time + prowling_time, ident, 'customer picked up') |
| 19 | + prowling_ends = trip_ends + compute_delay(FIND_PASSENGER_INTERVAL) |
| 20 | + yield Event(prowling_ends, ident, 'passenger picked up') |
20 | 21 |
|
21 | | - trip_time = compute_delay(TRIP_DURATION) |
22 | | - yield Event(sim.time + trip_time, ident, 'customer dropped off') |
| 22 | + trip_ends = prowling_ends + compute_delay(TRIP_DURATION) |
| 23 | + yield Event(trip_ends, ident, 'passenger dropped off') |
23 | 24 |
|
24 | 25 |
|
25 | 26 | class Simulator: |
26 | 27 |
|
27 | | - def __init__(self): |
| 28 | + def __init__(self, actors): |
28 | 29 | self.events = queue.PriorityQueue() |
| 30 | + self.actors = list(actors) |
29 | 31 | self.time = 0 |
30 | 32 |
|
| 33 | + def schedule_events(self, end_time): |
| 34 | + for index, actor in enumerate(list(self.actors)): |
| 35 | + try: |
| 36 | + future_event = next(actor) |
| 37 | + except StopIteration: |
| 38 | + self.actors.remove(actor) # remove exhausted actor |
| 39 | + else: |
| 40 | + self.events.put(future_event) |
| 41 | + |
31 | 42 | def run(self, end_time): |
32 | | - #import pdb; pdb.set_trace() |
33 | | - taxis = [taxi_process(self, i) for i in range(3)] |
34 | 43 | while self.time < end_time: |
35 | | - for index, taxi in enumerate(taxis): |
36 | | - try: |
37 | | - future_event = next(taxi) |
38 | | - except StopIteration: |
39 | | - del taxis[index] # remove taxi not in service |
40 | | - else: |
41 | | - self.events.put(future_event) |
| 44 | + self.schedule_events(end_time) |
42 | 45 | if self.events.empty(): |
43 | 46 | print('*** end of events ***') |
44 | 47 | break |
45 | 48 | event = self.events.get() |
46 | 49 | self.time = event.time |
47 | | - print('taxi:', event.actor, event) |
| 50 | + print('taxi:', event.actor, event.actor * ' ', event) |
48 | 51 | else: |
49 | | - print('*** end of simulation time ***') |
| 52 | + msg = '*** end of simulation time: {} events pending ***' |
| 53 | + print(msg.format(self.events.qsize())) |
| 54 | + |
| 55 | + |
| 56 | +def extract_seed(args): |
| 57 | + """Set random seed if given in command line""" |
| 58 | + for index, arg in enumerate(list(args)): |
| 59 | + if arg.startswith('seed='): # for testing... |
| 60 | + seed = int(arg.split('=')[1]) |
| 61 | + random.seed(seed) # get reproducible results |
| 62 | + del args[index] |
| 63 | + return |
50 | 64 |
|
51 | 65 |
|
52 | 66 | def main(args): |
53 | | - if 'debug' in args: # for testing... |
54 | | - random.seed(0) # get reproducible results |
55 | | - args.remove('debug') |
| 67 | + extract_seed(args) |
56 | 68 | if args: |
57 | 69 | end_time = int(args[0]) |
58 | 70 | else: |
59 | | - end_time = 10 |
60 | | - sim = Simulator() |
| 71 | + end_time = 100 |
| 72 | + taxis = [taxi_process(i, (i+1)*2) for i in range(3)] |
| 73 | + sim = Simulator(taxis) |
61 | 74 | sim.run(end_time) |
62 | 75 |
|
63 | 76 | if __name__ == '__main__': |
64 | 77 | main(sys.argv[1:]) |
| 78 | + |
| 79 | + |
| 80 | +""" |
| 81 | +Sample run: |
| 82 | +
|
| 83 | +$ python3 taxi_sim.py seed=5 110 |
| 84 | +taxi: 0 Event(time=4, actor=0, description='passenger picked up') |
| 85 | +taxi: 1 Event(time=6, actor=1, description='passenger picked up') |
| 86 | +taxi: 2 Event(time=7, actor=2, description='passenger picked up') |
| 87 | +taxi: 1 Event(time=20, actor=1, description='passenger dropped off') |
| 88 | +taxi: 1 Event(time=23, actor=1, description='passenger picked up') |
| 89 | +taxi: 0 Event(time=33, actor=0, description='passenger dropped off') |
| 90 | +taxi: 2 Event(time=33, actor=2, description='passenger dropped off') |
| 91 | +taxi: 0 Event(time=34, actor=0, description='passenger picked up') |
| 92 | +taxi: 0 Event(time=45, actor=0, description='passenger dropped off') |
| 93 | +taxi: 2 Event(time=45, actor=2, description='passenger picked up') |
| 94 | +taxi: 1 Event(time=47, actor=1, description='passenger dropped off') |
| 95 | +taxi: 2 Event(time=47, actor=2, description='passenger dropped off') |
| 96 | +taxi: 2 Event(time=49, actor=2, description='passenger picked up') |
| 97 | +taxi: 1 Event(time=50, actor=1, description='passenger picked up') |
| 98 | +taxi: 1 Event(time=58, actor=1, description='passenger dropped off') |
| 99 | +taxi: 2 Event(time=58, actor=2, description='passenger dropped off') |
| 100 | +taxi: 1 Event(time=59, actor=1, description='passenger picked up') |
| 101 | +taxi: 2 Event(time=59, actor=2, description='passenger picked up') |
| 102 | +taxi: 1 Event(time=63, actor=1, description='passenger dropped off') |
| 103 | +taxi: 2 Event(time=84, actor=2, description='passenger dropped off') |
| 104 | +taxi: 2 Event(time=90, actor=2, description='passenger picked up') |
| 105 | +taxi: 2 Event(time=92, actor=2, description='passenger dropped off') |
| 106 | +taxi: 2 Event(time=99, actor=2, description='passenger picked up') |
| 107 | +taxi: 2 Event(time=101, actor=2, description='passenger dropped off') |
| 108 | +*** end of events *** |
| 109 | +
|
| 110 | +""" |
0 commit comments