most-queue 1.63__py3-none-any.whl → 2.1__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 (79) hide show
  1. most_queue/general/distribution_fitting.py +14 -22
  2. most_queue/general/plots.py +1 -1
  3. most_queue/general/tables.py +7 -21
  4. most_queue/misc/approx_cdf_make.py +1 -5
  5. most_queue/misc/calc_v_pls.py +26 -16
  6. most_queue/misc/compare_fj_calc.py +3 -1
  7. most_queue/misc/flow_sum.py +3 -6
  8. most_queue/misc/run_mgn_with_h2_delay_cold_warm.py +16 -16
  9. most_queue/misc/test_fj_delta.py +8 -10
  10. most_queue/misc/test_network_opt_approx.py +7 -6
  11. most_queue/misc/test_network_opt_plus.py +6 -6
  12. most_queue/rand_distribution.py +27 -22
  13. most_queue/sim/base.py +24 -31
  14. most_queue/sim/batch.py +3 -1
  15. most_queue/sim/finite_source.py +1 -1
  16. most_queue/sim/flow_sum.py +10 -5
  17. most_queue/sim/fork_join.py +1 -1
  18. most_queue/sim/fork_join_delta.py +3 -5
  19. most_queue/sim/negative.py +21 -17
  20. most_queue/sim/networks/base_network_sim.py +103 -0
  21. most_queue/sim/networks/network.py +85 -50
  22. most_queue/sim/networks/priority_network.py +124 -88
  23. most_queue/sim/priority.py +83 -76
  24. most_queue/sim/utils/distribution_utils.py +17 -15
  25. most_queue/sim/utils/servers.py +10 -11
  26. most_queue/sim/utils/tasks.py +5 -7
  27. most_queue/sim/vacations.py +27 -8
  28. most_queue/structs.py +163 -0
  29. most_queue/theory/base_queue.py +75 -0
  30. most_queue/theory/batch/mm1.py +94 -47
  31. most_queue/theory/calc_params.py +5 -6
  32. most_queue/theory/closed/engset.py +86 -34
  33. most_queue/theory/fifo/ek_d_n.py +79 -47
  34. most_queue/theory/fifo/gi_m_1.py +89 -32
  35. most_queue/theory/fifo/gi_m_n.py +89 -37
  36. most_queue/theory/fifo/m_d_n.py +45 -13
  37. most_queue/theory/fifo/mg1.py +77 -35
  38. most_queue/theory/fifo/mgn_takahasi.py +101 -49
  39. most_queue/theory/fifo/mmnr.py +60 -10
  40. most_queue/theory/fork_join/m_m_n.py +98 -19
  41. most_queue/theory/fork_join/split_join.py +67 -246
  42. most_queue/theory/impatience/mm1.py +62 -15
  43. most_queue/theory/negative/mg1_disasters.py +77 -25
  44. most_queue/theory/negative/mg1_rcs.py +61 -34
  45. most_queue/theory/negative/mgn_disaster.py +220 -184
  46. most_queue/theory/negative/mgn_rcs.py +143 -106
  47. most_queue/theory/negative/structs.py +0 -89
  48. most_queue/theory/networks/base_network_calc.py +123 -0
  49. most_queue/theory/networks/network_viewer.py +2 -6
  50. most_queue/theory/networks/open_network.py +68 -29
  51. most_queue/theory/networks/open_network_prty.py +68 -30
  52. most_queue/theory/networks/opt/transition.py +28 -34
  53. most_queue/theory/networks/opt/transition_approx.py +18 -18
  54. most_queue/theory/networks/opt/transition_plus.py +12 -12
  55. most_queue/theory/priority/mgn_invar_approx.py +84 -35
  56. most_queue/theory/priority/non_preemptive/mg1.py +59 -6
  57. most_queue/theory/priority/preemptive/m_ph_n_busy_approx.py +123 -52
  58. most_queue/theory/priority/preemptive/mg1.py +48 -29
  59. most_queue/theory/priority/preemptive/{mmn_3cls_busy_approx.py → mm2_3cls_busy_approx.py} +222 -153
  60. most_queue/theory/priority/preemptive/mmn_2cls_pr_busy_approx.py +181 -113
  61. most_queue/theory/utils/busy_periods.py +2 -6
  62. most_queue/theory/utils/conditional.py +3 -10
  63. most_queue/theory/utils/diff5dots.py +3 -9
  64. most_queue/theory/utils/flow_sum.py +2 -10
  65. most_queue/theory/utils/max_dist.py +196 -0
  66. most_queue/theory/utils/passage_time.py +29 -41
  67. most_queue/theory/utils/q_poisson_arrival_calc.py +3 -15
  68. most_queue/theory/utils/student_stat.py +1 -5
  69. most_queue/theory/utils/transforms.py +1 -3
  70. most_queue/theory/utils/utilization_approx.py +4 -1
  71. most_queue/theory/vacations/m_h2_h2warm.py +184 -139
  72. most_queue/theory/vacations/mg1_warm_calc.py +71 -18
  73. most_queue/theory/vacations/mgn_with_h2_delay_cold_warm.py +157 -119
  74. most_queue/theory/vacations/mmn_with_h2_cold_and_h2_warmup.py +257 -191
  75. {most_queue-1.63.dist-info → most_queue-2.1.dist-info}/METADATA +8 -8
  76. most_queue-2.1.dist-info/RECORD +109 -0
  77. most_queue-1.63.dist-info/RECORD +0 -104
  78. {most_queue-1.63.dist-info → most_queue-2.1.dist-info}/WHEEL +0 -0
  79. {most_queue-1.63.dist-info → most_queue-2.1.dist-info}/licenses/LICENSE +0 -0
