LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
polling_qsys_1limited.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_POLLING_POLLING_QSYS_1LIMITED_H
6
#define LINE_API_POLLING_POLLING_QSYS_1LIMITED_H
7
8
/**
9
* @file
10
* @ingroup api_polling
11
* Mean waiting times in polling systems: 1-limited and decrementing service.
12
*
13
* Templated port of matlab/src/api/polling/polling_qsys_1limited.m and
14
* polling_qsys_decrementing.m. The MATLAB versions take MAP descriptors and
15
* reduce them to the first two moments of the arrival, service and switchover
16
* processes; this port takes those moments directly, so the MAP reduction stays
17
* in line::mam (map_lambda, map_mean, map_moment, map_var) and the waiting-time
18
* formula is a pure rational function of the moments. Callers holding MAPs
19
* compose the two.
20
*
21
* Both formulas stay in the field, so a polling system with rational parameters
22
* has an exactly representable mean waiting time. Worth having: the denominator
23
* 1 - rho - lambda R vanishes at the stability boundary, and near it a rounded
24
* evaluation can return a finite but meaningless number where the exact one
25
* shows the pole.
26
*/
27
28
#include <cstddef>
29
#include <limits>
30
#include <vector>
31
32
#include "
line/num/number.h
"
33
#include "
line/util/error.h
"
34
35
namespace
line
{
36
namespace
polling
{
37
38
/**
39
* Per-queue first two moments of the arrival, service and switchover
40
* processes, the reduced form both formulas consume.
41
*/
42
template
<
class
T>
43
struct
PollingMoments
{
44
std::vector<T>
lambda
;
///< arrival rate per queue
45
std::vector<T>
b
;
///< mean service time per queue
46
std::vector<T>
b2
;
///< second raw moment of the service time
47
std::vector<T>
r
;
///< mean switchover time per queue
48
std::vector<T>
delta2
;
///< variance of the switchover time per queue
49
50
std::size_t
size
()
const
{
return
lambda
.size(); }
51
void
validate
(
const
char
* who)
const
{
52
if
(
lambda
.empty())
throw
InputError
(std::string(who) +
": empty system"
);
53
if
(
b
.size() !=
lambda
.size() ||
b2
.size() !=
lambda
.size() ||
54
r
.size() !=
lambda
.size() ||
delta2
.size() !=
lambda
.size())
55
throw
InputError
(std::string(who) +
": moment vectors have different lengths"
);
56
}
57
};
58
59
/**
60
* 1-limited polling: one job served per visit.
61
*
62
* W_i = (1-rho+rho_i)/(1-rho-lambda_i R) * (1-rho)/((1-rho)rho + sum rho_j^2)
63
* * (rho/(2(1-rho)) sum_j lambda_j b2_j + rho sum_j delta2_j/(2R)
64
* + R/(2(1-rho)) rho_i (1+rho_i))
65
*/
66
template
<
class
T>
67
std::vector<T>
polling_qsys_1limited
(
const
PollingMoments<T>
& m) {
68
m.
validate
(
"polling_qsys_1limited"
);
69
const
std::size_t n = m.
size
();
70
const
T zero =
num_traits<T>::from_int
(0), one =
num_traits<T>::from_int
(1);
71
const
T two =
num_traits<T>::from_int
(2);
72
73
std::vector<T> rho1(n);
74
T rho = zero, R = zero, sumLb2 = zero, sumDelta2 = zero, sumRho2 = zero;
75
for
(std::size_t i = 0; i < n; ++i) {
76
rho1[i] = m.
lambda
[i] * m.
b
[i];
77
rho += rho1[i];
78
R += m.
r
[i];
79
sumLb2 += m.
lambda
[i] * m.
b2
[i];
80
sumDelta2 += m.
delta2
[i];
81
sumRho2 += rho1[i] * rho1[i];
82
}
83
if
(rho >= one)
throw
NumericError
(
"polling_qsys_1limited: unstable system, rho >= 1"
);
84
if
(R == zero)
throw
InputError
(
"polling_qsys_1limited: zero total switchover time"
);
85
86
const
T den2 = (one - rho) * rho + sumRho2;
87
if
(den2 == zero)
throw
NumericError
(
"polling_qsys_1limited: degenerate load configuration"
);
88
89
std::vector<T> W(n);
90
for
(std::size_t i = 0; i < n; ++i) {
91
const
T den1 = one - rho - m.
lambda
[i] * R;
92
// AT THE POLE THE ANSWER IS INFINITE, NOT UNAVAILABLE. Queue i is stable
93
// under 1-limited service while rho + lambda_i R < 1; on the boundary its
94
// mean waiting time diverges, and polling_qsys_1limited.m divides through
95
// and returns Inf rather than erroring. Refusing here turned a model the
96
// reference answers into a failed solve (polling_klimited, whose second
97
// class sits exactly on the boundary). An exact field has no infinity, so
98
// there the pole is still reported rather than misrepresented as a number.
99
if
(den1 == zero) {
100
if
constexpr
(
num_traits<T>::is_exact
) {
101
throw
NumericError
(
102
"polling_qsys_1limited: queue at the stability boundary, "
103
"rho + lambda_i R = 1, and the exact field has no infinity"
);
104
}
else
{
105
W[i] =
num_traits<T>::from_double
(std::numeric_limits<double>::infinity());
106
continue
;
107
}
108
}
109
T w = (one - rho + rho1[i]) / den1;
110
w *= (one - rho) / den2;
111
w *= rho / (two * (one - rho)) * sumLb2 + rho * sumDelta2 / (two * R) +
112
R / (two * (one - rho)) * (rho1[i] * (one + rho1[i]));
113
W[i] = w;
114
}
115
return
W;
116
}
117
118
/**
119
* Decrementing service, symmetric systems only (the MATLAB version rejects
120
* asymmetric parameters with a 1e-6 relative tolerance; here the check is
121
* exact, which is the right test in an exact field and a stricter one in
122
* double).
123
*
124
* W = delta2/(2r) + (N lambda b2 (1 - lambda r) + (r + lambda delta2)(N - rho))
125
* / (2 (1 - rho - lambda r (N - rho)))
126
*/
127
template
<
class
T>
128
std::vector<T>
polling_qsys_decrementing
(
const
PollingMoments<T>
& m) {
129
m.
validate
(
"polling_qsys_decrementing"
);
130
const
std::size_t n = m.
size
();
131
for
(std::size_t i = 1; i < n; ++i)
132
if
(m.
lambda
[i] != m.
lambda
[0] || m.
b
[i] != m.
b
[0] || m.
b2
[i] != m.
b2
[0] ||
133
m.
r
[i] != m.
r
[0] || m.
delta2
[i] != m.
delta2
[0])
134
throw
InputError
(
135
"polling_qsys_decrementing: only symmetric systems are supported (identical "
136
"arrival, service and switchover parameters across all queues)"
);
137
138
const
T zero =
num_traits<T>::from_int
(0), one =
num_traits<T>::from_int
(1);
139
const
T two =
num_traits<T>::from_int
(2);
140
const
T N =
num_traits<T>::from_int
(
static_cast<
long
>
(n));
141
const
T lam = m.
lambda
[0], b2s = m.
b2
[0], r = m.
r
[0], d2 = m.
delta2
[0];
142
const
T rho = N * lam * m.
b
[0];
143
144
const
T denom = two * (one - rho - lam * r * (N - rho));
145
if
(denom <= zero)
146
throw
NumericError
(
147
"polling_qsys_decrementing: unstable system, rho + lambda r (N - rho) >= 1"
);
148
149
const
T residualSwitchover = (r > zero) ? d2 / (two * r) : zero;
150
const
T w = residualSwitchover +
151
(N * lam * b2s * (one - lam * r) + (r + lam * d2) * (N - rho)) / denom;
152
return
std::vector<T>(n, w);
153
}
154
155
}
// namespace polling
156
}
// namespace line
157
158
#endif
// LINE_API_POLLING_POLLING_QSYS_1LIMITED_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
line::NumericError::NumericError
NumericError(const std::string &what)
Definition
error.h:45
error.h
The exception types the port throws.
line::polling
Definition
polling_qsys_1limited.h:36
line::polling::polling_qsys_decrementing
std::vector< T > polling_qsys_decrementing(const PollingMoments< T > &m)
Decrementing service, symmetric systems only (the MATLAB version rejects asymmetric parameters with a...
Definition
polling_qsys_1limited.h:128
line::polling::polling_qsys_1limited
std::vector< T > polling_qsys_1limited(const PollingMoments< T > &m)
1-limited polling: one job served per visit.
Definition
polling_qsys_1limited.h:67
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
line::num_traits
Definition
number.h:111
line::polling::PollingMoments
Per-queue first two moments of the arrival, service and switchover processes, the reduced form both f...
Definition
polling_qsys_1limited.h:43
line::polling::PollingMoments::validate
void validate(const char *who) const
Definition
polling_qsys_1limited.h:51
line::polling::PollingMoments::b2
std::vector< T > b2
second raw moment of the service time
Definition
polling_qsys_1limited.h:46
line::polling::PollingMoments::lambda
std::vector< T > lambda
arrival rate per queue
Definition
polling_qsys_1limited.h:44
line::polling::PollingMoments::delta2
std::vector< T > delta2
variance of the switchover time per queue
Definition
polling_qsys_1limited.h:48
line::polling::PollingMoments::r
std::vector< T > r
mean switchover time per queue
Definition
polling_qsys_1limited.h:47
line::polling::PollingMoments::b
std::vector< T > b
mean service time per queue
Definition
polling_qsys_1limited.h:45
line::polling::PollingMoments::size
std::size_t size() const
Definition
polling_qsys_1limited.h:50
include
line
api
polling
polling_qsys_1limited.h
Generated by
1.18.0