most-queue 1.63__py3-none-any.whl → 2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of most-queue might be problematic. Click here for more details.

Files changed (83) hide show
  1. most_queue/distr_utils/__init__.py +0 -0
  2. most_queue/{general/interfaces.py → distr_utils/base_distribution.py} +2 -2
  3. most_queue/{general → distr_utils}/distribution_fitting.py +28 -41
  4. most_queue/{rand_distribution.py → distributions.py} +52 -47
  5. most_queue/general/plots.py +1 -1
  6. most_queue/general/results_structs.py +163 -0
  7. most_queue/general/tables.py +7 -21
  8. most_queue/misc/approx_cdf_make.py +4 -8
  9. most_queue/misc/calc_v_pls.py +27 -17
  10. most_queue/misc/compare_fj_calc.py +3 -1
  11. most_queue/misc/flow_sum.py +13 -16
  12. most_queue/misc/run_mgn_with_h2_delay_cold_warm.py +81 -81
  13. most_queue/misc/test_fj_delta.py +10 -12
  14. most_queue/misc/test_network_opt_approx.py +8 -7
  15. most_queue/misc/test_network_opt_plus.py +7 -7
  16. most_queue/misc/vacations_paper_utils.py +5 -5
  17. most_queue/sim/base.py +24 -31
  18. most_queue/sim/batch.py +3 -1
  19. most_queue/sim/finite_source.py +1 -1
  20. most_queue/sim/flow_sum.py +15 -10
  21. most_queue/sim/fork_join.py +1 -1
  22. most_queue/sim/fork_join_delta.py +4 -6
  23. most_queue/sim/negative.py +21 -17
  24. most_queue/sim/networks/base_network_sim.py +103 -0
  25. most_queue/sim/networks/network.py +86 -51
  26. most_queue/sim/networks/priority_network.py +125 -89
  27. most_queue/sim/priority.py +83 -76
  28. most_queue/sim/utils/distribution_utils.py +17 -15
  29. most_queue/sim/utils/servers.py +11 -12
  30. most_queue/sim/utils/tasks.py +5 -7
  31. most_queue/sim/vacations.py +27 -8
  32. most_queue/theory/base_queue.py +75 -0
  33. most_queue/theory/batch/mm1.py +94 -47
  34. most_queue/theory/calc_params.py +5 -6
  35. most_queue/theory/closed/engset.py +86 -34
  36. most_queue/theory/fifo/ek_d_n.py +80 -48
  37. most_queue/theory/fifo/gi_m_1.py +92 -35
  38. most_queue/theory/fifo/gi_m_n.py +92 -40
  39. most_queue/theory/fifo/m_d_n.py +45 -13
  40. most_queue/theory/fifo/mg1.py +77 -35
  41. most_queue/theory/fifo/mgn_takahasi.py +102 -50
  42. most_queue/theory/fifo/mmnr.py +61 -11
  43. most_queue/theory/fork_join/m_m_n.py +98 -19
  44. most_queue/theory/fork_join/split_join.py +67 -246
  45. most_queue/theory/impatience/mm1.py +62 -15
  46. most_queue/theory/negative/mg1_disasters.py +78 -26
  47. most_queue/theory/negative/mg1_rcs.py +62 -35
  48. most_queue/theory/negative/mgn_disaster.py +221 -185
  49. most_queue/theory/negative/mgn_rcs.py +144 -107
  50. most_queue/theory/negative/structs.py +0 -89
  51. most_queue/theory/networks/base_network_calc.py +123 -0
  52. most_queue/theory/networks/network_viewer.py +2 -6
  53. most_queue/theory/networks/open_network.py +69 -30
  54. most_queue/theory/networks/open_network_prty.py +69 -31
  55. most_queue/theory/networks/opt/transition.py +28 -34
  56. most_queue/theory/networks/opt/transition_approx.py +18 -18
  57. most_queue/theory/networks/opt/transition_plus.py +12 -12
  58. most_queue/theory/priority/mgn_invar_approx.py +84 -35
  59. most_queue/theory/priority/non_preemptive/mg1.py +60 -7
  60. most_queue/theory/priority/preemptive/m_ph_n_busy_approx.py +131 -60
  61. most_queue/theory/priority/preemptive/mg1.py +48 -29
  62. most_queue/theory/priority/preemptive/{mmn_3cls_busy_approx.py → mm2_3cls_busy_approx.py} +226 -157
  63. most_queue/theory/priority/preemptive/mmn_2cls_pr_busy_approx.py +183 -115
  64. most_queue/theory/utils/busy_periods.py +3 -7
  65. most_queue/theory/utils/conditional.py +5 -12
  66. most_queue/theory/utils/diff5dots.py +3 -9
  67. most_queue/theory/utils/flow_sum.py +8 -16
  68. most_queue/theory/utils/max_dist.py +196 -0
  69. most_queue/theory/utils/passage_time.py +29 -41
  70. most_queue/theory/utils/q_poisson_arrival_calc.py +4 -16
  71. most_queue/theory/utils/student_stat.py +1 -5
  72. most_queue/theory/utils/transforms.py +2 -4
  73. most_queue/theory/utils/utilization_approx.py +4 -1
  74. most_queue/theory/vacations/m_h2_h2warm.py +185 -140
  75. most_queue/theory/vacations/mg1_warm_calc.py +72 -19
  76. most_queue/theory/vacations/mgn_with_h2_delay_cold_warm.py +160 -122
  77. most_queue/theory/vacations/mmn_with_h2_cold_and_h2_warmup.py +258 -192
  78. {most_queue-1.63.dist-info → most_queue-2.2.dist-info}/METADATA +66 -10
  79. most_queue-2.2.dist-info/RECORD +110 -0
  80. most_queue-1.63.dist-info/RECORD +0 -104
  81. /most_queue/{general → distr_utils}/distribution_params.py +0 -0
  82. {most_queue-1.63.dist-info → most_queue-2.2.dist-info}/WHEEL +0 -0
  83. {most_queue-1.63.dist-info → most_queue-2.2.dist-info}/licenses/LICENSE +0 -0
