LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
aoi_fcfs_mgi1.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_FCFS_MGI1_H
6
#define LINE_API_AOI_FCFS_MGI1_H
7
8
/**
9
* @file
10
* @ingroup api_aoi
11
* Mean Age of Information, its transform and the peak age of an M/GI/1 FCFS
12
* queue.
13
*
14
* Templated port of matlab/src/api/aoi/aoi_fcfs_mgi1.m, cross-checked against
15
* jar/src/main/java/jline/api/aoi/Aoi_fcfs_mgi1.java (identical).
16
*
17
* W*(s) = (1-rho) s / (s - lambda + lambda H*(s)) (Pollaczek-Khinchine)
18
* T*(s) = H*(s) W*(s)
19
* A*(s) = lambda H*(s) / (s + lambda - lambda H*(s)) * W*(s) (Theorem 2)
20
* E[A] = E[H] + E[T] + (1 - 2 rho)/lambda - (d/ds) T*(s) at s = lambda
21
* E[Apeak] = E[T] + 1/lambda
22
*
23
* from Inoue, Masuyama, Takine and Tanaka (IEEE Trans. IT 65(12), 2019). The
24
* derivative term is what carries the correlation between the interarrival
25
* time and the system time.
26
*
27
* static_assert(num_traits<T>::has_transcendental) -- the derivative is taken
28
* by MATLAB's central difference with step 1e-6 max(1,lambda), reproduced here
29
* so the two agree digit for digit. That step is a tolerance, not an exact
30
* operation: in an exact field the function would return an exact value of the
31
* wrong quantity, which is worse than refusing.
32
*
33
* Note that the transform A*(s) itself is a rational function of s whenever
34
* H*(s) is, so the returned Lst is exact for its argument; only the mean is
35
* approximate.
36
*/
37
38
#include "
line/api/aoi/aoi_types.h
"
39
#include "
line/num/number.h
"
40
#include "
line/util/error.h
"
41
42
namespace
line
{
43
namespace
aoi
{
44
45
/**
46
* @brief Mean Age of Information, its transform and the peak age of an M/GI/1
47
* FCFS queue.
48
*
49
* @param lambda arrival rate, > 0
50
* @param H_lst LST of the service time
51
* @param E_H mean service time, > 0
52
* @param E_H2 second raw moment of the service time, >= E_H^2
53
* @return [meanAoI, peakAoI, A*(s)]
54
*/
55
template
<
class
T>
56
AoiLstResult<T>
aoi_fcfs_mgi1
(
const
T& lambda,
const
Lst<T>
& H_lst,
const
T& E_H,
const
T& E_H2) {
57
static_assert
(
num_traits<T>::has_transcendental
,
58
"aoi_fcfs_mgi1 requires transcendental arithmetic"
);
59
detail::require_positive(lambda,
"aoi_fcfs_mgi1"
,
"the arrival rate lambda"
);
60
detail::require_positive(E_H,
"aoi_fcfs_mgi1"
,
"the mean service time E_H"
);
61
if
(!H_lst)
throw
InputError
(
"aoi_fcfs_mgi1: the service-time LST must be callable"
);
62
if
(E_H2 < E_H * E_H)
throw
InputError
(
"aoi_fcfs_mgi1: E_H2 must be at least E_H^2"
);
63
const
T one =
num_traits<T>::from_int
(1), two =
num_traits<T>::from_int
(2);
64
const
T rho = lambda * E_H;
65
detail::require_stable(rho,
"aoi_fcfs_mgi1"
);
66
67
const
T E_Y = one / lambda;
68
const
T E_W = lambda * E_H2 / (two * (one - rho));
69
const
T E_T = E_W + E_H;
70
71
const
Lst<T>
Tstar = [lambda, H_lst, rho, one](
const
T& s) {
72
if
(
num_traits<T>::to_double
(s < T(0) ? T(-s) : s) < 1e-12)
73
return
one;
// removable 0/0 at the origin
74
const
T Hs = H_lst(s);
75
return
T(Hs * ((one - rho) * s / (s - lambda + lambda * Hs)));
76
};
77
const
T dTstar = detail::lst_derivative<T>(Tstar, lambda);
78
const
T meanAoI = E_H + E_T + (one - two * rho) / lambda - dTstar;
79
const
T peakAoI = E_T + E_Y;
80
81
// LST of AoI (Inoue et al. 2019, Theorem 2), via the general age formula
82
// A*(s) = (lambda/s) * ( T*(s) - Apeak*(s) )
83
// the cycle average of exp(-s*age) over a departure interval: the age starts
84
// each cycle at the system time T of the packet just delivered and grows to
85
// the peak T + (next interarrival) at the next delivery. For M/GI/1 FCFS
86
// Lindley gives W' = max(0, T - Y), so W' + Y is max(Y, T), and with
87
// Y ~ Exp(lambda) independent of T,
88
// E[exp(-s*max(Y,T))] = T*(s) - (s/(s+lambda)) * T*(s+lambda).
89
//
90
// THE PREVIOUS FORM WAS NOT AN LST: (lambda*H*(s))/(s+lambda-lambda*H*(s))
91
// diverges as s -> 0, so A*(0) was +Inf instead of 1 and the value exceeded
92
// 1 for small s. Checked against simulation on M/E2/1: at s = 0.3 the old
93
// form gave 1.3062, the form below 0.56935, and the sample path 0.56948.
94
Lst<T>
lstAoI = [lambda, H_lst, Tstar, one](
const
T& s) {
95
if
(
num_traits<T>::to_double
(s < T(0) ? T(-s) : s) < 1e-12)
96
return
one;
// A*(0) = 1 for any proper LST
97
const
T Hs = H_lst(s);
98
const
T Ts = Tstar(s);
99
const
T Tsl = Tstar(T(s + lambda));
100
const
T peak = Hs * (Ts - (s / (s + lambda)) * Tsl);
101
return
T((lambda / s) * (Ts - peak));
102
};
103
return
{meanAoI, peakAoI, lstAoI,
true
};
104
}
105
106
}
// namespace aoi
107
}
// namespace line
108
109
#endif
// LINE_API_AOI_FCFS_MGI1_H
aoi_types.h
Shared return types and arithmetic helpers for the templated Age of Information port.
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
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::aoi::aoi_fcfs_mgi1
AoiLstResult< T > aoi_fcfs_mgi1(const T &lambda, const Lst< T > &H_lst, const T &E_H, const T &E_H2)
Mean Age of Information, its transform and the peak age of an M/GI/1 FCFS queue.
Definition
aoi_fcfs_mgi1.h:56
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::num_traits
Definition
number.h:111
include
line
api
aoi
aoi_fcfs_mgi1.h
Generated by
1.18.0