返回介绍

A.5 第16章:出租车队离散事件仿真

发布于 2024-02-05 21:59:46 字数 7073 浏览 0 评论 0 收藏 0

示例 A-6 是 16.9.2 节讨论的 taxi_sim.py 脚本的完整代码。

示例 A-6 taxi_sim.py:出租车队仿真程序

"""
出租车仿真程序
==============

在控制台中驱动出租车::

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

运行示例:有两辆出租车,随机种子是10。这是有效的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 ***

模块末尾有个更长的运行示例。

"""

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):
  """每次状态变化时向仿真程序产出一个事件"""
  time = yield Event(start_time, ident, 'leave garage')
  for i in range(trips):
    time = yield Event(time, ident, 'pick up passenger')
    time = yield Event(time, ident, 'drop off passenger')

  yield Event(time, ident, 'going home')
  # 结束出租车进程
# 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):
    """调度并显示事件,直到时间结束"""
    # 调度各辆出租车的第一个事件
    for _, proc in sorted(self.procs.items()):
      first_event = next(proc)
      self.events.put(first_event)

    # 此次仿真的主循环
    sim_time = 0
    while sim_time < end_time:
      if self.events.empty():
        print('*** end of events ***')
        break

      current_event = self.events.get()
      sim_time, proc_id, previous_action = current_event
      print('taxi:', proc_id, proc_id * '   ', current_event)
      active_proc = self.procs[proc_id]
      next_time = sim_time + compute_duration(previous_action)
      try:
        next_event = active_proc.send(next_time)
      except StopIteration:
        del self.procs[proc_id]
      else:
        self.events.put(next_event)
    else:
      msg = '*** end of simulation time: {} events pending ***'
      print(msg.format(self.events.qsize()))
# END TAXI_SIMULATOR


def compute_duration(previous_action):
  """使用指数分布计算操作的耗时"""
  if previous_action in ['leave garage', 'drop off passenger']:
    # 新状态是四处徘徊
    interval = SEARCH_DURATION
  elif previous_action == 'pick up passenger':
    # 新状态是行程开始
    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):
  """初始化随机生成器,构建过程,运行仿真程序"""
  if seed is not None:
    random.seed(seed)  # 获得可复现的结果

  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)


"""

命令行中的运行示例:seed=3,最长用时=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

"""

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文