File without changes
@@ -55,10 +55,10 @@ class Distribution(ABC):
55
55
 
56
56
  @staticmethod
57
57
  @abstractmethod
58
- def get_params_by_mean_and_coev(f1: float, coev: float):
58
+ def get_params_by_mean_and_cv(f1: float, cv: float):
59
59
  """
60
60
  :param f1: mean of the distribution.
61
- :param coev: coefficient of variation (std_dev / mean).
61
+ :param cv: coefficient of variation (std_dev / mean).
62
62
  :return: Parameters for the distribution that correspond
63
63
  to the given mean and coefficient of variation.
64
64
  """
@@ -8,10 +8,14 @@ from dataclasses import dataclass
8
8
 
9
9
  import numpy as np
10
10
 
11
- from most_queue.general.distribution_params import (Cox2Params, ErlangParams,
12
- GammaParams, H2Params,
13
- ParetoParams,
14
- WeibullParams)
11
+ from most_queue.distr_utils.distribution_params import (
12
+ Cox2Params,
13
+ ErlangParams,
14
+ GammaParams,
15
+ H2Params,
16
+ ParetoParams,
17
+ WeibullParams,
18
+ )
15
19
 
16
20
 
17
21
  @dataclass
@@ -98,28 +102,22 @@ def fit_h2_clx(moments: list[float], fitting_params: FittingParams | None = None
98
102
 
99
103
  if fitting_params.is_fitting:
100
104
  # проверка на близость распределения к экспоненциальному
101
- coev = cmath.sqrt(moments[1] - moments[0] ** 2) / moments[0]
102
- if math.fabs(coev.real - 1.0) < fitting_params.ee:
105
+ cv = cmath.sqrt(moments[1] - moments[0] ** 2) / moments[0]
106
+ if math.fabs(cv.real - 1.0) < fitting_params.ee:
103
107
  if fitting_params.verbose:
104
- print(
105
- f"H2 is close to Exp. Multiply moments to (1+je)"
106
- f"coev = {coev:5.3f}, e = {fitting_params.e:5.3f}."
107
- )
108
+ print(f"H2 is close to Exp. Multiply moments to (1+je)" f"cv = {cv:5.3f}, e = {fitting_params.e:5.3f}.")
108
109
  f = []
109
110
  for i, mom in enumerate(moments):
110
111
  f.append(mom * complex(1, (i + 1) * fitting_params.e))
111
112
 
112
113
  return fit_h2_clx(f, fitting_params=fitting_params)
113
114
 
114
- coev = cmath.sqrt(moments[1] - moments[0] ** 2) / moments[0]
115
+ cv = cmath.sqrt(moments[1] - moments[0] ** 2) / moments[0]
115
116
 
116
117
  # проверка на близость распределения к Эрланга 2-го порядка
117
- if math.fabs(coev.real - 1.0 / math.sqrt(2.0)) < fitting_params.ee:
118
+ if math.fabs(cv.real - 1.0 / math.sqrt(2.0)) < fitting_params.ee:
118
119
  if fitting_params.verbose:
119
- print(
120
- f"H2 is close to E2. Multiply moments to (1+je)"
121
- f"coev = {coev:5.3f}, e = {fitting_params.e:5.3f}."
122
- )
120
+ print(f"H2 is close to E2. Multiply moments to (1+je)" f"cv = {cv:5.3f}, e = {fitting_params.e:5.3f}.")
123
121
  f = []
124
122
  for i, mom in enumerate(moments):
125
123
  f.append(mom * complex(1, (i + 1) * fitting_params.e))
@@ -148,26 +146,23 @@ def fit_cox(moments: list[float], fitting_params: FittingParams | None = None) -
148
146
 
149
147
  if fitting_params.is_fitting:
150
148
  # проверка на близость распределения к экспоненциальному
151
- coev = cmath.sqrt(moments[1] - moments[0] ** 2) / moments[0]
149
+ cv = cmath.sqrt(moments[1] - moments[0] ** 2) / moments[0]
152
150
  if abs(moments[1] - moments[0] * moments[0]) < fitting_params.ee:
153
151
  if fitting_params.verbose:
154
- print(
155
- f"Cox special 1. Multiply moments to (1+je)"
156
- f"coev = {coev:5.3f} e = {fitting_params.e:5.3f}."
157
- )
152
+ print(f"Cox special 1. Multiply moments to (1+je)" f"cv = {cv:5.3f} e = {fitting_params.e:5.3f}.")
158
153
  f = []
159
154
  for i, mom in enumerate(moments):
160
155
  f.append(mom * complex(1, (i + 1) * fitting_params.e))
161
156
 
162
157
  return fit_cox(f, fitting_params=fitting_params)
163
158
 
164
- coev = cmath.sqrt(moments[1] - moments[0] ** 2) / moments[0]
159
+ cv = cmath.sqrt(moments[1] - moments[0] ** 2) / moments[0]
165
160
 
166
161
  # проверка на близость распределения к Эрланга 2-го порядка
167
162
  if abs(moments[1] - (3.0 / 4) * moments[0] * moments[0]) < fitting_params.ee:
168
163
  if fitting_params.verbose:
169
164
  print("Cox special 2. Multiply moments to (1+je)")
170
- print(f"\tcoev = {coev:5.3f}, e = {fitting_params.e:5.3f}")
165
+ print(f"\tcv = {cv:5.3f}, e = {fitting_params.e:5.3f}")
171
166
  f = []
172
167
  for i, mom in enumerate(moments):
173
168
  f.append(mom * complex(1, (i + 1) * fitting_params.e))
@@ -176,9 +171,7 @@ def fit_cox(moments: list[float], fitting_params: FittingParams | None = None) -
176
171
  for i in range(3):
177
172
  f[i] = moments[i] / math.factorial(i + 1)
178
173
 
179
- d = np.power(f[2] - f[0] * f[1], 2) - 4.0 * (f[1] - np.power(f[0], 2)) * (
180
- f[0] * f[2] - np.power(f[1], 2)
181
- )
174
+ d = np.power(f[2] - f[0] * f[1], 2) - 4.0 * (f[1] - np.power(f[0], 2)) * (f[0] * f[2] - np.power(f[1], 2))
182
175
  mu2 = f[0] * f[1] - f[2] + cmath.sqrt(d)
183
176
  mu2 /= 2.0 * (np.power(f[1], 2) - f[0] * f[2])
184
177
  mu1 = (mu2 * f[0] - 1.0) / (mu2 * f[1] - f[0])
@@ -200,13 +193,13 @@ def fit_pareto_moments(moments: list[float]):
200
193
  return ParetoParams(alpha=a, K=k)
201
194
 
202
195
 
203
- def fit_pareto_by_mean_and_coev(f1: float, coev: float):
196
+ def fit_pareto_by_mean_and_cv(f1: float, cv: float):
204
197
  """
205
198
  Get parameters of the distribution by mean and coefficient of variation.
206
199
  :param f1: float, mean value of the distribution
207
- :param coev: float, coefficient of variation (mean / std)
200
+ :param cv: float, coefficient of variation (mean / std)
208
201
  """
209
- d = pow(f1 * coev, 2)
202
+ d = pow(f1 * cv, 2)
210
203
  c = pow(f1, 2) / d
211
204
  disc = 4 * (1 + c)
212
205
  a = (2 + math.sqrt(disc)) / 2
@@ -287,9 +280,7 @@ def fit_gamma(moments: list[float]) -> GammaParams:
287
280
  else:
288
281
  B.append(moments[i - 1])
289
282
  for j in range(len(moments) + 1):
290
- A[i].append(
291
- calc_gamma_func(alpha + i + j) / (pow(mu, i + j) * calc_gamma_func(alpha))
292
- )
283
+ A[i].append(calc_gamma_func(alpha + i + j) / (pow(mu, i + j) * calc_gamma_func(alpha)))
293
284
  g = np.linalg.solve(A, B)
294
285
  return GammaParams(mu=mu, alpha=alpha, g=g)
295
286
 
@@ -311,14 +302,10 @@ def fit_weibull(moments: list[float]) -> WeibullParams:
311
302
  a = moments[1] / (moments[0] * moments[0])
312
303
  u0 = math.log(2 * a) / (2.0 * math.log(2))
313
304
  ee = 1e-6
314
- u1 = (1.0 / (2 * math.log(2))) * math.log(
315
- a * math.sqrt(math.pi) * math.gamma(u0 + 1) / math.gamma(u0 + 0.5)
316
- )
305
+ u1 = (1.0 / (2 * math.log(2))) * math.log(a * math.sqrt(math.pi) * math.gamma(u0 + 1) / math.gamma(u0 + 0.5))
317
306
  delta = u1 - u0
318
307
  while math.fabs(delta) > ee:
319
- u1 = (1.0 / (2 * math.log(2))) * math.log(
320
- a * math.sqrt(math.pi) * math.gamma(u0 + 1) / math.gamma(u0 + 0.5)
321
- )
308
+ u1 = (1.0 / (2 * math.log(2))) * math.log(a * math.sqrt(math.pi) * math.gamma(u0 + 1) / math.gamma(u0 + 0.5))
322
309
  delta = u1 - u0
323
310
  u0 = u1
324
311
  k = 1 / u1
@@ -327,14 +314,14 @@ def fit_weibull(moments: list[float]) -> WeibullParams:
327
314
  return WeibullParams(k=k, W=big_w)
328
315
 
329
316
 
330
- def gamma_moments_by_mean_and_coev(mean: float, coev: float) -> list[float]:
317
+ def gamma_moments_by_mean_and_cv(mean: float, cv: float) -> list[float]:
331
318
  """
332
319
  Calculate the first three moments of a gamma distribution
333
320
  given the mean and coefficient of variation.
334
321
  """
335
322
  f = [0, 0, 0]
336
- alpha = 1 / (coev**2)
323
+ alpha = 1 / (cv**2)
337
324
  f[0] = mean
338
- f[1] = pow(f[0], 2) * (pow(coev, 2) + 1)
325
+ f[1] = pow(f[0], 2) * (pow(cv, 2) + 1)
339
326
  f[2] = f[1] * f[0] * (1.0 + 2 / alpha)
340
327
  return f
@@ -1,3 +1,4 @@
1
+ # pylint: disable=too-many-lines
1
2
  """
2
3
  Random distributions for simulation.
3
4
  """
@@ -8,17 +9,30 @@ import numpy as np
8
9
  import scipy.special as sp
9
10
  from scipy import stats
10
11
 
11
- from most_queue.general.distribution_fitting import (
12
- FittingParams, calc_gamma_func, fit_cox, fit_erlang, fit_gamma, fit_h2,
13
- fit_h2_clx, fit_pareto_by_mean_and_coev, fit_pareto_moments, fit_weibull,
14
- gamma_moments_by_mean_and_coev)
15
- from most_queue.general.distribution_params import (Cox2Params, ErlangParams,
16
- GammaParams,
17
- GaussianParams, H2Params,
18
- ParetoParams,
19
- UniformParams,
20
- WeibullParams)
21
- from most_queue.general.interfaces import Distribution
12
+ from most_queue.distr_utils.base_distribution import Distribution
13
+ from most_queue.distr_utils.distribution_fitting import (
14
+ FittingParams,
15
+ calc_gamma_func,
16
+ fit_cox,
17
+ fit_erlang,
18
+ fit_gamma,
19
+ fit_h2,
20
+ fit_h2_clx,
21
+ fit_pareto_by_mean_and_cv,
22
+ fit_pareto_moments,
23
+ fit_weibull,
24
+ gamma_moments_by_mean_and_cv,
25
+ )
26
+ from most_queue.distr_utils.distribution_params import (
27
+ Cox2Params,
28
+ ErlangParams,
29
+ GammaParams,
30
+ GaussianParams,
31
+ H2Params,
32
+ ParetoParams,
33
+ UniformParams,
34
+ WeibullParams,
35
+ )
22
36
 
23
37
 
24
38
  class Weibull(Distribution):
@@ -85,17 +99,17 @@ class Weibull(Distribution):
85
99
  return fit_weibull(moments)
86
100
 
87
101
  @staticmethod
88
- def get_params_by_mean_and_coev(f1: float, coev: float) -> WeibullParams:
102
+ def get_params_by_mean_and_cv(f1: float, cv: float) -> WeibullParams:
89
103
  """
90
104
  Subselect parameters of Weibull distribution by the given mean and coefficient of variation.
91
105
  Args:
92
106
  f1 (float): The first parameter of the Weibull distribution.
93
- coev (float): The coefficient of variation.
107
+ cv (float): The coefficient of variation.
94
108
  Returns:
95
109
  WeibullParams
96
110
  """
97
111
 
98
- f = gamma_moments_by_mean_and_coev(f1, coev)
112
+ f = gamma_moments_by_mean_and_cv(f1, cv)
99
113
 
100
114
  return Weibull.get_params(f)
101
115
 
@@ -188,15 +202,15 @@ class NormalDistribution(Distribution):
188
202
  return GaussianParams(mean, std_dev)
189
203
 
190
204
  @staticmethod
191
- def get_params_by_mean_and_coev(f1: float, coev: float):
205
+ def get_params_by_mean_and_cv(f1: float, cv: float):
192
206
  """
193
207
  :param f1: mean of the distribution.
194
- :param coev: coefficient of variation (std_dev / mean).
208
+ :param cv: coefficient of variation (std_dev / mean).
195
209
  :return: Parameters for the distribution that correspond
196
210
  to the given mean and coefficient of variation.
197
211
  """
198
212
  mean = f1
199
- std_dev = coev * mean
213
+ std_dev = cv * mean
200
214
  return GaussianParams(mean, std_dev)
201
215
 
202
216
 
@@ -246,9 +260,7 @@ class UniformDistribution(Distribution):
246
260
  mean, half_interval = params.mean, params.half_interval
247
261
  f = [0.0] * num
248
262
  for i in range(num):
249
- f[i] = (pow(mean + half_interval, i + 2) - pow(mean - half_interval, i + 2)) / (
250
- 2 * half_interval * (i + 2)
251
- )
263
+ f[i] = (pow(mean + half_interval, i + 2) - pow(mean - half_interval, i + 2)) / (2 * half_interval * (i + 2))
252
264
  return f
253
265
 
254
266
  @staticmethod
@@ -264,13 +276,13 @@ class UniformDistribution(Distribution):
264
276
  return UniformParams(mean=mean, half_interval=half_interval)
265
277
 
266
278
  @staticmethod
267
- def get_params_by_mean_and_coev(f1: float, coev: float) -> UniformParams:
279
+ def get_params_by_mean_and_cv(f1: float, cv: float) -> UniformParams:
268
280
  """
269
281
  Get parameters of the uniform distribution by mean and coefficient of variation.
270
282
  Returns mean and half interval.
271
283
  """
272
284
 
273
- D = pow(coev * f1, 2)
285
+ D = pow(cv * f1, 2)
274
286
  half_interval = math.sqrt(3 * D)
275
287
 
276
288
  return UniformParams(mean=f1, half_interval=half_interval)
@@ -369,9 +381,7 @@ class H2Distribution(Distribution):
369
381
  y2 = 1.0 - params.p1
370
382
 
371
383
  for i in range(num):
372
- f[i] = math.factorial(i + 1) * (
373
- params.p1 / pow(params.mu1, i + 1) + y2 / pow(params.mu2, i + 1)
374
- )
384
+ f[i] = math.factorial(i + 1) * (params.p1 / pow(params.mu1, i + 1) + y2 / pow(params.mu2, i + 1))
375
385
  return f
376
386
 
377
387
  @staticmethod
@@ -394,9 +404,7 @@ class H2Distribution(Distribution):
394
404
  return fit_h2(moments)
395
405
 
396
406
  @staticmethod
397
- def get_params_clx(
398
- moments: list[float], fitting_params: FittingParams | None = None
399
- ) -> H2Params:
407
+ def get_params_clx(moments: list[float], fitting_params: FittingParams | None = None) -> H2Params:
400
408
  """
401
409
  Method of fitting H2 distribution parameters to given initial moments.
402
410
  Uses the method of moments and optimization to fit the parameters.
@@ -406,12 +414,12 @@ class H2Distribution(Distribution):
406
414
  return fit_h2_clx(moments, fitting_params=fitting_params)
407
415
 
408
416
  @staticmethod
409
- def get_params_by_mean_and_coev(f1: float, coev: float, is_clx=False) -> H2Params:
417
+ def get_params_by_mean_and_cv(f1: float, cv: float, is_clx=False) -> H2Params:
410
418
  """
411
419
  Get parameters of the H2 distribution by mean and coefficient of variation.
412
420
  """
413
421
 
414
- f = gamma_moments_by_mean_and_coev(f1, coev)
422
+ f = gamma_moments_by_mean_and_cv(f1, cv)
415
423
 
416
424
  if is_clx:
417
425
  return H2Distribution.get_params_clx(f)
@@ -505,10 +513,7 @@ class CoxDistribution(Distribution):
505
513
  y2 = 1.0 - y1
506
514
  f = [0.0] * 3
507
515
  f[0] = y2 / m1 + y1 * (1.0 / m1 + 1.0 / m2)
508
- f[1] = 2.0 * (
509
- y2 / math.pow(m1, 2)
510
- + y1 * (1.0 / math.pow(m1, 2) + 1.0 / (m1 * m2) + 1.0 / math.pow(m2, 2))
511
- )
516
+ f[1] = 2.0 * (y2 / math.pow(m1, 2) + y1 * (1.0 / math.pow(m1, 2) + 1.0 / (m1 * m2) + 1.0 / math.pow(m2, 2)))
512
517
  f[2] = 6.0 * (
513
518
  y2 / (math.pow(m1, 3))
514
519
  + y1
@@ -530,12 +535,12 @@ class CoxDistribution(Distribution):
530
535
  return fit_cox(moments, fitting_params=fitting_params)
531
536
 
532
537
  @staticmethod
533
- def get_params_by_mean_and_coev(f1: float, coev: float) -> Cox2Params:
538
+ def get_params_by_mean_and_cv(f1: float, cv: float) -> Cox2Params:
534
539
  """
535
540
  Get parameters of C2 distribution by mean and coefficient of variation
536
541
  """
537
542
 
538
- f = gamma_moments_by_mean_and_coev(f1, coev)
543
+ f = gamma_moments_by_mean_and_cv(f1, cv)
539
544
 
540
545
  return CoxDistribution.get_params(f)
541
546
 
@@ -584,10 +589,10 @@ class DeterministicDistribution(Distribution):
584
589
  return moments[0]
585
590
 
586
591
  @staticmethod
587
- def get_params_by_mean_and_coev(f1: float, coev: float):
592
+ def get_params_by_mean_and_cv(f1: float, cv: float):
588
593
  """
589
594
  :param f1: mean of the distribution.
590
- :param coev: coefficient of variation (std_dev / mean).
595
+ :param cv: coefficient of variation (std_dev / mean).
591
596
  :return: Parameters for the distribution that correspond
592
597
  to the given mean and coefficient of variation.
593
598
  """
@@ -689,14 +694,14 @@ class ParetoDistribution(Distribution):
689
694
  return fit_pareto_moments(moments)
690
695
 
691
696
  @staticmethod
692
- def get_params_by_mean_and_coev(f1: float, coev: float):
697
+ def get_params_by_mean_and_cv(f1: float, cv: float):
693
698
  """
694
699
  Get parameters of the distribution by mean and coefficient of variation.
695
700
  :param f1: float, mean value of the distribution
696
- :param coev: float, coefficient of variation (mean / std)
701
+ :param cv: float, coefficient of variation (mean / std)
697
702
  """
698
703
 
699
- return fit_pareto_by_mean_and_coev(f1, coev)
704
+ return fit_pareto_by_mean_and_cv(f1, cv)
700
705
 
701
706
 
702
707
  class ErlangDistribution(Distribution):
@@ -782,14 +787,14 @@ class ErlangDistribution(Distribution):
782
787
  return fit_erlang(moments)
783
788
 
784
789
  @staticmethod
785
- def get_params_by_mean_and_coev(f1: float, coev: float) -> ErlangParams:
790
+ def get_params_by_mean_and_cv(f1: float, cv: float) -> ErlangParams:
786
791
  """
787
792
  Method selects the parameters of the Erlang distribution
788
793
  by mean and coefficient of variation.
789
794
  """
790
795
  f = [0, 0]
791
796
  f[0] = f1
792
- f[1] = (math.pow(coev, 2) + 1) * math.pow(f[0], 2)
797
+ f[1] = (math.pow(cv, 2) + 1) * math.pow(f[0], 2)
793
798
  return ErlangDistribution.get_params(f)
794
799
 
795
800
 
@@ -840,11 +845,11 @@ class ExpDistribution(Distribution):
840
845
  return ErlangDistribution.get_params(moments).mu
841
846
 
842
847
  @staticmethod
843
- def get_params_by_mean_and_coev(f1: float, coev: float) -> float:
848
+ def get_params_by_mean_and_cv(f1: float, cv: float) -> float:
844
849
  """
845
850
  Get parameters of the exponential distribution from mean and coefficient of variation.
846
851
  :param f1: mean value
847
- :param coev: coefficient of variation (coefficient of dispersion)
852
+ :param cv: coefficient of variation (coefficient of dispersion)
848
853
  """
849
854
  return 1 / f1
850
855
 
@@ -872,11 +877,11 @@ class GammaDistribution(Distribution):
872
877
  return fit_gamma(moments)
873
878
 
874
879
  @staticmethod
875
- def get_params_by_mean_and_coev(f1: float, coev: float) -> GammaParams:
880
+ def get_params_by_mean_and_cv(f1: float, cv: float) -> GammaParams:
876
881
  """
877
882
  Get parameters of gamma distribution by mean and coefficient of variation.
878
883
  """
879
- d = pow(f1 * coev, 2)
884
+ d = pow(f1 * cv, 2)
880
885
  mu = f1 / d
881
886
  alpha = mu * f1
882
887
  return GammaParams(mu=mu, alpha=alpha)
@@ -26,7 +26,7 @@ def plot_sim_vs_calc_moments(
26
26
  is_errors=False,
27
27
  is_waiting_time=True,
28
28
  save_path=None,
29
- ):
29
+ ): # pylint: disable=too-many-positional-arguments, too-many-arguments
30
30
  """
31
31
  Plots the simulation and calculated moments for a given list of x values.
32
32
  :param xs: A list of x values (e.g., utilization factors or number of channels).
@@ -0,0 +1,163 @@
1
+ """
2
+ Structures for queueing systems.
3
+ """
4
+
5
+ import json
6
+ from dataclasses import asdict, dataclass, is_dataclass
7
+
8
+
9
+ @dataclass
10
+ class QueueResults:
11
+ """
12
+ Result of calculation for queueing system.
13
+ """
14
+
15
+ v: list[float] | None = None # sojourn time initial moments
16
+ w: list[float] | None = None # waiting time initial moments
17
+ p: list[float] | None = None # probabilities of states
18
+ pi: list[float] | None = None # probabilities of states before arrival
19
+ utilization: float | None = None # utilization factor
20
+
21
+ duration: float = 0.0 # calculation or simulation duration in seconds
22
+
23
+
24
+ @dataclass
25
+ class PriorityResults:
26
+ """
27
+ Results of priority queue calculation
28
+ """
29
+
30
+ v: list[list[float]] | None = None # sojourn time moments for each class
31
+ w: list[list[float]] | None = None # waiting time moments for each class
32
+ p: list[float] | None = None # probabilities of states (low priority jobs)
33
+
34
+ h: list[list[float]] | None = None # initial moments of active time
35
+ busy: list[list[float]] | None = None # initial moments of busy period
36
+ w_with_pr: list[list[float]] | None = None # initial moments of waiting for service with interruptions
37
+
38
+ utilization: float | None = None # utilization factor
39
+
40
+ duration: float = 0.0 # calculation or simulation duration in seconds
41
+
42
+
43
+ @dataclass
44
+ class VacationResults(QueueResults):
45
+ """
46
+ Result of queue with vacations.
47
+ """
48
+
49
+ warmup_prob: float = 0
50
+ cold_prob: float = 0
51
+ cold_delay_prob: float = 0
52
+ servers_busy_probs: list[float] | None = None
53
+
54
+
55
+ @dataclass
56
+ class NetworkResults:
57
+ """
58
+ Data class to store network results.
59
+ """
60
+
61
+ v: list[float] | None = None # initial moments of sojourn time distribution
62
+ intensities: list[float] | None = None # intensities of arrivals into nodes
63
+ loads: list[float] | None = None # nodes utilizations
64
+
65
+ duration: float = 0.0 # calculation or simulation duration in seconds
66
+
67
+ arrived: int = 0 # number of arrived jobs (for simulation)
68
+ served: int = 0 # number of served jobs (for simulation)
69
+
70
+
71
+ @dataclass
72
+ class NetworkResultsPriority:
73
+ """
74
+ Data class to store results for network with priority discipline in nodes.
75
+ """
76
+
77
+ v: list[list[float]] | None = None # initial moments of sojourn time distribution for each class
78
+ intensities: list[list[float]] | None = None # intensities of arrivals into nodes for each class
79
+ loads: list[float] | None = None # nodes utilizations
80
+
81
+ duration: float = 0.0 # calculation or simulation duration in seconds
82
+
83
+ arrived: int = 0 # number of arrived jobs (for simulation)
84
+ served: int = 0 # number of served jobs (for simulation)
85
+
86
+
87
+ @dataclass
88
+ class NegativeArrivalsResults(QueueResults):
89
+ """
90
+ Class for storing results related to negative arrivals in a queueing system.
91
+ Contains lists of waiting times (w), sojourn times (v),
92
+ sojourn times of served jobs (v_served), sojourn times of broken jobs (v_broken),
93
+ and probabilities (p).
94
+ """
95
+
96
+ v_served: list[float] | None = None
97
+ v_broken: list[float] | None = None
98
+
99
+
100
+ @dataclass
101
+ class DependsOnChannelsResults:
102
+ """
103
+ Class for storing results that depend on the number of channels.
104
+ Contains calculated and simulated results,
105
+ as well as parameters such as the number of channels,
106
+ utilization factor, and service time variation coefficient.
107
+ """
108
+
109
+ calc: list[NegativeArrivalsResults]
110
+ sim: list[NegativeArrivalsResults]
111
+ channels: list[int]
112
+ utilization_factor: float
113
+ service_time_variation_coef: float
114
+
115
+
116
+ @dataclass
117
+ class DependsOnUtilizationResults:
118
+ """
119
+ Class for storing results that depend on the utilization factor.
120
+ Contains calculated and simulated results,
121
+ as well as parameters such as the number of channels,
122
+ utilization factor, and service time variation coefficient.
123
+ """
124
+
125
+ calc: list[NegativeArrivalsResults]
126
+ sim: list[NegativeArrivalsResults]
127
+ utilization_factor: list[float]
128
+ channels: int
129
+ service_time_variation_coef: float
130
+
131
+
132
+ @dataclass
133
+ class DependsOnVariationResults:
134
+ """
135
+ Class for storing results that depend on the service time variation coefficient.
136
+ Contains calculated and simulated results,
137
+ as well as parameters such as the number of channels,
138
+ utilization factor, and service time variation coefficient.
139
+ """
140
+
141
+ calc: list[NegativeArrivalsResults]
142
+ sim: list[NegativeArrivalsResults]
143
+ service_time_variation_coef: list[float]
144
+ channels: int
145
+ utilization_factor: float
146
+
147
+
148
+ class DependsOnJSONEncoder(json.JSONEncoder):
149
+ """
150
+ Encoder for dataclasses to JSON.
151
+ """
152
+
153
+ def default(self, o):
154
+ if is_dataclass(o):
155
+ json_res = {
156
+ "service_time_variation_coef": o.service_time_variation_coef,
157
+ "channels": o.channels,
158
+ "utilization_factor": o.utilization_factor,
159
+ "calc": [asdict(r) for r in o.calc],
160
+ "sim": [asdict(r) for r in o.sim],
161
+ }
162
+ return json_res
163
+ return super().default(o)
@@ -16,7 +16,7 @@ def times_print(
16
16
  header=None,
17
17
  sim_header="Sim",
18
18
  calc_header="Num",
19
- ):
19
+ ): # pylint: disable=too-many-positional-arguments, too-many-arguments
20
20
  """
21
21
  Prints the initial moments of waiting or sojourn time in the system.
22
22
  Args:
@@ -41,9 +41,7 @@ def times_print(
41
41
  print("-" * 45)
42
42
  if isinstance(sim_moments, list):
43
43
  for j in range(min(len(sim_moments), len(calc_moments))):
44
- calc_mom = (
45
- calc_moments[j].real if isinstance(calc_moments[j], complex) else calc_moments[j]
46
- )
44
+ calc_mom = calc_moments[j].real if isinstance(calc_moments[j], complex) else calc_moments[j]
47
45
  sim_mom = sim_moments[j].real if isinstance(sim_moments[j], complex) else sim_moments[j]
48
46
  print(
49
47
  Fore.CYAN
@@ -78,7 +76,7 @@ def times_print_with_two_numerical(
78
76
  is_w=True,
79
77
  num1_header="Num1",
80
78
  num2_header="Num2",
81
- ):
79
+ ): # pylint: disable=too-many-positional-arguments, too-many-arguments
82
80
  """
