most-queue 1.45__tar.gz → 1.46__tar.gz

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 (93) hide show
  1. {most_queue-1.45 → most_queue-1.46}/PKG-INFO +6 -3
  2. {most_queue-1.45 → most_queue-1.46}/README.md +1 -1
  3. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/batch_sim.py +8 -8
  4. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/fj_delta_sim.py +37 -23
  5. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/fj_sim.py +47 -32
  6. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/impatient_queue_sim.py +71 -30
  7. most_queue-1.46/most_queue/sim/priority_network.py +228 -0
  8. most_queue-1.46/most_queue/sim/priority_queue_sim.py +725 -0
  9. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/qs_sim.py +53 -40
  10. most_queue-1.46/most_queue/sim/queue_finite_source_sim.py +244 -0
  11. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/utils/distribution_utils.py +30 -0
  12. most_queue-1.46/most_queue/sim/utils/servers.py +219 -0
  13. most_queue-1.46/most_queue/sim/utils/tasks.py +117 -0
  14. {most_queue-1.45/most_queue/tests → most_queue-1.46/most_queue/theory}/__init__.py +0 -0
  15. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/batch_mm1.py +4 -6
  16. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/ek_d_n_calc.py +53 -43
  17. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/mmn3_pnz_cox_approx.py +2 -2
  18. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/priority_calc.py +8 -8
  19. {most_queue-1.45/most_queue/theory → most_queue-1.46/most_queue/theory/utils}/__init__.py +0 -0
  20. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/utils/passage_time.py +5 -5
  21. {most_queue-1.45 → most_queue-1.46}/most_queue.egg-info/PKG-INFO +6 -3
  22. {most_queue-1.45 → most_queue-1.46}/most_queue.egg-info/SOURCES.txt +23 -23
  23. {most_queue-1.45 → most_queue-1.46}/most_queue.egg-info/top_level.txt +1 -0
  24. {most_queue-1.45 → most_queue-1.46}/pyproject.toml +1 -1
  25. {most_queue-1.45 → most_queue-1.46}/setup.py +2 -2
  26. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_fj_delta.py +1 -0
  27. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_impatience.py +1 -3
  28. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_network_im_prty.py +1 -1
  29. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_qs_sim_prty.py +2 -4
  30. most_queue-1.45/most_queue/sim/priority_network.py +0 -167
  31. most_queue-1.45/most_queue/sim/priority_queue_sim.py +0 -785
  32. most_queue-1.45/most_queue/sim/queue_finite_source_sim.py +0 -247
  33. most_queue-1.45/most_queue/sim/utils/servers.py +0 -113
  34. most_queue-1.45/most_queue/sim/utils/tasks.py +0 -70
  35. {most_queue-1.45 → most_queue-1.46}/LICENSE +0 -0
  36. {most_queue-1.45 → most_queue-1.46}/most_queue/__init__.py +0 -0
  37. {most_queue-1.45 → most_queue-1.46}/most_queue/general_utils/__init__.py +0 -0
  38. {most_queue-1.45 → most_queue-1.46}/most_queue/general_utils/approx_cdf_make.py +0 -0
  39. {most_queue-1.45 → most_queue-1.46}/most_queue/general_utils/conv.py +0 -0
  40. {most_queue-1.45 → most_queue-1.46}/most_queue/general_utils/tables.py +0 -0
  41. {most_queue-1.45 → most_queue-1.46}/most_queue/general_utils/vacations_paper_utils.py +0 -0
  42. {most_queue-1.45 → most_queue-1.46}/most_queue/rand_distribution.py +0 -0
  43. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/__init__.py +0 -0
  44. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/flow_sum_sim.py +0 -0
  45. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/utils/__init__.py +0 -0
  46. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/utils/exceptions.py +0 -0
  47. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/utils/phase.py +0 -0
  48. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/utils/qs_queue.py +0 -0
  49. {most_queue-1.45 → most_queue-1.46}/most_queue/sim/utils/stats_update.py +0 -0
  50. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/engset_model.py +0 -0
  51. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/fj_calc.py +0 -0
  52. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/gi_m_1_calc.py +0 -0
  53. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/gi_m_n_calc.py +0 -0
  54. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/impatience_calc.py +0 -0
  55. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/m_d_n_calc.py +0 -0
  56. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/m_h2_h2warm.py +0 -0
  57. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/m_ph_n_prty.py +0 -0
  58. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/mg1_calc.py +0 -0
  59. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/mg1_warm_calc.py +0 -0
  60. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/mgn_tt.py +0 -0
  61. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/mgn_with_h2_delay_cold_warm.py +0 -0
  62. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/mmn_prty_pnz_approx.py +0 -0
  63. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/mmn_with_h2_cold_and_h2_warmup.py +0 -0
  64. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/mmnr_calc.py +0 -0
  65. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/network_calc.py +0 -0
  66. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/network_viewer.py +0 -0
  67. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/utils/binom_probs.py +0 -0
  68. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/utils/diff5dots.py +0 -0
  69. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/utils/flow_sum.py +0 -0
  70. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/utils/q_poisson_arrival_calc.py +0 -0
  71. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/utils/student_stat.py +0 -0
  72. {most_queue-1.45 → most_queue-1.46}/most_queue/theory/utils/weibull.py +0 -0
  73. {most_queue-1.45 → most_queue-1.46}/most_queue.egg-info/dependency_links.txt +0 -0
  74. {most_queue-1.45 → most_queue-1.46}/most_queue.egg-info/not-zip-safe +0 -0
  75. {most_queue-1.45 → most_queue-1.46}/setup.cfg +0 -0
  76. {most_queue-1.45/most_queue/theory/utils → most_queue-1.46/tests}/__init__.py +0 -0
  77. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_batch.py +0 -0
  78. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_ek_d_n.py +0 -0
  79. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_engset.py +0 -0
  80. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_fj_im.py +0 -0
  81. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_gi_m_1_calc.py +0 -0
  82. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_gi_m_n_calc.py +0 -0
  83. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_m_d_n_calc.py +0 -0
  84. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_m_h2_h2warm.py +0 -0
  85. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_m_ph_n_prty.py +0 -0
  86. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_mg1_calc.py +0 -0
  87. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_mgn_tt.py +0 -0
  88. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_mgn_with_h2_delay_cold_warm.py +0 -0
  89. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_mmn3_pnz_cox_approx.py +0 -0
  90. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_mmn_h2cold_h2warm.py +0 -0
  91. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_mmn_prty_pnz_approx.py +0 -0
  92. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_qs_sim_test.py +0 -0
  93. {most_queue-1.45/most_queue → most_queue-1.46}/tests/test_queue_types.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: most_queue
