LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
qsys_gg1.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_GG1_H
6#define LINE_API_QSYS_QSYS_GG1_H
7
8/**
9 * @file
10 * @ingroup api_qsys
11 * G/G/1 dispatcher: exact where a two-moment description determines the
12 * answer, Allen-Cunneen otherwise.
13 *
14 * Templated port of matlab/src/api/qsys/qsys_gg1.m, cross-checked against
15 * jar/src/main/java/jline/api/qsys/Qsys_gg1.java.
16 *
17 * ca2 = cs2 = 1 -> qsys_mm1 (exact)
18 * ca2 = 1 -> qsys_mg1 with cs = sqrt(cs2) (exact)
19 * cs2 = 1 -> qsys_gm1 at the G/M/1 root (exact)
20 * otherwise -> qsys_gig1_approx_allencunneen (approximation)
21 *
22 * In the G/M/1 branch the interarrival law is fitted from (lambda, ca2) by a
23 * two-moment renewal process -- a balanced-means H2 for ca2 > 1, a Tijms
24 * mixture of Erlang-(j-1)/Erlang-j for ca2 < 1, deterministic below 1e-6 --
25 * and sigma is the root in (0,1) of sigma = A*(mu(1-sigma)) with A* the
26 * interarrival LST. The map T(x) = A*(mu(1-x)) is increasing and the queue
27 * root is its smallest fixed point, so the iterates from sigma_0 = rho
28 * converge monotonically; MATLAB runs at most 100000 of them and stops at an
29 * absolute step below 1e-13, which is reproduced here.
30 *
31 * ARITHMETIC. The fixed point is driven to a tolerance and the deterministic
32 * branch evaluates exp, so the whole function is gated on transcendental
33 * arithmetic. The three exact branches are individually available at Rational
34 * through qsys_mm1, qsys_mg1 and qsys_gm1; only the dispatcher, whose tolerance
35 * test |ca2-1| < 1e-8 is itself inexact, is gated.
36 *
37 * MATLAB-vs-JAR. The JAR returns L, Lq, W, Wq, p0 (and, in a second overload,
38 * a geometric pk) whereas MATLAB returns [W, rhohat]. The W they compute is
39 * the same; the port follows the MATLAB return list, since rhohat is what the
40 * rest of the qsys family consumes.
41 */
42
48#include "line/num/number.h"
49
50namespace line {
51namespace qsys {
52
53namespace detail {
54
55/**
56 * Root in (0,1) of sigma = A*(mu(1-sigma)) for the two-moment fit of the
57 * interarrival LST A*. MATLAB's local qsys_gm1_sigma.
58 */
59template <class T>
60T qsys_gm1_sigma(const T& lambda, const T& mu, const T& ca2) {
61 static_assert(num_traits<T>::has_transcendental,
62 "qsys_gm1_sigma requires transcendental arithmetic");
63 const T one = num_traits<T>::from_int(1);
64 const T two = num_traits<T>::from_int(2);
65 const T tiny = T(num_traits<T>::from_double(1e-6));
66 const T step_tol = T(num_traits<T>::from_double(1e-13));
67
68 unsigned jj = 0;
69 T p = num_traits<T>::from_int(0), nu = num_traits<T>::from_int(0);
70 T p1 = num_traits<T>::from_int(0), l1 = num_traits<T>::from_int(0),
71 l2 = num_traits<T>::from_int(0);
72 if (ca2 >= one) {
73 // hyperexponential H2 with balanced means
74 p1 = (one + num_sqrt(T((ca2 - one) / (ca2 + one)))) / two;
75 l1 = two * p1 * lambda;
76 l2 = two * (one - p1) * lambda;
77 } else if (ca2 >= tiny) {
78 // mixed-Erlang phase-count rationale: see _kb/03-api-layer.md (cpp port notes: qsys)
79 const double inv = 1.0 / num_traits<T>::to_double(ca2);
80 jj = static_cast<unsigned>(std::ceil(inv));
81 if (jj < 1) jj = 1;
82 const T jt = num_traits<T>::from_int(static_cast<long>(jj));
83 p = (jt * ca2 - num_sqrt(T(jt * (one + ca2) - jt * jt * ca2))) / (one + ca2);
84 nu = (jt - p) * lambda;
85 }
86
87 T sigma = lambda / mu;
88 for (unsigned it = 0; it < 100000u; ++it) {
89 const T s = mu * (one - sigma);
90 T signew;
91 if (ca2 < tiny) {
92 signew = num_exp(T(-s / lambda)); // deterministic interarrival times
93 } else if (ca2 < one) {
94 signew = p * num_pow_int(T(nu / (s + nu)), jj - 1) +
95 (one - p) * num_pow_int(T(nu / (s + nu)), jj);
96 } else {
97 signew = p1 * l1 / (s + l1) + (one - p1) * l2 / (s + l2);
98 }
99 const bool done = num_abs(T(signew - sigma)) < step_tol;
100 sigma = signew;
101 if (done) break;
102 }
103 return sigma;
104}
105
106} // namespace detail
107
108/**
109 * @brief G/G/1 dispatcher: exact where a two-moment description determines
110 * the answer, Allen-Cunneen otherwise.
111 *
112 * @param lambda arrival rate
113 * @param mu service rate
114 * @param ca2 squared coefficient of variation of the interarrival time
115 * @param cs2 squared coefficient of variation of the service time
116 */
117template <class T>
118QsysResult<T> qsys_gg1(const T& lambda, const T& mu, const T& ca2, const T& cs2) {
120 "qsys_gg1 requires transcendental arithmetic");
121 const T one = num_traits<T>::from_int(1);
122 const T tol = T(num_traits<T>::from_double(1e-8));
123 const bool ca_markov = num_abs(T(ca2 - one)) < tol;
124 const bool cs_markov = num_abs(T(cs2 - one)) < tol;
125
126 if (ca_markov && cs_markov) return qsys_mm1(lambda, mu);
127 if (ca_markov) return qsys_mg1(lambda, mu, T(detail::num_sqrt(cs2)));
128 if (cs_markov) {
129 const T sigma = detail::qsys_gm1_sigma(lambda, mu, ca2);
130 const T W = qsys_gm1(sigma, mu);
131 return {W, detail::rhohat_from_W(W, lambda)};
132 }
133 return qsys_gig1_approx_allencunneen(lambda, mu, T(detail::num_sqrt(ca2)),
134 T(detail::num_sqrt(cs2)));
135}
136
137} // namespace qsys
138} // namespace line
139
140#endif // LINE_API_QSYS_QSYS_GG1_H
QsysResult< T > qsys_mm1(const T &lambda, const T &mu)
Exact mean response time of the M/M/1 queue.
Definition qsys_mm1.h:35
T qsys_gm1(const T &sigma, const T &mu)
Exact mean response time of the G/M/1 queue.
Definition qsys_gm1.h:40
QsysResult< T > qsys_mg1(const T &lambda, const T &mu, const T &cs)
Exact mean response time of the M/G/1 queue (Pollaczek-Khinchine).
Definition qsys_mg1.h:39
QsysResult< T > qsys_gig1_approx_allencunneen(const T &lambda, const T &mu, const T &ca, const T &cs)
Allen-Cunneen approximation of the mean response time of a G/I/G/1 queue.
QsysResult< T > qsys_gg1(const T &lambda, const T &mu, const T &ca2, const T &cs2)
G/G/1 dispatcher: exact where a two-moment description determines the answer, Allen-Cunneen otherwise...
Definition qsys_gg1.h:118
T num_abs(const T &v)
Definition number.h:172
T num_pow_int(const T &base, unsigned e)
Integer power, valid in any field (no transcendental requirement).
Definition number.h:192
Number-type abstraction for the templated API port.
Allen-Cunneen approximation of the mean response time of a G/I/G/1 queue.
Exact mean response time of the G/M/1 queue.
Exact mean response time of the M/G/1 queue (Pollaczek-Khinchine).
Exact mean response time of the M/M/1 queue.
Shared return type and arithmetic helpers for the templated qsys port.
Return value of the qsys family, mirroring MATLAB's [W,rhohat] and the JAR's Ret.qsys.
Definition qsys_types.h:37