LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
qsys_mtgs0_mol.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_MTGS0_MOL_H
6#define LINE_API_QSYS_MTGS0_MOL_H
7
8/**
9 * @file
10 * @ingroup api_qsys
11 * Modified-offered-load and pointwise-stationary approximations for a
12 * time-varying multiserver system.
13 *
14 * Templated port of matlab/src/api/qsys/qsys_mtgs0_mol.m, cross-checked against
15 * jar/src/main/java/jline/api/qsys/Qsys_mtgs0_mol.java.
16 *
17 * THE ONE IDEA. A stationary loss system with offered load a blocks with
18 * probability B(s,a). In a time-varying system the question is WHICH LOAD goes
19 * into that formula. PSA uses the instantaneous one, lambda(t)E[S]. MOL uses the
20 * offered load of the corresponding INFINITE-SERVER system,
21 *
22 * m(t) = E[S] E[lambda(t - Se)] = int_0^Inf lambda(t-x) P(S>x) dx,
23 *
24 * which is EXACT there and therefore carries the time lag and the smoothing the
25 * finite-server system also has. MOL is then B(s,m(t)). The difference between
26 * the two is precisely the lag: PSA peaks when the arrival rate peaks, MOL peaks
27 * later, and the real system peaks later too.
28 *
29 * WHAT TO EXPECT. Against the exact time-varying birth-death chain on a
30 * sinusoidal rate, MOL cuts the mean RELATIVE error roughly threefold (0.13
31 * against 0.44 at s = 100) because it gets the phase right; it does not always
32 * win on ABSOLUTE error, which is dominated by the peak of the cycle. Under
33 * constant input MOL is exact.
34 *
35 * ARITHMETIC. The offered load is a quadrature, so transcendental only. The
36 * Erlang recursions themselves are exact and are exposed separately.
37 *
38 * Reference: W. A. Massey, W. Whitt (1994). An analysis of the modified offered
39 * load approximation for the nonstationary Erlang loss model. Annals of Applied
40 * Probability 4(4), 1145-1160; W. Whitt (1991). Management Science 37(3),
41 * 307-314.
42 */
43
44#include <cstddef>
45#include <functional>
46#include <limits>
47#include <vector>
48
50#include "line/num/number.h"
51#include "line/util/error.h"
52
53namespace line {
54namespace qsys {
55
56/** MOL and PSA measures of a time-varying multiserver system. */
57template <class T>
59 std::vector<T> times; ///< the evaluation times
60 std::vector<T> offeredLoad; ///< m(t), the infinite-server load
61 std::vector<T> instantLoad; ///< lambda(t)E[S]
62 std::vector<T> probBlockMOL; ///< B(s,m(t)) or C(s,m(t))
63 std::vector<T> probBlockPSA; ///< the same at the instantaneous load
64 std::vector<T> meanBusyMOL; ///< carried load m(t)(1-B), or min(m,s) for the delay model
65 std::vector<T> arrivalRate; ///< lambda(t)
66};
67
68/**
69 * Erlang B by the recursion B_j = a B_{j-1}/(j + a B_{j-1}), which never forms
70 * a^s/s! and so never overflows.
71 *
72 * @param s number of servers
73 * @param a offered load in erlangs
74 */
75template <class T>
76T qsys_erlang_b(unsigned s, const T& a) {
78 for (unsigned j = 1; j <= s; ++j)
79 b = a * b / (num_traits<T>::from_int(static_cast<long>(j)) + a * b);
80 return b;
81}
82
83/**
84 * Erlang C from the same recursion; 1 when the load saturates the servers.
85 *
86 * @param s number of servers
87 * @param a offered load in erlangs
88 */
89template <class T>
90T qsys_erlang_c(unsigned s, const T& a) {
91 const T one = num_traits<T>::from_int(1);
92 const T sT = num_traits<T>::from_int(static_cast<long>(s));
93 if (a >= sT) return one;
94 const T b = qsys_erlang_b(s, a);
95 const T rho = a / sT;
96 return b / (one - rho * (one - b));
97}
98
99/**
100 * @brief Modified-offered-load and pointwise-stationary approximations for a
101 * time-varying multiserver system.
102 *
103 * @param lambdaFun the arrival rate
104 * @param serviceCcdf G^c(x) = P(S > x)
105 * @param ES the mean service time
106 * @param s number of servers
107 * @param tvals times at which to evaluate
108 * @param startTime time the system started empty; -Inf assumes an infinite past
109 * @param delay use Erlang C rather than Erlang B
110 */
111template <class T>
112QsysMolResult<T> qsys_mtgs0_mol(const std::function<T(const T&)>& lambdaFun,
113 const std::function<T(const T&)>& serviceCcdf, const T& ES,
114 unsigned s, const std::vector<T>& tvals,
115 double startTime = -std::numeric_limits<double>::infinity(),
116 bool delay = false) {
118 "qsys_mtgs0_mol integrates the offered load, so it needs inexact arithmetic");
119 if (s < 1) throw InputError("qsys_mtgs0_mol: the number of servers s must be at least 1");
120 const QsysMtginfResult<T> inf =
121 qsys_mtginf<T>(lambdaFun, serviceCcdf, ES, tvals, startTime);
123 r.times = inf.times;
124 r.offeredLoad = inf.meanNumber;
126 r.arrivalRate = inf.arrivalRate;
127 const std::size_t n = inf.times.size();
128 r.probBlockMOL.resize(n);
129 r.probBlockPSA.resize(n);
130 r.meanBusyMOL.resize(n);
131 const T sT = num_traits<T>::from_int(static_cast<long>(s));
132 for (std::size_t i = 0; i < n; ++i) {
133 r.probBlockMOL[i] = delay ? qsys_erlang_c(s, r.offeredLoad[i])
134 : qsys_erlang_b(s, r.offeredLoad[i]);
135 r.probBlockPSA[i] = delay ? qsys_erlang_c(s, r.instantLoad[i])
136 : qsys_erlang_b(s, r.instantLoad[i]);
137 r.meanBusyMOL[i] = delay ? detail::num_min(r.offeredLoad[i], sT)
138 : T(r.offeredLoad[i] * (num_traits<T>::from_int(1) - r.probBlockMOL[i]));
139 }
140 return r;
141}
142
143} // namespace qsys
144} // namespace line
145
146#endif // LINE_API_QSYS_MTGS0_MOL_H
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
QsysMtginfResult< T > qsys_mtginf(const std::function< T(const T &)> &lambdaFun, const std::function< T(const T &)> &serviceCcdf, const T &ES, const std::vector< T > &tvals, double startTime=-std::numeric_limits< double >::infinity(), double ES2=std::numeric_limits< double >::quiet_NaN(), const std::function< T(const T &)> &servicePdf=std::function< T(const T &)>(), double tol=1e-12, std::size_t panels=4000, double maxAge=1e12)
Exact time-varying analysis of the Mt/G/infinity queue.
T qsys_erlang_c(unsigned s, const T &a)
Erlang C from the same recursion; 1 when the load saturates the servers.
QsysMolResult< T > qsys_mtgs0_mol(const std::function< T(const T &)> &lambdaFun, const std::function< T(const T &)> &serviceCcdf, const T &ES, unsigned s, const std::vector< T > &tvals, double startTime=-std::numeric_limits< double >::infinity(), bool delay=false)
Modified-offered-load and pointwise-stationary approximations for a time-varying multiserver system.
T qsys_erlang_b(unsigned s, const T &a)
Erlang B by the recursion B_j = a B_{j-1}/(j + a B_{j-1}), which never forms a^s/s!
Number-type abstraction for the templated API port.
Exact time-varying analysis of the Mt/G/infinity queue.
MOL and PSA measures of a time-varying multiserver system.
std::vector< T > times
the evaluation times
std::vector< T > probBlockPSA
the same at the instantaneous load
std::vector< T > instantLoad
lambda(t)E[S]
std::vector< T > probBlockMOL
B(s,m(t)) or C(s,m(t)).
std::vector< T > meanBusyMOL
carried load m(t)(1-B), or min(m,s) for the delay model
std::vector< T > arrivalRate
lambda(t)
std::vector< T > offeredLoad
m(t), the infinite-server load
Time-varying measures of the Mt/G/infinity queue.
Definition qsys_mtginf.h:57
std::vector< T > meanNumber
m(t), the Poisson mean
Definition qsys_mtginf.h:59
std::vector< T > times
the evaluation times
Definition qsys_mtginf.h:58
std::vector< T > arrivalRate
lambda(t)
Definition qsys_mtginf.h:61
std::vector< T > offeredLoadPSA
ES lambda(t), the pointwise stationary approximation.
Definition qsys_mtginf.h:63