3
- Version: 1.45
3
+ Version: 1.46
4
4
  Summary: Software package for calculation and simulation of queuing systems
5
5
  Home-page: https://github.com/xabarov/most-queue
6
6
  Author: Xabarov Roman
@@ -31,8 +31,11 @@ Classifier: Operating System :: OS Independent
31
31
  Requires-Python: >=3.7
32
32
  Description-Content-Type: text/markdown
33
33
  License-File: LICENSE
34
+ Dynamic: author
35
+ Dynamic: home-page
36
+ Dynamic: license-file
34
37
 
35
- # MostQueue
38
+ # Queueing systems. Simulation and numerical methods of queuing theory
36
39
 
37
40
  ![Queue](assets/queue6.jpg)
38
41
 
@@ -1,4 +1,4 @@
1
- # MostQueue
1
+ # Queueing systems. Simulation and numerical methods of queuing theory
2
2
 
3
3
  ![Queue](assets/queue6.jpg)
4
4
 
@@ -1,5 +1,5 @@
1
1
  """
2
- QS with batch arrival
2
+ Queueing system with batch arrivals.
3
3
  """
4
4
  import numpy as np
5
5
 
@@ -8,17 +8,17 @@ from most_queue.sim.qs_sim import QueueingSystemSimulator, Task
8
8
 
9
9
  class QueueingSystemBatchSim(QueueingSystemSimulator):
10
10
  """
11
- QS with batch arrivals
11
+ Queueing system with batch arrivals.
12
12
  """
13
13
 
14
14
  def __init__(self, num_of_channels,
15
15
  batch_prob,
16
16
  buffer=None, verbose=True):
