LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
qsys_gig1_bnds_extremal.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_GIG1_BNDS_EXTREMAL_H
6
#define LINE_API_QSYS_GIG1_BNDS_EXTREMAL_H
7
8
/**
9
* @file
10
* @ingroup api_qsys
11
* Extremal two-moment bounds for the GI/GI/1 queue.
12
*
13
* Templated port of matlab/src/api/qsys/qsys_gig1_bnds_extremal.m, cross-checked
14
* against jar/src/main/java/jline/api/qsys/Qsys_gig1_bnds_extremal.java.
15
*
16
* Two moments do not determine E[W]; they determine a SET of possible values,
17
* and the width of that set is the honest uncertainty in any two-moment
18
* approximation. The ends are attained by extremal laws:
19
*
20
* lower D(1) interarrivals and a three-point service law on multiples of it,
21
* E[W] = rho((1+cs^2)rho - 1)^+ / (2(1-rho)) (2.12)
22
* upper two-point laws: an interarrival atom at 0, and a service law whose
23
* upper atom runs to infinity as its probability vanishes (3.2)
24
*
25
* Making an interarrival time larger only empties the queue once, but making a
26
* service time larger delays every customer behind it, which is why the two ends
27
* look so different. The upper end reduces to a D(1/p)/RS(D(rho),p)/1 model with
28
* p = 1/(1+ca^2), whose mean wait is evaluated by Spitzer's identity
29
* sum_n E[Sn^+]/n with Sn = rho(NB(n,1-p)+n) - n/p (Algorithm 1). The closed
30
* form (3.4) uses the D/M/1 root delta = exp(-(1-delta)/rho) and is within about
31
* 1% of it.
32
*
33
* ARITHMETIC. The tight bound is a truncated infinite sum and delta comes out of
34
* a bisection, so nothing here is exact; the instantiation is restricted to the
35
* transcendental types.
36
*
37
* PARITY. All four codebases form the negative binomial pmf in LOG space,
38
* log P(NB(n,1-p)=k) = lgamma(n+k) - lgamma(k+1) - lgamma(n)
39
* + n log p + k log(1-p),
40
* from one precomputed table of log-gammas, rather than by the ratio recursion
41
* Algorithm 1 prints. The two are equivalent, but the recursion accumulates
42
* rounding over thousands of multiplications and would leave the ports agreeing
43
* only to about 1e-4.
44
*
45
* Reference: Y. Chen, W. Whitt (2020). Algorithms for the upper bound mean
46
* waiting time in the GI/GI/1 queue. Queueing Systems 94, 327-356.
47
*/
48
49
#include <cmath>
50
#include <cstddef>
51
#include <vector>
52
53
#include "
line/api/qsys/qsys_types.h
"
54
#include "
line/num/number.h
"
55
#include "
line/util/error.h
"
56
57
namespace
line
{
58
namespace
qsys
{
59
60
/** The bounds, all as TIMES IN QUEUE: add 1/mu for a response time. */
61
template
<
class
T>
62
struct
Gig1ExtremalResult
{
63
T
trafficIntensity
;
///< rho = lambda/mu
64
T
lowerBound
;
///< the tight lower bound, eq. (2.12)
65
T
upperBound
;
///< the conjectured tight upper bound, eq. (3.2)
66
T
upperBoundClosed
;
///< the closed-form upper bound, eq. (3.4)
67
T
upperBoundDaley
;
///< Daley's bound, eq. (2.7)
68
T
upperBoundKingman
;
///< Kingman's bound, eq. (2.6)
69
T
heavyTraffic
;
///< the heavy-traffic approximation, eq. (2.9)
70
T
delta
;
///< the D/M/1 root behind upperBoundClosed
71
T
relativeWidth
;
///< (upper-lower)/upper, what two moments leave undetermined
72
bool
tightComputed
;
///< whether the O(K*N) bound was evaluated
73
};
74
75
namespace
detail {
76
77
/**
78
* The D/M/1 root of eq. (3.5), delta = exp(-(1-delta)/rho), in (0,1).
79
*
80
* g(delta) = delta - exp(-(1-delta)/rho) is negative at 0 and positive just
81
* below 1, where the second root delta = 1 sits, so bisection on [0,1) finds the
82
* wanted root without landing on the trivial one.
83
*/
84
template
<
class
T>
85
T extremal_delta(
const
T& rho) {
86
using
std::exp;
87
const
T two =
num_traits<T>::from_int
(2);
88
T lo =
num_traits<T>::from_int
(0);
89
T hi =
num_traits<T>::from_int
(1) -
num_traits<T>::from_double
(1e-15);
90
for
(
int
i = 0; i < 200; ++i) {
91
const
T mid = (lo + hi) / two;
92
if
(mid - exp(-(
num_traits<T>::from_int
(1) - mid) / rho) <
num_traits<T>::from_int
(0)) {
93
lo = mid;
94
}
else
{
95
hi = mid;
96
}
97
}
98
return
(lo + hi) / two;
99
}
100
101
/** Algorithm 1: the mean waiting time of the extremal model, by the log pmf. */
102
template
<
class
T>
103
T extremal_tight(
const
T& rho,
const
T& ca2,
const
T& cs2, std::size_t K, std::size_t N) {
104
using
std::exp;
105
using
std::lgamma;
106
using
std::log;
107
using
std::log1p;
108
const
T zero =
num_traits<T>::from_int
(0);
109
const
T one =
num_traits<T>::from_int
(1);
110
const
T two =
num_traits<T>::from_int
(2);
111
const
T p = one / (one + ca2);
112
const
T logp = log(p);
113
const
T log1mp = log1p(-p);
114
std::vector<T> lg(N + K + 2, zero);
115
for
(std::size_t i = 1; i < lg.size(); ++i)
116
lg[i] = lgamma(
num_traits<T>::from_int
(
static_cast<
long
>
(i)));
117
T total = rho * ca2 + rho * rho * cs2 / (two * (one - rho));
118
for
(std::size_t k = 1; k <= K; ++k) {
119
T s = zero;
120
for
(std::size_t n = 1; n <= N; ++n) {
121
const
T nT =
num_traits<T>::from_int
(
static_cast<
long
>
(n));
122
const
T step =
num_traits<T>::from_int
(
static_cast<
long
>
(n + k)) * rho - nT / p;
123
if
(step > zero) {
124
const
T lpmf = lg[n + k] - lg[k + 1] - lg[n] + nT * logp +
125
num_traits<T>::from_int
(
static_cast<
long
>
(k)) * log1mp;
126
s += exp(lpmf) * step / nT;
127
}
128
}
129
total += s;
130
}
131
return
total;
132
}
133
134
}
// namespace detail
135
136
/**
137
* @brief Extremal two-moment bounds for the GI/GI/1 queue.
138
*
139
* @param lambda arrival rate
140
* @param mu service rate
141
* @param ca coefficient of variation of the interarrival time
142
* @param cs coefficient of variation of the service time
143
* @param K truncation of the negative binomial value
144
* @param N truncation of the random-walk length
145
* @param skipTight skip the O(K*N) tight bound and return the closed forms only
146
*/
147
template
<
class
T>
148
Gig1ExtremalResult<T>
qsys_gig1_bnds_extremal
(
const
T& lambda,
const
T& mu,
const
T& ca,
149
const
T& cs, std::size_t K = 4000,
150
std::size_t N = 2000,
bool
skipTight =
false
) {
151
static_assert
(
num_traits<T>::has_transcendental
,
152
"qsys_gig1_bnds_extremal truncates an infinite sum, so it needs inexact arithmetic"
);
153
const
T zero =
num_traits<T>::from_int
(0);
154
const
T one =
num_traits<T>::from_int
(1);
155
const
T two =
num_traits<T>::from_int
(2);
156
if
(lambda <= zero || mu <= zero)
157
throw
InputError
(
"qsys_gig1_bnds_extremal: the arrival and service rates must be positive"
);
158
const
T rho = lambda / mu;
159
if
(rho >= one)
160
throw
InputError
(
"qsys_gig1_bnds_extremal: the bounds require a stable queue, rho < 1"
);
161
const
T ca2 = ca * ca;
162
const
T cs2 = cs * cs;
163
// The reference sets E[U] = 1, so every waiting time carries the factor
164
// 1/lambda, that time unit expressed in the caller's units.
165
const
T scale = one / lambda;
166
167
Gig1ExtremalResult<T>
r;
168
r.
trafficIntensity
= rho;
169
const
T lowNum = (one + cs2) * rho - one;
170
r.
lowerBound
= scale * rho * (lowNum > zero ? lowNum : zero) / (two * (one - rho));
171
r.
upperBoundKingman
= scale * rho * rho * (ca2 / (rho * rho) + cs2) / (two * (one - rho));
172
r.
upperBoundDaley
=
173
scale * rho * rho * ((two - rho) * ca2 / rho + cs2) / (two * (one - rho));
174
r.
heavyTraffic
= scale * rho * rho * (ca2 + cs2) / (two * (one - rho));
175
r.
delta
= detail::extremal_delta(rho);
176
r.
upperBoundClosed
=
177
scale * (two * (one - rho) * rho / (one - r.
delta
) * ca2 + rho * rho * cs2) /
178
(two * (one - rho));
179
if
(skipTight) {
180
r.
upperBound
= r.
upperBoundClosed
;
181
r.
tightComputed
=
false
;
182
}
else
{
183
r.
upperBound
= scale * detail::extremal_tight(rho, ca2, cs2, K, N);
184
r.
tightComputed
=
true
;
185
}
186
r.
relativeWidth
= r.
upperBound
> zero ? T((r.
upperBound
- r.
lowerBound
) / r.
upperBound
) : zero;
187
return
r;
188
}
189
190
}
// namespace qsys
191
}
// namespace line
192
193
#endif
// LINE_API_QSYS_GIG1_BNDS_EXTREMAL_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
error.h
The exception types the port throws.
line::qsys
Definition
qsys_bmapm1.h:58
line::qsys::qsys_gig1_bnds_extremal
Gig1ExtremalResult< T > qsys_gig1_bnds_extremal(const T &lambda, const T &mu, const T &ca, const T &cs, std::size_t K=4000, std::size_t N=2000, bool skipTight=false)
Extremal two-moment bounds for the GI/GI/1 queue.
Definition
qsys_gig1_bnds_extremal.h:148
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
qsys_types.h
Shared return type and arithmetic helpers for the templated qsys port.
line::num_traits
Definition
number.h:111
line::qsys::Gig1ExtremalResult
The bounds, all as TIMES IN QUEUE: add 1/mu for a response time.
Definition
qsys_gig1_bnds_extremal.h:62
line::qsys::Gig1ExtremalResult::upperBoundClosed
T upperBoundClosed
the closed-form upper bound, eq. (3.4)
Definition
qsys_gig1_bnds_extremal.h:66
line::qsys::Gig1ExtremalResult::upperBoundKingman
T upperBoundKingman
Kingman's bound, eq. (2.6).
Definition
qsys_gig1_bnds_extremal.h:68
line::qsys::Gig1ExtremalResult::upperBoundDaley
T upperBoundDaley
Daley's bound, eq. (2.7).
Definition
qsys_gig1_bnds_extremal.h:67
line::qsys::Gig1ExtremalResult::delta
T delta
the D/M/1 root behind upperBoundClosed
Definition
qsys_gig1_bnds_extremal.h:70
line::qsys::Gig1ExtremalResult::trafficIntensity
T trafficIntensity
rho = lambda/mu
Definition
qsys_gig1_bnds_extremal.h:63
line::qsys::Gig1ExtremalResult::heavyTraffic
T heavyTraffic
the heavy-traffic approximation, eq. (2.9)
Definition
qsys_gig1_bnds_extremal.h:69
line::qsys::Gig1ExtremalResult::upperBound
T upperBound
the conjectured tight upper bound, eq. (3.2)
Definition
qsys_gig1_bnds_extremal.h:65
line::qsys::Gig1ExtremalResult::relativeWidth
T relativeWidth
(upper-lower)/upper, what two moments leave undetermined
Definition
qsys_gig1_bnds_extremal.h:71
line::qsys::Gig1ExtremalResult::tightComputed
bool tightComputed
whether the O(K*N) bound was evaluated
Definition
qsys_gig1_bnds_extremal.h:72
line::qsys::Gig1ExtremalResult::lowerBound
T lowerBound
the tight lower bound, eq. (2.12)
Definition
qsys_gig1_bnds_extremal.h:64
include
line
api
qsys
qsys_gig1_bnds_extremal.h
Generated by
1.18.0