Hide keyboard shortcuts

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 

3 

4from openqtsim.customer import Customer 

5from openqtsim.arrival_process import ArrivalProcess 

6from openqtsim.service_process import ServiceProcess 

7 

8 

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 """ 

19 

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 """ 

25 

26 self.A = A 

27 self.S = S 

28 self.c = c 

29 self.K = K 

30 self.N = N 

31 self.D = D 

32 

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 """ 

38 

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: 

41 

42 # Draw IAT from distribution, move time forward and register arrival time (AT) 

43 IAT = Sim.queue.A.get_IAT(Sim.customer_nr) 

44 

45 yield Env.timeout(IAT) 

46 

47 # determine AT 

48 AT = Env.now - Env.epoch 

49 

50 # Create a customer 

51 customer_new = Customer(Env, Sim) # init: +1 for the next customer 

52 

53 # Make the customer go through the system 

54 Env.process(customer_new.move(IAT, AT)) 

55 

56 @property 

57 def kendall_notation(self): 

58 """ 

59 Return queue name according to the Kendall notation. 

60 """ 

61 

62 return "{}/{}/{}/{}/{}/{}".format( 

63 self.A.symbol, self.S.symbol, str(self.c), str(self.K), str(self.N), self.D 

64 ) 

65 

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 """ 

70 

71 kendall = "{}/{}/{}".format(self.A.symbol, self.S.symbol, str(self.c)) 

72 

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]]) 

88 

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 ]) 

105 

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 ]) 

130 

131 df = pd.DataFrame(data, index=utilisations, columns=nr_of_servers) 

132 

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) 

136 

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) 

139 

140 # Return waiting factor 

141 return waiting_factor 

142 

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 """ 

147 

148 kendall = "{}/{}/{}".format(self.A.symbol, self.S.symbol, str(self.c)) 

149 

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]]) 

165 

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 ]) 

182 

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 ]) 

207 

208 df = pd.DataFrame(data, index=utilisations, columns=nr_of_servers) 

209 

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) 

213 

214 occupancy = np.polyval(p_p, factor) 

215 

216 # Return occupancy 

217 return occupancy