@@ -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.general.distribution_params import (
12
+ Cox2Params,
13
+ ErlangParams,
14
+ GammaParams,
15
+ H2Params,
16
+ ParetoParams,
17
+ WeibullParams,
18
+ )
15
19
 
16
20
 
17
21
  @dataclass
@@ -117,8 +121,7 @@ def fit_h2_clx(moments: list[float], fitting_params: FittingParams | None = None
117
121
  if math.fabs(coev.real - 1.0 / math.sqrt(2.0)) < fitting_params.ee:
118
122
  if fitting_params.verbose:
119
123
  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}."
124
+ f"H2 is close to E2. Multiply moments to (1+je)" f"coev = {coev:5.3f}, e = {fitting_params.e:5.3f}."
122
125
  )
123
126
  f = []
124
127
  for i, mom in enumerate(moments):
@@ -151,10 +154,7 @@ def fit_cox(moments: list[float], fitting_params: FittingParams | None = None) -
151
154
  coev = cmath.sqrt(moments[1] - moments[0] ** 2) / moments[0]
152
155
  if abs(moments[1] - moments[0] * moments[0]) < fitting_params.ee:
153
156
  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
- )
157
+ print(f"Cox special 1. Multiply moments to (1+je)" f"coev = {coev:5.3f} e = {fitting_params.e:5.3f}.")
158
158
  f = []
159
159
  for i, mom in enumerate(moments):
160
160
  f.append(mom * complex(1, (i + 1) * fitting_params.e))
@@ -176,9 +176,7 @@ def fit_cox(moments: list[float], fitting_params: FittingParams | None = None) -
176
176
  for i in range(3):
177
177
  f[i] = moments[i] / math.factorial(i + 1)
178
178
 
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
- )
179
+ 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
180
  mu2 = f[0] * f[1] - f[2] + cmath.sqrt(d)
183
181
  mu2 /= 2.0 * (np.power(f[1], 2) - f[0] * f[2])
184
182
  mu1 = (mu2 * f[0] - 1.0) / (mu2 * f[1] - f[0])
@@ -287,9 +285,7 @@ def fit_gamma(moments: list[float]) -> GammaParams:
287
285
  else:
288
286
  B.append(moments[i - 1])
289
287
  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
- )
288
+ A[i].append(calc_gamma_func(alpha + i + j) / (pow(mu, i + j) * calc_gamma_func(alpha)))
293
289
  g = np.linalg.solve(A, B)
294
290
  return GammaParams(mu=mu, alpha=alpha, g=g)
295
291
 
@@ -311,14 +307,10 @@ def fit_weibull(moments: list[float]) -> WeibullParams:
311
307
  a = moments[1] / (moments[0] * moments[0])
312
308
  u0 = math.log(2 * a) / (2.0 * math.log(2))
313
309
  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
