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.
- {most_queue-1.60 → most_queue-1.62}/.gitignore +1 -1
- {most_queue-1.60 → most_queue-1.62}/PKG-INFO +8 -5
- {most_queue-1.60 → most_queue-1.62}/README.md +7 -4
- most_queue-1.62/assets/1.gif +0 -0
- most_queue-1.62/assets/2.gif +0 -0
- most_queue-1.62/assets/3.gif +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/general/distribution_params.py +9 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/general/tables.py +2 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/misc/flow_sum.py +3 -3
- {most_queue-1.60 → most_queue-1.62}/most_queue/rand_distribution.py +127 -1
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/base.py +38 -18
- most_queue-1.62/most_queue/sim/networks/network.py +181 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/priority.py +18 -15
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/tasks.py +10 -5
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/ek_d_n.py +1 -1
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/mgn_takahasi.py +61 -1
- most_queue-1.62/most_queue/theory/networks/open_network.py +126 -0
- 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
- most_queue-1.62/most_queue/theory/networks/opt/transition.py +330 -0
- most_queue-1.62/most_queue/theory/networks/opt/transition_approx.py +132 -0
- most_queue-1.62/most_queue/theory/networks/opt/transition_plus.py +162 -0
- most_queue-1.62/most_queue/theory/utils/residual.py +19 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/transforms.py +3 -0
- most_queue-1.62/most_queue/theory/utils/utilization_approx.py +62 -0
- {most_queue-1.60 → most_queue-1.62}/pyproject.toml +1 -1
- {most_queue-1.60 → most_queue-1.62}/setup.py +1 -1
- {most_queue-1.60 → most_queue-1.62}/tests/cold_warm_delay_params.yaml +0 -1
- most_queue-1.62/tests/default_params.yaml +35 -0
- {most_queue-1.60 → most_queue-1.62}/tests/test_base_qs_sim.py +26 -8
- {most_queue-1.60 → most_queue-1.62}/tests/test_batch.py +22 -9
- {most_queue-1.60 → most_queue-1.62}/tests/test_ek_d_n.py +27 -10
- {most_queue-1.60 → most_queue-1.62}/tests/test_engset.py +36 -10
- most_queue-1.62/tests/test_fj_delta.py +85 -0
- most_queue-1.60/tests/test_fj_im.py → most_queue-1.62/tests/test_fj_sim.py +45 -28
- {most_queue-1.60 → most_queue-1.62}/tests/test_gi_m_1_calc.py +26 -36
- {most_queue-1.60 → most_queue-1.62}/tests/test_gi_m_n_calc.py +32 -31
- most_queue-1.62/tests/test_impatience.py +68 -0
- {most_queue-1.60 → most_queue-1.62}/tests/test_m_d_n_calc.py +27 -9
- {most_queue-1.60 → most_queue-1.62}/tests/test_m_h2_h2warm.py +41 -18
- {most_queue-1.60 → most_queue-1.62}/tests/test_m_ph_n_prty.py +40 -33
- most_queue-1.62/tests/test_mg1_calc.py +80 -0
- {most_queue-1.60 → most_queue-1.62}/tests/test_mg1_disaster.py +36 -13
- {most_queue-1.60 → most_queue-1.62}/tests/test_mg1_rcs.py +24 -10
- {most_queue-1.60 → most_queue-1.62}/tests/test_mg1_warmup.py +29 -13
- {most_queue-1.60 → most_queue-1.62}/tests/test_mgn_disaster.py +33 -7
- {most_queue-1.60 → most_queue-1.62}/tests/test_mgn_rcs.py +34 -8
- most_queue-1.62/tests/test_mgn_tt.py +118 -0
- 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
- {most_queue-1.60 → most_queue-1.62}/tests/test_mmn_h2cold_h2warm.py +55 -21
- {most_queue-1.60 → most_queue-1.62}/tests/test_mmn_prty_pnz_approx.py +43 -17
- {most_queue-1.60 → most_queue-1.62}/tests/test_network_im_prty.py +44 -21
- most_queue-1.62/tests/test_network_no_prty.py +77 -0
- most_queue-1.62/tests/test_network_opt.py +51 -0
- most_queue-1.62/tests/test_network_opt_approx.py +42 -0
- most_queue-1.62/tests/test_network_opt_plus.py +49 -0
- most_queue-1.62/tests/units/test_tt_up_probs.py +48 -0
- most_queue-1.62/tests/units/test_v1_on_channels.py +54 -0
- most_queue-1.62/tests/units/test_v1_utlization_approx.py +10 -0
- most_queue-1.62/tests/units/test_weibull.py +29 -0
- most_queue-1.62/tests/units/v1_on_channels.png +0 -0
- most_queue-1.62/tests/units/v1_on_utilization_approx.png +0 -0
- {most_queue-1.60 → most_queue-1.62}/tutorials/network_with_priorities.ipynb +17 -17
- {most_queue-1.60 → most_queue-1.62}/tutorials/queue_sim.ipynb +4 -4
- most_queue-1.62/works/negative_queues/__init__.py +0 -0
- most_queue-1.62/works/negative_queues/base_parameters.yaml +21 -0
- most_queue-1.62/works/negative_queues/work_mgn_negatives.py +303 -0
- most_queue-1.62/works/vacations/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/works/vacations/main.py +1 -1
- most_queue-1.60/most_queue/misc/test_weibull.py +0 -37
- most_queue-1.60/most_queue/theory/utils/weibull.py +0 -155
- most_queue-1.60/tests/test_fj_delta.py +0 -66
- most_queue-1.60/tests/test_impatience.py +0 -47
- most_queue-1.60/tests/test_mg1_calc.py +0 -104
- most_queue-1.60/tests/test_mgn_tt.py +0 -94
- most_queue-1.60/tests/test_mmn3_pnz_cox_approx.py +0 -104
- most_queue-1.60/works/negative_queues/work_mgn_disasters.py +0 -358
- most_queue-1.60/works/negative_queues/work_mgn_rcs.py +0 -358
- {most_queue-1.60 → most_queue-1.62}/LICENSE +0 -0
- {most_queue-1.60 → most_queue-1.62}/assets/queue_long.png +0 -0
- {most_queue-1.60 → most_queue-1.62}/deploy.txt +0 -0
- {most_queue-1.60 → most_queue-1.62}/docs/Makefile +0 -0
- {most_queue-1.60 → most_queue-1.62}/docs/make.bat +0 -0
- {most_queue-1.60 → most_queue-1.62}/docs/source/conf.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/docs/source/index.rst +0 -0
- {most_queue-1.60 → most_queue-1.62}/docs/source/modules.rst +0 -0
- {most_queue-1.60 → most_queue-1.62}/docs/source/most_queue.rst +0 -0
- {most_queue-1.60 → most_queue-1.62}/docs/source/most_queue.sim.rst +0 -0
- {most_queue-1.60 → most_queue-1.62}/docs/source/most_queue.theory.rst +0 -0
- {most_queue-1.60 → most_queue-1.62}/googleb31d3dccb40f969f.html +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/general/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/general/interfaces.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/general/plots.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/misc/approx_cdf_make.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/misc/calc_v_pls.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/misc/compare_fj_calc.py +0 -0
- /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
- {most_queue-1.60 → most_queue-1.62}/most_queue/misc/vacations_paper_utils.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/batch.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/finite_source.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/flow_sum.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/fork_join.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/fork_join_delta.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/impatient.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/negative.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/networks/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/networks/priority_network.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/distribution_utils.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/exceptions.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/phase.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/qs_queue.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/servers.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/utils/stats_update.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/sim/vacations.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/batch/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/batch/mm1.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/closed/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/closed/engset.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/gi_m_1.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/gi_m_n.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/m_d_n.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/mg1.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fifo/mmnr.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fork_join/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fork_join/m_m_n.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/fork_join/split_join.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/impatience/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/impatience/mm1.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/mg1_disasters.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/mg1_rcs.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/mgn_disaster.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/mgn_rcs.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/negative/structs.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/networks/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/networks/network_viewer.py +0 -0
- {most_queue-1.60/most_queue/theory/priority → most_queue-1.62/most_queue/theory/networks/opt}/__init__.py +0 -0
- {most_queue-1.60/most_queue/theory/priority/non_preemptive → most_queue-1.62/most_queue/theory/priority}/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/mgn_invar_approx.py +0 -0
- {most_queue-1.60/most_queue/theory/priority/preemptive → most_queue-1.62/most_queue/theory/priority/non_preemptive}/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/non_preemptive/mg1.py +0 -0
- {most_queue-1.60/most_queue/theory/utils → most_queue-1.62/most_queue/theory/priority/preemptive}/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/preemptive/m_ph_n_busy_approx.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/preemptive/mg1.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/preemptive/mmn_2cls_pr_busy_approx.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/priority/preemptive/mmn_3cls_busy_approx.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/r_example.gexf +0 -0
- {most_queue-1.60/most_queue/theory/vacations → most_queue-1.62/most_queue/theory/utils}/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/binom_probs.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/busy_periods.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/conditional.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/conv.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/diff5dots.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/flow_sum.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/passage_time.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/q_poisson_arrival_calc.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/utils/student_stat.py +0 -0
- {most_queue-1.60/tests → most_queue-1.62/most_queue/theory/vacations}/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/vacations/m_h2_h2warm.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/vacations/mg1_warm_calc.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/vacations/mgn_with_h2_delay_cold_warm.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/most_queue/theory/vacations/mmn_with_h2_cold_and_h2_warmup.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/requirements.txt +0 -0
- {most_queue-1.60/works → most_queue-1.62/tests}/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/tests/test_qs_sim.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/tests/test_qs_sim_prty.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/tests/units/h2_params_cv_greater_than_exp.png +0 -0
- {most_queue-1.60 → most_queue-1.62}/tests/units/h2_params_cv_less_than_exp.png +0 -0
- {most_queue-1.60 → most_queue-1.62}/tests/units/test_busy_moments_calc.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/tests/units/test_conditionals.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/tests/units/test_h2_params_cv.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/tests/units/test_queue_types.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/tutorials/m_h2_h2warm.ipynb +0 -0
- {most_queue-1.60 → most_queue-1.62}/tutorials/mgn_takahasi_takami.ipynb +0 -0
- {most_queue-1.60 → most_queue-1.62}/tutorials/priority_queue.ipynb +0 -0
- {most_queue-1.60/works/negative_queues → most_queue-1.62/works}/__init__.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/works/vacations/base_parameters.yaml +0 -0
- {most_queue-1.60 → most_queue-1.62}/works/vacations/channels.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/works/vacations/cooling.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/works/vacations/cooling_delay.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/works/vacations/run_one_calc_vs_sim.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/works/vacations/service.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/works/vacations/utilization.py +0 -0
- {most_queue-1.60 → most_queue-1.62}/works/vacations/utils.py +0 -0
- {most_queue-1.60 → 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.
|
|
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
|
-

|
|
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/
|
|
133
|
-
| 2. | M/G/c/Split-Join | Solving for Split-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/
|
|
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. |
|
|
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
|
-

|
|
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/
|
|
92
|
-
| 2. | M/G/c/Split-Join | Solving for Split-Join queueing system | [link](https://github.com/xabarov/most-queue/blob/main/tests/
|
|
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. |
|
|
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
|
"""
|
|
@@ -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
|
-
|
|
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=
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
self.queue
|
|
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
|