LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
qsys_mg1_prio_pr.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_QSYS_QSYS_MG1_PRIO_PR_H
6#define LINE_API_QSYS_QSYS_MG1_PRIO_PR_H
7
8/**
9 * @file
10 * @ingroup api_qsys
11 * M/G/1 with preemptive-resume priorities: per-class mean (and optionally
12 * variance of the) response time.
13 *
14 * Port of matlab/src/api/qsys/qsys_mg1_prio_pr.m. Class 1 is the highest
15 * priority. With sigma_i = sum_{j<=i} rho_j and M2_i = sum_{j<=i} lambda_j E[S_j^2],
16 *
17 * W_i = E[S_i]/(1 - sigma_{i-1}) + M2_i / (2 (1 - sigma_{i-1})(1 - sigma_i)),
18 *
19 * and, given third moments, the variance of Takagi (1991) Sec. 3.5. The
20 * returned rho is the qsys family's Q/(1+Q) with Q = sum_i lambda_i W_i.
21 *
22 * ARITHMETIC: field; exact for T = Rational.
23 */
24
25#include <cstddef>
26#include <vector>
27
29#include "line/num/number.h"
30#include "line/util/error.h"
31
32namespace line {
33namespace qsys {
34
35/** MATLAB's [W, rho, res] outputs. */
36template <class T>
38 std::vector<T> W; ///< per-class mean response time, class 1 first
39 T rho; ///< Q/(1+Q)
40 QsysResT<T> res; ///< meanSojournTime, meanWaitingTime, meanQueueLength, utilization[, varSojournTime], analyzer
41};
42
43/**
44 * @brief M/G/1 with preemptive-resume priorities.
45 *
46 * @param lambda per-class arrival rates, highest priority first
47 * @param mu per-class service rates
48 * @param cs per-class coefficients of variation of the service time
49 * @param ES3 per-class third moments of the service time (MATLAB's 'ES3'
50 * option); empty when not given
51 */
52template <class T>
53Mg1PrioPrResult<T> qsys_mg1_prio_pr(const std::vector<T>& lambda, const std::vector<T>& mu,
54 const std::vector<T>& cs, const std::vector<T>& ES3 = std::vector<T>()) {
55 const std::size_t R = lambda.size();
56 if (mu.size() != R || cs.size() != R)
57 throw InputError(ErrorKind("Argument"), "qsys_mg1_prio_pr: lambda, mu and cs must have the same length");
58 const T zero = num_traits<T>::from_int(0), one = num_traits<T>::from_int(1);
59 const T two = num_traits<T>::from_int(2), three = num_traits<T>::from_int(3), four = num_traits<T>::from_int(4);
60 for (std::size_t i = 0; i < R; ++i)
61 if (lambda[i] <= zero || mu[i] <= zero || cs[i] < zero)
62 throw InputError(ErrorKind("Argument"),
63 "qsys_mg1_prio_pr: lambda and mu must be positive and cs non-negative");
64 std::vector<T> ES(R), ES2(R), rho_i(R);
65 T rhoSum = zero;
66 for (std::size_t i = 0; i < R; ++i) {
67 ES[i] = T(one / mu[i]);
68 ES2[i] = T((one + cs[i] * cs[i]) / (mu[i] * mu[i]));
69 rho_i[i] = T(lambda[i] * ES[i]);
70 rhoSum += rho_i[i];
71 }
72 if (rhoSum >= one) resdetail::throw_unstable("qsys_mg1_prio_pr", "rho", num_traits<T>::to_double(rhoSum));
73 std::vector<T> sig(R + 1, zero), M2(R + 1, zero); // sig[i] = sigma_{i-1} in 1-based terms
74 for (std::size_t i = 0; i < R; ++i) {
75 sig[i + 1] = T(sig[i] + rho_i[i]);
76 M2[i + 1] = T(M2[i] + lambda[i] * ES2[i]);
77 }
79 r.W.assign(R, zero);
80 T Q = zero;
81 for (std::size_t i = 0; i < R; ++i) {
82 r.W[i] = T(ES[i] / (one - sig[i]) + M2[i + 1] / (two * (one - sig[i]) * (one - sig[i + 1])));
83 Q += T(lambda[i] * r.W[i]);
84 }
85 r.rho = T(Q / (one + Q));
86 std::vector<T> Wq(R), Qi(R);
87 for (std::size_t i = 0; i < R; ++i) {
88 Wq[i] = T(r.W[i] - ES[i]);
89 Qi[i] = T(lambda[i] * r.W[i]);
90 }
91 r.res.set("meanSojournTime", r.W);
92 r.res.set("meanWaitingTime", Wq);
93 r.res.set("meanQueueLength", Qi);
94 r.res.set("utilization", rhoSum);
95 if (!ES3.empty()) {
96 if (ES3.size() != R)
97 throw InputError(ErrorKind("Argument"), "qsys_mg1_prio_pr: ES3 must have one entry per class");
98 std::vector<T> M3(R + 1, zero);
99 for (std::size_t i = 0; i < R; ++i) M3[i + 1] = T(M3[i] + lambda[i] * ES3[i]);
100 std::vector<T> V(R);
101 for (std::size_t i = 0; i < R; ++i) {
102 const T a = T(one - sig[i]), b = T(one - sig[i + 1]);
103 V[i] = T((ES2[i] - ES[i] * ES[i]) / (a * a) + ES[i] * M2[i] / (a * a * a) +
104 M3[i + 1] / (three * a * a * b) + M2[i + 1] * M2[i + 1] / (four * a * a * b * b) +
105 M2[i + 1] * M2[i] / (two * a * a * a * b));
106 }
107 r.res.set("varSojournTime", V);
108 }
109 r.res.analyzer = "exact:M/G/1-prio-pr";
110 return r;
111}
112
113} // namespace qsys
114} // namespace line
115
116#endif // LINE_API_QSYS_QSYS_MG1_PRIO_PR_H
InputError(const std::string &what)
Definition error.h:105
The exception types the port throws.
void throw_unstable(const char *fn, const char *what, double v)
A LINE:input:Unstable refusal "fn: unstable system: <what> = %g >= 1".
Definition qsys_res.h:213
Mg1PrioPrResult< T > qsys_mg1_prio_pr(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs, const std::vector< T > &ES3=std::vector< T >())
M/G/1 with preemptive-resume priorities.
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52
Number-type abstraction for the templated API port.
The res struct the exact queueing-system functions return, and the numeric helpers those functions sh...
ErrorKind(std::string n)
Definition error.h:39
MATLAB's [W, rho, res] outputs.
QsysResT< T > res
meanSojournTime, meanWaitingTime, meanQueueLength, utilization[, varSojournTime], analyzer
std::vector< T > W
per-class mean response time, class 1 first
MATLAB's res struct: named measures in insertion order, plus res.analyzer.
Definition qsys_res.h:57
std::string analyzer
Definition qsys_res.h:59
void set(const std::string &name, const T &v)
Sets (or overwrites) a scalar field.
Definition qsys_res.h:62