most-queue 1.60__tar.gz → 1.62__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 (188) hide show
  1. {most_queue-1.60 → most_queue-1.62}/.gitignore +1 -1
  2. {most_queue-1.60 → most_queue-1.62}/PKG-INFO +8 -5
  3. {most_queue-1.60 → most_queue-1.62}/README.md +7 -4
  4. most_queue-1.62/assets/1.gif +0 -0
  5. most_queue-1.62/assets/2.gif +0 -0
  6. most_queue-1.62/assets/3.gif +0 -0
  7. {most_queue-1.60 → most_queue-1.62}/most_queue/general/distribution_params.py +9 -0
  8. {most_queue-1.60 → most_queue-1.62}/most_queue/general/tables.py +2 -0
  9. {most_queue-1.60 → most_queue-1.62}/most_queue/misc/flow_sum.py +3 -3
  10. {most_queue-1.60 → most_queue-1.62}/most_queue/rand_distribution.py +127 -1
  11. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/base.py +38 -18
  12. most_queue-1.62/most_queue/sim/networks/network.py +181 -0
  13. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/priority.py +18 -15
  14. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/tasks.py +10 -5
  15. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/ek_d_n.py +1 -1
  16. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/mgn_takahasi.py +61 -1
  17. most_queue-1.62/most_queue/theory/networks/open_network.py +126 -0
  18. most_queue-1.60/most_queue/theory/networks/open_network.py → most_queue-1.62/most_queue/theory/networks/open_network_prty.py +1 -1
  19. most_queue-1.62/most_queue/theory/networks/opt/transition.py +330 -0
  20. most_queue-1.62/most_queue/theory/networks/opt/transition_approx.py +132 -0
  21. most_queue-1.62/most_queue/theory/networks/opt/transition_plus.py +162 -0
  22. most_queue-1.62/most_queue/theory/utils/residual.py +19 -0
  23. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/transforms.py +3 -0
  24. most_queue-1.62/most_queue/theory/utils/utilization_approx.py +62 -0
  25. {most_queue-1.60 → most_queue-1.62}/pyproject.toml +1 -1
  26. {most_queue-1.60 → most_queue-1.62}/setup.py +1 -1
  27. {most_queue-1.60 → most_queue-1.62}/tests/cold_warm_delay_params.yaml +0 -1
  28. most_queue-1.62/tests/default_params.yaml +35 -0
  29. {most_queue-1.60 → most_queue-1.62}/tests/test_base_qs_sim.py +26 -8
  30. {most_queue-1.60 → most_queue-1.62}/tests/test_batch.py +22 -9
  31. {most_queue-1.60 → most_queue-1.62}/tests/test_ek_d_n.py +27 -10
  32. {most_queue-1.60 → most_queue-1.62}/tests/test_engset.py +36 -10
  33. most_queue-1.62/tests/test_fj_delta.py +85 -0
  34. most_queue-1.60/tests/test_fj_im.py → most_queue-1.62/tests/test_fj_sim.py +45 -28
  35. {most_queue-1.60 → most_queue-1.62}/tests/test_gi_m_1_calc.py +26 -36
  36. {most_queue-1.60 → most_queue-1.62}/tests/test_gi_m_n_calc.py +32 -31
  37. most_queue-1.62/tests/test_impatience.py +68 -0
  38. {most_queue-1.60 → most_queue-1.62}/tests/test_m_d_n_calc.py +27 -9
  39. {most_queue-1.60 → most_queue-1.62}/tests/test_m_h2_h2warm.py +41 -18
  40. {most_queue-1.60 → most_queue-1.62}/tests/test_m_ph_n_prty.py +40 -33
  41. most_queue-1.62/tests/test_mg1_calc.py +80 -0
  42. {most_queue-1.60 → most_queue-1.62}/tests/test_mg1_disaster.py +36 -13
  43. {most_queue-1.60 → most_queue-1.62}/tests/test_mg1_rcs.py +24 -10
  44. {most_queue-1.60 → most_queue-1.62}/tests/test_mg1_warmup.py +29 -13
  45. {most_queue-1.60 → most_queue-1.62}/tests/test_mgn_disaster.py +33 -7
  46. {most_queue-1.60 → most_queue-1.62}/tests/test_mgn_rcs.py +34 -8
  47. most_queue-1.62/tests/test_mgn_tt.py +118 -0
  48. most_queue-1.60/tests/test_mgn_with_h2_delay_cold_warm_one_shot.py → most_queue-1.62/tests/test_mgn_with_h2_delay_cold_warm.py +66 -18
  49. {most_queue-1.60 → most_queue-1.62}/tests/test_mmn_h2cold_h2warm.py +55 -21
  50. {most_queue-1.60 → most_queue-1.62}/tests/test_mmn_prty_pnz_approx.py +43 -17
  51. {most_queue-1.60 → most_queue-1.62}/tests/test_network_im_prty.py +44 -21
  52. most_queue-1.62/tests/test_network_no_prty.py +77 -0
  53. most_queue-1.62/tests/test_network_opt.py +51 -0
  54. most_queue-1.62/tests/test_network_opt_approx.py +42 -0
  55. most_queue-1.62/tests/test_network_opt_plus.py +49 -0
  56. most_queue-1.62/tests/units/test_tt_up_probs.py +48 -0
  57. most_queue-1.62/tests/units/test_v1_on_channels.py +54 -0
  58. most_queue-1.62/tests/units/test_v1_utlization_approx.py +10 -0
  59. most_queue-1.62/tests/units/test_weibull.py +29 -0
  60. most_queue-1.62/tests/units/v1_on_channels.png +0 -0
  61. most_queue-1.62/tests/units/v1_on_utilization_approx.png +0 -0
  62. {most_queue-1.60 → most_queue-1.62}/tutorials/network_with_priorities.ipynb +17 -17
  63. {most_queue-1.60 → most_queue-1.62}/tutorials/queue_sim.ipynb +4 -4
  64. most_queue-1.62/works/negative_queues/__init__.py +0 -0
  65. most_queue-1.62/works/negative_queues/base_parameters.yaml +21 -0
  66. most_queue-1.62/works/negative_queues/work_mgn_negatives.py +303 -0
  67. most_queue-1.62/works/vacations/__init__.py +0 -0
  68. {most_queue-1.60 → most_queue-1.62}/works/vacations/main.py +1 -1
  69. most_queue-1.60/most_queue/misc/test_weibull.py +0 -37
  70. most_queue-1.60/most_queue/theory/utils/weibull.py +0 -155
  71. most_queue-1.60/tests/test_fj_delta.py +0 -66
  72. most_queue-1.60/tests/test_impatience.py +0 -47
  73. most_queue-1.60/tests/test_mg1_calc.py +0 -104
  74. most_queue-1.60/tests/test_mgn_tt.py +0 -94
  75. most_queue-1.60/tests/test_mmn3_pnz_cox_approx.py +0 -104
  76. most_queue-1.60/works/negative_queues/work_mgn_disasters.py +0 -358
  77. most_queue-1.60/works/negative_queues/work_mgn_rcs.py +0 -358
  78. {most_queue-1.60 → most_queue-1.62}/LICENSE +0 -0
  79. {most_queue-1.60 → most_queue-1.62}/assets/queue_long.png +0 -0
  80. {most_queue-1.60 → most_queue-1.62}/deploy.txt +0 -0
  81. {most_queue-1.60 → most_queue-1.62}/docs/Makefile +0 -0
  82. {most_queue-1.60 → most_queue-1.62}/docs/make.bat +0 -0
  83. {most_queue-1.60 → most_queue-1.62}/docs/source/conf.py +0 -0
  84. {most_queue-1.60 → most_queue-1.62}/docs/source/index.rst +0 -0
  85. {most_queue-1.60 → most_queue-1.62}/docs/source/modules.rst +0 -0
  86. {most_queue-1.60 → most_queue-1.62}/docs/source/most_queue.rst +0 -0
  87. {most_queue-1.60 → most_queue-1.62}/docs/source/most_queue.sim.rst +0 -0
  88. {most_queue-1.60 → most_queue-1.62}/docs/source/most_queue.theory.rst +0 -0
  89. {most_queue-1.60 → most_queue-1.62}/googleb31d3dccb40f969f.html +0 -0
  90. {most_queue-1.60 → most_queue-1.62}/most_queue/__init__.py +0 -0
  91. {most_queue-1.60 → most_queue-1.62}/most_queue/general/__init__.py +0 -0
  92. {most_queue-1.60 → most_queue-1.62}/most_queue/general/interfaces.py +0 -0
  93. {most_queue-1.60 → most_queue-1.62}/most_queue/general/plots.py +0 -0
  94. {most_queue-1.60 → most_queue-1.62}/most_queue/misc/approx_cdf_make.py +0 -0
  95. {most_queue-1.60 → most_queue-1.62}/most_queue/misc/calc_v_pls.py +0 -0
  96. {most_queue-1.60 → most_queue-1.62}/most_queue/misc/compare_fj_calc.py +0 -0
  97. /most_queue-1.60/tests/test_mgn_with_h2_delay_cold_warm.py → /most_queue-1.62/most_queue/misc/run_mgn_with_h2_delay_cold_warm.py +0 -0
  98. {most_queue-1.60 → most_queue-1.62}/most_queue/misc/vacations_paper_utils.py +0 -0
  99. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/__init__.py +0 -0
  100. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/batch.py +0 -0
  101. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/finite_source.py +0 -0
  102. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/flow_sum.py +0 -0
  103. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/fork_join.py +0 -0
  104. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/fork_join_delta.py +0 -0
  105. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/impatient.py +0 -0
  106. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/negative.py +0 -0
  107. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/networks/__init__.py +0 -0
  108. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/networks/priority_network.py +0 -0
  109. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/__init__.py +0 -0
  110. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/distribution_utils.py +0 -0
  111. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/exceptions.py +0 -0
  112. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/phase.py +0 -0
  113. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/qs_queue.py +0 -0
  114. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/servers.py +0 -0
  115. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/stats_update.py +0 -0
  116. {most_queue-1.60 → most_queue-1.62}/most_queue/sim/vacations.py +0 -0
  117. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/__init__.py +0 -0
  118. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/batch/__init__.py +0 -0
  119. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/batch/mm1.py +0 -0
  120. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/closed/__init__.py +0 -0
  121. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/closed/engset.py +0 -0
  122. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/__init__.py +0 -0
  123. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/gi_m_1.py +0 -0
  124. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/gi_m_n.py +0 -0
  125. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/m_d_n.py +0 -0
  126. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/mg1.py +0 -0
  127. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/mmnr.py +0 -0
  128. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fork_join/__init__.py +0 -0
  129. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fork_join/m_m_n.py +0 -0
  130. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fork_join/split_join.py +0 -0
  131. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/impatience/__init__.py +0 -0
  132. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/impatience/mm1.py +0 -0
  133. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/mg1_disasters.py +0 -0
  134. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/mg1_rcs.py +0 -0
  135. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/mgn_disaster.py +0 -0
  136. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/mgn_rcs.py +0 -0
  137. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/structs.py +0 -0
  138. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/networks/__init__.py +0 -0
  139. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/networks/network_viewer.py +0 -0
  140. {most_queue-1.60/most_queue/theory/priority → most_queue-1.62/most_queue/theory/networks/opt}/__init__.py +0 -0
  141. {most_queue-1.60/most_queue/theory/priority/non_preemptive → most_queue-1.62/most_queue/theory/priority}/__init__.py +0 -0
  142. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/mgn_invar_approx.py +0 -0
  143. {most_queue-1.60/most_queue/theory/priority/preemptive → most_queue-1.62/most_queue/theory/priority/non_preemptive}/__init__.py +0 -0
  144. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/non_preemptive/mg1.py +0 -0
  145. {most_queue-1.60/most_queue/theory/utils → most_queue-1.62/most_queue/theory/priority/preemptive}/__init__.py +0 -0
  146. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/preemptive/m_ph_n_busy_approx.py +0 -0
  147. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/preemptive/mg1.py +0 -0
  148. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/preemptive/mmn_2cls_pr_busy_approx.py +0 -0
  149. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/preemptive/mmn_3cls_busy_approx.py +0 -0
  150. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/r_example.gexf +0 -0
  151. {most_queue-1.60/most_queue/theory/vacations → most_queue-1.62/most_queue/theory/utils}/__init__.py +0 -0
  152. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/binom_probs.py +0 -0
  153. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/busy_periods.py +0 -0
  154. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/conditional.py +0 -0
  155. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/conv.py +0 -0
  156. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/diff5dots.py +0 -0
  157. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/flow_sum.py +0 -0
  158. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/passage_time.py +0 -0
  159. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/q_poisson_arrival_calc.py +0 -0
  160. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/student_stat.py +0 -0
  161. {most_queue-1.60/tests → most_queue-1.62/most_queue/theory/vacations}/__init__.py +0 -0
  162. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/vacations/m_h2_h2warm.py +0 -0
  163. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/vacations/mg1_warm_calc.py +0 -0
  164. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/vacations/mgn_with_h2_delay_cold_warm.py +0 -0
  165. {most_queue-1.60 → most_queue-1.62}/most_queue/theory/vacations/mmn_with_h2_cold_and_h2_warmup.py +0 -0
  166. {most_queue-1.60 → most_queue-1.62}/requirements.txt +0 -0
  167. {most_queue-1.60/works → most_queue-1.62/tests}/__init__.py +0 -0
  168. {most_queue-1.60 → most_queue-1.62}/tests/test_qs_sim.py +0 -0
  169. {most_queue-1.60 → most_queue-1.62}/tests/test_qs_sim_prty.py +0 -0
  170. {most_queue-1.60 → most_queue-1.62}/tests/units/h2_params_cv_greater_than_exp.png +0 -0
  171. {most_queue-1.60 → most_queue-1.62}/tests/units/h2_params_cv_less_than_exp.png +0 -0
  172. {most_queue-1.60 → most_queue-1.62}/tests/units/test_busy_moments_calc.py +0 -0
  173. {most_queue-1.60 → most_queue-1.62}/tests/units/test_conditionals.py +0 -0
  174. {most_queue-1.60 → most_queue-1.62}/tests/units/test_h2_params_cv.py +0 -0
  175. {most_queue-1.60 → most_queue-1.62}/tests/units/test_queue_types.py +0 -0
  176. {most_queue-1.60 → most_queue-1.62}/tutorials/m_h2_h2warm.ipynb +0 -0
  177. {most_queue-1.60 → most_queue-1.62}/tutorials/mgn_takahasi_takami.ipynb +0 -0
  178. {most_queue-1.60 → most_queue-1.62}/tutorials/priority_queue.ipynb +0 -0
  179. {most_queue-1.60/works/negative_queues → most_queue-1.62/works}/__init__.py +0 -0
  180. {most_queue-1.60 → most_queue-1.62}/works/vacations/base_parameters.yaml +0 -0
  181. {most_queue-1.60 → most_queue-1.62}/works/vacations/channels.py +0 -0
  182. {most_queue-1.60 → most_queue-1.62}/works/vacations/cooling.py +0 -0
  183. {most_queue-1.60 → most_queue-1.62}/works/vacations/cooling_delay.py +0 -0
  184. {most_queue-1.60 → most_queue-1.62}/works/vacations/run_one_calc_vs_sim.py +0 -0
  185. {most_queue-1.60 → most_queue-1.62}/works/vacations/service.py +0 -0
  186. {most_queue-1.60 → most_queue-1.62}/works/vacations/utilization.py +0 -0
  187. {most_queue-1.60 → most_queue-1.62}/works/vacations/utils.py +0 -0
  188. {most_queue-1.60 → most_queue-1.62}/works/vacations/warmup.py +0 -0