17
17
  """
18
- Args:
19
- num_of_channels:
20
- batch_prob: list[float], probs of batch size 1, 2, .. len(batch_probs)
21
- buffer: Optional(int, None) : length of queueu
18
+ :param num_of_channels: int : number of channels (servers)
19
+ :param batch_prob: list : probabilities for different batch sizes
20
+ :param buffer: Optional(int, None) : length of queueu
21
+ :param verbose: bool : if True prints info about simulation process
22
22
  """
23
23
  super().__init__(num_of_channels, buffer, verbose)
24
24
 
@@ -52,7 +52,7 @@ class QueueingSystemBatchSim(QueueingSystemSimulator):
52
52
 
53
53
  self.arrival_time = self.ttek + self.source.generate()
54
54
 
55
- for tsk in range(batch_size):
55
+ for _tsk in range(batch_size):
56
56
  self.arrived += 1
57
57
  self.p[self.in_sys] += self.arrival_time - self.t_old
58
58
 
@@ -89,5 +89,5 @@ class QueueingSystemBatchSim(QueueingSystemSimulator):
89
89
  # Проверям, не наступил ли ПНЗ:
90
90
  if self.free_channels == 0:
91
91
  if self.in_sys == self.n:
92
- self.start_ppnz = self.ttek
92
+ self.start_busy = self.ttek
93
93
  break
@@ -12,13 +12,16 @@ class ForkJoinSimDelta(ForkJoinSim):
12
12
  Имитационная модель СМО Fork-Join, Split-Join
13
13
  """
14
14
 
15
- def __init__(self, num_of_channels, num_of_parts, delta, is_SJ=False, buffer=None):
15
+ def __init__(self, num_of_channels, num_of_parts, delta, is_sj=False, buffer=None):
16
16
  """
17
- num_of_channels - количество каналов СМО
18
- buffer - максимальная длина очереди
17
+ :param num_of_channels: int : количество каналов СМО
18
+ :param num_of_parts: int : количество частей на которые разбивается задача
19
+ :param delta: float : параметр модели Fork-Join с дельта-разбиением
20
+ :param is_sj: bool : если True, то используется модель Split-Join, иначе - Fork-Join
21
+ :param buffer: Optional(int, None) : максимальная длина очереди
19
22
  """
20
23
  ForkJoinSim.__init__(self, num_of_channels,
21
- num_of_parts, is_SJ, buffer)
24
+ num_of_parts, is_sj, buffer)
22
25
  self.delta = delta
23
26
  self.subtask_arr_queue = []
24
27
  self.serv_task_id = -1
@@ -26,7 +29,7 @@ class ForkJoinSimDelta(ForkJoinSim):
26
29
 
27
30
  def task_arrival(self):
28
31
  """