- )
310
+ u1 = (1.0 / (2 * math.log(2))) * math.log(a * math.sqrt(math.pi) * math.gamma(u0 + 1) / math.gamma(u0 + 0.5))
317
311
  delta = u1 - u0
318
312
  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
- )
313
+ u1 = (1.0 / (2 * math.log(2))) * math.log(a * math.sqrt(math.pi) * math.gamma(u0 + 1) / math.gamma(u0 + 0.5))
322
314
  delta = u1 - u0
323
315
  u0 = u1
324
316
  k = 1 / u1
@@ -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).
@@ -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}")
@@ -55,11 +55,7 @@ if __name__ == "__main__":
55
55
  print("{0:^3s}|{1:^15s}|{2:^15s}|{3:^15s}".format("№", "Реал", "Gamma", "H2"))
56
56
  print("-" * 50)
57
57
  for i in range(3):
58
- print(
59
- "{0:^4d}|{1:^15.3g}|{2:^15.3g}|{3:^15.3g}".format(
60
- i + 1, b[i], b_approx_gamma[i], b_approx_h2[i]
61
- )
62
- )
58
+ print("{0:^4d}|{1:^15.3g}|{2:^15.3g}|{3:^15.3g}".format(i + 1, b[i], b_approx_gamma[i], b_approx_h2[i]))
63
59
 
64
60
  dots_num = 10000
65
61
 
@@ -24,16 +24,11 @@ class MGnNegativeRCSCalc(MGnCalc):
24
24
  def __init__(
25
25
  self,
26
26
  n: int,
27
- l_pos: float,
28
- l_neg: float,
29
- b: list[float],
30
27
  buffer: int | None = None,
31
28
  calc_params: TakahashiTakamiParams | None = None,
32
29
  ):
33
30
  """
34
31
  n: number of servers
35
- l: arrival rate of positive jobs
36
- l_neg: arrival rate of negative jobs
37
32
  b: initial moments of service time distribution
38
33
  buffer: size of the buffer (optional)
39
34
  N: number of levels in the system (default is 150)
@@ -42,9 +37,29 @@ class MGnNegativeRCSCalc(MGnCalc):
42
37
  verbose: whether to print intermediate results (default is False)
43
38
  """
44
39
 
40
+ super().__init__(n=n, buffer=buffer, calc_params=calc_params)
41
+
42
+ self.l_pos = None
43
+ self.l_neg = None
44
+ self.b = None
45
+
46
+ def set_sources(self, l_pos: float, l_neg: float): # pylint: disable=arguments-differ
47
+ """
48
+ Set the arrival rates of positive and negative jobs
49
+ :param l_pos: arrival rate of positive jobs
50
+ :param l_neg: arrival rate of negative jobs
51
+ """
52
+ self.l_pos = l_pos
45
53
  self.l_neg = l_neg
54
+ self.is_sources_set = True
46
55
 
47
- super().__init__(n=n, l=l_pos, b=b, buffer=buffer, calc_params=calc_params)
56
+ def set_servers(self, b: list[float]): # pylint: disable=arguments-differ
57
+ """
58
+ Set the initial moments of service time distribution
59
+ :param b: initial moments of service time distribution
60
+ """
61
+ self.b = b
62
+ self.is_servers_set = True
48
63
 
49
64
  def get_q(self) -> float:
50
65
  """
@@ -150,9 +165,7 @@ class MGnNegativeRCSCalc(MGnCalc):
150
165
  a = np.array(
151
166
  [
152
167
  lst_exp(
153
- key_numbers[j][0] * self.mu[0]
154
- + key_numbers[j][1] * self.mu[1]
155
- + self.l_neg,
168
+ key_numbers[j][0] * self.mu[0] + key_numbers[j][1] * self.mu[1] + self.l_neg,
156
169
  s,
157
170
  )
158
171
  for j in range(k + 2)
@@ -241,7 +254,8 @@ class MGnNegativeRCSCalc(MGnCalc):
241
254
  """
242
255
  w = self.get_w(derivate=False)
243
256
 
244
- # serving = min(H2_b, exp(l_neg)) = H2(y1=y1, mu1 = mu1+l_neg, mu2=mu2+l_neg)
257
+ # serving = min(H2_b, exp(l_neg)) = H2(y1=y1, mu1 = mu1+l_neg,
258
+ # mu2=mu2+l_neg)
245
259
 
