LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
qsys_mmcc_retrial_fp.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_MMCC_RETRIAL_FP_H
6
#define LINE_API_QSYS_QSYS_MMCC_RETRIAL_FP_H
7
8
/**
9
* @file
10
* @ingroup api_qsys
11
* Fixed-point approximation for the M/M/c/c retrial queue.
12
*
13
* Port of matlab/src/api/qsys/qsys_mmcc_retrial_fp.m. Blocked customers join an
14
* orbit and retry; under the assumption that the retrial rate is small relative
15
* to the service rate the superposition of fresh and retrial arrivals is
16
* approximated by a Poisson stream of rate lambda + r, with r the solution of
17
*
18
* r = (lambda + r) B((lambda + r)/mu, c),
19
*
20
* B being Erlang's loss formula. Cohen (1957); Phung-Duc, "Retrial Queueing
21
* Models: A Survey on Theory and Applications" (2019), eq. (1).
22
*
23
* With non-persistent customers (Phung-Duc 2019, Sec. 3.2), a blocked fresh
24
* customer joins the orbit with probability p and a blocked retrial customer
25
* returns to it with probability q. The orbit then sends retrials at the rate
26
*
27
* r = lambda p B / (1 - q B), B = B((lambda + r)/mu, c),
28
*
29
* iterated as r <- lambda p B + q B r, which is Cohen's iteration when
30
* p = q = 1 (so the iteration count is unchanged there). A fresh customer is
31
* lost with probability B(1-p) + B p (1-q) B/(1 - q B), zero when p = q = 1.
32
*
33
* The reference evaluates B by the rational recursion
34
* B_k = a B_{k-1}/(k + a B_{k-1}), which is exactly what line::lossn::erlang_b
35
* declines to do (it goes through log/exp and says so). This port keeps the
36
* reference's recursion, so B itself is a rational function of a and needs no
37
* transcendental arithmetic. The static_assert is nonetheless present because
38
* the OUTER iteration is a fixed point tested against a tolerance: it converges
39
* geometrically but not in a finite number of field operations, and at Rational
40
* the iterates would grow without bound in representation size while never
41
* meeting an exact stopping rule.
42
*
43
* The iteration is a monotone increasing map of r started from 0 and bounded
44
* above by lambda/(1-B) at the fixed point, so it converges from below and the
45
* successive-difference test is a genuine stopping criterion rather than a
46
* heuristic. The reference does NOT report non-convergence; when maxiter is
47
* exhausted it silently returns the last iterate, and the port reports the
48
* iteration count so the caller can tell the two apart, exactly as the third
49
* MATLAB output niter does.
50
*/
51
52
#include <cstddef>
53
#include <string>
54
55
#include "
line/num/number.h
"
56
#include "
line/util/error.h
"
57
58
namespace
line
{
59
namespace
qsys
{
60
61
/** Return value of qsys_mmcc_retrial_fp, mirroring the four MATLAB outputs. */
62
template
<
class
T>
63
struct
MmccRetrialFpResult
{
64
T
blockingProbability
;
///< B((lambda + r)/mu, c)
65
T
retrialRate
;
///< r, the extra arrival rate contributed by the orbit
66
T
lossProbability
;
///< probability that a fresh customer is eventually lost
67
std::size_t
iterations
;
///< iterations performed, = maxiter when unconverged
68
bool
converged
;
///< whether the successive-difference test was met
69
};
70
71
/**
72
* Erlang's loss formula B(a, c) by the numerically stable rational recursion
73
* B_0 = 1, B_k = a B_{k-1}/(k + a B_{k-1}). Exact in any field: no logs, no
74
* factorials, no cancellation.
75
*/
76
template
<
class
T>
77
T
erlang_b_recursive
(
const
T& a,
unsigned
c) {
78
T b =
num_traits<T>::from_int
(1);
79
for
(
unsigned
i = 1; i <= c; ++i) b = a * b / (
num_traits<T>::from_int
(
static_cast<
long
>
(i)) + a * b);
80
return
b;
81
}
82
83
/**
84
* M/M/c/c with retrials by the Cohen fixed point.
85
*
86
* @param lambda fresh arrival rate
87
* @param mu service rate of one server
88
* @param c number of servers, which is also the capacity
89
* @param tol stopping tolerance on |r_{k+1} - r_k|
90
* @param maxiter iteration cap
91
* @param p probability that a blocked fresh customer joins the orbit (default 1)
92
* @param q probability that a blocked retrial customer stays in the orbit (default 1)
93
*/
94
template
<
class
T>
95
MmccRetrialFpResult<T>
qsys_mmcc_retrial_fp
(
const
T& lambda,
const
T& mu,
unsigned
c,
const
T& tol,
96
std::size_t maxiter,
97
const
T& p =
num_traits<T>::from_int
(1),
98
const
T& q =
num_traits<T>::from_int
(1)) {
99
static_assert
(
num_traits<T>::has_transcendental
,
100
"qsys_mmcc_retrial_fp is a tolerance-terminated fixed point"
);
101
const
T zero =
num_traits<T>::from_int
(0);
102
if
(lambda <= zero)
throw
InputError
(
"qsys_mmcc_retrial_fp: arrival rate must be positive"
);
103
if
(mu <= zero)
throw
InputError
(
"qsys_mmcc_retrial_fp: service rate must be positive"
);
104
if
(c == 0)
throw
InputError
(
"qsys_mmcc_retrial_fp: at least one server is required"
);
105
if
(tol <= zero)
throw
InputError
(
"qsys_mmcc_retrial_fp: tolerance must be positive"
);
106
if
(maxiter == 0)
throw
InputError
(
"qsys_mmcc_retrial_fp: maxiter must be positive"
);
107
const
T one =
num_traits<T>::from_int
(1);
108
if
(p < zero || p > one || q < zero || q > one)
109
throw
InputError
(
"qsys_mmcc_retrial_fp: The join and persistence probabilities P and Q must be in [0, 1]."
);
110
if
(!(q < one) && p > zero &&
111
!(lambda * p / mu <
num_traits<T>::from_int
(
static_cast<
long
>
(c)))) {
112
// a persistent orbit grows without bound: no fixed point exists
113
throw
InputError
(
ErrorKind
(
"Unstable"
),
114
"qsys_mmcc_retrial_fp: unstable retrial queue: lambda*p/mu = "
+
115
std::to_string(
num_traits<T>::to_double
(T(lambda * p / mu))) +
" >= c = "
+
116
std::to_string(c) +
", the persistent orbit grows without bound"
);
117
}
118
119
T r = zero;
120
std::size_t it = 0;
121
bool
converged =
false
;
122
for
(; it < maxiter;) {
123
++it;
124
const
T a = (lambda + r) / mu;
125
const
T b =
erlang_b_recursive
(a, c);
126
// r = lambda*p*B + q*B*r, the same iteration as Cohen's r = (lambda + r)*B,
127
// to which it reduces when p = q = 1
128
const
T rnew = lambda * p * b + q * b * r;
129
const
T gap =
num_abs
(T(rnew - r));
130
r = rnew;
131
if
(gap < tol) {
132
converged =
true
;
133
break
;
134
}
135
}
136
137
MmccRetrialFpResult<T>
out;
138
out.
retrialRate
= r;
139
out.
blockingProbability
=
erlang_b_recursive
(T((lambda + r) / mu), c);
140
const
T B = out.
blockingProbability
;
141
out.
lossProbability
= T(B * (one - p) + B * p * (one - q) * B / (one - q * B));
142
out.
iterations
= it;
143
out.
converged
= converged;
144
return
out;
145
}
146
147
/** qsys_mmcc_retrial_fp with the reference defaults tol = 1e-10, maxiter = 10000. */
148
template
<
class
T>
149
MmccRetrialFpResult<T>
qsys_mmcc_retrial_fp
(
const
T& lambda,
const
T& mu,
unsigned
c) {
150
return
qsys_mmcc_retrial_fp
(lambda, mu, c, T(
num_traits<T>::from_double
(1e-10)),
151
static_cast<
std::size_t
>
(10000));
152
}
153
154
}
// namespace qsys
155
}
// namespace line
156
157
#endif
// LINE_API_QSYS_QSYS_MMCC_RETRIAL_FP_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:105
error.h
The exception types the port throws.
line::qsys
Definition
qsys_bmapm1.h:58
line::qsys::erlang_b_recursive
T erlang_b_recursive(const T &a, unsigned c)
Erlang's loss formula B(a, c) by the numerically stable rational recursion B_0 = 1,...
Definition
qsys_mmcc_retrial_fp.h:77
line::qsys::qsys_mmcc_retrial_fp
MmccRetrialFpResult< T > qsys_mmcc_retrial_fp(const T &lambda, const T &mu, unsigned c, const T &tol, std::size_t maxiter, const T &p=num_traits< T >::from_int(1), const T &q=num_traits< T >::from_int(1))
M/M/c/c with retrials by the Cohen fixed point.
Definition
qsys_mmcc_retrial_fp.h:95
line
Conservation laws of a layered queueing network, enumerated from its structure.
Definition
aoi_dist2ph.h:52
line::num_abs
T num_abs(const T &v)
Definition
number.h:184
number.h
Number-type abstraction for the templated API port.
line::ErrorKind::ErrorKind
ErrorKind(std::string n)
Definition
error.h:39
line::num_traits
Definition
number.h:123
line::qsys::MmccRetrialFpResult
Return value of qsys_mmcc_retrial_fp, mirroring the four MATLAB outputs.
Definition
qsys_mmcc_retrial_fp.h:63
line::qsys::MmccRetrialFpResult::converged
bool converged
whether the successive-difference test was met
Definition
qsys_mmcc_retrial_fp.h:68
line::qsys::MmccRetrialFpResult::blockingProbability
T blockingProbability
B((lambda + r)/mu, c).
Definition
qsys_mmcc_retrial_fp.h:64
line::qsys::MmccRetrialFpResult::retrialRate
T retrialRate
r, the extra arrival rate contributed by the orbit
Definition
qsys_mmcc_retrial_fp.h:65
line::qsys::MmccRetrialFpResult::lossProbability
T lossProbability
probability that a fresh customer is eventually lost
Definition
qsys_mmcc_retrial_fp.h:66
line::qsys::MmccRetrialFpResult::iterations
std::size_t iterations
iterations performed, = maxiter when unconverged
Definition
qsys_mmcc_retrial_fp.h:67
include
line
api
qsys
qsys_mmcc_retrial_fp.h
Generated by
1.18.0