29
- Действия по прибытию заявки в СМО.
32
+ Действия по прибытию заявки в СМО.
30
33
  """
31
34
 
32
35
  self.arrived += 1
@@ -37,7 +40,7 @@ class ForkJoinSimDelta(ForkJoinSim):
37
40
  is_dropped = False
38
41
 
39
42
  if self.buffer: # ограниченная длина очереди
40
- if not self.is_SJ:
43
+ if not self.is_sj:
41
44
  if self.queue.size() + self.k - 1 > self.buffer + self.free_channels:
42
45
  self.dropped += 1
43
46
  is_dropped = True
@@ -54,7 +57,7 @@ class ForkJoinSimDelta(ForkJoinSim):
54
57
  self.in_sys += 1
55
58
  self.sub_task_in_sys += 1
56
59
 
57
- if not self.is_SJ: # Fork-Join discipline
60
+ if not self.is_sj: # Fork-Join discipline
58
61
 
59
62
  if self.free_channels == 0:
60
63
  self.queue.append(t.subtasks[0])
@@ -85,6 +88,9 @@ class ForkJoinSimDelta(ForkJoinSim):
85
88
  self.subtask_arr_queue.append(t.subtasks[i])
86
89
 
87
90
  def subtask_arrival(self, subtask_num):
91
+ """
92
+ Действия по прибытию подзадачи в СМО.
93
+ """
88
94
 
89
95
  subtsk = self.subtask_arr_queue.pop(subtask_num)
90
96
  self.p[self.in_sys] += subtsk.future_arr_time - self.t_old
@@ -99,7 +105,7 @@ class ForkJoinSimDelta(ForkJoinSim):
99
105
  if not is_dropped:
100
106
  self.sub_task_in_sys += 1
101
107
 
102
- if not self.is_SJ: # Fork-Join discipline
108
+ if not self.is_sj: # Fork-Join discipline
103
109
 
104
110
  if self.free_channels == 0:
105
111
  self.queue.append(subtsk)
@@ -136,7 +142,7 @@ class ForkJoinSimDelta(ForkJoinSim):
136
142
  self.total += 1
137
143
  self.free_channels += 1
138
144
 
139
- if not self.is_SJ:
145
+ if not self.is_sj:
140
146
 
141
147
  if self.served_subtask_in_task[end_ts.task_id] == self.k:
142
148
  self.served += 1
@@ -186,6 +192,9 @@ class ForkJoinSimDelta(ForkJoinSim):
186
192
  q for q in self.queue.queue if q.task_id != end_ts.task_id]
187
193
 
188
194
  def run_one_step(self):
195
+ """
196
+ Runs one step of simulation.
197
+ """
189
198
 
190
199
  num_of_server_earlier = -1
191
200
  serv_earl = 1e10
@@ -198,9 +207,9 @@ class ForkJoinSimDelta(ForkJoinSim):
198
207
  subtask_arr_time_earl = 1e10
199
208
  num_of_subtask_earl = -1
200
209
 
201
- for c in range(len(self.subtask_arr_queue)):
202
- if self.subtask_arr_queue[c].future_arr_time < subtask_arr_time_earl:
203
- subtask_arr_time_earl = self.subtask_arr_queue[c].future_arr_time
210
+ for c, subtask in enumerate(self.subtask_arr_queue):
211
+ if subtask.future_arr_time < subtask_arr_time_earl:
212
+ subtask_arr_time_earl = subtask.future_arr_time
204
213
  num_of_subtask_earl = c
205
214
 
206
215
  is_task_arr = False
@@ -219,37 +228,42 @@ class ForkJoinSimDelta(ForkJoinSim):
219
228
  self.serving(num_of_server_earlier)
220
229
 
221
230
  def __str__(self, is_short=False):
231
+ """
232
+ Returns string representation of the system
233
+ :param is_short: bool : if True returns short version of string
234
+ :return: str : string representation of the system
235
+ """
222
236
 
223
237
  res = "Queueing system " + self.source_types + \
224
238
  "/" + self.server_types + "/" + str(self.n)
225
- if self.buffer != None:
239
+ if self.buffer is not None:
226
240
  res += "/" + str(self.buffer)
227
- if self.is_SJ:
241
+ if self.is_sj:
228
242
  res += '| Split-Join'
229
243
  else:
230
244
  res += '| Fork-Join'
231
245
 
232
246
  res += "\n"
233
247
  # res += "Load: " + "{0:4.3f}".format(self.calc_load()) + "\n"
234
- res += "Current Time " + "{0:8.3f}".format(self.ttek) + "\n"
235
- res += "Arrival Time: " + "{0:8.3f}".format(self.arrival_time) + "\n"
248
+ res += f"Current Time {self.ttek:8.3f}\n"
249
+ res += f"Arrival Time: {self.arrival_time:8.3f}\n"
236
250
 
237
251
  res += "Sojourn moments:\n"
238
252
  for i in range(3):
239
- res += "\t" + "{0:8.4f}".format(self.v[i])
253
+ res += f"\t{self.v[i]:8.4f}"
240
254
  res += "\n"
241
255
 
242
256
  if not is_short:
243
257
  res += "Stationary prob:\n"
244
258
  res += "\t"
245
259
  for i in range(10):
246
- res += "{0:6.5f}".format(self.p[i] / self.ttek) + " "
260
+ res += f"{self.p[i] / self.ttek:6.5f} "
247
261
  res += "\n"
248
- res += "Arrived: " + str(self.arrived) + "\n"
249
- if self.buffer != None:
250
- res += "Dropped: " + str(self.dropped) + "\n"
251
- res += "Served: " + str(self.served) + "\n"
252
- res += "In System:" + str(self.in_sys) + "\n"
262
+ res += f"Arrived: {self.arrived}\n"
263
+ if self.buffer is not None:
264
+ res += f"Dropped: {self.dropped}\n"
265
+ res += f"Served: {self.served}\n"
266
+ res += f"In System: {self.in_sys}\n"
253
267
 
254
268
  for c in range(self.n):
255
269
  res += str(self.servers[c])
@@ -2,7 +2,6 @@
2
2
  ForkJoin Queue
3
3
  """
