美文网首页
03-yield小应用-《流畅的Python》16.9.2出租车

03-yield小应用-《流畅的Python》16.9.2出租车

作者: 依依东望_220b | 来源:发表于2019-02-19 00:12 被阅读0次
#出租车队运营仿真
import collections

#优先级列表,用来维护事件列表,用于实现将所有事件按照发生先后顺序执行
class PriorityList:
    def __init__(self):
        self.list=[]

    #获取事件队列中最早发生的事件
    def get_first(self):
        #将事件列表中所有发生事件按照发生事件排序后输出排序后的第一个值
        self.list.sort(key=lambda elem:elem.time)
        return self.list[0]

    #向列表中添加事件
    def add_list(self,event):
        self.list.append(event)

    #从事件队列中删除事件
    def del_list(self,event):
        self.list.remove(event)

    #事件列表是否为空
    def is_empty(self):
        return self.list==[]

#基本单位
#time 事件发生事件  proc 所属出租车协程  action 出租车活动事件
Event=collections.namedtuple('Event','time proc action')

#出租车协程,模拟出租车的各种活动
def taxi_process(ident,trips,start_time=0):
    """
    每次改变状态时创建事件,将控制权让给仿真器
    """
    time=yield Event(start_time,ident,'level 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')

#测试taxi_process,模拟出租车运行
def main_01():
    taxi=taxi_process(ident=13,trips=2,start_time=0)

    current_state=taxi.send(None) #预激出租车协程
    print(current_state)  #level garge 开出车库

    #第1次接客(发生在离开车库7分钟后),载客行驶事件23分钟
    current_state=taxi.send(current_state.time+7)
    print(current_state) #pick up passenger 接到乘客

    current_state=taxi.send(current_state.time+23)
    print(current_state) #drop off passenger 卸载乘客

    #第2次接客(发生在离开车库5分钟后),载客行驶时间48分钟
    current_state=taxi.send(current_state.time+5)
    print(current_state) #pick up passenger 接到乘客

    current_state=taxi.send(current_state.time+48)
    print(current_state) #drop off passenger 卸载乘客

    #返回车库(发生在最后一次卸载乘客10分钟后)
    current_state=taxi.send(current_state.time+10)
    print(current_state) #going home 返回车库

    try:
        current_state=taxi.send(current_state.time+1)
        print(current_state)
    except StopIteration as e:
        print('此时出租车协程执行完毕,抛出StopInteration')

"""
执行:
    main_01()
    
输出结果如下:

    Event(time=0, proc=13, action='level garage')
    Event(time=7, proc=13, action='pick up passenger')
    Event(time=30, proc=13, action='drop off passenger')
    Event(time=35, proc=13, action='pick up passenger')
    Event(time=83, proc=13, action='drop off passenger')
    Event(time=93, proc=13, action='going home')
    此时出租车协程执行完毕,抛出StopInteration
"""

#出租车模拟类
import random

class Simulator:
    #计算指定aciton到下一个action之间的耗时
    def compute_duration(self,previous_action):
        if previous_action=='drop off passenger':
            return random.choice([1,2])
        elif previous_action=='pick up passenger':
            return random.choice([7,8])
        elif previous_action=='level garage':
            return random.choice([10,15])
        elif previous_action=='going home':
            return random.choice([20,30])
        else:
            raise Exception('Unknown Previoud_Action')

    def __init__(self,procs_dict):
        self.events=PriorityList()
        self.procs=procs_dict

    #仿真系统主逻辑
    def run(self,end_time):
        #预激每一个出租车协程
        for _,proc in self.procs.items():
            #每个出租车协程的第一个事件
            first_event=proc.send(None) #预激
            #将每个出租车协程的第一个事件放入事件列表
            self.events.add_list(first_event)


        #这个仿真系统的事件主循环
        sim_time=0
        #遍历并处理每个事件
        while sim_time<end_time:#判断运行时间是否超时
            #事件列表为空,所有事件执行完毕
            if self.events.is_empty():
                print('******** end all events ********')
                return

            current_event=self.events.get_first() #获取事件列表中最早发生的事件

            #处理当前事件(此处用打印来模拟处理过程)
            sim_time,proc_id,previous_action=current_event
            print('taxi:',proc_id,proc_id*'    ',current_event) #打印当前事件
            #从事件标记列表中移除已处理过的事件
            self.events.del_list(current_event)

            active_proc=self.procs[proc_id] #获取这个事件所属的出租车协程
            next_time=sim_time+self.compute_duration(previous_action) #计算下一个事件的发生时间

            try:
                next_event=active_proc.send(next_time) #向出租车协程发送参数(参数表示下次事件发生的时间)
            except StopIteration:
                #如果触发这个异常表示出租车协程执行完毕
                del self.procs[proc_id]
            else:
                #将新事件添加到事件列表
                self.events.add_list(next_event)
        else:
            #执行时间超时后的处理
            print('---->执行超时<----')


