Coverage for C:\checkouts\github\OpenQTSim\openqtsim\queue.py : 62%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import numpy as np
2import pandas as pd
4from openqtsim.customer import Customer
5from openqtsim.arrival_process import ArrivalProcess
6from openqtsim.service_process import ServiceProcess
9class Queue:
10 """
11 Queueing class based on Kendall's notation, in which:
12 - A is the arrival process
13 - S is the service time distribution
14 - c is the number of servers
15 - K is the number of places in the system
16 - N is the calling population
17 - D is the queue discipline
18 """
20 def __init__(self, A=ArrivalProcess(), S=ServiceProcess(), c=1, K=np.inf, N=np.inf, D="FIFO"):
21 """
22 The first six inputs are the typical Kendall inputs. Without inputs the queue object returns an M/M/1 object as
23 default
24 """
26 self.A = A
27 self.S = S
28 self.c = c
29 self.K = K
30 self.N = N
31 self.D = D
33 def populate(self, Env, Sim):
34 """
35 While the simulation time does not exceed the maximum duration, generate customers
36 according to the distribution of the arrival process to populate the queue
37 """
39 # Simulation stops either when max arrivals (max_arr) is reached or the tolerance limits are achieved
40 while Sim.customer_nr < Sim.max_arr:
42 # Draw IAT from distribution, move time forward and register arrival time (AT)
43 IAT = Sim.queue.A.get_IAT(Sim.customer_nr)
45 yield Env.timeout(IAT)
47 # determine AT
48 AT = Env.now - Env.epoch
50 # Create a customer
51 customer_new = Customer(Env, Sim) # init: +1 for the next customer
53 # Make the customer go through the system
54 Env.process(customer_new.move(IAT, AT))
56 @property
57 def kendall_notation(self):
58 """
59 Return queue name according to the Kendall notation.
60 """
62 return "{}/{}/{}/{}/{}/{}".format(
63 self.A.symbol, self.S.symbol, str(self.c), str(self.K), str(self.N), self.D
64 )
66 def occupancy_to_waitingfactor(self, utilisation=.3, nr_of_servers_to_chk=4, poly_order=6):
67 """
68 Waiting time factor (E2/E2/n or M/E2/n) queueing theory using 6th order polynomial regression)
69 """
71 kendall = "{}/{}/{}".format(self.A.symbol, self.S.symbol, str(self.c))
73 if kendall[0:4] == 'M/M/':
74 # Create dataframe with data from Groenveld (2007) - Table I (M/M/n)
75 # See also PIANC 2014 Table 6.2
76 utilisations = np.array([.1, .2, .3, .4, .5, .6, .7, .8, .9])
77 nr_of_servers = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
78 data = np.array([
79 [0.1111, 0.0101, 0.0014, 0.0002, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
80 [0.2500, 0.0417, 0.0103, 0.0030, 0.0010, 0.0003, 0.0001, 0.0000, 0.0000, 0.0000],
81 [0.4286, 0.0989, 0.0333, 0.0132, 0.0058, 0.0027, 0.0013, 0.0006, 0.0003, 0.0002],
82 [0.6667, 0.1905, 0.0784, 0.0378, 0.0199, 0.0111, 0.0064, 0.0039, 0.0024, 0.0015],
83 [1.0000, 0.3333, 0.1579, 0.0870, 0.0521, 0.0330, 0.0218, 0.0148, 0.0102, 0.0072],
84 [1.5000, 0.5625, 0.2956, 0.1794, 0.1181, 0.0819, 0.0589, 0.0436, 0.0330, 0.0253],
85 [2.3333, 0.9608, 0.5470, 0.3572, 0.2519, 0.1867, 0.1432, 0.1128, 0.0906, 0.0739],
86 [4.0000, 1.7778, 1.0787, 0.7455, 0.5541, 0.4315, 0.3471, 0.2860, 0.2401, 0.2046],
87 [9.0000, 4.2632, 2.7235, 1.9693, 1.5250, 1.2335, 1.0285, 0.8769, 0.7606, 0.6687]])
89 elif kendall[0:6] == 'E2/E2/':
90 # Create dataframe with data from Groenveld (2007) - Table V (E2/E2/n)
91 # See also PIANC 2014 Table 6.2
92 utilisations = np.array([.1, .2, .3, .4, .5, .6, .7, .8, .9])
93 nr_of_servers = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
94 data = np.array([
95 [0.0166, 0.0006, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
96 [0.0604, 0.0065, 0.0011, 0.0002, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
97 [0.1310, 0.0235, 0.0062, 0.0019, 0.0007, 0.0002, 0.0001, 0.0000, 0.0000, 0.0000],
98 [0.2355, 0.0576, 0.0205, 0.0085, 0.0039, 0.0019, 0.0009, 0.0005, 0.0003, 0.0001],
99 [0.3904, 0.1181, 0.0512, 0.0532, 0.0142, 0.0082, 0.0050, 0.0031, 0.0020, 0.0013],
100 [0.6306, 0.2222, 0.1103, 0.0639, 0.0400, 0.0265, 0.0182, 0.0128, 0.0093, 0.0069],
101 [1.0391, 0.4125, 0.2275, 0.1441, 0.0988, 0.0712, 0.0532, 0.0407, 0.0319, 0.0258],
102 [1.8653, 0.8300, 0.4600, 0.3300, 0.2300, 0.1900, 0.1400, 0.1200, 0.0900, 0.0900],
103 [4.3590, 2.0000, 1.2000, 0.9200, 0.6500, 0.5700, 0.4400, 0.4000, 0.3200, 0.3000]
104 ])
106 elif kendall[0:5] == 'M/E2/n':
107 # Create dataframe with data from Groenveld (2007) - Table IV (M/E2/n)
108 # See also PIANC 2014 Table 6.1
109 utilisations = np.array([.1, .15, .2, .25, .3, .35, .4, .45, .5, .55, .6, .65, .7, .75, .8, .85, .9])
110 nr_of_servers = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
111 data = np.array([
112 [0.08, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
113 [0.13, 0.02, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
114 [0.19, 0.03, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
115 [0.25, 0.05, 0.02, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
116 [0.32, 0.08, 0.03, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
117 [0.40, 0.11, 0.04, 0.02, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
118 [0.50, 0.15, 0.06, 0.03, 0.02, 0.01, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
119 [0.60, 0.20, 0.08, 0.05, 0.03, 0.02, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
120 [0.75, 0.26, 0.12, 0.07, 0.04, 0.03, 0.02, 0.01, 0.01, 0.01, 0.00, 0.00, 0.00, 0.00],
121 [0.91, 0.33, 0.16, 0.10, 0.06, 0.04, 0.03, 0.02, 0.02, 0.01, 0.01, 0.01, 0.00, 0.00],
122 [1.13, 0.43, 0.23, 0.14, 0.09, 0.06, 0.05, 0.03, 0.03, 0.02, 0.02, 0.01, 0.01, 0.01],
123 [1.38, 0.55, 0.30, 0.19, 0.12, 0.09, 0.07, 0.05, 0.04, 0.03, 0.03, 0.02, 0.02, 0.02],
124 [1.75, 0.73, 0.42, 0.27, 0.19, 0.14, 0.11, 0.09, 0.07, 0.06, 0.05, 0.04, 0.03, 0.03],
125 [2.22, 0.96, 0.59, 0.39, 0.28, 0.21, 0.17, 0.14, 0.12, 0.10, 0.08, 0.07, 0.06, 0.05],
126 [3.00, 1.34, 0.82, 0.57, 0.42, 0.33, 0.27, 0.22, 0.18, 0.16, 0.13, 0.11, 0.10, 0.09],
127 [4.50, 2.00, 1.34, 0.90, 0.70, 0.54, 0.46, 0.39, 0.34, 0.30, 0.26, 0.23, 0.20, 0.18],
128 [6.75, 3.14, 2.01, 1.45, 1.12, 0.91, 0.76, 0.65, 0.56, 0.50, 0.45, 0.40, 0.36, 0.33]
129 ])
131 df = pd.DataFrame(data, index=utilisations, columns=nr_of_servers)
133 # Create a 6th order polynomial fit through the data (for nr_of_stations_chk)
134 target = df.loc[:, nr_of_servers_to_chk];
135 p_p = np.polyfit(target.index, target.values, poly_order)
137 waiting_factor = np.polyval(p_p, utilisation)
138 # todo: when the nr of servers > 10 the waiting factor should be set to inf (definitively more equipment needed)
140 # Return waiting factor
141 return waiting_factor
143 def waitingfactor_to_occupancy(self, factor=.3, nr_of_servers_to_chk=4, poly_order=6):
144 """
145 Waiting time factor (E2/E2/n or M/E2/n) queueing theory using 6th order polynomial regression)
146 """
148 kendall = "{}/{}/{}".format(self.A.symbol, self.S.symbol, str(self.c))
150 if kendall[0:4] == 'M/M/':
151 # Create dataframe with data from Groenveld (2007) - Table I (M/M/n)
152 # See also PIANC 2014 Table 6.2
153 utilisations = np.array([.1, .2, .3, .4, .5, .6, .7, .8, .9])
154 nr_of_servers = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
155 data = np.array([
156 [0.1111, 0.0101, 0.0014, 0.0002, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
157 [0.2500, 0.0417, 0.0103, 0.0030, 0.0010, 0.0003, 0.0001, 0.0000, 0.0000, 0.0000],
158 [0.4286, 0.0989, 0.0333, 0.0132, 0.0058, 0.0027, 0.0013, 0.0006, 0.0003, 0.0002],
159 [0.6667, 0.1905, 0.0784, 0.0378, 0.0199, 0.0111, 0.0064, 0.0039, 0.0024, 0.0015],
160 [1.0000, 0.3333, 0.1579, 0.0870, 0.0521, 0.0330, 0.0218, 0.0148, 0.0102, 0.0072],
161 [1.5000, 0.5625, 0.2956, 0.1794, 0.1181, 0.0819, 0.0589, 0.0436, 0.0330, 0.0253],
162 [2.3333, 0.9608, 0.5470, 0.3572, 0.2519, 0.1867, 0.1432, 0.1128, 0.0906, 0.0739],
163 [4.0000, 1.7778, 1.0787, 0.7455, 0.5541, 0.4315, 0.3471, 0.2860, 0.2401, 0.2046],
164 [9.0000, 4.2632, 2.7235, 1.9693, 1.5250, 1.2335, 1.0285, 0.8769, 0.7606, 0.6687]])
166 elif kendall[0:6] == 'E2/E2/':
167 # Create dataframe with data from Groenveld (2007) - Table V (E2/E2/n)
168 # See also PIANC 2014 Table 6.2
169 utilisations = np.array([.1, .2, .3, .4, .5, .6, .7, .8, .9])
170 nr_of_servers = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
171 data = np.array([
172 [0.0166, 0.0006, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
173 [0.0604, 0.0065, 0.0011, 0.0002, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
174 [0.1310, 0.0235, 0.0062, 0.0019, 0.0007, 0.0002, 0.0001, 0.0000, 0.0000, 0.0000],
175 [0.2355, 0.0576, 0.0205, 0.0085, 0.0039, 0.0019, 0.0009, 0.0005, 0.0003, 0.0001],
176 [0.3904, 0.1181, 0.0512, 0.0532, 0.0142, 0.0082, 0.0050, 0.0031, 0.0020, 0.0013],
177 [0.6306, 0.2222, 0.1103, 0.0639, 0.0400, 0.0265, 0.0182, 0.0128, 0.0093, 0.0069],
178 [1.0391, 0.4125, 0.2275, 0.1441, 0.0988, 0.0712, 0.0532, 0.0407, 0.0319, 0.0258],
179 [1.8653, 0.8300, 0.4600, 0.3300, 0.2300, 0.1900, 0.1400, 0.1200, 0.0900, 0.0900],
180 [4.3590, 2.0000, 1.2000, 0.9200, 0.6500, 0.5700, 0.4400, 0.4000, 0.3200, 0.3000]
181 ])
183 elif kendall[0:5] == 'M/E2/n':
184 # Create dataframe with data from Groenveld (2007) - Table IV (M/E2/n)
185 # See also PIANC 2014 Table 6.1
186 utilisations = np.array([.1, .15, .2, .25, .3, .35, .4, .45, .5, .55, .6, .65, .7, .75, .8, .85, .9])
187 nr_of_servers = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
188 data = np.array([
189 [0.08, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
190 [0.13, 0.02, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
191 [0.19, 0.03, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
192 [0.25, 0.05, 0.02, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
193 [0.32, 0.08, 0.03, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
194 [0.40, 0.11, 0.04, 0.02, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
195 [0.50, 0.15, 0.06, 0.03, 0.02, 0.01, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
196 [0.60, 0.20, 0.08, 0.05, 0.03, 0.02, 0.01, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00],
197 [0.75, 0.26, 0.12, 0.07, 0.04, 0.03, 0.02, 0.01, 0.01, 0.01, 0.00, 0.00, 0.00, 0.00],
198 [0.91, 0.33, 0.16, 0.10, 0.06, 0.04, 0.03, 0.02, 0.02, 0.01, 0.01, 0.01, 0.00, 0.00],
199 [1.13, 0.43, 0.23, 0.14, 0.09, 0.06, 0.05, 0.03, 0.03, 0.02, 0.02, 0.01, 0.01, 0.01],
200 [1.38, 0.55, 0.30, 0.19, 0.12, 0.09, 0.07, 0.05, 0.04, 0.03, 0.03, 0.02, 0.02, 0.02],
201 [1.75, 0.73, 0.42, 0.27, 0.19, 0.14, 0.11, 0.09, 0.07, 0.06, 0.05, 0.04, 0.03, 0.03],
202 [2.22, 0.96, 0.59, 0.39, 0.28, 0.21, 0.17, 0.14, 0.12, 0.10, 0.08, 0.07, 0.06, 0.05],
203 [3.00, 1.34, 0.82, 0.57, 0.42, 0.33, 0.27, 0.22, 0.18, 0.16, 0.13, 0.11, 0.10, 0.09],
204 [4.50, 2.00, 1.34, 0.90, 0.70, 0.54, 0.46, 0.39, 0.34, 0.30, 0.26, 0.23, 0.20, 0.18],
205 [6.75, 3.14, 2.01, 1.45, 1.12, 0.91, 0.76, 0.65, 0.56, 0.50, 0.45, 0.40, 0.36, 0.33]
206 ])
208 df = pd.DataFrame(data, index=utilisations, columns=nr_of_servers)
210 # Create a 6th order polynomial fit through the data (for nr_of_stations_chk)
211 target = df.loc[:, nr_of_servers_to_chk]
212 p_p = np.polyfit(target.values, target.index, poly_order)
214 occupancy = np.polyval(p_p, factor)
216 # Return occupancy
217 return occupancy