4
4
  import math
5
- import sys
6
5
 
7
6
  from colorama import Fore, Style, init
8
7
  from tqdm import tqdm
@@ -15,35 +14,39 @@ init()
15
14
 
16
15
  class ForkJoinSim(QueueingSystemSimulator):
17
16
  """
18
- Имитационная модель СМО Fork-Join, Split-Join
17
+ Simulation of a ForkJoin Queueing System (Fork-Join, Split-Join)
19
18
  """
20
19
 
21
- def __init__(self, num_of_channels, k, is_SJ=False, is_Purge=False, buffer=None):
20
+ def __init__(self, num_of_channels, k, is_sj=False, is_purge=False, buffer=None):
22
21
  """
23
- num_of_channels - количество каналов СМО
24
- buffer - максимальная длина очереди
22
+ :param num_of_channels: int : number of channels in the system
23
+ :param k: int : number of parts a task is split into
24
+ :param is_sj: bool : if True, then Split-Join model is used, otherwise Fork-Join model is used
25
+ :param buffer: Optional(int, None) : maximum length of the queue
26
+ :param is_purge: bool : if True, then Purge model is used
27
+
25
28
  """
26
29
  QueueingSystemSimulator.__init__(self, num_of_channels, buffer)
27
30
  self.k = k
28
- self.is_SJ = is_SJ
29
- self.is_Purge = is_Purge
31
+ self.is_sj = is_sj
32
+ self.is_purge = is_purge
30
33
  self.served_subtask_in_task = {}
31
34
  self.sub_task_in_sys = 0
32
35
 
33
36
  self.queues = []
34
- for i in range(num_of_channels):
37
+ for _ in range(num_of_channels):
35
38
  self.queues.append([])
36
39
 
37
40
  def calc_load(self):
38
41
  """
39
- вычисляет коэффициент загрузки СМО
42
+ calculates the load of the system.
40
43
  """
41
44
 
42
45
  pass
43
46
 
44
47
  def arrival(self):
45
48
  """
46
- Действия по прибытию заявки в СМО.
49
+ action on arrival of a task in the system.
47
50
  """
48
51
 
49
52
  self.arrived += 1
@@ -55,7 +58,7 @@ class ForkJoinSim(QueueingSystemSimulator):
55
58
  is_dropped = False
56
59
 
57
60
  if self.buffer: # ограниченная длина очереди
58
- if not self.is_SJ:
61
+ if not self.is_sj:
59
62
 
60
63
  if self.queue.size() + self.k - 1 > self.buffer + self.free_channels:
61
64
  self.dropped += 1
@@ -71,7 +74,7 @@ class ForkJoinSim(QueueingSystemSimulator):
71
74
  self.in_sys += 1
72
75
  self.sub_task_in_sys += self.n
73
76
 
74
- if not self.is_SJ: # Fork-Join discipline
77
+ if not self.is_sj: # Fork-Join discipline
75
78
 
76
79
  for i in range(self.n):
77
80
  if self.free_channels == 0:
@@ -96,8 +99,8 @@ class ForkJoinSim(QueueingSystemSimulator):
96
99
 
97
100
  def serving(self, c):
98
101
  """
99
- Дейтсвия по поступлению заявки на обслуживание
100
- с - номер канала
102
+ Action when a service is completed on channel c.
103
+ :param c: int : number of channel where service is completed.
101
104
  """
102
105
  time_to_end = self.servers[c].time_to_end_service
103
106
  self.p[self.in_sys] += time_to_end - self.t_old
@@ -109,11 +112,11 @@ class ForkJoinSim(QueueingSystemSimulator):
109
112
  self.free_channels += 1
110
113
  self.sub_task_in_sys -= 1
111
114
 
112
- if not self.is_SJ:
115
+ if not self.is_sj:
113
116
 
114
117
  if self.served_subtask_in_task[end_ts.task_id] == self.k:
