5#ifndef LINE_API_QSYS_MTGINF_H
6#define LINE_API_QSYS_MTGINF_H
73void mtginf_simpson(
const T& a,
const T& b, std::size_t n, std::vector<T>& x, std::vector<T>& w) {
83 for (std::size_t i = 0; i <= n; ++i) {
85 const long c = (i == 0 || i == n) ? 1 : (i % 2 == 1 ? 4 : 2);
91template <
class T,
class Ccdf>
92T mtginf_tail_cut(Ccdf&& ccdf,
double tol,
double cap) {
96 while (ccdf(x) > tolT) {
98 if (x > capT)
return capT;
109template <
class T,
class Lam,
class Ccdf>
110std::vector<T> mtginf_mean(Lam&& lambdaFun, Ccdf&& serviceCcdf,
const std::vector<T>& t,
111 double startTime,
const T& cut, std::size_t panels,
bool unbounded) {
112 std::vector<T> xs, ws, gcs;
114 mtginf_simpson(num_traits<T>::from_int(0), cut, panels, xs, ws);
115 gcs.resize(xs.size());
116 for (std::size_t j = 0; j < xs.size(); ++j) gcs[j] = serviceCcdf(xs[j]);
118 std::vector<T> m(t.size(), num_traits<T>::from_int(0));
119 std::vector<T> x, w, gc;
120 for (std::size_t i = 0; i < t.size(); ++i) {
121 const std::vector<T>*px;
122 const std::vector<T>*pw;
123 const std::vector<T>*pgc;
129 T hi = t[i] - num_traits<T>::from_double(startTime);
130 if (hi < num_traits<T>::from_int(0)) hi = num_traits<T>::from_int(0);
131 if (hi > cut) hi = cut;
132 mtginf_simpson(num_traits<T>::from_int(0), hi, panels, x, w);
134 for (std::size_t j = 0; j < x.size(); ++j) gc[j] = serviceCcdf(x[j]);
139 T acc = num_traits<T>::from_int(0);
140 for (std::size_t j = 0; j < px->size(); ++j)
142 acc += (*pw)[j] * lambdaFun(T(t[i] - (*px)[j])) * (*pgc)[j];
167 const std::function<T(
const T&)>& lambdaFun,
const std::function<T(
const T&)>& serviceCcdf,
168 const T& ES,
const std::vector<T>& tvals,
169 double startTime = -std::numeric_limits<double>::infinity(),
170 double ES2 = std::numeric_limits<double>::quiet_NaN(),
171 const std::function<T(
const T&)>& servicePdf = std::function<T(
const T&)>(),
172 double tol = 1e-12, std::size_t panels = 4000,
double maxAge = 1e12) {
174 "qsys_mtginf integrates against a tail cut, so it needs inexact arithmetic");
176 throw InputError(
"qsys_mtginf: the mean service time ES must be positive");
177 if (!lambdaFun || !serviceCcdf)
178 throw InputError(
"qsys_mtginf: the arrival rate and the service ccdf must be callable");
180 const T cut = detail::mtginf_tail_cut<T>(serviceCcdf, tol, maxAge);
181 const bool unbounded = std::isinf(startTime);
185 res.
meanNumber = detail::mtginf_mean<T>(lambdaFun, serviceCcdf, tvals, startTime, cut, panels,
190 for (std::size_t i = 0; i < tvals.size(); ++i) {
198 for (std::size_t i = 0; i < tvals.size(); ++i) {
203 if (hi > cut) hi = cut;
207 for (std::size_t j = 0; j < x.size(); ++j)
208 acc += w[j] * lambdaFun(T(tvals[i] - x[j])) * servicePdf(x[j]);
216 std::vector<T> tu(tvals.size()), td(tvals.size());
217 for (std::size_t i = 0; i < tvals.size(); ++i) {
218 tu[i] = tvals[i] + h;
219 td[i] = tvals[i] - h;
221 const std::vector<T> up =
222 detail::mtginf_mean<T>(lambdaFun, serviceCcdf, tu, startTime, cut, panels, unbounded);
223 const std::vector<T> dn =
224 detail::mtginf_mean<T>(lambdaFun, serviceCcdf, td, startTime, cut, panels, unbounded);
225 for (std::size_t i = 0; i < tvals.size(); ++i)
230 if (!std::isnan(ES2)) {
234 for (std::size_t i = 0; i < tvals.size(); ++i)
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.
Number-type abstraction for the templated API port.
Shared return type and arithmetic helpers for the templated qsys port.
Time-varying measures of the Mt/G/infinity queue.
std::vector< T > meanNumber
m(t), the Poisson mean
std::vector< T > departureRate
delta(t) = E[lambda(t-S)]
std::vector< T > varNumber
equal to meanNumber, the law being Poisson
std::vector< T > times
the evaluation times
std::vector< T > arrivalRate
lambda(t)
std::vector< T > offeredLoadPSA
ES lambda(t), the pointwise stationary approximation.
bool hasLag
whether the two fields above are set
T meanLag
E[Se], set only when ES2 was supplied.
std::vector< T > lagApproximation
ES lambda(t-E[Se]), likewise.