83
81
  Prints the initial moments of waiting or sojourn time in the system.
84
82
  Args:
@@ -103,12 +101,8 @@ def times_print_with_two_numerical(
103
101
  print("-" * 60)
104
102
  if isinstance(sim_moments, list):
105
103
  for j in range(min(len(sim_moments), len(calc_moments1), len(calc_moments2))):
106
- calc_mom1 = (
107
- calc_moments1[j].real if isinstance(calc_moments1[j], complex) else calc_moments1[j]
108
- )
109
- calc_mom2 = (
110
- calc_moments2[j].real if isinstance(calc_moments2[j], complex) else calc_moments2[j]
111
- )
104
+ calc_mom1 = calc_moments1[j].real if isinstance(calc_moments1[j], complex) else calc_moments1[j]
105
+ calc_mom2 = calc_moments2[j].real if isinstance(calc_moments2[j], complex) else calc_moments2[j]
112
106
  sim_mom = sim_moments[j].real if isinstance(sim_moments[j], complex) else sim_moments[j]
113
107
  print(
114
108
  Fore.CYAN
@@ -167,11 +161,7 @@ def times_print_no_compare(wait_times=None, sojourn_times=None):
167
161
  if isinstance(wait_times, list):
168
162
  for j in range(min(len(wait_times), len(sojourn_times))):
169
163
  w_mom = wait_times[j].real if isinstance(wait_times[j], complex) else wait_times[j]
170
- v_mom = (
171
- sojourn_times[j].real
172
- if isinstance(sojourn_times[j], complex)
173
- else sojourn_times[j]
174
- )
164
+ v_mom = sojourn_times[j].real if isinstance(sojourn_times[j], complex) else sojourn_times[j]
175
165
  print(
176
166
  Fore.CYAN
177
167
  + f"{j + 1:^15d}|"
@@ -352,10 +342,6 @@ def print_mrx(mrx, is_short=False):
352
342
  print(f"{color}{mrx[i, j].real:^4.2f} | ", end="")
353
343
  else:
354
344
  print(f"{color}{mrx[i, j]:^5.3f} | ", end="")
355
- print(
356
- "\n" + "-------" * col
357
- if is_short or mrx[i, j].imag == 0.0
358
- else "\n" + "---------------" * col
359
- )
345
+ print("\n" + "-------" * col if is_short or mrx[i, j].imag == 0.0 else "\n" + "---------------" * col)
360
346
 
361
347
  print(f"{Style.RESET_ALL}")