115
118
 
116
- if self.is_Purge:
119
+ if self.is_purge:
117
120
  # найти все остальные подзадачи в СМО и выкинуть
118
121
  task_id = end_ts.task_id
119
122
  for i in range(self.n):
@@ -147,6 +150,11 @@ class ForkJoinSim(QueueingSystemSimulator):
147
150
  self.free_channels -= 1
148
151
 
149
152
  def run_one_step(self):
153
+ """
154
+ Run one step of the simulation.
155
+ If there is an arrival before the earliest service completion time,
156
+ then process the arrival. Otherwise, process the earliest service completion.
157
+ """
150
158
 
151
159
  num_of_server_earlier = -1
152
160
  serv_earl = 1e10
@@ -164,12 +172,15 @@ class ForkJoinSim(QueueingSystemSimulator):
164
172
  self.serving(num_of_server_earlier)
165
173
 
166
174
  def run(self, total_served, is_real_served=True):
175
+ """
176
+ Run simulation until total_served tasks are served.
177
+ """
167
178
 
168
179
  if is_real_served:
169
-
180
+
170
181
  last_percent = 0
171
182
 
172
- with tqdm(total=100, unit='jobs') as pbar:
183
+ with tqdm(total=100) as pbar:
173
184
  while self.served < total_served:
174
185
  self.run_one_step()
175
186
  percent = int(100*(self.served/total_served))
@@ -178,7 +189,7 @@ class ForkJoinSim(QueueingSystemSimulator):
178
189
  pbar.update(1)
179
190
  pbar.set_description(Fore.MAGENTA + '\rJob served: ' +
180
191
  Fore.YELLOW + f'{self.served}/{total_served}' + Fore.LIGHTGREEN_EX)
181
-
192
+
182
193
  else:
183
194
  print(Fore.GREEN + '\rStart simulation')
184
195
  print(Style.RESET_ALL)
@@ -197,8 +208,7 @@ class ForkJoinSim(QueueingSystemSimulator):
197
208
 
198
209
  def get_p(self):
199
210
  """
200
- Возвращает список с вероятностями состояний СМО
201
- p[j] - вероятность того, что в СМО в случайный момент времени будет ровно j заявок
211
+ Get probabilities of states for Fork-Join model
202
212
  """
203
213
  res = [0.0] * len(self.p)
204
214
  for j in range(0, self.num_of_states):
@@ -206,37 +216,42 @@ class ForkJoinSim(QueueingSystemSimulator):
206
216
  return res
207
217
 
208
218
  def __str__(self, is_short=False):
219
+ """
220
+ Prints the model of the queueing system
221
+ :param is_short: bool : if True, then short information about the model of the queueing system is returned
222
+ :return: str : string representation of the model of the queueing system
223
+ """
209
224
 
210
225
  res = "Queueing system " + self.source_types + \
211
226
  "/" + self.server_types + "/" + str(self.n)
212
- if self.buffer != None:
227
+ if self.buffer is not None:
213
228
  res += "/" + str(self.buffer)
214
- if self.is_SJ:
229
+ if self.is_sj:
215
230
  res += '| Split-Join'
216
231
  else:
217
232
  res += '| Fork-Join'
218
233
 
219
234
  res += "\n"
220
235
  # res += "Load: " + "{0:4.3f}".format(self.calc_load()) + "\n"
221
- res += "Current Time " + "{0:8.3f}".format(self.ttek) + "\n"
222
- res += "Arrival Time: " + "{0:8.3f}".format(self.arrival_time) + "\n"
236
+ res += f"Current Time {self.ttek:8.3f}\n"
237
+ res += f"Arrival Time: {self.arrival_time:8.3f}\n"
223
238
 
224
239
  res += "Sojourn moments:\n"
225
240
  for i in range(3):
226
- res += "\t" + "{0:8.4f}".format(self.v[i])
241
+ res += f"\t{self.v[i]:8.4f}"
227
242
  res += "\n"
228
243
 
229
244
  if not is_short:
230
245
  res += "Stationary prob:\n"
231
246
  res += "\t"
232
247
  for i in range(10):
233
- res += "{0:6.5f}".format(self.p[i] / self.ttek) + " "
248
+ res += f"{self.p[i] / self.ttek:6.5f} "
234
249
  res += "\n"
