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
* The reference evaluates B by the rational recursion
24
* B_k = a B_{k-1}/(k + a B_{k-1}), which is exactly what line::lossn::erlang_b
25
* declines to do (it goes through log/exp and says so). This port keeps the
26
* reference's recursion, so B itself is a rational function of a and needs no
27
* transcendental arithmetic. The static_assert is nonetheless present because
28
* the OUTER iteration is a fixed point tested against a tolerance: it converges
29
* geometrically but not in a finite number of field operations, and at Rational
30
* the iterates would grow without bound in representation size while never
31
* meeting an exact stopping rule.
32
*
33
* The iteration is a monotone increasing map of r started from 0 and bounded
34
* above by lambda/(1-B) at the fixed point, so it converges from below and the
35
* successive-difference test is a genuine stopping criterion rather than a
36
* heuristic. The reference does NOT report non-convergence; when maxiter is
37
* exhausted it silently returns the last iterate, and the port reports the
38
* iteration count so the caller can tell the two apart, exactly as the third
39
* MATLAB output niter does.
40
*/
41
42
#include <cstddef>
43
44
#include "
line/num/number.h
"
45
#include "
line/util/error.h
"
46
47
namespace
line
{
48
namespace
qsys
{
49
50
/** Return value of qsys_mmcc_retrial_fp, mirroring the three MATLAB outputs. */
51
template
<
class
T>
52
struct
MmccRetrialFpResult
{
53
T
blockingProbability
;
///< B((lambda + r)/mu, c)
54
T
retrialRate
;
///< r, the extra arrival rate contributed by the orbit
55
std::size_t
iterations
;
///< iterations performed, = maxiter when unconverged
56
bool
converged
;
///< whether the successive-difference test was met
57
};
58
59
/**
60
* Erlang's loss formula B(a, c) by the numerically stable rational recursion
61
* B_0 = 1, B_k = a B_{k-1}/(k + a B_{k-1}). Exact in any field: no logs, no
62
* factorials, no cancellation.
63
*/
64
template
<
class
T>
65
T
erlang_b_recursive
(
const
T& a,
unsigned
c) {
66
T b =
num_traits<T>::from_int
(1);
67
for
(
unsigned
i = 1; i <= c; ++i) b = a * b / (
num_traits<T>::from_int
(
static_cast<
long
>
(i)) + a * b);
68
return
b;
69
}
70
71
/**
72
* M/M/c/c with retrials by the Cohen fixed point.
73
*
74
* @param lambda fresh arrival rate
75
* @param mu service rate of one server
76
* @param c number of servers, which is also the capacity
77
* @param tol stopping tolerance on |r_{k+1} - r_k|
78
* @param maxiter iteration cap
79
*/
80
template
<
class
T>
81
MmccRetrialFpResult<T>
qsys_mmcc_retrial_fp
(
const
T& lambda,
const
T& mu,
unsigned
c,
const
T& tol,
82
std::size_t maxiter) {
83
static_assert
(
num_traits<T>::has_transcendental
,
84
"qsys_mmcc_retrial_fp is a tolerance-terminated fixed point"
);
85
const
T zero =
num_traits<T>::from_int
(0);
86
if
(lambda <= zero)
throw
InputError
(
"qsys_mmcc_retrial_fp: arrival rate must be positive"
);
87
if
(mu <= zero)
throw
InputError
(
"qsys_mmcc_retrial_fp: service rate must be positive"
);
88
if
(c == 0)
throw
InputError
(
"qsys_mmcc_retrial_fp: at least one server is required"
);
89
if
(tol <= zero)
throw
InputError
(
"qsys_mmcc_retrial_fp: tolerance must be positive"
);
90
if
(maxiter == 0)
throw
InputError
(
"qsys_mmcc_retrial_fp: maxiter must be positive"
);
91
92
T r = zero;
93
std::size_t it = 0;
94
bool
converged =
false
;
95
for
(; it < maxiter;) {
96
++it;
97
const
T a = (lambda + r) / mu;
98
const
T b =
erlang_b_recursive
(a, c);
99
const
T rnew = (lambda + r) * b;
100
const
T gap =
num_abs
(T(rnew - r));
101
r = rnew;
102
if
(gap < tol) {
103
converged =
true
;
104
break
;
105
}
106
}
107
108
MmccRetrialFpResult<T>
out;
109
out.
retrialRate
= r;
110
out.
blockingProbability
=
erlang_b_recursive
(T((lambda + r) / mu), c);
111
out.
iterations
= it;
112
out.
converged
= converged;
113
return
out;
114
}
115
116
/** qsys_mmcc_retrial_fp with the reference defaults tol = 1e-10, maxiter = 10000. */
117
template
<
class
T>
118
MmccRetrialFpResult<T>
qsys_mmcc_retrial_fp
(
const
T& lambda,
const
T& mu,
unsigned
c) {
119
return
qsys_mmcc_retrial_fp
(lambda, mu, c, T(
num_traits<T>::from_double
(1e-10)),
120
static_cast<
std::size_t
>
(10000));
121
}
122
123
}
// namespace qsys
124
}
// namespace line
125
126
#endif
// LINE_API_QSYS_QSYS_MMCC_RETRIAL_FP_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::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:65
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)
M/M/c/c with retrials by the Cohen fixed point.
Definition
qsys_mmcc_retrial_fp.h:81
line
Definition
aoi_dist2ph.h:52
line::num_abs
T num_abs(const T &v)
Definition
number.h:172
number.h
Number-type abstraction for the templated API port.
line::num_traits
Definition
number.h:111
line::qsys::MmccRetrialFpResult
Return value of qsys_mmcc_retrial_fp, mirroring the three MATLAB outputs.
Definition
qsys_mmcc_retrial_fp.h:52
line::qsys::MmccRetrialFpResult::converged
bool converged
whether the successive-difference test was met
Definition
qsys_mmcc_retrial_fp.h:56
line::qsys::MmccRetrialFpResult::blockingProbability
T blockingProbability
B((lambda + r)/mu, c).
Definition
qsys_mmcc_retrial_fp.h:53
line::qsys::MmccRetrialFpResult::retrialRate
T retrialRate
r, the extra arrival rate contributed by the orbit
Definition
qsys_mmcc_retrial_fp.h:54
line::qsys::MmccRetrialFpResult::iterations
std::size_t iterations
iterations performed, = maxiter when unconverged
Definition
qsys_mmcc_retrial_fp.h:55
include
line
api
qsys
qsys_mmcc_retrial_fp.h
Generated by
1.18.0