simpy交通灯模拟

时间:2019-11-03 21:50:11

标签: python simpy

我试图依次模拟带有一系列交通信号灯的环形道路。车辆通过泊松过程进入系统。一旦进入系统,它们就会在每盏灯处排队。他们经过一个队列需要一个时间单位。当他们经过多个等于其行程长度的队列时,他们退出系统。队列仅在绿色阶段运行。汽车用整数表示。

问题是,即使代码的这一部分只能通过if语句(检查该双端队列中是否装有汽车)才能到达,但我始终收到错误消息“从空双端队列弹出”。我对simpy不太熟悉,因此我认为问题与超时有关。如果我在弹出操作后将超时时间移到该代码,则该代码有效。但这不是我想要的安静。

{{1}}

2 个答案:

答案 0 :(得分:0)

不是解决方法,而是解决方法...



import simpy
from simpy.util import start_delayed
# import numpy.random
from collections import deque,namedtuple
from numpy import random
NUM_INT = 3
ARRIVAL_TIME_MEAN = 1.1
TRIP_LENGTH = 4
GREEN_TIME = 3.0
RED_TIME = 3.0

class Simulation(object):
    def __init__(self,env):
        self.env = env
        self.intersections = [Intersection(env,i) for i in range(NUM_INT)]
        for (i,intersection) in enumerate(self.intersections):
            intersection.set_next_intersection(self.intersections[(i+1)%NUM_INT])
        self.env.process(self.light())
        self.env.process(self.arrivals())

    def arrivals(self):
        while True:
            yield self.env.timeout(random.exponential(ARRIVAL_TIME_MEAN))
            intersection = random.choice(self.intersections)
            intersection.receive(TRIP_LENGTH)

    def light(self):
        while True:
            for intersection in self.intersections:
                intersection.start_departing()
            yield self.env.timeout(GREEN_TIME)
            for intersection in self.intersections:
                intersection.turn_red()
            yield env.timeout(RED_TIME)


class Intersection(object):
    def __init__(self,env,index):
        self.index = index
        self.queue = deque()
        self.env = env
        self.start_departing()

    def set_next_intersection(self,intersection):
        self.next_intersection = intersection

    def start_departing(self):
        self.is_departing = True
        self.action = env.process(self.departure())

    def turn_red(self):
        if self.is_departing:
            self.is_departing = False
            self.action.interrupt('red light')

    def receive(self,car):
        self.queue.append(car)
        if not self.is_departing:
            self.start_departing()

    def departure(self):
        while True:
            try:
                if len(self.queue)==0:
                    self.is_departing = False
                    self.env.exit('no more cars in %d'%self.index)
                else:
                    yield self.env.timeout(1.0)
                    if len(self.queue)>0:
                        if len(self.queue)==1:
                            car=self.queue[0]
                            self.queue.clear()
                        else:
                            car = self.queue.popleft()
                        car = car - 1
                        if car > 0:
                            self.next_intersection.receive(car)
            except simpy.Interrupt as i:
                print('interrupted by',i.cause)

env = simpy.Environment()
sim = Simulation(env)
env.run(until=15.0)

告诉我这是否适合您

答案 1 :(得分:0)

departure中,如果队列不为空,则立即屈服,这将使调用进程运行,这可能导致其他事件导致队列为空并引发异常。这有点像协作式多任务处理,但是没有锁,因此您在放置yield的位置上要格外小心。

yield移到if的末尾可以为我修复。

    def departure(self):
        while True:
            try:
                if len(self.queue)==0:
                    self.is_departing = False
                    self.env.exit('no more cars in %d'%self.index)
                else:
                    car = self.queue.popleft()
                    car = car - 1
                    if car > 0:
                        self.next_intersection.receive(car)
                    yield self.env.timeout(1.0)
            except simpy.Interrupt as i:
                print('interrupted by',i.cause)
                yield self.env.timeout(1.0)