235
- res += "Arrived: " + str(self.arrived) + "\n"
236
- if self.buffer != None:
237
- res += "Dropped: " + str(self.dropped) + "\n"
238
- res += "Served: " + str(self.served) + "\n"
239
- res += "In System:" + str(self.in_sys) + "\n"
250
+ res += f"Arrived: {self.arrived}\n"
251
+ if self.buffer is not None:
252
+ res += f"Dropped: {self.dropped}\n"
253
+ res += f"Served: {self.served}\n"
254
+ res += f"In System: {self.in_sys}\n"
240
255
 
241
256
  for c in range(self.n):
242
257
  res += str(self.servers[c])
@@ -1,38 +1,65 @@
1
- from most_queue.sim.utils.distribution_utils import create_distribution
2
- from most_queue.sim.qs_sim import QueueingSystemSimulator, Task
1
+ """
2
+ Simulation model for queueing systems with impatient tasks
3
+ """
4
+ from colorama import Fore, Style, init
3
5
 
6
+ from most_queue.sim.qs_sim import QueueingSystemSimulator
7
+ from most_queue.sim.utils.distribution_utils import create_distribution
8
+ from most_queue.sim.utils.tasks import ImpatientTask
4
9
 
5
- class ImpatientTask(Task):
6
- def __init__(self, arr_time, moment_to_leave):
7
- super().__init__(arr_time)
8
- self.moment_to_leave = moment_to_leave
10
+ init()
9
11
 
10
- def __str__(self):
11
- return f'Task # {self.id}\nArrival moment: {self.arr_time:8.3f}\nMoment to leave: {self.moment_to_leave:8.3f}'
12
+ class ImpatientQueueSim(QueueingSystemSimulator):
13
+ """
14
+ Queueing system with impatient tasks
12
15
 
16
+ """
13
17
 
14
- class ImpatientQueueSim(QueueingSystemSimulator):
15
18
  def __init__(self, num_of_channels, buffer=None, verbose=True):
19
+ """
20
+ :param num_of_channels: int
21
+ Number of channels in the system.
22
+ :param buffer: int or None
23
+ Buffer size. If None, then infinite buffer.
24
+ :param verbose: bool
25
+ If True, then print information about simulation process.
26
+
27
+ To start the simulation, you need to:
28
+ - call the constructor with parameters
29
+ - set the input arrival distribution using the set_sorces() method
30
+ - set the service distribution using the set_servers() method
31
+ - set the impatience distribution using the set_impatience() method
32
+ - start the simulation using the run() method
33
+ to which you need to pass the number of job required for servicing
34
+
35
+ See supported distributions params in the README.md file or use
36
+ ```
37
+ from most_queue.sim.utils.distribution_utils import print_supported_distributions
38
+ print_supported_distributions()
39
+ ```
40
+
41
+ """
16
42
  super().__init__(num_of_channels, buffer, verbose)
17
43
 
18
44
  self.impatience_params = None
19
45
  self.impatience_types = None
20
-
46
+
21
47
  self.impatience = None
22
48
  self.is_set_impatience_params = False
23
49
 
24
- def set_impatiens(self, params, types):
50
+ def set_impatience(self, params, types):
25
51
  """
26
- Задает тип и параметры распределения интервала нетерпения заявок.
27
- Вид распределения Тип[types] Параметры [params]
28
- Экспоненциальное 'М' [mu]
29
- Гиперэкспоненциальное 2-го порядка 'Н' [y1, mu1, mu2]
30
- Гамма-распределение 'Gamma' [mu, alpha]
31
- Эрланга 'E' [r, mu]
32
- Кокса 2-го порядка 'C' [y1, mu1, mu2]
33
- Парето 'Pa' [alpha, K]
34
- Детерминированное 'D' [b]
35
- Равномерное 'Uniform' [mean, half_interval]
52
+ set impatience parameters and types
53
+ :param params: list
54
+ List of lists with parameters for each type of impatience.
55
+ :param types: list
56
+ List of strings with types of impatience.
57
+
58
+ See supported distributions params in the README.md file or use
59
+ ```
60
+ from most_queue.sim.utils.distribution_utils import print_supported_distributions
61
+ print_supported_distributions()
62
+ ```
36
63
  """