#测试出租车协程能否正常执行
def main_02():
    data_dict={
        1:taxi_process(ident=1,trips=3,start_time=0),
        2:taxi_process(ident=2,trips=4,start_time=30),
        3:taxi_process(ident=3,trips=2,start_time=13),
    }

    sim1=Simulator(data_dict)
    sim1.run(100) #时间足够执行完成所有的出租车协程

'''
执行:
    main_02()
输出结果:
    taxi: 1      Event(time=0, proc=1, action='level garage')
    taxi: 1      Event(time=10, proc=1, action='pick up passenger')
    taxi: 3              Event(time=13, proc=3, action='level garage')
    taxi: 1      Event(time=17, proc=1, action='drop off passenger')
    taxi: 1      Event(time=18, proc=1, action='pick up passenger')
    taxi: 1      Event(time=26, proc=1, action='drop off passenger')
    taxi: 3              Event(time=28, proc=3, action='pick up passenger')
    taxi: 1      Event(time=28, proc=1, action='pick up passenger')
    taxi: 2          Event(time=30, proc=2, action='level garage')
    taxi: 1      Event(time=35, proc=1, action='drop off passenger')
    taxi: 3              Event(time=36, proc=3, action='drop off passenger')
    taxi: 1      Event(time=37, proc=1, action='going home')
    taxi: 3              Event(time=38, proc=3, action='pick up passenger')
    taxi: 2          Event(time=40, proc=2, action='pick up passenger')
    taxi: 3              Event(time=46, proc=3, action='drop off passenger')
    taxi: 2          Event(time=47, proc=2, action='drop off passenger')
    taxi: 3              Event(time=48, proc=3, action='going home')
    taxi: 2          Event(time=48, proc=2, action='pick up passenger')
    taxi: 2          Event(time=56, proc=2, action='drop off passenger')
    taxi: 2          Event(time=57, proc=2, action='pick up passenger')
    taxi: 2          Event(time=64, proc=2, action='drop off passenger')
    taxi: 2          Event(time=66, proc=2, action='pick up passenger')
    taxi: 2          Event(time=74, proc=2, action='drop off passenger')
    taxi: 2          Event(time=75, proc=2, action='going home')
    ******** end all events ********
'''

#测试设置超时时间是否有效
def main_03():
    data_dict={
        1:taxi_process(ident=1,trips=3,start_time=0),
        2:taxi_process(ident=2,trips=4,start_time=30),
        3:taxi_process(ident=3,trips=2,start_time=13),
    }

    sim1=Simulator(data_dict)
    sim1.run(30) #时间不足以执行完成所有的出租车协程
'''
执行
    main_03()
输出结果:
    taxi: 1      Event(time=0, proc=1, action='level garage')
    taxi: 3              Event(time=13, proc=3, action='level garage')
    taxi: 1      Event(time=15, proc=1, action='pick up passenger')
    taxi: 1      Event(time=22, proc=1, action='drop off passenger')
    taxi: 3              Event(time=23, proc=3, action='pick up passenger')
    taxi: 1      Event(time=23, proc=1, action='pick up passenger')
    taxi: 2          Event(time=30, proc=2, action='level garage')
    taxi: 3              Event(time=30, proc=3, action='drop off passenger')
    taxi: 1      Event(time=30, proc=1, action='drop off passenger')
    ---->执行超时<---- 
'''

相关文章

网友评论

      本文标题:03-yield小应用-《流畅的Python》16.9.2出租车

      本文链接:https://www.haomeiwen.com/subject/iqptyqtx.html