most-queue 1.61__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 (184) hide show
  1. {most_queue-1.61 → most_queue-1.62}/PKG-INFO +8 -5
  2. {most_queue-1.61 → most_queue-1.62}/README.md +7 -4
  3. most_queue-1.62/assets/1.gif +0 -0
  4. most_queue-1.62/assets/2.gif +0 -0
  5. most_queue-1.62/assets/3.gif +0 -0
  6. {most_queue-1.61 → most_queue-1.62}/most_queue/general/tables.py +2 -0
  7. {most_queue-1.61 → most_queue-1.62}/most_queue/misc/flow_sum.py +3 -3
  8. {most_queue-1.61 → most_queue-1.62}/most_queue/rand_distribution.py +2 -1
  9. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/base.py +38 -18
  10. most_queue-1.62/most_queue/sim/networks/network.py +181 -0
  11. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/priority.py +18 -15
  12. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/utils/tasks.py +10 -5
  13. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fifo/ek_d_n.py +1 -1
  14. most_queue-1.62/most_queue/theory/networks/open_network.py +126 -0
  15. most_queue-1.61/most_queue/theory/networks/open_network.py → most_queue-1.62/most_queue/theory/networks/open_network_prty.py +1 -1
  16. most_queue-1.62/most_queue/theory/networks/opt/transition.py +330 -0
  17. most_queue-1.62/most_queue/theory/networks/opt/transition_approx.py +132 -0
  18. most_queue-1.62/most_queue/theory/networks/opt/transition_plus.py +162 -0
  19. most_queue-1.62/most_queue/theory/utils/utilization_approx.py +62 -0
  20. {most_queue-1.61 → most_queue-1.62}/pyproject.toml +1 -1
  21. {most_queue-1.61 → most_queue-1.62}/setup.py +1 -1
  22. {most_queue-1.61 → most_queue-1.62}/tests/cold_warm_delay_params.yaml +0 -1
  23. most_queue-1.62/tests/default_params.yaml +35 -0
  24. {most_queue-1.61 → most_queue-1.62}/tests/test_base_qs_sim.py +26 -8
  25. {most_queue-1.61 → most_queue-1.62}/tests/test_batch.py +22 -9
  26. {most_queue-1.61 → most_queue-1.62}/tests/test_ek_d_n.py +27 -10
  27. {most_queue-1.61 → most_queue-1.62}/tests/test_engset.py +36 -10
  28. most_queue-1.62/tests/test_fj_delta.py +85 -0
  29. most_queue-1.61/tests/test_fj_im.py → most_queue-1.62/tests/test_fj_sim.py +45 -28
  30. {most_queue-1.61 → most_queue-1.62}/tests/test_gi_m_1_calc.py +26 -36
  31. {most_queue-1.61 → most_queue-1.62}/tests/test_gi_m_n_calc.py +32 -31
  32. most_queue-1.62/tests/test_impatience.py +68 -0
  33. {most_queue-1.61 → most_queue-1.62}/tests/test_m_d_n_calc.py +27 -9
  34. {most_queue-1.61 → most_queue-1.62}/tests/test_m_h2_h2warm.py +41 -18
  35. {most_queue-1.61 → most_queue-1.62}/tests/test_m_ph_n_prty.py +40 -33
  36. most_queue-1.62/tests/test_mg1_calc.py +80 -0
  37. {most_queue-1.61 → most_queue-1.62}/tests/test_mg1_disaster.py +36 -13
  38. {most_queue-1.61 → most_queue-1.62}/tests/test_mg1_rcs.py +24 -10
  39. {most_queue-1.61 → most_queue-1.62}/tests/test_mg1_warmup.py +29 -13
  40. {most_queue-1.61 → most_queue-1.62}/tests/test_mgn_disaster.py +33 -7
  41. {most_queue-1.61 → most_queue-1.62}/tests/test_mgn_rcs.py +34 -8
  42. most_queue-1.62/tests/test_mgn_tt.py +118 -0
  43. most_queue-1.61/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
  44. {most_queue-1.61 → most_queue-1.62}/tests/test_mmn_h2cold_h2warm.py +55 -21
  45. {most_queue-1.61 → most_queue-1.62}/tests/test_mmn_prty_pnz_approx.py +43 -17
  46. {most_queue-1.61 → most_queue-1.62}/tests/test_network_im_prty.py +44 -21
  47. most_queue-1.62/tests/test_network_no_prty.py +77 -0
  48. most_queue-1.62/tests/test_network_opt.py +51 -0
  49. most_queue-1.62/tests/test_network_opt_approx.py +42 -0
  50. most_queue-1.62/tests/test_network_opt_plus.py +49 -0
  51. most_queue-1.62/tests/units/test_v1_on_channels.py +54 -0
  52. most_queue-1.62/tests/units/test_v1_utlization_approx.py +10 -0
  53. most_queue-1.62/tests/units/v1_on_channels.png +0 -0
  54. most_queue-1.62/tests/units/v1_on_utilization_approx.png +0 -0
  55. {most_queue-1.61 → most_queue-1.62}/tutorials/network_with_priorities.ipynb +17 -17
  56. {most_queue-1.61 → most_queue-1.62}/tutorials/queue_sim.ipynb +3 -3
  57. most_queue-1.62/works/vacations/__init__.py +0 -0
  58. most_queue-1.61/tests/test_fj_delta.py +0 -66
  59. most_queue-1.61/tests/test_impatience.py +0 -47
  60. most_queue-1.61/tests/test_mg1_calc.py +0 -104
  61. most_queue-1.61/tests/test_mgn_tt.py +0 -97
  62. most_queue-1.61/tests/test_mmn3_pnz_cox_approx.py +0 -104
  63. {most_queue-1.61 → most_queue-1.62}/.gitignore +0 -0
  64. {most_queue-1.61 → most_queue-1.62}/LICENSE +0 -0
  65. {most_queue-1.61 → most_queue-1.62}/assets/queue_long.png +0 -0
  66. {most_queue-1.61 → most_queue-1.62}/deploy.txt +0 -0
  67. {most_queue-1.61 → most_queue-1.62}/docs/Makefile +0 -0
  68. {most_queue-1.61 → most_queue-1.62}/docs/make.bat +0 -0
  69. {most_queue-1.61 → most_queue-1.62}/docs/source/conf.py +0 -0
  70. {most_queue-1.61 → most_queue-1.62}/docs/source/index.rst +0 -0
  71. {most_queue-1.61 → most_queue-1.62}/docs/source/modules.rst +0 -0
  72. {most_queue-1.61 → most_queue-1.62}/docs/source/most_queue.rst +0 -0
  73. {most_queue-1.61 → most_queue-1.62}/docs/source/most_queue.sim.rst +0 -0
  74. {most_queue-1.61 → most_queue-1.62}/docs/source/most_queue.theory.rst +0 -0
  75. {most_queue-1.61 → most_queue-1.62}/googleb31d3dccb40f969f.html +0 -0
  76. {most_queue-1.61 → most_queue-1.62}/most_queue/__init__.py +0 -0
  77. {most_queue-1.61 → most_queue-1.62}/most_queue/general/__init__.py +0 -0
  78. {most_queue-1.61 → most_queue-1.62}/most_queue/general/distribution_params.py +0 -0
  79. {most_queue-1.61 → most_queue-1.62}/most_queue/general/interfaces.py +0 -0
  80. {most_queue-1.61 → most_queue-1.62}/most_queue/general/plots.py +0 -0
  81. {most_queue-1.61 → most_queue-1.62}/most_queue/misc/approx_cdf_make.py +0 -0
  82. {most_queue-1.61 → most_queue-1.62}/most_queue/misc/calc_v_pls.py +0 -0
  83. {most_queue-1.61 → most_queue-1.62}/most_queue/misc/compare_fj_calc.py +0 -0
  84. /most_queue-1.61/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
  85. {most_queue-1.61 → most_queue-1.62}/most_queue/misc/vacations_paper_utils.py +0 -0
  86. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/__init__.py +0 -0
  87. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/batch.py +0 -0
  88. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/finite_source.py +0 -0
  89. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/flow_sum.py +0 -0
  90. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/fork_join.py +0 -0
  91. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/fork_join_delta.py +0 -0
  92. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/impatient.py +0 -0
  93. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/negative.py +0 -0
  94. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/networks/__init__.py +0 -0
  95. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/networks/priority_network.py +0 -0
  96. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/utils/__init__.py +0 -0
  97. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/utils/distribution_utils.py +0 -0
  98. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/utils/exceptions.py +0 -0
  99. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/utils/phase.py +0 -0
  100. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/utils/qs_queue.py +0 -0
  101. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/utils/servers.py +0 -0
  102. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/utils/stats_update.py +0 -0
  103. {most_queue-1.61 → most_queue-1.62}/most_queue/sim/vacations.py +0 -0
  104. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/__init__.py +0 -0
  105. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/batch/__init__.py +0 -0
  106. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/batch/mm1.py +0 -0
  107. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/closed/__init__.py +0 -0
  108. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/closed/engset.py +0 -0
  109. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fifo/__init__.py +0 -0
  110. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fifo/gi_m_1.py +0 -0
  111. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fifo/gi_m_n.py +0 -0
  112. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fifo/m_d_n.py +0 -0
  113. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fifo/mg1.py +0 -0
  114. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fifo/mgn_takahasi.py +0 -0
  115. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fifo/mmnr.py +0 -0
  116. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fork_join/__init__.py +0 -0
  117. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fork_join/m_m_n.py +0 -0
  118. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/fork_join/split_join.py +0 -0
  119. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/impatience/__init__.py +0 -0
  120. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/impatience/mm1.py +0 -0
  121. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/negative/mg1_disasters.py +0 -0
  122. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/negative/mg1_rcs.py +0 -0
  123. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/negative/mgn_disaster.py +0 -0
  124. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/negative/mgn_rcs.py +0 -0
  125. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/negative/structs.py +0 -0
  126. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/networks/__init__.py +0 -0
  127. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/networks/network_viewer.py +0 -0
  128. {most_queue-1.61/most_queue/theory/priority → most_queue-1.62/most_queue/theory/networks/opt}/__init__.py +0 -0
  129. {most_queue-1.61/most_queue/theory/priority/non_preemptive → most_queue-1.62/most_queue/theory/priority}/__init__.py +0 -0
  130. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/priority/mgn_invar_approx.py +0 -0
  131. {most_queue-1.61/most_queue/theory/priority/preemptive → most_queue-1.62/most_queue/theory/priority/non_preemptive}/__init__.py +0 -0
  132. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/priority/non_preemptive/mg1.py +0 -0
  133. {most_queue-1.61/most_queue/theory/utils → most_queue-1.62/most_queue/theory/priority/preemptive}/__init__.py +0 -0
  134. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/priority/preemptive/m_ph_n_busy_approx.py +0 -0
  135. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/priority/preemptive/mg1.py +0 -0
  136. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/priority/preemptive/mmn_2cls_pr_busy_approx.py +0 -0
  137. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/priority/preemptive/mmn_3cls_busy_approx.py +0 -0
  138. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/r_example.gexf +0 -0
  139. {most_queue-1.61/most_queue/theory/vacations → most_queue-1.62/most_queue/theory/utils}/__init__.py +0 -0
  140. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/binom_probs.py +0 -0
  141. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/busy_periods.py +0 -0
  142. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/conditional.py +0 -0
  143. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/conv.py +0 -0
  144. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/diff5dots.py +0 -0
  145. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/flow_sum.py +0 -0
  146. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/passage_time.py +0 -0
  147. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/q_poisson_arrival_calc.py +0 -0
  148. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/residual.py +0 -0
  149. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/student_stat.py +0 -0
  150. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/utils/transforms.py +0 -0
  151. {most_queue-1.61/tests → most_queue-1.62/most_queue/theory/vacations}/__init__.py +0 -0
  152. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/vacations/m_h2_h2warm.py +0 -0
  153. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/vacations/mg1_warm_calc.py +0 -0
  154. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/vacations/mgn_with_h2_delay_cold_warm.py +0 -0
  155. {most_queue-1.61 → most_queue-1.62}/most_queue/theory/vacations/mmn_with_h2_cold_and_h2_warmup.py +0 -0
  156. {most_queue-1.61 → most_queue-1.62}/requirements.txt +0 -0
  157. {most_queue-1.61/works → most_queue-1.62/tests}/__init__.py +0 -0
  158. {most_queue-1.61 → most_queue-1.62}/tests/test_qs_sim.py +0 -0
  159. {most_queue-1.61 → most_queue-1.62}/tests/test_qs_sim_prty.py +0 -0
  160. {most_queue-1.61 → most_queue-1.62}/tests/units/h2_params_cv_greater_than_exp.png +0 -0
  161. {most_queue-1.61 → most_queue-1.62}/tests/units/h2_params_cv_less_than_exp.png +0 -0
  162. {most_queue-1.61 → most_queue-1.62}/tests/units/test_busy_moments_calc.py +0 -0
  163. {most_queue-1.61 → most_queue-1.62}/tests/units/test_conditionals.py +0 -0
  164. {most_queue-1.61 → most_queue-1.62}/tests/units/test_h2_params_cv.py +0 -0
  165. {most_queue-1.61 → most_queue-1.62}/tests/units/test_queue_types.py +0 -0
  166. {most_queue-1.61 → most_queue-1.62}/tests/units/test_tt_up_probs.py +0 -0
  167. {most_queue-1.61 → most_queue-1.62}/tests/units/test_weibull.py +0 -0
  168. {most_queue-1.61 → most_queue-1.62}/tutorials/m_h2_h2warm.ipynb +0 -0
  169. {most_queue-1.61 → most_queue-1.62}/tutorials/mgn_takahasi_takami.ipynb +0 -0
  170. {most_queue-1.61 → most_queue-1.62}/tutorials/priority_queue.ipynb +0 -0
  171. {most_queue-1.61/works/negative_queues → most_queue-1.62/works}/__init__.py +0 -0
  172. {most_queue-1.61/works/vacations → most_queue-1.62/works/negative_queues}/__init__.py +0 -0
  173. {most_queue-1.61 → most_queue-1.62}/works/negative_queues/base_parameters.yaml +0 -0
  174. {most_queue-1.61 → most_queue-1.62}/works/negative_queues/work_mgn_negatives.py +0 -0
  175. {most_queue-1.61 → most_queue-1.62}/works/vacations/base_parameters.yaml +0 -0
  176. {most_queue-1.61 → most_queue-1.62}/works/vacations/channels.py +0 -0
  177. {most_queue-1.61 → most_queue-1.62}/works/vacations/cooling.py +0 -0
  178. {most_queue-1.61 → most_queue-1.62}/works/vacations/cooling_delay.py +0 -0
  179. {most_queue-1.61 → most_queue-1.62}/works/vacations/main.py +0 -0
  180. {most_queue-1.61 → most_queue-1.62}/works/vacations/run_one_calc_vs_sim.py +0 -0
  181. {most_queue-1.61 → most_queue-1.62}/works/vacations/service.py +0 -0
  182. {most_queue-1.61 → most_queue-1.62}/works/vacations/utilization.py +0 -0
  183. {most_queue-1.61 → most_queue-1.62}/works/vacations/utils.py +0 -0
  184. {most_queue-1.61 → most_queue-1.62}/works/vacations/warmup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: most_queue