246
260
  params = H2Params(p1=self.y[0], mu1=self.mu[0], mu2=self.mu[1])
247
261
  #
@@ -249,9 +263,7 @@ class MGnNegativeRCSCalc(MGnCalc):
249
263
  for i in range(1, self.n):
250
264
  l_neg += self.p[i] * self.l_neg / i
251
265
 
252
- b = H2Distribution.calc_theory_moments(
253
- H2Params(p1=params.p1, mu1=l_neg + params.mu1, mu2=l_neg + params.mu2)
254
- )
266
+ b = H2Distribution.calc_theory_moments(H2Params(p1=params.p1, mu1=l_neg + params.mu1, mu2=l_neg + params.mu2))
255
267
 
256
268
  return conv_moments(w, b)
257
269
 
@@ -300,9 +312,7 @@ class MGnNegativeRCSCalc(MGnCalc):
300
312
  right = self.l_neg * i / (num - 1)
301
313
  left_from_next = self.l_neg * (i + 1) / (num - 1)
302
314
 
303
- output[i, i] = ((num - i - 1) * self.mu[0] + left) * self.y[0] + (
304
- i * self.mu[1] + right
305
- ) * self.y[1]
315
+ output[i, i] = ((num - i - 1) * self.mu[0] + left) * self.y[0] + (i * self.mu[1] + right) * self.y[1]
306
316
 
307
317
  if i != num - 1:
308
318
  output[i, i + 1] = ((num - i - 1) * self.mu[0] + left) * self.y[1]
@@ -81,7 +81,9 @@ def test_fj_calc():
81
81
  # расчет средних времен пребывания с помощью аппроксимаций. \
82
82
  # На вход каждого из методов - l, mu, nn (число каналов СМО)
83
83
 
84
- calcs = ForkJoinMarkovianCalc(l, mu, nn)
84
+ calcs = ForkJoinMarkovianCalc(n=nn)
85
+ calcs.set_sources(l=l)
86
+ calcs.set_servers(mu=mu)
85
87
 
86
88
  v_varki.append(calcs.get_v1_fj_varki_merchant())
87
89
  v_varma.append(calcs.get_v1_fj_varma())
@@ -26,7 +26,8 @@ def test():
26
26
  # число суммируемых потоков
27
27
  ns = [x + 2 for x in range(n_nums - 1)]
28
28
 
29
- # начальные моменты суммируемых потоков. В нашем случае все потоки одинаково распределены
29
+ # начальные моменты суммируемых потоков. В нашем случае все потоки
30
+ # одинаково распределены
30
31
  a = []
31
32
  for i in range(n_nums):
32
33
  params1 = GammaDistribution.get_params_by_mean_and_coev(mean, coev)
@@ -53,11 +54,7 @@ def test():
53
54
  errors_coev = []
54
55
 
55
56
  str_f = "{0:^18s}|{1:^10.3f}|{2:^10.3f}|{3:^10.3f}|{4:^10.3f}|{5:^10.3f}"
56
- print(
57
- "{0:^18s}|{1:^10s}|{2:^10s}|{3:^10s}|{4:^10s}|{5:^10s}".format(
58
- "-", "a1", "a2", "a3", "a4", "coev"
59
- )
60
- )
57
+ print("{0:^18s}|{1:^10s}|{2:^10s}|{3:^10s}|{4:^10s}|{5:^10s}".format("-", "a1", "a2", "a3", "a4", "coev"))
61
58
  print("-" * 80)
62
59
 
63
60
  for i in range(n_nums - 1):
@@ -9,12 +9,18 @@ import time
9
9
  import numpy as np
10
10
 
11
11
  from most_queue.misc.vacations_paper_utils import (
12
- calc_moments_by_mean_and_coev, dump_stat, load_stat, make_plot,
13
- print_table)
12
+ calc_moments_by_mean_and_coev,
13
+ dump_stat,
14
+ load_stat,
15
+ make_plot,
16
+ print_table,
17
+ )
14
18
  from most_queue.rand_distribution import GammaDistribution
15
19
  from most_queue.sim.vacations import VacationQueueingSystemSimulator
16
- from most_queue.theory.vacations.mgn_with_h2_delay_cold_warm import \
17
- MGnH2ServingColdWarmDelay
20
+ from most_queue.theory.vacations.mgn_with_h2_delay_cold_warm import (
21
+ MGnH2ServingColdWarmDelay,
22
+ TakahashiTakamiParams,
23
+ )
18
24
 