@@ -162,4 +162,4 @@ cython_debug/
162
162
 
163
163
  .vscode
164
164
 
165
- /works/results/
165
+ works/negative_queues/results/*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: most_queue
3
- Version: 1.60
3
+ Version: 1.62
4
4
  Summary: Software package for calculation and simulation of queuing systems
5
5
  Project-URL: Homepage, https://github.com/xabarov/most-queue
6
6
  Author-email: Xabarov Roman <xabarov1985@gmail.com>
@@ -41,7 +41,7 @@ Description-Content-Type: text/markdown
41
41
 
42
42
  # Queueing Systems: Simulation & Numerical Methods 🔄
43
43
 
44
- ![Queue](assets/queue_long.png)
44
+ ![Queue](assets/3.gif)
45
45
 
46
46
  A Python package for simulating and analyzing queueing systems (QS) and networks.
47
47
 
@@ -129,8 +129,8 @@ Most_queue consists of two main parts:
129
129
 
130
130
  | # | Kendall Notations | Description | Example | Tutorial |
131
131
  |-----|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|-------------------|
132
- | 1. | M/M/c/Fork-Join | Solving for Fork-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_fj_im.py) | |
133
- | 2. | M/G/c/Split-Join | Solving for Split-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_fj_im.py) | |
132
+ | 1. | M/M/c/Fork-Join | Solving for Fork-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_fj_sim.py) | |
133
+ | 2. | M/G/c/Split-Join | Solving for Split-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_fj_sim.py) | |
134
134
 
135
135
 
136
136
  ### Others
@@ -139,7 +139,10 @@ Most_queue consists of two main parts:
139
139
  | 1. | M<sup>x</sup>/M/1 | Solving for the of M<sup>x</sup>/M/1 QS with batch arrival | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_batch.py) | |
140
140
  | 2. | M/M/1/D | Solving for M/M/1 with exponential impatience | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_impatience.py) | |
141
141
  | 3. | M/M/1/N | Solving for the Engset model for M/M/1 with a finite number of sources. | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_engset.py) | |
142
- | 4. | General Network | Numerical calculation of queuing network with priorities in nodes | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_network_im_prty.py) | [link](https://github.com/xabarov/most-queue/blob/main/tutorials/network_with_priorities.ipynb) |
142
+ | 4. | Queuing Network | Numerical calculation of queuing network | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_network_no_prty.py) | |
143
+ | 5. | Queuing Network with Priorities | Numerical calculation of queuing network with priorities in nodes | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_network_sim_prty.py) | [link](https://github.com/xabarov/most-queue/blob/main/tutorials/network_with_priorities.ipynb) |
144
+ | 6. | Queuing Network Optimization | Optimization of queuing network transition matrix | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_network_opt.py) | |
145
+
143
146
 
144
147
  ---
145
148
 
@@ -1,6 +1,6 @@
1
1
  # Queueing Systems: Simulation & Numerical Methods 🔄
2
2
 
3
- ![Queue](assets/queue_long.png)
3
+ ![Queue](assets/3.gif)
4
4
 
5
5
  A Python package for simulating and analyzing queueing systems (QS) and networks.
6
6
 
@@ -88,8 +88,8 @@ Most_queue consists of two main parts:
88
88
 
89
89
  | # | Kendall Notations | Description | Example | Tutorial |
90
90
  |-----|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|-------------------|
91
- | 1. | M/M/c/Fork-Join | Solving for Fork-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_fj_im.py) | |
92
- | 2. | M/G/c/Split-Join | Solving for Split-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_fj_im.py) | |
91
+ | 1. | M/M/c/Fork-Join | Solving for Fork-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_fj_sim.py) | |
92
+ | 2. | M/G/c/Split-Join | Solving for Split-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_fj_sim.py) | |
93
93
 
94
94
 
95
95
  ### Others
@@ -98,7 +98,10 @@ Most_queue consists of two main parts:
98
98
  | 1. | M<sup>x</sup>/M/1 | Solving for the of M<sup>x</sup>/M/1 QS with batch arrival | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_batch.py) | |
99
99
  | 2. | M/M/1/D | Solving for M/M/1 with exponential impatience | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_impatience.py) | |
100
100
  | 3. | M/M/1/N | Solving for the Engset model for M/M/1 with a finite number of sources. | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_engset.py) | |
101
- | 4. | General Network | Numerical calculation of queuing network with priorities in nodes | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_network_im_prty.py) | [link](https://github.com/xabarov/most-queue/blob/main/tutorials/network_with_priorities.ipynb) |
101
+ | 4. | Queuing Network | Numerical calculation of queuing network | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_network_no_prty.py) | |
102
+ | 5. | Queuing Network with Priorities | Numerical calculation of queuing network with priorities in nodes | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_network_sim_prty.py) | [link](https://github.com/xabarov/most-queue/blob/main/tutorials/network_with_priorities.ipynb) |
103
+ | 6. | Queuing Network Optimization | Optimization of queuing network transition matrix | [link](https://github.com/xabarov/most-queue/blob/main/tests/test_network_opt.py) | |
104
+
102
105
 
103
106
  ---
104
107
 
Binary file
Binary file
Binary file
@@ -35,6 +35,15 @@ class GammaParams:
35
35
  g: list[float] | None = None
36
36
 
37
37
 
38
+ @dataclass
39
+ class WeibullParams:
40
+ """
41
+ Weibull distribution parameters.
42
+ """
43
+ k: float # Shape parameter
44
+ W: float # Scale parameter
45
+
46
+
38
47
  @dataclass
39
48
  class GaussianParams:
40
49
  """
@@ -320,3 +320,5 @@ def print_mrx(mrx, is_short=False):
320
320
  print(f"{color}{mrx[i, j]:^5.3f} | ", end="")
321
321
  print("\n" + "-------" *
322
322
  col if is_short or mrx[i, j].imag == 0.0 else "\n" + "---------------" * col)
323
+
324
+ print(f'{Style.RESET_ALL}')
@@ -1,9 +1,9 @@
1
1
  import matplotlib
2
2
  import matplotlib.pyplot as plt
3
3
 
4
- from most_queue.theory.utils.flow_sum import SummatorNumeric
5
4
  from most_queue.rand_distribution import GammaDistribution
6
5
  from most_queue.sim.flow_sum import FlowSumSim
6
+ from most_queue.theory.utils.flow_sum import SummatorNumeric
7
7
 
8
8
  matplotlib.use('TkAgg')
9
9
 
@@ -19,7 +19,7 @@ def test():
19
19
  mean = 1 # среднее каждого потока
20
20
  num_of_jobs = 400000 # количество заявок для ИМ
21
21
  is_semi = False # True, если необходимо использовать метод семиинвариантов вместо H2
22
- distr_im = "Gamma" # распределение, используемое для ИМ
22
+ distr_sim = "Gamma" # распределение, используемое для ИМ
23
23
 
24
24
  # число суммируемых потоков
25
25
  ns = [x + 2 for x in range(n_nums - 1)]
@@ -38,7 +38,7 @@ def test():
38
38
  # i - кол-во суммируемых потоков, j - номер начального момента
39
39
 
40
40
  # ИМ
41
- s_sim = FlowSumSim(a, distr=distr_im, num_of_jobs=num_of_jobs)
41
+ s_sim = FlowSumSim(a, distr=distr_sim, num_of_jobs=num_of_jobs)
42
42
  # в s_sim._flows[i][j] содержатся начальные моменты суммируемых потокоы,
43
43
  s_sim.sum_flows()
44
44
  # i - кол-во суммируемых потоков, j - номер начального момента
@@ -16,10 +16,135 @@ from most_queue.general.distribution_params import (
16
16
  H2Params,
17
17
  ParetoParams,
18
18
  UniformParams,
19
+ WeibullParams
19
20
  )
20
21
  from most_queue.general.interfaces import Distribution
21
22
 
22
23
 
24
+ class Weibull(Distribution):
25
+ """
26
+ Class for working with the Weibull distribution
27
+ """
28
+
29
+ def __init__(self, params: WeibullParams, generator=None):
30
+ """
31
+ :param params: WeibullParams object containing shape parameter (k) and scale parameter (T)
32
+ :param generator: random number generator. If None, np.random is used.
33
+ """
34
+
35
+ self.k = params.k
36
+ self.W = params.W
37
+ self.params = params
38
+ self.type = 'Weibull'
39
+ self.generator = generator
40
+
41
+ @staticmethod
42
+ def generate_static(params: WeibullParams, generator=None):
43
+ """
44
+ Generates a random number according to the Weibull distribution.
45
+ """
46
+ if generator:
47
+ p = generator.random()
48
+ else:
49
+ p = np.random.rand()
50
+ return math.pow(-math.log(p)*params.W, -1 / params.k)
51
+
52
+ def generate(self) -> float:
53
+ """
54
+ Generates a random number according to the Weibull distribution.
55
+ """
56
+
57
+ return self.generate_static(self.params, self.generator)
58
+
59
+ @staticmethod
60
+ def calc_theory_moments(params: WeibullParams, num: int) -> list[float]:
61
+ """
62
+ Calculates theoretical moments of the distribution up to the specified order.
63
+ :param params: WeibullParams parameters for the distribution.
64
+ :param num: number of moments to calculate.
65
+ :return: list[float]
66
+ """
67
+ f = [0.0]*num
68
+ for i in range(num):
69
+ f[i] = math.gamma(1 + i/params.k) * math.pow(params.W, i/params.k)
70
+ return f
71
+
72
+ @staticmethod
73
+ def get_params(moments: list[float]) -> WeibullParams:
74
+ """
75
+ Parameter selection for the distribution based
76
+ on initial moments of the distribution
77
+
78
+ params:
79
+ moments: initial moments of the random variable
80
+
81
+ return:
82
+ WeibullParams
83
+
84
+ """
85
+ a = moments[1] / (moments[0] * moments[0])
86
+ u0 = math.log(2 * a) / (2.0 * math.log(2))
87
+ ee = 1e-6
88
+ u1 = (1.0 / (2 * math.log(2))) * math.log(
89
+ a * math.sqrt(math.pi) * math.gamma(u0 + 1) / math.gamma(u0 + 0.5))
90
+ delta = u1 - u0
91
+ while math.fabs(delta) > ee:
92
+ u1 = (1.0 / (2 * math.log(2))) * math.log(
93
+ a * math.sqrt(math.pi) * math.gamma(u0 + 1) / math.gamma(u0 + 0.5))
94
+ delta = u1 - u0
95
+ u0 = u1
96
+ k = 1 / u1
97
+ big_w = math.pow(moments[0] / math.gamma(u1 + 1), k)
98
+
99
+ return WeibullParams(k=k, W=big_w)
100
+
101
+ @staticmethod
102
+ def get_params_by_mean_and_coev(f1: float, coev: float) -> WeibullParams:
103
+ """
104
+ Subselect parameters of Weibull distribution by the given mean and coefficient of variation.
105
+ Args:
106
+ f1 (float): The first parameter of the Weibull distribution.
107
+ coev (float): The coefficient of variation.
108
+ Returns:
109
+ WeibullParams
110
+ """
111
+
112
+ f = [0, 0, 0]
113
+ alpha = 1 / (coev ** 2)
114
+ f[0] = f1
115
+ f[1] = pow(f[0], 2) * (pow(coev, 2) + 1)
116
+ f[2] = f[1] * f[0] * (1.0 + 2 / alpha)
117
+
118
+ return Weibull.get_params(f)
119
+
120
+ @staticmethod
121
+ def get_tail(params: WeibullParams, t: float) -> float:
122
+ """
123
+ Calculate the tail probability of a Weibull distribution at a given value.
124
+ Args:
125
+ params (WeibullParams): The parameters of Weibull distribution
126
+ t: The value at which to calculate the tail probability.
127
+ """
128
+ k = params.k
129
+ big_w = params.W
130
+
131
+ return math.exp(-math.pow(t, k) / big_w)
132
+
133
+ @staticmethod
134
+ def get_cdf(params: WeibullParams, t: float) -> float:
135
+ """
136
+ Calculate the cumulative distribution function (CDF) of a Weibull distribution for a given set of values.
137
+ Args:
138
+ params (WeibullParams): The parameters of Weibull distribution
139
+ t: The value at which to calculate the cdf probability.
140
+
141
+ """
142
+ k = params.k
143
+ big_w = params.W
144
+
145
+ return 1.0 - math.exp(-math.pow(t, k) / big_w)
146
+
147
+
23
148
  class NormalDistribution(Distribution):
24
149
  """
25
150
  Gaussian distribution. Generates random numbers from a normal (Gaussian) distribution.
@@ -806,7 +931,8 @@ class ErlangDistribution(Distribution):
806
931
  @staticmethod
807
932
  def get_params_by_mean_and_coev(f1: float, coev: float) -> ErlangParams:
808
933
  """
809
- Method selects the parameters of the Erlang distribution by mean and coefficient of variation.
934
+ Method selects the parameters of the Erlang distribution
935
+ by mean and coefficient of variation.
810
936
  """
811
937
  f = [0, 0]
812
938
  f[0] = f1
@@ -105,7 +105,8 @@ class QsSim:
105
105
 
106
106
  self.is_set_source_params = True
107
107
 
108
- self.source = create_distribution(params, kendall_notation, self.generator)
108
+ self.source = create_distribution(
109
+ params, kendall_notation, self.generator)
109
110
 
110
111
  self.arrival_time = self.source.generate()
111
112
 
@@ -137,14 +138,17 @@ class QsSim:
137
138
  self.server_kendall_notation,
138
139
  self.server_params, self.n)
139
140
 
140
- def send_task_to_channel(self, is_warm_start=False):
141
+ def send_task_to_channel(self, is_warm_start=False, tsk=None):
141
142
  """
142
143
  Sends a job to the service channel
143
144
  """
145
+
146
+ if tsk is None:
147
+ tsk = Task(self.ttek)
148
+ tsk.wait_time = 0
149
+
144
150
  for s in self.servers:
145
151
  if s.is_free:
146
- tsk = Task(self.ttek)
147
- tsk.wait_time = 0
148
152
  self.taked += 1
149
153
  self.refresh_w_stat(tsk.wait_time)
150
154
  self.zero_wait_arrivals_num += 1
@@ -159,42 +163,53 @@ class QsSim:
159
163
 
160
164
  break
161
165
 
162
- def send_task_to_queue(self):
166
+ def send_task_to_queue(self, new_tsk=None):
163
167
  """
164
168
  Send Task to Queue
165
169
  """
166
- if self.buffer is None: # queue length is not specified, i.e. infinite queue
170
+
171
+ if new_tsk is None:
167
172
  new_tsk = Task(self.ttek)
168
173
  new_tsk.start_waiting_time = self.ttek
174
+
175
+ if self.buffer is None: # queue length is not specified, i.e. infinite queue
176
+
169
177
  self.queue.append(new_tsk)
170
178
  else:
171
179
  if self.queue.size() < self.buffer:
172
- new_tsk = Task(self.ttek)
173
- new_tsk.start_waiting_time = self.ttek
174
180
  self.queue.append(new_tsk)
175
181
  else:
176
182
  self.dropped += 1
177
183
  self.in_sys -= 1
178
184
 
179
- def arrival(self):
185
+ def arrival(self, moment=None, ts=None):
180
186
  """
181
187
  Actions upon arrival of the job by the QS.
182
188
  """
183
-
189
+
184
190
  self.arrived += 1
185
191
  self.p[self.in_sys] += self.arrival_time - self.ttek
186
192
 
187
- self.in_sys += 1
188
- self.ttek = self.arrival_time
189
- self.arrival_time = self.ttek + self.source.generate()
193
+ if moment:
194
+ self.ttek = moment
195
+ ts.arr_time = moment
196
+ ts.wait_time = 0
197
+ ts.start_waiting_time = -1
198
+ ts.time_to_end_service = 0
199
+
200
+ else:
201
+ self.ttek = self.arrival_time
202
+ self.arrival_time = self.ttek + self.source.generate()
190
203
 
204
+ self.in_sys += 1
205
+
191
206
  if self.free_channels == 0:
192
- self.send_task_to_queue()
207
+ self.send_task_to_queue(new_tsk=ts)
193
208
 
194
209
  else: # there are free channels:
195
- self.send_task_to_channel()
210
+ self.send_task_to_channel(tsk=ts)
196
211
 
197
- def serving(self, c):
212
+ def serving(self, c, is_network=False):
198
213
  """
199
214
  Actions upon receipt of a service job with - channel number
200
215
  """
@@ -219,9 +234,12 @@ class QsSim:
219
234
  self.refresh_busy_stat(self.ttek - self.start_busy)
220
235
 
221
236
  if self.queue.size() != 0:
222
- self.send_head_of_queue_to_channel(c)
237
+ self.send_head_of_queue_to_channel(c, is_network=is_network)
238
+
239
+ if is_network:
240
+ return end_ts
223
241
 
224
- def send_head_of_queue_to_channel(self, channel_num):
242
+ def send_head_of_queue_to_channel(self, channel_num, is_network=False):
225
243
  """
226
244
  Send first Task (head of queue) to Channel
227
245
  """
@@ -232,6 +250,8 @@ class QsSim:
232
250
 
233
251
  self.taked += 1
234
252
  que_ts.wait_time += self.ttek - que_ts.start_waiting_time
253
+ if is_network:
254
+ que_ts.wait_network += self.ttek - que_ts.start_waiting_time
235
255
  self.refresh_w_stat(que_ts.wait_time)
236
256
 
237
257
  self.servers[channel_num].start_service(que_ts, self.ttek)
@@ -0,0 +1,181 @@
1
+ """
2
+ Simulation of a priority network with priorities and multiple channels.
3
+ """
4
+ import math
5
+
6
+ import numpy as np
7
+ from colorama import Fore, Style, init
8
+ from tqdm import tqdm
9
+
10
+ from most_queue.rand_distribution import ExpDistribution
11
+ from most_queue.sim.base import QsSim
12
+ from most_queue.sim.utils.tasks import Task
13
+
14
+ init()
15
+
16
+
17
+ class NetworkSimulator:
18
+ """
19
+ Simulation of network with multiple channels in each node.
20
+ """
21
+
22
+ def __init__(self, arrival_rate: float, R: np.matrix, n: list[int],
23
+ serv_params):
24
+ """
25
+ arrival_rate: arrival rate of tasks.
26
+
27
+ R: routing matrix
28
+ n: list of number of channels in each node.
29
+
30
+ serv_params: list of dictionaries with service parameters for each node
31
+ [m][dict(type, params)]
32
+ where m - node number,
33
+ type - distribution type, params - distribution parameters.
34
+ """
35
+ self.arrival_time = arrival_rate
36
+ self.R = R
37
+ self.n_num = len(n) # number of nodes
38
+ self.nodes = n # n[i] - number of channels in node i
39
+
40
+ self.serv_params = serv_params
41
+
42
+ self.qs = []
43
+
44
+ for m in range(self.n_num):
45
+ self.qs.append(QsSim(n[m]))
46
+ self.qs[m].set_servers(serv_params[m]['params'], kendall_notation=serv_params[m]['type'])
47
+
48
+ self.source = ExpDistribution(self.arrival_time)
49
+ self.arrival_time = self.source.generate()
50
+ self.v_network = [0.0] * 3
51
+ self.w_network = [0.0] * 3
52
+
53
+ self.ttek = 0
54
+ self.total = 0
55
+ self.served = 0
56
+ self.in_sys = 0
57
+ self.arrived = 0
58
+
59
+ def choose_next_node(self, current_node):
60
+ """
61
+ Choose the next node for a task based on the current node
62
+ :param current_node: The current node of the task.
63
+ :return: The index of the next node.
64
+ """
65
+ sum_p = 0
66
+ p = np.random.rand()
67
+ for i in range(self.R.shape[0]):
68
+ sum_p += self.R[current_node + 1, i]
69
+ if sum_p > p:
70
+ return i
71
+ return 0
72
+
73
+ def refresh_v_stat(self, new_a):
74
+ """
75
+ Refresh sojourn time statistics
76
+ :param new_a: The new arrival time.
77
+ """
78
+ factor = (1.0 - (1.0 / self.served))
79
+ a_pow = [math.pow(new_a, i + 1) for i in range(3)]
80
+ for i in range(3):
81
+ self.v_network[i] = self.v_network[i] * \
82
+ factor + a_pow[i] / self.served
83
+
84
+ def refresh_w_stat(self, new_a):
85
+ """
86
+ Refresh waiting time statistics
87
+ :param new_a: The new arrival time.
88
+
89
+ """
90
+ factor = (1.0 - (1.0 / self.served))
91
+ a_pow = [math.pow(new_a, i + 1) for i in range(3)]
92
+ for i in range(3):
93
+ self.w_network[i] = self.w_network[i] * \
94
+ factor + a_pow[i] / self.served
95
+
96
+ def run_one_step(self):
97
+ """
98
+ Run one step of the simulation.
99
+ """
100
+ num_of_serv_ch_earlier = -1 # номер канала узла, мин время до окончания обслуживания
101
+ num_of_node_earlier = -1 # номер узла, в котором раньше всех закончится обслуживание
102
+ arrival_earlier = 1e10 # момент прибытия ближайшего
103
+ serving_earlier = 1e10 # момент ближайшего обслуживания
104
+
105
+ if self.arrival_time < arrival_earlier:
106
+ arrival_earlier = self.arrival_time
107
+
108
+ for node in range(self.n_num):
109
+ for c in range(self.nodes[node]):
110
+ if self.qs[node].servers[c].time_to_end_service < serving_earlier:
111
+ serving_earlier = self.qs[node].servers[c].time_to_end_service
112
+ num_of_serv_ch_earlier = c
113
+ num_of_node_earlier = node
114
+
115
+ if arrival_earlier < serving_earlier:
116
+ self.on_arrival(arrival_earlier)
117
+ else:
118
+ self.on_serving(serving_earlier,
119
+ num_of_serv_ch_earlier, num_of_node_earlier)
120
+
121
+ def on_arrival(self, arrival_earlier):
122
+ """
123
+ Handle arrival event
124
+ """
125
+ self.ttek = arrival_earlier
126
+ self.arrived += 1
127
+ self.in_sys += 1
128
+
129
+ self.arrival_time = self.ttek + self.source.generate()
130
+
131
+ next_node = self.choose_next_node(-1)
132
+
133
+ ts = Task(self.ttek, is_network=True)
134
+
135
+ self.qs[next_node].arrival(self.ttek, ts)
136
+
137
+ def on_serving(self, serving_earlier, num_of_serv_ch_earlier, num_of_node_earlier):
138
+ """
139
+ Handle serving event
140
+ """
141
+ self.ttek = serving_earlier
142
+ ts = self.qs[num_of_node_earlier].serving(
143
+ num_of_serv_ch_earlier, True)
144
+
145
+ next_node = self.choose_next_node(num_of_node_earlier)
146
+
147
+ if next_node == self.n_num:
148
+ self.served += 1
149
+ self.in_sys -= 1
150
+
151
+ self.refresh_v_stat(self.ttek - ts.arr_network)
152
+ self.refresh_w_stat(ts.wait_network)
153
+
154
+ else:
155
+ self.qs[next_node].arrival(self.ttek, ts)
156
+
157
+ def run(self, job_served, is_real_served=True):
158
+ """
159
+ Run simulation
160
+ """
161
+ if is_real_served:
162
+ last_percent = 0
163
+
164
+ with tqdm(total=100) as pbar:
165
+ while self.served < job_served:
166
+ self.run_one_step()
167
+ percent = int(100*(self.served/job_served))
168
+ if last_percent != percent:
169
+ last_percent = percent
170
+ pbar.update(1)
171
+ pbar.set_description(Fore.MAGENTA + '\rJob served: ' +
172
+ Fore.YELLOW + f'{self.served}/{job_served}' + Fore.LIGHTGREEN_EX)
173
+ else:
174
+ print(Fore.GREEN + '\rStart simulation')
175
+ print(Style.RESET_ALL)
176
+
177
+ for _ in tqdm(range(job_served)):
178
+ self.run_one_step()
179
+
180
+ print(Fore.GREEN + '\rSimulation is finished')
181
+ print(Style.RESET_ALL)
@@ -60,12 +60,9 @@ class PriorityQueueSimulator:
60
60
 
61
61
  # probability of states of the system (number of requests in it j):
62
62
  self.p = []
63
- if self.prty_type == "No":
64
- # for no priority system, we have one queue for all classes of requests:
65
- self.queue = [] # queue of Task's
66
- else:
67
- for _ in range(self.k):
68
- self.queue.append([])
63
+
64
+ for _ in range(self.k):
65
+ self.queue.append([])
69
66
 
70
67
  for _ in range(self.k):
71
68
  self.busy.append([0, 0, 0])
@@ -369,12 +366,12 @@ class PriorityQueueSimulator:
369
366
  """
370
367
  if not self.buffer: # no buffer, infinite queue length
371
368
  new_tsk.start_waiting_time = self.ttek
372
- self.queue.append(new_tsk)
369
+ self.queue[k].append(new_tsk)
373
370
  else:
374
371
 
375
372
  if len(self.queue) < self.buffer:
376
373
  new_tsk.start_waiting_time = self.ttek
377
- self.queue.append(new_tsk)
374
+ self.queue[k].append(new_tsk)
378
375
  else:
379
376
  self.dropped[k] += 1
380
377
  self.in_sys[k] -= 1
@@ -473,13 +470,14 @@ class PriorityQueueSimulator:
473
470
  self.refresh_w_stat(k, end_ts.wait_time)
474
471
  self.in_sys[k] -= 1
475
472
 
476
- if len(self.queue[k]) == 0 and self.free_channels == 1:
477
- if self.in_sys[k] == self.n - 1 and self.class_busy_started != -1:
478
- # End of busy period
479
- self.busy_moments[k] += 1
480
- self.refresh_busy_stat(k, self.ttek - self.start_busy)
481
473
 
482
474
  if self.prty_type != "No":
475
+ if len(self.queue[k]) == 0 and self.free_channels == 1:
476
+ if self.in_sys[k] == self.n - 1 and self.class_busy_started != -1:
477
+ # End of busy period
478
+ self.busy_moments[k] += 1
479
+ self.refresh_busy_stat(k, self.ttek - self.start_busy)
480
+
483
481
 
484
482
  start_number = 0
485
483
  if self.prty_type == "PR" or self.prty_type == "RS" or self.prty_type == "RW":
@@ -507,10 +505,15 @@ class PriorityQueueSimulator:
507
505
  self.free_channels -= 1
508
506
  break
509
507
  else:
508
+ if len(self.queue[0]) == 0 and self.free_channels == 1:
509
+ if self.in_sys == self.n - 1 and self.class_busy_started != -1:
510
+ # End of busy period
511
+ self.busy_moments += 1
512
+ self.refresh_busy_stat(0, self.ttek - self.start_busy)
510
513
  # one queue
511
- if len(self.queue) != 0:
514
+ if len(self.queue[0]) != 0:
512
515
 
513
- que_ts = self.queue.pop(0)
516
+ que_ts = self.queue[0].pop(0)
514
517
 
515
518
  if self.free_channels == 1 and k != end_ts.k:
516
519
  self.start_busy[k] = self.ttek