3
- Version: 1.61
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
@@ -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 - номер начального момента
@@ -931,7 +931,8 @@ class ErlangDistribution(Distribution):
931
931
  @staticmethod
932
932
  def get_params_by_mean_and_coev(f1: float, coev: float) -> ErlangParams:
933
933
  """
934
- 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.
935
936
  """
936
937
  f = [0, 0]
937
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
@@ -10,10 +10,15 @@ class Task:
10
10
  """
11
11
  id = 0
12
12
 
13
- def __init__(self, arr_time):
13
+ def __init__(self, arr_time, is_network=False):
14
14
  """
15
15
  :param arr_time: Момент прибытия в СМО
16
16
  """
17
+
18
+ if is_network:
19
+ self.arr_network = arr_time
20
+ self.wait_network = 0
21
+
17
22
  self.arr_time = arr_time
18
23
 
19
24
  self.start_waiting_time = 0
@@ -115,8 +120,8 @@ class ImpatientTask(Task):
115
120
  A task that can leave the queue if it has not been served by a server within a certain time.
116
121
  """
117
122
 
118
- def __init__(self, arr_time, moment_to_leave):
119
- super().__init__(arr_time)
123
+ def __init__(self, arr_time, moment_to_leave, is_network=False):
124
+ super().__init__(arr_time, is_network)
120
125
  self.moment_to_leave = moment_to_leave
