LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
aoi_fcfs_gim1.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_GIM1_H
6
#define LINE_API_AOI_FCFS_GIM1_H
7
8
/**
9
* @file
10
* @ingroup api_aoi
11
* Mean Age of Information, its transform and the peak age of a GI/M/1 FCFS
12
* queue.
13
*
14
* Templated port of matlab/src/api/aoi/aoi_fcfs_gim1.m, cross-checked against
15
* jar/src/main/java/jline/api/aoi/Aoi_fcfs_gim1.java (identical).
16
*
17
* sigma solves Y*(mu - mu sigma) = sigma in (0,1); eta = mu (1 - sigma)
18
* E[D] = 1/eta
19
* E[A] = lambda E[Y^2]/2 + 1/mu + lambda (-Y*'(eta))/eta
20
* E[Apeak] = E[Y] + E[D]
21
* A*(s) = (lambda/s) * ( T*(s) - Apeak*(s) ) (Theorem 3)
22
* with T*(s) = eta/(s + eta) the exponential system time and
23
* Apeak*(s) = mu/(s + mu) * ( Y*(s) - s/(s + eta) * Y*(s + eta) )
24
*
25
* from Inoue et al. (2019). The stationary system time is exponential with
26
* rate eta and independent of the next interarrival, which is why the
27
* correlation term reduces to -Y*'(eta)/eta.
28
*
29
* static_assert(num_traits<T>::has_transcendental) -- a bracketed root of a
30
* transcendental equation plus MATLAB's finite-difference derivative.
31
*
32
* Note that MATLAB uses the argument E_Y2 in the mean but never validates it
33
* against Y_lst, so an inconsistent pair silently produces an inconsistent
34
* answer; the port keeps that behaviour and only checks E_Y2 >= E_Y^2.
35
*/
36
37
#include "
line/api/aoi/aoi_types.h
"
38
#include "
line/num/number.h
"
39
#include "
line/util/error.h
"
40
41
namespace
line
{
42
namespace
aoi
{
43
44
/**
45
* @brief Mean Age of Information, its transform and the peak age of a GI/M/1
46
* FCFS queue.
47
*
48
* @param Y_lst LST of the interarrival time
49
* @param mu service rate, > 0
50
* @param E_Y mean interarrival time, > 0
51
* @param E_Y2 second raw moment of the interarrival time, >= E_Y^2
52
* @return [meanAoI, peakAoI, A*(s)]
53
*/
54
template
<
class
T>
55
AoiLstResult<T>
aoi_fcfs_gim1
(
const
Lst<T>
& Y_lst,
const
T& mu,
const
T& E_Y,
const
T& E_Y2) {
56
static_assert
(
num_traits<T>::has_transcendental
,
57
"aoi_fcfs_gim1 requires transcendental arithmetic"
);
58
detail::require_positive(mu,
"aoi_fcfs_gim1"
,
"the service rate mu"
);
59
detail::require_positive(E_Y,
"aoi_fcfs_gim1"
,
"the mean interarrival time E_Y"
);
60
if
(!Y_lst)
throw
InputError
(
"aoi_fcfs_gim1: the interarrival LST must be callable"
);
61
if
(E_Y2 < E_Y * E_Y)
throw
InputError
(
"aoi_fcfs_gim1: E_Y2 must be at least E_Y^2"
);
62
const
T one =
num_traits<T>::from_int
(1), two =
num_traits<T>::from_int
(2);
63
const
T lambda = one / E_Y;
64
const
T rho = lambda / mu;
65
detail::require_stable(rho,
"aoi_fcfs_gim1"
);
66
67
const
T sigma = detail::gim1_sigma<T>(Y_lst, mu,
"aoi_fcfs_gim1"
);
68
const
T E_D = one / (mu * (one - sigma));
69
const
T eta = mu * (one - sigma);
70
const
T dYstar = detail::lst_derivative<T>(Y_lst, eta);
71
72
const
T meanAoI = lambda * E_Y2 / two + one / mu + lambda * (-dYstar) / eta;
73
const
T peakAoI = E_Y + E_D;
74
75
// LST of AoI (Inoue et al. 2019, Theorem 3), via the general age formula
76
// A*(s) = (lambda/s) * ( T*(s) - Apeak*(s) )
77
// the cycle average of exp(-s*age) over a departure interval. In GI/M/1 the
78
// system time is EXPONENTIAL at rate eta = mu*(1-sigma), so T*(s) =
79
// eta/(s+eta), and Lindley gives W' + Y = max(Y, T) with T ~ Exp(eta)
80
// independent of the next interarrival Y, so
81
// E[exp(-s*max(Y,T))] = Y*(s) - (s/(s+eta)) * Y*(s+eta),
82
// and the peak adds one fresh Exp(mu) service. A*(0) = 1 follows from the
83
// defining relation Y*(eta) = sigma.
84
//
85
// THE PREVIOUS FORM WAS NOT AN LST: (mu*sigma(s))/(s+mu-mu*sigma(s))*D*(s)
86
// gives sigma/(1-sigma) at s = 0 rather than 1, and it re-solved sigma(s)
87
// by bisection at every point. Checked against simulation on E2/M/1: at
88
// s = 0.2 the old form gave 0.23056, the form below 0.59319, and the sample
89
// path 0.59332.
90
Lst<T>
lstAoI = [Y_lst, mu, eta, lambda, one](
const
T& s) {
91
if
(
num_traits<T>::to_double
(s < T(0) ? T(-s) : s) < 1e-12)
92
return
one;
// A*(0) = 1 for any proper LST
93
const
T Ts = eta / (s + eta);
94
const
T peak = (mu / (s + mu)) * (Y_lst(s) - (s / (s + eta)) * Y_lst(T(s + eta)));
95
return
T((lambda / s) * (Ts - peak));
96
};
97
return
{meanAoI, peakAoI, lstAoI,
true
};
98
}
99
100
}
// namespace aoi
101
}
// namespace line
102
103
#endif
// LINE_API_AOI_FCFS_GIM1_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_gim1
AoiLstResult< T > aoi_fcfs_gim1(const Lst< T > &Y_lst, const T &mu, const T &E_Y, const T &E_Y2)
Mean Age of Information, its transform and the peak age of a GI/M/1 FCFS queue.
Definition
aoi_fcfs_gim1.h:55
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_gim1.h
Generated by
1.18.0