基于排队论模型的收银台服务系统的分析及可视化设计
一. 收款台服务
1.1问题描述
某商店只有一个收款台。
顾客到达收款台的时间间隔服从平均时间为10s的负指数分布。
每个顾客的服务时间服从均值为6.5s,标准差为1.2s的正态分布。
情景:
客户到达,客户排队,一个柜台服务, 服务耗时, 客户离开。
t1 表示客户平均到达时间间隔
t2 表示客户平均服务时间
sigma 表示客户服务时间标准差
num 表示客户数
1.2计算
顾客的平均逗留时间,系统的服务强度(服务时间/所有时间),平均队长(排队人数)。
1.3输入:
方案一:直接输入参数(到达时间分布参数:到达时间平均间隔;服务时间分布参数:平均服务时间、服务时间标准差;排队模型模拟人数。)
方案二:导入csv文件(如下表所示,详见附件一:T.csv)
(arrive为到达时间间隔,serve为服务时间。其中顾客到达收款台的时间间隔服从平均时间为10s的负指数分布。每个顾客的服务时间服从均值为6.5s,标准差为1.2s的正态分布。
)
方案一:直接输入参数(到达时间分布参数:到达时间平均间隔;服务时间分布参数:平均服务时间、服务时间标准差;排队模型模拟人数。)
方案二:导入csv文件(如下表所示,详见附件一:T.csv)
(arrive为到达时间间隔,serve为服务时间。其中顾客到达收款台的时间间隔服从平均时间为10s的负指数分布。每个顾客的服务时间服从均值为6.5s,标准差为1.2s的正态分布。
)
arrive | serve |
---|---|
9.622203751 | 5.005639909 |
3.885598622 | 7.112047687 |
9.337939136 | 6.19733889 |
6.886054426 | 7.139145964 |
1.4GUI界面输出与程序封装
概率密度函数图像:到达时间分布、服务时间分布。
各种排队论指标:顾客的平均逗留时间,系统的服务强度(服务时间/所有时间),平均队长(排队人数)。
方案二输入,另外输出极大似然估计计算得到的参数:到达时间平均间隔;服务时间分布参数:平均服务时间、服务时间标准差。
界面输出如下图:
1.4.1开始界面
1.4.2点击直接输入参数
1.4.2.1输入参数,点击确定
1.4.3点击导入csv文件
1.4.3.1输入csv文件路径,点击确定
附录一:代码(python+jupyter notebook)
1. #导包
2. from numpy.random import *
3. from simpy import *
4. import pandas as pd
5. import numpy as np
6. import matplotlib.pyplot as plt
7. import seaborn as sns
8. from scipy.stats import norm
9. from tkinter import *
10. import tkinter as tk
11. from PIL import Image, ImageTk
12. import os
13. import glob
14. import shutil
15. from gooey import Gooey, GooeyParser
16. from matplotlib import font_manager
17. my_font=font_manager.FontProperties(fname='C:\Windows\Fonts\msyh.ttc',size=10)
18.
19. #收款台服务问题:FIFO 直接输入参数
20. def cashierService_param(t1,t2,sigma,num,win):
21. """
22. 收款台服务问题
23. 某商店只有一个收款台
24. 顾客到达收款台的时间间隔服从平均时间为10s的负指数分布
25. 每个顾客的服务时间服从均值为6.5s,标准差为1.2s的正态分布
26. 计算:顾客的平均逗留时间,系统的服务强度(服务时间/所有时间),平均队长(排队人数)。
27.
28. 情景:
29. 客户到达,客户排队,一个柜台服务, 服务耗时, 客户离开
30. %t1 表示客户平均到达时间间隔
31. %t2 表示客户平均服务时间
32. %sigma 表示客户服务时间标准差
33. %num 表示客户数
34. """
35. # win1 = Toplevel()
36. # win1.title("排队模型仿真")
37. # win1.geometry('1000x450+100+100')
38. # win1.resizable(0,0)
39.
40. #客户到达时间间隔(负指数分布)
41. def arrive(t1,num):
42. sample = np.random.exponential(t1, size=num) # 产生num个满足指数分布的随机数
43. # print(np.sum(sample)/num)
44. return sample
45. #客户服务时间(正态分布)
46. def serve(t2,sigma,num):
47. sample = np.random.normal(t2, sigma, size=num)
48. return sample
49.
50. """顾客服务与离开仿真"""
51. #顾客到达时刻
52. a=list(arrive(t1,num))
53. arrive_t=[0]*num #客户到达时间列表
54. arrive_t[0]=a[0]
55. for i in range(num-1):
56. arrive_t[i+1] = arrive_t[i]+a[i+1]
57. #顾客开始服务时刻
58. b=list(serve(t2,sigma,num))
59. serve_t=[0]*num #客户服务时间列表
60. serve_t[0]=arrive_t[0]
61. for i in range(num-1):
62. if serve_t[i]+b[i]>arrive_t[i+1]:
63. serve_t[i+1] = serve_t[i]+b[i]
64. else:serve_t[i+1] =arrive_t[i+1]
65.
66. # 计算每人平均逗留时间
67. T=0
68. for i in range(num):
69. t=serve_t[i]+b[i]-arrive_t[i]
70. T+=t
71. print("每人平均逗留时间(分钟):{0:n}".format(T/num) )
72. tk.Label(win, text="每人平均逗留时间(分钟):{0:n}".format(T/num)).grid(row=1,column=2)
73.
74. #计算系统的服务强度
75. print("系统的服务强度:{0:n}".format(np.sum(b)/(serve_t[-1]+b[-1])) )
76. tk.Label(win, text="系统的服务强度:{0:n}".format(np.sum(b)/(serve_t[-1]+b[-1]))).grid(row=2,column=2)
77.
78. #计算平均队长(队长即某时刻排队人数。每当有人到达,记录一次队长)
79. n=1; x=0
80. list_len=[0]*num
81. for i in range(num-1):
82. n+=1
83. for j in range(x,i):
84. if arrive_t[i+1]>serve_t[j]+b[j]:
85. n-=1
86. x=j+1
87. list_len[i]=n
88. print("平均队长(人数):{0:n}".format(np.sum(list_len)/(len(list_len))))
89. tk.Label(win, text="平均队长(人数):{0:n}".format(np.sum(list_len)/(len(list_len)))).grid(row=3,column=2)
90.
91.
92. #负指数分布
93. plt.hist(arrive(t1,num), bins=100, alpha=0.7, normed=True)
94. plt.margins(0.02)
95. lam = 1 / t1
96. x = np.arange(0,t1*8,0.1)
97. y = lam * np.exp(- lam * x)
98. plt.plot(x,y,color='orange', lw=3)
99. plt.title('到达时间分布',fontproperties=my_font)
100. plt.xlabel('time')
101. plt.ylabel('PDF')
102. plt.savefig(fname="到达时间分布.png",figsize=[5,5])
103. plt.cla()
104.
105. #正态分布
106. plt. hist(serve(t2,sigma,num), bins=100, alpha=0.7, normed=True)
107. x = np.linspace(t2-3*sigma,t2+3*sigma,num)
108. y = pdf = np.exp(-((x - t2)**2) / (2* sigma**2)) / (sigma * np.sqrt(2*np.pi))
109. plt.plot(x,y, color='orange', lw=3)
110. plt.title('服务时间分布',fontproperties=my_font)
111. plt.xlabel('time')
112. plt.ylabel('PDF')
113. plt.savefig(fname="服务时间分布.png",figsize=[5,5])
114. plt.cla()
115.
116. img_png = tk.PhotoImage(file = '到达时间分布.png')
117. tk.Label(win,image = img_png).grid(row=7)
118. img_png1 = tk.PhotoImage(file = '服务时间分布.png')
119. tk.Label(win,image = img_png1).grid(row=7,column=2)
120. win.mainloop()
121.
122. def param(): #直接输入参数
123. win = Toplevel()
124. win.title("超市收银台")
125. win.geometry('1500x800+100+100')
126. win.resizable(0,0)
127. text=tk.Label(win,text="超市收银台",font=( 'Times',20)).grid(row=0,column=1)
128. #标签
129. tk.Label(win, text="平均到达时间(分钟):").grid(row=1)
130. tk.Label(win, text="平均服务时间(分钟):").grid(row=2)
131. tk.Label(win, text="服务时间标准差:").grid(row=3)
132. tk.Label(win, text="请输入客户数量(人):").grid(row=4)
133. # 创建输入框控件
134. e1 = tk.Entry(win)
135. e2 = tk.Entry(win)
136. e3 = tk.Entry(win)
137. e4 = tk.Entry(win)
138. e1.grid(row=1, column=1, padx=10, pady=5)
139. e2.grid(row=2, column=1, padx=10, pady=5)
140. e3.grid(row=3, column=1, padx=10, pady=5)
141. e4.grid(row=4, column=1, padx=10, pady=5)
142. def calc1():
143. t1 = float(e1.get())
144. t2=float(e2.get())
145. sigma=float(e3.get())
146. num=int(e4.get())
147. cashierService_param(t1,t2,sigma,num,win)
148. tk.Button(win, text="确定", width=10, command=calc1).grid(row=5, column=0, sticky="w", padx=10, pady=5)
149. tk.Button(win, text="退出", width=10, command=win.quit).grid(row=5, column=1, sticky="e", padx=10, pady=5)
150.
151. #收款台服务问题:FIFO 导入csv文件
152. def cashierService_csv(Time,win):
153. """
154. 收款台服务问题
155. 某商店只有一个收款台
156. 顾客到达收款台的时间间隔服从平均时间为10s的负指数分布
157. 每个顾客的服务时间服从均值为6.5s,标准差为1.2s的正态分布
158. 计算:顾客在收款台的平均逗留时间(,系统的服务强度(服务时间/所有时间),平均队长(排队人数)。
159.
160. 情景:
161. 客户到达,客户排队,一个柜台服务, 服务耗时, 客户离开
162. %t1 表示客户平均到达时间间隔
163. %t2 表示客户平均服务时间
164. %sigma 表示客户服务时间标准差
165. %num 表示客户数
166. """
167. # win1 = Toplevel()
168. # win1.title("排队模型仿真")
169. # win1.geometry('1000x450+100+100')
170. # win1.resizable(0,0)
171.
172. num = len(Time["serve"])
173.
174. """顾客服务与离开仿真"""
175. #顾客到达时刻
176. a=list(Time["arrive"])
177. arrive_t=[0]*num #客户到达时间列表
178. arrive_t[0]=a[0]
179. for i in range(num-1):
180. arrive_t[i+1] = arrive_t[i]+a[i+1]
181. #顾客开始服务时刻
182. b=list(Time["serve"])
183. serve_t=[0]*num #客户服务时间列表
184. serve_t[0]=arrive_t[0]
185. for i in range(num-1):
186. if serve_t[i]+b[i]>arrive_t[i+1]:
187. serve_t[i+1] = serve_t[i]+b[i]
188. else:serve_t[i+1] =arrive_t[i+1]
189. # 计算每人平均逗留时间
190. T=0
191. for i in range(num):
192. t=serve_t[i]+b[i]-arrive_t[i]
193. T+=t
194. print("每人平均逗留时间(分钟):{0:n}".format(T/num) )
195. tk.Label(win, text="每人平均逗留时间(分钟):{0:n}".format(T/num)).grid(row=1,column=2)
196.
197. #计算系统的服务强度
198. print("系统的服务强度:{0:n}".format(np.sum(b)/(serve_t[-1]+b[-1])) )
199. tk.Label(win, text="系统的服务强度:{0:n}".format(np.sum(b)/(serve_t[-1]+b[-1]))).grid(row=2,column=2)
200.
201. #计算平均队长(队长即某时刻排队人数。每当有人到达,记录一次队长)
202. n=1; x=0
203. list_len=[0]*num
204. for i in range(num-1):
205. n+=1
206. for j in range(x,i):
207. if arrive_t[i+1]>serve_t[j]+b[j]:
208. n-=1
209. x=j+1
210. list_len[i]=n
211. print("平均队长(人数):{0:n}".format(np.sum(list_len)/(len(list_len))) )
212. tk.Label(win, text="平均队长(人数):{0:n}".format(np.sum(list_len)/(len(list_len)))).grid(row=3,column=2)
213.
214. #负指数分布
215. plt.hist(Time["arrive"], bins=100, alpha=0.7, normed=True)
216. plt.margins(0.02)
217. t1=np.sum(Time["arrive"])/num
218. tk.Label(win, text="到达时间间隔均值(分钟):{0:n}".format(t1)).grid(row=4,column=2)
219. lam = 1 / t1
220. x = np.arange(0,t1*8,0.1)
221. y = lam * np.exp(- lam * x)
222. plt.plot(x,y,color='orange', lw=3)
223. plt.title('到达时间分布',fontproperties=my_font)
224. plt.xlabel('time')
225. plt.ylabel('PDF')
226. plt.savefig(fname="到达时间分布.png",figsize=[5,5])
227. plt.cla()
228. #正态分布
229. t2=norm.fit(Time["serve"])[0]
230. tk.Label(win, text="服务时间均值(分钟):{0:n}".format(t2)).grid(row=5,column=2)
231. sigma=norm.fit(Time["serve"])[1]
232. tk.Label(win, text="服务时间标准差:{0:n}".format(sigma)).grid(row=6,column=2)
233. plt. hist((Time["serve"]), bins=100, alpha=0.7, normed=True)
234. x = np.linspace(t2-3*sigma,t2+3*sigma,num)
235. y = pdf = np.exp(-((x - t2)**2) / (2* sigma**2)) / (sigma * np.sqrt(2*np.pi))
236. plt.plot(x,y, color='orange', lw=3)
237. plt.title('服务时间分布',fontproperties=my_font)
238. plt.xlabel('time')
239. plt.ylabel('PDF')
240. plt.savefig(fname="服务时间分布.png",figsize=[5,5])
241. plt.cla()
242.
243. img_png = tk.PhotoImage(file = '到达时间分布.png')
244. tk.Label(win,image = img_png).grid(row=8,column=0)
245. img_png1 = tk.PhotoImage(file = '服务时间分布.png')
246. tk.Label(win,image = img_png1).grid(row=8,column=2)
247. win.mainloop()
248.
249. def csv(): #导入csv文件
250. win = Toplevel()
251. win.title("超市收银台")
252. win.geometry('1500x900+100+100')
253. win.resizable(0,0)
254. text=tk.Label(win,text="超市收银台",font=( 'Times',20)).grid(row=0,column=1)
255. #标签
256. tk.Label(win, text="csv文件路径:").grid(row=1)
257. # 创建输入框控件
258. e1 = tk.Entry(win)
259. e1.grid(row=1, column=1, padx=10, pady=5)
260. def calc2():
261. Time = pd.read_csv(e1.get())
262. cashierService_csv(Time,win)
263. tk.Button(win, text="确定", width=10, command=calc2).grid(row=7, column=0, sticky="w", padx=10, pady=5)
264. tk.Button(win, text="退出", width=10, command=win.quit).grid(row=7, column=1, sticky="e", padx=10, pady=5)
265.
266. #主函数
267. import tkinter as tk
268. root_window =tk.Tk()
269. root_window.title('基于排队论模型的收银台服务系统的分析及可视化设计')
270. root_window.geometry('500x100+200+200')
271. text=tk.Label(root_window,text="请选择参数输入方式:",font=( 'Times',20))
272. text.pack()
273. button=tk.Button(root_window,text="导入csv文件",width=10,command=csv)
274. button.pack(side="bottom")
275. button=tk.Button(root_window,text="直接输入参数",width=10,command=param)
276. button.pack(side="bottom")
277. root_window.mainloop()