121
126
 
122
127
  def __str__(self):
@@ -132,8 +137,8 @@ class ImpatientTaskWithRepairs(ImpatientTask):
132
137
  Tracking if the task arrived in repair mode or not.
133
138
  """
134
139
 
135
- def __init__(self, arr_time, moment_to_leave, arrive_in_repair_mode=False):
136
- super().__init__(arr_time, moment_to_leave)
140
+ def __init__(self, arr_time, moment_to_leave, arrive_in_repair_mode=False, is_network=False):
141
+ super().__init__(arr_time, moment_to_leave, is_network)
137
142
  self.arrive_in_repair_mode = arrive_in_repair_mode
138
143
  self.end_repair_time = 1e16
139
144
  self.is_end_repair = False
@@ -16,7 +16,7 @@ class EkDn:
16
16
 
17
17
  def __init__(self, erlang_params: ErlangParams, b, n, e=1e-12, p_num=100):
18
18
  """
19
- l, k - parameters of the Erlang input request distribution
19
+ erlang_params - parameters of the Erlang input request distribution
20
20
  b - service time in a channel
21
21
  n - number of channels
22
22
  e - accuracy of calculations
@@ -0,0 +1,126 @@
1
+ """
2
+ Calculates queueing network.
3
+ """
4
+ import numpy as np
5
+
6
+ from most_queue.rand_distribution import GammaDistribution
7
+ from most_queue.theory.fifo.mgn_takahasi import MGnCalc
8
+ from most_queue.theory.fifo.mmnr import MMnrCalc
9
+ from most_queue.theory.utils.diff5dots import diff5dots
10
+ from most_queue.theory.utils.transforms import lst_gamma
11
+
12
+
13
+ class OpenNetworkCalc:
14
+ """
15
+ Calculates queueing network.
16
+ """
17
+
18
+ def __init__(self, R: np.matrix, b: list[list[float]],
19
+ n: list[int], arrival_rate: float):
20
+ """
21
+ R: routing matrix
22
+ b: list of theoretical moments of service time distribution for each node.
23
+ n: list of number of channels in each node.
24
+ L: arrival intensitiy.
25
+ """
26
+ self.R = R
27
+ self.b = b
28
+ self.n = n
29
+ self.arrival_rate = arrival_rate
30
+
31
+ def balance_equation(self, L, R):
32
+ """
33
+ Calc the balance equation for the network.
34
+ """
35
+ # Create copies to avoid modifying original matrices
36
+ L = np.array(L)
37
+ R = np.array(R)
38
+
39
+ # Identify null columns using vectorized operation
40
+ null_mask = np.all(np.abs(R) < 1e-6, axis=0)
41
+ _null_numbers = np.where(null_mask)[0]
42
+
43
+ # Remove null columns and corresponding rows
44
+ R_nonull = R[:, ~null_mask]
45
+ R_nonull = R_nonull[~null_mask, :]
46
+
47
+ n_rows_mod, n_cols_mod = R_nonull.shape
48
+
49
+ # Calculate b and Q matrices using efficient indexing
50
+ if n_rows_mod > 0:
51
+ b = np.dot(L, R_nonull[0, :-1])
52
+ Q = R_nonull[1:, :-1]
53
+ A = np.eye(n_cols_mod - 1) - Q.T
54
+ intensities = np.linalg.solve(A, b)
55
+ else:
56
+ intensities = np.array([], dtype=np.float64)
57
+
58
+ # Create output array with zeros for null columns
59
+ l_out = np.zeros(R.shape[1] - 1, dtype=np.float64)
60
+
61
+ # Fill non-null columns
62
+ _valid_indices = np.arange(len(intensities))
63
+ l_out[~null_mask[:-1]] = intensities.flatten()
64
+
65
+ return l_out
66
+
67
+ def run(self, is_markovian=False):
68
+ """
69
+ Run the simulation and calculate the results.
70
+ """
71
+ res = {}
72
+
73
+ nodes = len(self.n)
74
+ res['loads'] = [0.0] * nodes
75
+ res['v'] = []
76
+
77
+ intensities = self.balance_equation(self.arrival_rate, self.R)
78
+
79
+ res['v_node'] = []
80
+ for i in range(nodes):
81
+ node_arrival_rate = intensities[i]
82
+ b1_node = self.b[i][0]
83
+
84
+ res['loads'][i] = node_arrival_rate * b1_node / self.n[i]
85
+
86
+ if is_markovian:
87
+ mmnr_calc = MMnrCalc(l=node_arrival_rate, mu=1/b1_node, n=self.n[i], r=100)
88
+ res['v_node'].append(mmnr_calc.get_v())
89
+ else:
90
+ mgn_calc = MGnCalc(n=self.n[i], l=node_arrival_rate, b=self.b[i])
91
+ mgn_calc.run()
92
+ res['v_node'].append(mgn_calc.get_v())
93
+
94
+ h = 0.0001
95
+ s = [h * (i + 1) for i in range(4)]
96
+
97
+ I = np.eye(nodes)
98
+ N = np.zeros((nodes, nodes))
99
+ P = self.R[0, :nodes].reshape(1, -1)
100
+ T = self.R[1:, nodes].reshape(-1, 1)
101
+ Q = self.R[1:, :nodes]
102
+
103
+ gamma_mu_alpha = [GammaDistribution.get_params(
104
+ [res['v_node'][i][0], res['v_node'][i][1]]) for i in range(nodes)]
105
+
106
+ g_PLS = []
107
+ for i in range(4):
108
+ N = np.diag([lst_gamma(
109
+ gamma_mu_alpha[j], s[i]) for j in range(nodes)])
110
+
111
+ G = np.dot(N, Q)
112
+ FF = I - G
113
+ F = np.linalg.inv(FF)
114
+ F = np.dot(P, np.dot(F, np.dot(N, T)))
115
+ g_PLS.append(F[0, 0])
116
+
117
+ res['v'] = diff5dots(g_PLS, h)
118
+ res['v'][0] = -res['v'][0]
119
+ res['v'][2] = -res['v'][2]
120
+
121
+ res['intensities'] = intensities
122
+ res['v'] = [float(v) for v in res['v']]
123
+ res['loads'] = [float(l) for l in res['loads']]
124
+
125
+
126
+ return res