LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
aoi_types.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_AOI_TYPES_H
6
#define LINE_API_AOI_TYPES_H
7
8
/**
9
* @file
10
* @ingroup api_aoi
11
* Shared return types and arithmetic helpers for the templated Age of
12
* Information port.
13
*
14
* The MATLAB AoI family in matlab/src/api/aoi/ returns one of two triples:
15
* [meanAoI, varAoI, peakAoI] for the fully parameterized queues (M/M/1,
16
* M/D/1, D/M/1) and [meanAoI, lstAoI, peakAoI] for the ones taking a
17
* Laplace-Stieltjes transform as input (M/GI/1, GI/M/1). Both live here,
18
* mirroring jline.api.aoi.AoiResult and jline.api.aoi.AoiLstResult; each
19
* ported function lives in its own header named after the MATLAB file, as
20
* required by the port convention.
21
*
22
* An LST is represented as a std::function<T(const T&)> rather than a
23
* distribution object, exactly as MATLAB represents it as a function handle
24
* and the JAR as a LstFunction. Nothing in the family inverts an LST: the
25
* transforms are evaluated at real arguments only, and where MATLAB needs a
26
* derivative it takes a central difference with a fixed step.
27
*/
28
29
#include <cmath>
30
#include <functional>
31
#include <string>
32
33
#include "
line/num/number.h
"
34
#include "
line/util/error.h
"
35
36
namespace
line
{
37
namespace
aoi
{
38
39
/** A Laplace-Stieltjes transform evaluated at real arguments. */
40
template
<
class
T>
41
using
Lst
= std::function<T(
const
T&)>;
42
43
/** [meanAoI, varAoI, peakAoI], mirroring jline.api.aoi.AoiResult. */
44
template
<
class
T>
45
struct
AoiResult
{
46
T
meanAoI
;
47
T
varAoI
;
48
T
peakAoI
;
49
};
50
51
/**
52
* [meanAoI, lstAoI, peakAoI], mirroring jline.api.aoi.AoiLstResult.
53
*
54
* has_lst is false for the LCFS-D and LCFS-S disciplines, where MATLAB
55
* returns [] because the transform has no tractable closed form.
56
*/
57
template
<
class
T>
58
struct
AoiLstResult
{
59
T
meanAoI
;
60
T
peakAoI
;
61
Lst<T>
lstAoI
;
62
bool
has_lst
;
63
};
64
65
namespace
detail {
66
67
/** exp(v), resolved by ADL so double, cpp_bin_float and mpfr all work. */
68
template
<
class
T>
69
inline
T num_exp(
const
T& v) {
70
using
std::exp;
71
return
exp(v);
72
}
73
74
/** Guard on positivity of a rate or a time. */
75
template
<
class
T>
76
inline
void
require_positive(
const
T& v,
const
char
* fn,
const
char
* what) {
77
if
(v <=
num_traits<T>::from_int
(0))
78
throw
InputError
(std::string(fn) +
": "
+ what +
" must be positive"
);
79
}
80
81
/** Guard on stability; every function in the family requires rho < 1. */
82
template
<
class
T>
83
inline
void
require_stable(
const
T& rho,
const
char
* fn) {
84
if
(rho >= num_traits<T>::from_int(1))
85
throw
NumericError
(std::string(fn) +
": unstable system, rho >= 1"
);
86
}
87
88
/**
89
* Central difference of an LST at s with MATLAB's step, h = 1e-6 max(1,|s|).
90
*
91
* Every MATLAB file in the family that needs d/ds H*(s) uses exactly this
92
* step; reproducing it, rather than improving on it, is what makes the port
93
* agree with MATLAB to the twelfth digit. The approximation is the reason
94
* these functions require transcendental arithmetic even when the transform
95
* itself is rational: the answer is step-dependent, so an exact field would
96
* return an exact value of the wrong quantity.
97
*/
98
template
<
class
T>
99
inline
T lst_derivative(
const
Lst<T>
& f,
const
T& s) {
100
const
T one = num_traits<T>::from_int(1);
101
const
T mag = s < num_traits<T>::from_int(0) ? T(-s) : s;
102
const
T scale = mag > one ? mag : one;
103
const
T h = num_traits<T>::from_double(1e-6) * scale;
104
return
(f(T(s + h)) - f(T(s - h))) / (num_traits<T>::from_int(2) * h);
105
}
106
107
/**
108
* Bisection on a bracketed sign change, the replacement for MATLAB's fzero.
109
*
110
* MATLAB brackets every sigma root in this family on [0.001, 0.999] and calls
111
* fzero (Brent); the JAR replaces it with bisection (Aoi_fcfs_dm1). This port
112
* follows the JAR. With max_iter = 200 the bracket collapses below the
113
* representable resolution of double and of the 50-digit real type alike.
114
*/
115
template
<
class
T,
class
F>
116
inline
T bisect(
const
F& f, T lo, T hi,
const
char
* fn,
unsigned
max_iter = 200) {
117
const
T zero = num_traits<T>::from_int(0);
118
T flo = f(lo);
119
const
T fhi = f(hi);
120
if
((flo > zero && fhi > zero) || (flo < zero && fhi < zero))
121
throw
NumericError
(std::string(fn) +
": the root is not bracketed by [0.001, 0.999]"
);
122
for
(
unsigned
it = 0; it < max_iter; ++it) {
123
const
T mid = (lo + hi) / num_traits<T>::from_int(2);
124
if
(mid == lo || mid == hi)
break
;
125
const
T fm = f(mid);
126
if
(fm == zero)
return
mid;
127
if
((fm > zero) == (flo > zero)) { lo = mid; flo = fm; }
128
else
{ hi = mid; }
129
}
130
return
(lo + hi) / num_traits<T>::from_int(2);
131
}
132
133
/**
134
* The sigma of a GI/M/1 queue: the unique root in (0,1) of Y*(mu - mu s) = s,
135
* the probability an arriving job finds the server busy.
136
*/
137
template
<
class
T>
138
inline
T gim1_sigma(
const
Lst<T>
& Y_lst,
const
T& mu,
const
char
* fn) {
139
return
bisect<T>([&](
const
T& s) {
return
T(Y_lst(T(mu - mu * s)) - s); },
140
num_traits<T>::from_double(0.001), num_traits<T>::from_double(0.999), fn);
141
}
142
143
}
// namespace detail
144
145
}
// namespace aoi
146
}
// namespace line
147
148
#endif
// LINE_API_AOI_TYPES_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::aoi
Definition
aoi_dist2ph.h:53
line::aoi::Lst
std::function< T(const T &)> Lst
A Laplace-Stieltjes transform evaluated at real arguments.
Definition
aoi_types.h:41
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
line::aoi::AoiLstResult
[meanAoI, lstAoI, peakAoI], mirroring jline.api.aoi.AoiLstResult.
Definition
aoi_types.h:58
line::aoi::AoiLstResult::meanAoI
T meanAoI
Definition
aoi_types.h:59
line::aoi::AoiLstResult::peakAoI
T peakAoI
Definition
aoi_types.h:60
line::aoi::AoiLstResult::lstAoI
Lst< T > lstAoI
Definition
aoi_types.h:61
line::aoi::AoiLstResult::has_lst
bool has_lst
Definition
aoi_types.h:62
line::aoi::AoiResult
[meanAoI, varAoI, peakAoI], mirroring jline.api.aoi.AoiResult.
Definition
aoi_types.h:45
line::aoi::AoiResult::peakAoI
T peakAoI
Definition
aoi_types.h:48
line::aoi::AoiResult::varAoI
T varAoI
Definition
aoi_types.h:47
line::aoi::AoiResult::meanAoI
T meanAoI
Definition
aoi_types.h:46
line::num_traits
Definition
number.h:111
include
line
api
aoi
aoi_types.h
Generated by
1.18.0