LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
qsys_gigk_approx_whitt.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_GIGK_APPROX_WHITT_H
6
#define LINE_API_QSYS_GIGK_APPROX_WHITT_H
7
8
/**
9
* @file
10
* @ingroup api_qsys
11
* Whitt (1993) approximation for the GI/G/k queue, eqs. (2.16)-(2.25).
12
*
13
* Templated port of matlab/src/api/qsys/qsys_gigk_approx_whitt.m.
14
*
15
* gamma = min(0.24, (1-rho)(k-1)(sqrt(4+5k)-2)/(16 k rho)) (2.17)
16
* phi1 = 1 + gamma (2.16)
17
* phi2 = 1 - 4 gamma (2.18)
18
* phi3 = phi2 exp(-2(1-rho)/(3 rho)) (2.20)
19
* phi4 = min(1, (phi1+phi3)/2) (2.21)
20
* psi = 1 if c2 >= 1 else phi4^(2(1-c2)) (2.22)
21
* phi = psi if ca^2 == cs^2
22
* = 4(ca^2-cs^2)/(4ca^2-3cs^2) phi1 + cs^2/(4ca^2-3cs^2) psi
23
* if ca^2 > cs^2 (2.25)
24
* = (cs^2-ca^2)/(2(ca^2+cs^2)) phi3 + (cs^2+3ca^2)/(2(ca^2+cs^2)) psi
25
* otherwise
26
* Wq = phi c2 Wq(M/M/k), c2 = (ca^2+cs^2)/2 (2.24)
27
*
28
* The equality branch is taken when |ca^2-cs^2| < 1e-12, exactly as in MATLAB
29
* and the JAR, so the port keeps that literal tolerance.
30
*
31
* DIVERGENCE: jar/.../Qsys_gigk_approx_whitt.java names its arguments ca2 and
32
* cs2 and uses them unsquared, i.e. it expects squared coefficients of
33
* variation, whereas MATLAB takes ca, cs and squares them internally. MATLAB
34
* is ground truth, so this port takes ca, cs. The JAR also returns {L,W,Q,U}
35
* instead of [W,rhohat].
36
*
37
* Reference: Whitt, W. (1993). Approximations for the GI/G/m queue.
38
* Production and Operations Management 2(2), 114-161.
39
*
40
* Carries sqrt, exp and a real-valued power, so it requires transcendental
41
* arithmetic and cannot be instantiated at T = Rational.
42
*/
43
44
#include "
line/api/qsys/qsys_mmk.h
"
45
#include "
line/api/qsys/qsys_types.h
"
46
#include "
line/num/number.h
"
47
48
namespace
line
{
49
namespace
qsys
{
50
51
/**
52
* @brief Whitt (1993) approximation for the GI/G/k queue, eqs. (2.16)-(2.25).
53
*
54
* @param lambda arrival rate
55
* @param mu service rate of a single server
56
* @param ca coefficient of variation of the interarrival time
57
* @param cs coefficient of variation of the service time
58
* @param k number of servers, k >= 1
59
*/
60
template
<
class
T>
61
QsysResult<T>
qsys_gigk_approx_whitt
(
const
T& lambda,
const
T& mu,
const
T& ca,
const
T& cs,
62
unsigned
k) {
63
static_assert
(
num_traits<T>::has_transcendental
,
64
"qsys_gigk_approx_whitt requires transcendental arithmetic"
);
65
const
T one =
num_traits<T>::from_int
(1);
66
const
T two =
num_traits<T>::from_int
(2);
67
const
T three =
num_traits<T>::from_int
(3);
68
const
T four =
num_traits<T>::from_int
(4);
69
const
T kT =
num_traits<T>::from_int
(
static_cast<
long
>
(k));
70
const
T ca2 =
num_pow_int
(ca, 2);
71
const
T cs2 =
num_pow_int
(cs, 2);
72
const
T rho = lambda / (kT * mu);
73
74
const
T Wq_mmk =
qsys_mmk
(lambda, mu, k).W - one / mu;
75
76
const
T gamma = detail::num_min(
77
num_traits<T>::from_rational
(6, 25),
78
(one - rho) * (kT - one) *
79
(detail::num_sqrt(T(four +
num_traits<T>::from_int
(5) * kT)) - two) /
80
(
num_traits<T>::from_int
(16) * kT * rho));
81
const
T phi1 = one + gamma;
82
const
T phi2 = one - four * gamma;
83
const
T phi3 = phi2 * detail::num_exp(T(-two * (one - rho) / (three * rho)));
84
const
T phi4 = detail::num_min(one, T((phi1 + phi3) / two));
85
86
const
T c2 = (ca2 + cs2) / two;
87
T psi;
88
if
(c2 >= one) {
89
psi = one;
90
}
else
{
91
psi = detail::num_pow(phi4, T(two * (one - c2)));
92
}
93
94
T phi;
95
if
(
num_abs
(T(ca2 - cs2)) <
num_traits<T>::from_double
(1e-12)) {
96
phi = psi;
97
}
else
if
(ca2 > cs2) {
98
phi = (four * (ca2 - cs2) / (four * ca2 - three * cs2)) * phi1 +
99
(cs2 / (four * ca2 - three * cs2)) * psi;
100
}
else
{
101
phi = ((cs2 - ca2) / (two * (ca2 + cs2))) * phi3 +
102
((cs2 + three * ca2) / (two * (ca2 + cs2))) * psi;
103
}
104
105
const
T Wq = phi * c2 * Wq_mmk;
106
const
T W = Wq + one / mu;
107
return
{W, detail::rhohat_from_W(W, lambda)};
108
}
109
110
}
// namespace qsys
111
}
// namespace line
112
113
#endif
// LINE_API_QSYS_GIGK_APPROX_WHITT_H
line::qsys
Definition
qsys_bmapm1.h:58
line::qsys::qsys_gigk_approx_whitt
QsysResult< T > qsys_gigk_approx_whitt(const T &lambda, const T &mu, const T &ca, const T &cs, unsigned k)
Whitt (1993) approximation for the GI/G/k queue, eqs.
Definition
qsys_gigk_approx_whitt.h:61
line::qsys::qsys_mmk
QsysResult< T > qsys_mmk(const T &lambda, const T &mu, unsigned k)
Exact mean response time of the M/M/k queue (Erlang-C).
Definition
qsys_mmk.h:60
line
Definition
aoi_dist2ph.h:52
line::num_abs
T num_abs(const T &v)
Definition
number.h:172
line::num_pow_int
T num_pow_int(const T &base, unsigned e)
Integer power, valid in any field (no transcendental requirement).
Definition
number.h:192
number.h
Number-type abstraction for the templated API port.
qsys_mmk.h
Exact mean response time of the M/M/k queue (Erlang-C).
qsys_types.h
Shared return type and arithmetic helpers for the templated qsys port.
line::num_traits
Definition
number.h:111
line::qsys::QsysResult
Return value of the qsys family, mirroring MATLAB's [W,rhohat] and the JAR's Ret.qsys.
Definition
qsys_types.h:37
include
line
api
qsys
qsys_gigk_approx_whitt.h
Generated by
1.18.0