37
64
  self.impatience_params = params
38
65
  self.impatience_types = types
@@ -43,7 +70,7 @@ class ImpatientQueueSim(QueueingSystemSimulator):
43
70
 
44
71
  def arrival(self):
45
72
  """
46
- Действия по прибытию заявки в СМО.
73
+ Actions on arrival of a task.
47
74
  """
48
75
 
49
76
  self.arrived += 1
@@ -57,7 +84,7 @@ class ImpatientQueueSim(QueueingSystemSimulator):
57
84
  moment_to_leave = self.ttek + self.impatience.generate()
58
85
 
59
86
  if self.free_channels == 0:
60
- if self.buffer == None: # не задана длина очереди, т.е бесконечная очередь
87
+ if self.buffer is None: # не задана длина очереди, т.е бесконечная очередь
61
88
  new_tsk = ImpatientTask(self.ttek, moment_to_leave)
62
89
  new_tsk.start_waiting_time = self.ttek
63
90
  self.queue.append(new_tsk)
@@ -87,14 +114,18 @@ class ImpatientQueueSim(QueueingSystemSimulator):
87
114
  # Проверям, не наступил ли ПНЗ:
88
115
  if self.free_channels == 0:
89
116
  if self.in_sys == self.n:
90
- self.start_ppnz = self.ttek
117
+ self.start_busy = self.ttek
91
118
  break
92
119
 
93
- def drop_task(self, num_of_task_in_queue, moment_to_leave_earlier):
120
+ def drop_task(self, num_of_task_earlier, moment_to_leave_earlier):
121
+ """
122
+ Drop a task from the queue and update statistics.
123
+ """
94
124
  self.ttek = moment_to_leave_earlier
95
125
  new_queue = []
126
+ end_ts = None
96
127
  for i, tsk in enumerate(self.queue.queue):
97
- if i != num_of_task_in_queue:
128
+ if i != num_of_task_earlier:
98
129
  new_queue.append(tsk)
99
130
  else:
100
131
  end_ts = self.queue.queue[i]
@@ -103,11 +134,16 @@ class ImpatientQueueSim(QueueingSystemSimulator):
103
134
  self.in_sys -= 1
104
135
  self.dropped += 1
105
136
  self.served += 1
106
- self.refresh_v_stat(self.ttek - end_ts.arr_time)
107
- end_ts.wait_time = self.ttek - end_ts.arr_time
108
- self.refresh_w_stat(end_ts.wait_time)
137
+
138
+ if end_ts is not None:
139
+ self.refresh_v_stat(self.ttek - end_ts.arr_time)
140
+ end_ts.wait_time = self.ttek - end_ts.arr_time
141
+ self.refresh_w_stat(end_ts.wait_time)
109
142
 
110
143
  def run_one_step(self):
144
+ """
145
+ Run one step of the simulation.
146
+ """
111
147
 
112
148
  num_of_server_earlier = -1
113
149
  serv_earl = 1e10
@@ -138,6 +174,11 @@ class ImpatientQueueSim(QueueingSystemSimulator):
138
174
  self.drop_task(num_of_task_earlier, moment_to_leave_earlier)
139
175
 
140
176
  def __str__(self, is_short=False):
177
+ """
178
+ Returns a string representation of the system.
179
+ If `is_short` is True, it returns a short version of the string.
180
+ Otherwise, it returns a detailed version of the string.
181
+ """
141
182
  super().__str__(is_short)
142
183
  num_of_task_earlier = -1
143
184
  moment_to_leave_earlier = 1e10
@@ -145,4 +186,4 @@ class ImpatientQueueSim(QueueingSystemSimulator):
145
186
  if tsk.moment_to_leave < moment_to_leave_earlier:
146
187
  moment_to_leave_earlier = tsk.moment_to_leave
147
188
  num_of_task_earlier = i
148
- return f'Task {num_of_task_earlier} is earlier to leave at {moment_to_leave_earlier:8.3f}'
189
+ return f'{Fore.GREEN}Task {num_of_task_earlier}{Style.RESET_ALL} is earlier to leave at {Fore.YELLOW}{moment_to_leave_earlier:8.3f}{Style.RESET_ALL}'