19
25
 
20
26
  def get_sim_stat(stat, n, l, buff, b, b_c, b_w, b_d, num_of_jobs, p_limit, sim_ave):
@@ -113,18 +119,12 @@ def get_tt_stat(stat, n, l, buff, b, b_c, b_w, b_d, p_limit, w_pls_dt, stable_w_
113
119
  :return: None
114
120
  """
115
121
  tt_start = time.process_time()
116
- tt = MGnH2ServingColdWarmDelay(
117
- l,
118
- b,
119
- b_w,
120
- b_c,
121
- b_d,
122
- n,
123
- buffer=buff,
124
- verbose=verbose,
125
- w_pls_dt=w_pls_dt,
126
- stable_w_pls=stable_w_pls,
127
- )
122
+
123
+ tt_params = TakahashiTakamiParams(verbose=verbose, w_pls_dt=w_pls_dt, stable_w_pls=stable_w_pls)
124
+ tt = MGnH2ServingColdWarmDelay(n=n, buffer=buff, calc_params=tt_params)
125
+
126
+ tt.set_sources(l=l)
127
+ tt.set_servers(b=b, b_warm=b_w, b_cold=b_c, b_cold_delay=b_d)
128
128
 
129
129
  tt.run()
130
130
  p_tt = tt.get_p()
@@ -46,16 +46,16 @@ def test_fj_delta():
46
46
 
47
47
  b_params = GammaDistribution.get_params_by_mean_and_coev(SERVICE_TIME_AVERAGE, SERVICE_TIME_CV)
48
48
 
49
- delta_params = GammaDistribution.get_params_by_mean_and_coev(
50
- SERVICE_TIME_DELTA_AVERAGE, SERVICE_TIME_CV
51
- )
49
+ delta_params = GammaDistribution.get_params_by_mean_and_coev(SERVICE_TIME_DELTA_AVERAGE, SERVICE_TIME_CV)
52
50
  b_delta = GammaDistribution.calc_theory_moments(delta_params)
53
51
  b = GammaDistribution.calc_theory_moments(b_params)
54
52
 
55
- sj_delta = SplitJoinCalc(ARRIVAL_RATE, NUM_OF_CHANNELS, b, approximation="gamma")
53
+ sj_delta = SplitJoinCalc(n=NUM_OF_CHANNELS)
54
+ sj_delta.set_sources(l=ARRIVAL_RATE)
55
+ sj_delta.set_servers(b=b)
56
56
 
57
57
  v_num = sj_delta.get_v_delta(b_delta)
58
- ro = sj_delta.get_ro()
58
+ utilization = sj_delta.get_utilization()
59
59
 
60
60
  qs = ForkJoinSimDelta(NUM_OF_CHANNELS, NUM_OF_CHANNELS, b_delta, True)
61
61
 
@@ -68,16 +68,14 @@ def test_fj_delta():
68
68
  print(f"{'Split-Join QS with service start delay':^60s}")
69
69
  print("-" * 60)
70
70
  print(f"Coefficient of variation of service time: {SERVICE_TIME_CV}")
71
- print(f"Average delay before service start: {SERVICE_TIME_DELTA_AVERAGE:.3f}")
71
+ print(f"Average delay before service start: { SERVICE_TIME_DELTA_AVERAGE:.3f}")
72
72
  print(f"Coefficient of variation of delay: {SERVICE_TIME_CV:.3f}")
73
- print(f"Utilization coefficient: {ro:.3f}")
73
+ print(f"Utilization coefficient: {utilization:.3f}")
74
74
 
75
75
  times_print(v_sim, v_num, is_w=False)
76
76
 
77
77
  assert len(v_sim) == len(v_num)
78
- assert np.allclose(
79
- np.array(v_sim), np.array(v_num), rtol=MOMENTS_RTOL, atol=MOMENTS_ATOL
80
- ), ERROR_MSG
78
+ assert np.allclose(np.array(v_sim), np.array(v_num), rtol=MOMENTS_RTOL, atol=MOMENTS_ATOL), ERROR_MSG
81
79
 
82
80
 
83
81
  if __name__ == "__main__":
@@ -5,8 +5,8 @@ Test the NetworkOptimizerWithApprox class.
5
5
  import numpy as np
6
6
 
7
7
  from most_queue.rand_distribution import ExpDistribution
8
- from most_queue.theory.networks.opt.transition_approx import \
9
- NetworkOptimizerWithApprox
8
+ from most_queue.theory.networks.open_network import OpenNetworkCalc
9
+ from most_queue.theory.networks.opt.transition_approx import NetworkOptimizerWithApprox
10
10
 
11
11
 
12
12
  def test_network_opt_approx():
@@ -34,11 +34,12 @@ def test_network_opt_approx():
34
34
  ExpDistribution.calc_theory_moments(1.0) for _m in range(num_of_nodes)
35
35
  ] # List of service time moments for each node
36
36
 
37
+ network = OpenNetworkCalc()
38
+ network.set_sources(R=transition_mrx, arrival_rate=arrival_rate)
39
+ network.set_nodes(b=service_times, n=num_of_channels)
40
+
37
41
  optimizer = NetworkOptimizerWithApprox(
38
- transition_matrix=transition_mrx,
39
- arrival_rate=arrival_rate,
40
- b=service_times,
41
- num_channels=num_of_channels,
42
+ network=network,
42
43
  maximum_rates_to_end=max_ends,
43
44
  is_service_markovian=True,
44
45
  verbose=True,
@@ -5,8 +5,8 @@ Test the NetworkOptimizerPlus class.
5
5
  import numpy as np
6
6
 
7
7
  from most_queue.rand_distribution import ExpDistribution
8
- from most_queue.theory.networks.opt.transition_plus import (
9
- NetworkOptimizerPlus, Strategy)
8
+ from most_queue.theory.networks.open_network import OpenNetworkCalc
9
+ from most_queue.theory.networks.opt.transition_plus import NetworkOptimizerPlus, Strategy
10
10
 
11
11
 
12
12
  def test_network_opt_plus():
@@ -42,11 +42,11 @@ def test_network_opt_plus():
42
42
  Strategy.TOP_K,
43
43
  Strategy.ALL,
44
44
  ]:
45
+ network = OpenNetworkCalc()
46
+ network.set_sources(R=transition_mrx, arrival_rate=arrival_rate)
47
+ network.set_nodes(b=service_times, n=num_of_channels)
45
48
  optimizer = NetworkOptimizerPlus(
46
- transition_matrix=transition_mrx,
47
- arrival_rate=arrival_rate,
48
- b=service_times,
49
- num_channels=num_of_channels,
49
+ network=network,
50
50
  maximum_rates_to_end=max_ends,
51
51
  is_service_markovian=True,
52
52
  verbose=False,
@@ -1,3 +1,4 @@
1
+ # pylint: disable=too-many-lines
1
2
  """
2
3
  Random distributions for simulation.
3
4
  """
@@ -9,15 +10,28 @@ import scipy.special as sp
9
10
  from scipy import stats
10
11
 
11
12
  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)
13
+ FittingParams,
14
+ calc_gamma_func,
15
+ fit_cox,
16
+ fit_erlang,
17
+ fit_gamma,
18
+ fit_h2,
19
+ fit_h2_clx,
20
+ fit_pareto_by_mean_and_coev,
21
+ fit_pareto_moments,
22
+ fit_weibull,
23
+ gamma_moments_by_mean_and_coev,
24
+ )
25
+ from most_queue.general.distribution_params import (
26
+ Cox2Params,
27
+ ErlangParams,
28
+ GammaParams,
29
+ GaussianParams,
30
+ H2Params,
31
+ ParetoParams,
32
+ UniformParams,
33
+ WeibullParams,
34
+ )
21
35
  from most_queue.general.interfaces import Distribution
22
36
 
23
37
 
@@ -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
@@ -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.
@@ -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
most_queue/sim/base.py CHANGED
@@ -8,13 +8,13 @@ import numpy as np
8
8
  from colorama import Fore, Style, init
9
9
  from tqdm import tqdm
10
10
 
11
- from most_queue.sim.utils.distribution_utils import (calc_qs_load,
12
- create_distribution)
11
+ from most_queue.sim.utils.distribution_utils import calc_qs_load, create_distribution
13
12
  from most_queue.sim.utils.exceptions import QsWrongQueueTypeException
14
13
  from most_queue.sim.utils.qs_queue import QsQueueDeque, QsQueueList
15
14
  from most_queue.sim.utils.servers import Server
16
15
  from most_queue.sim.utils.stats_update import refresh_moments_stat
17
16
  from most_queue.sim.utils.tasks import Task
17
+ from most_queue.structs import QueueResults
18
18
 
19
19
  init()
20
20
 
@@ -285,7 +285,7 @@ class QsSim:
285
285
  # Arrival
286
286
  self.arrival()
287
287
 
288
- def run(self, total_served, is_real_served=True):
288
+ def run(self, total_served) -> QueueResults:
289
289
  """
290
290
  Run simulation process
291
291
  """
@@ -293,34 +293,34 @@ class QsSim:
293
293
 
294
294
  print(Fore.GREEN + "\rStart simulation")
295
295
 
296
- if is_real_served:
297
-
298
- last_percent = 0
299
-
300
- with tqdm(total=100) as pbar:
301
- while self.served < total_served:
302
- self.run_one_step()
303
- percent = int(100 * (self.served / total_served))
304
- if last_percent != percent:
305
- last_percent = percent
306
- pbar.update(1)
307
- pbar.set_description(
308
- Fore.MAGENTA
309
- + "\rJob served: "
310
- + Fore.YELLOW
311
- + f"{self.served}/{total_served}"
312
- + Fore.LIGHTGREEN_EX
313
- )
296
+ last_percent = 0
314
297
 
315
- else:
316
- for _ in tqdm(range(total_served)):
298
+ with tqdm(total=100) as pbar:
299
+ while self.served < total_served:
317
300
  self.run_one_step()
301
+ percent = int(100 * (self.served / total_served))
302
+ if last_percent != percent:
303
+ last_percent = percent
304
+ pbar.update(1)
305
+ pbar.set_description(
306
+ Fore.MAGENTA
307
+ + "\rJob served: "
308
+ + Fore.YELLOW
309
+ + f"{self.served}/{total_served}"
310
+ + Fore.LIGHTGREEN_EX
311
+ )
318
312
 
319
313
  print(Fore.GREEN + "\rSimulation is finished")
320
314
  print(Style.RESET_ALL)
321
315
 
316
+ v = self.get_v()
317
+ w = self.get_w()
318
+ p = self.get_p()
319
+
322
320
  self.time_spent = time.process_time() - start
323
321
 
322
+ return QueueResults(v=v, w=w, p=p, duration=self.time_spent, utilization=self.calc_load())
323
+
324
324
  def refresh_busy_stat(self, new_a):
325
325
  """
326
326
  Updating statistics of the busy period
@@ -366,14 +366,7 @@ class QsSim:
366
366
 
367
367
  def __str__(self, is_short=False):
368
368
 
369
- res = (
370
- "Queueing system "
371
- + self.source_kendall_notation
372
- + "/"
373
- + self.server_kendall_notation
374
- + "/"
375
- + str(self.n)
376
- )
369
+ res = "Queueing system " + self.source_kendall_notation + "/" + self.server_kendall_notation + "/" + str(self.n)
377
370
  if self.buffer is not None:
378
371
  res += "/" + str(self.buffer)
379
372
  res += f"\nLoad: {self.calc_load():4.3f}\n"
most_queue/sim/batch.py CHANGED
@@ -13,7 +13,9 @@ class QueueingSystemBatchSim(QsSim):
13
13
 
14
14
  """
15
15
 
16
- def __init__(self, num_of_channels, batch_prob, buffer=None, verbose=True, buffer_type="list"):
16
+ def __init__(
17
+ self, num_of_channels, batch_prob, buffer=None, verbose=True, buffer_type="list"
18
+ ): # pylint: disable=too-many-positional-arguments, too-many-arguments
17
19
  """
18
20
  :param num_of_channels: int : number of channels (servers)
19
21
  :param batch_prob: list : probabilities for different batch sizes
@@ -23,7 +23,7 @@ class QueueingFiniteSourceSim(QsSim):
23
23
  buffer=None,
24
24
  verbose=True,
25
25
  buffer_type="list",
26
- ):
26
+ ): # pylint: disable=too-many-positional-arguments, too-many-arguments
27
27
  """
28
28
  num_of_channels - number of channels in the system.
29
29
  number_of_sources - number of sources.