- 实验要求
仿真出高速公路收费站双收费口的服务行为。
主要参数包括但不限于(以下均通过随机数产生):
1)符合某一概率分布函数(负指数分布、正态分布、均匀分布等)的车头时距(自己标定参数);
2)每辆车的服务时长;
输出包括但不限于:
1)每辆车的到达时刻;
2)每辆车选择的队列(队列1和队列2);
3)每辆车的等待时间;
4)每辆车的服务时间;
5)队列1,2的平均服务时间;
6)队列1,2的平均等待时间。
鼓励使用可视化界面展示,也可以用Console程序输出结果。
- 实验环境
Python,Pycharm
- 实验原理
排队论,是通过对服务对象到来及服务时间的统计研究,得出这些数量指标(等待时间、排队长度、忙期长短等)的统计规律,然后根据这些规律来改进服务系统的结构或重新组织被服务对象,使得服务系统既能满足服务对象的需要,又能使机构的费用最经济或某些指标最优。它是数学运筹学的分支学科。也是研究服务系统中排队现象随机规律的学科。
1、排队模型的表示X/Y/Z/A/B/CX—顾客相继到达的间隔时间的分布;
Y—服务时间的分布;
M—负指数分布、D—确定型、Ek—k阶爱尔兰分布;
Z—服务台个数;
14A—系统容量限制(默认为∞);
B—顾客源数目(默认为∞);
C—服务规则(默认为先到先服务FCFS)。
2、排队系统的衡量指标服务队长Ls—服务中的顾客数;
排队长Lq—队列中的顾客数;
总队长L=Ls+Lq系统中的顾客总数;
逗留时间Ws—顾客在服务中的等待时间;
等待时间Wq—顾客在队列中的等待时间;
总时间W=Ws+Wq顾客在系统中的总停留时间;
- 实验步骤
1)程序编写思路
1、利用随机数产生函数产生服从负指数分布的随机数,作为车辆的车头时距,迭代累加可以得到每辆车的到达时刻;
2、利用随机数产生函数产生一个范围在[20,40]的随机数,作为车辆服务时间的范围;
3、首先车辆根据队伍长度选择排队的队列,在服务台进行二次排序;
4、在各个服务台排队的车辆的等候时间等于前一辆车的离开时间减去这一辆车的到达时间;
5、将各个队列的车辆服务时间加起来求平均数可得到各队列的平均服务时间;
6、将各个队列的车辆等待时间加起来求平均数可得到各队列的平均等待时间
- 分析总结
1.程序未能写出来,主要是逻辑上受困。
2.主要问题是前车与后车的随时变化关系,我难以用语言表达出来。
3.当有队列为空时车辆的离开时间和等候时间都好求,一个是出现时间+服务时间,一个是服务时间;
4.但当无空队列时,很复杂;因为我采取的模拟时间流动,所以是相当于静态模型,将某个时间点进行切片,再利用基本逻辑求取车辆的离开时间和等候时间。
5.我提前将每辆车的出现时间和服务时间放入列表里,因为这不是变量。
后一辆车的离开时间与前一辆的离开时间有关,二前一辆的离开时间又可能受再前一辆车的影响,这里搞得我很乱。
6.但前一辆的能进行排队一定是它前面那辆车走了,所以它的离开时间应该是前一辆车的离开时间加它的服务时间。
7.所以这是一个迭代模型,如果有排队,那么这辆车的离开时间=它队列前的车的离开时间+它本身的排队时间。
附录
import pygame,sys
import math,random
#线性同余发生器
def rd(start,num): #start 为初始值(小于m的奇数),num为取随机数的个数
x = []
a = 179 #a = 2**(p/2),同时接近 a = 8k +/- 3,p就是j
m = 2 ** 15 #m=2**j,伪随机数列的周期为m/4 及 总随机数生成的个数
x0 = start
for i in range(num):
x0 = a * x0 - int(a*x0/m) * m
x.append(x0/m)
return x #返回随机数列表
#产生负指数分布的随机数
def F(u):
x = -1/0.5*math.log1p(u-1) #反变换法
return round(x,5)
#生成符合负指数分布的随机数 列表
def x_e(ls):
ls_x_e = []
for i in ls:
ls_x_e.append(F(i))
lt = [round(i*10,3) for i in ls_x_e] #保留3位小数
return lt
#init 为初始值(小于m的奇数),num为取随机数的个数,start为随机数起始范围,end为终止范围
def rd2(init,num,start,end):
#最终输出的值的列表
x = []
# a = 2**(p/2),同时接近 a = 8k +/- 3,p就是j
a = 179
# m=2**j,伪随机数列的周期为m/4,总随机数生成的个数,这里是8000个
m = 2 ** 15
x0 = init
#经过100倍放大的0~1的随机数的列表
ls = []
#生成7000个随机数并筛选
for i in range(7000):
x0 = a * x0 - int(a*x0/m) * m
ls.append(x0/m*100)
if start<=x0<=end:
x.append(x0)
#假如没有直接生成到所需的数值范围数字的处理
if len(x) == 2:
return x[:num]
else:
for i in ls:
#创造符合范围的数值
if start<=i+start<=end:
x.append(i+start)
return x[:num]
x = rd(11,50) #控制随机数生成种子和个数,列表
x1 = x_e(x) #车头时距,列表
#将车头时距处理成每一辆车辆出现时间
x3 = [] #50个车辆出现时间,列表
for i in range(len(x1)):
s = 0
for n in range(i+1):
s = s + x1[n]
x3.append(round(s)) #保留0位小数
#生成对应的50个随机服务时间
x2 = [round(i) for i in rd2(3,50,20,40) ]
#两队列实时的存车数
row_much = [0,0]
#车辆的编号对应的数据:选择的队列,等待时间,服务时间,离开时间
d = {}
for i in range(1,51):
d[i] = []
#车辆编号
n = 1
#车辆选择的队列
row = 0
#车辆该出现的车辆编号
appe = 1
#车辆该消失的车辆编号
disap = 1
#模拟时间流逝
for time in range(10000):
#时间到车辆n出现
if time == x3[n-1]:
#判断队列有没有空列
if 0 in row_much: #有空列
for i in range(2): #空列在哪
if row_much[i] == 0:
row = i #该车辆选择的队列
row_much[row] += 1 #该队列存车加一
d[n] = d.get(n,[]) + [row] #存进车辆选择的队列
d[n] = d.get(n, []) + [0] #等待时间为0
d[n] = d.get(n, []) + [x2[n-1]] #服务时间为对应的随机服务时间
d[n] = d.get(n, []) + [x3[n-1]+x2[n-1]] #离开时间
else: #没有空列
#判断哪列车少
if row_much[0]x_dis[49] :
# break
#
#
# # print(x, x1,x3,x2)
同学用class类写的。
import random
def genServiceTime():
SERVE_TIME_MIN = 20
SERVE_TIME_MAX = 40
return random.randint(SERVE_TIME_MIN, SERVE_TIME_MAX)
# 此时间后不产生新车辆,但仍然处理已到达的车辆
END_TIME = 100
def rand(t):
r = random.random()
return r > 0.8
class Car:
def __init__(self, time_enterQueue, time_serveTime=genServiceTime()):
self.time_enterQueue = time_enterQueue
self.time_serveTime = time_serveTime
self.serving = False
self.queueAt = None
self.time_startServe = -1
self.time_waitForServe = -1
self.time_leaveQueue = -1
def startServe(self, t):
self.serving = True
self.time_startServe = t
self.time_waitForServe = self.time_startServe - self.time_enterQueue
def isServed(self, t):
return t - self.time_startServe + 1 > self.time_serveTime
def getRemainingServeTime(self, t):
return t - self.time_startServe
def leaveQueue(self, t):
self.time_leaveQueue = t
def showResult(self):
print(
f"到达时间: {self.time_enterQueue} ,"
f"选择的队列: {self.queueAt.name} ,"
f"等待时间: {self.time_waitForServe} ,"
f"所需服务时间: {self.time_serveTime}")
class Queue:
def __init__(self, name=""):
self.name = name
self.list: [Car] = []
self.sumLen = 0
self.avgTime_wait = 0
self.avgTime_serve = 0
def getLen(self):
return len(self.list)
def push(self, item):
item.queueAt = self
return self.list.append(item)
def pop(self, t):
item: Car = self.list.pop(0)
# new Avg(n)= ((n-1)*oldAvg+New)/n
self.sumLen += 1
self.avgTime_serve = ((self.sumLen - 1) / self.sumLen) * self.avgTime_serve + item.time_serveTime / self.sumLen
self.avgTime_wait = ((self.sumLen - 1) / self.sumLen) * self.avgTime_wait + item.time_waitForServe / self.sumLen
return item
def serve(self, t):
"""
对队列最前方车辆服务
:return:
"""
if len(self.list) == 0:
return
car: Car = self.list[0]
if car.serving is True:
if car.isServed(t):
self.pop(t)
car.leaveQueue(t)
return
else:
car.startServe(t)
return
def showCurrent(self, t):
if len(self.list) > 0:
print(f"{self.name}: 当前时间: {t}, 服务站 "
+ "" * (len(self.list) - 1)
+ f" 剩余服务时间:{self.list[0].time_serveTime + 1 if self.list[0].time_startServe == -1 else self.list[0].time_serveTime - (t - self.list[0].time_startServe)}")
else:
print(f"{self.name}: 当前时间: {t}, 服务站 ✅")
def showResult(self):
print(f"{self.name}: 总服务车辆数: {self.sumLen} 平均服务时间: {self.avgTime_serve} 平均等待时间: {self.avgTime_wait} ")
def pickShortestQueue(queueList: list[Queue]):
shortest = queueList[0]
for q in queueList:
if len(q.list) < len(shortest.list):
shortest = q
return shortest
def isAllEmpty(queueList: list[Queue]):
for q in queueList:
if q.getLen() != 0:
return False
return True
if __name__ == '__main__':
Cars = [] # 记录历史各车数据
queue1 = Queue("队列1")
queue2 = Queue("队列2")
queueList: list[Queue] = [queue1, queue2]
t = 0
for i in range(END_TIME):
t += 1
# 是否产生新车辆
if rand(t):
q = pickShortestQueue(queueList)
car = Car(t, genServiceTime())
q.push(car)
Cars.append(car) # 用于记录
# 处理当前队列
for q in queueList:
if q.getLen() == 0:
pass
else:
q.serve(t)
# 展示当前时间的状态
print(f"=====当前时间: {t} =====")
for q in queueList:
q.showCurrent(t)
# 时间结束后收尾工作
while not isAllEmpty(queueList):
t += 1
for q in queueList:
if q.getLen() == 0:
pass
else:
q.serve(t)
print(f"=====当前时间: {t} =====")
for q in queueList:
q.showCurrent(t)
# 展示结果
for q in queueList:
q.showResult()
for car in Cars:
car.showResult()



