LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
qsys_mmc_prio_eta.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_QSYS_MMC_PRIO_ETA_H
6#define LINE_API_QSYS_QSYS_MMC_PRIO_ETA_H
7
8/**
9 * @file
10 * @ingroup api_qsys
11 * Expected tardiness at arrival (ETA) in a multiclass priority M/M/c queue,
12 * conditional on the state the arriving order observes (Hafizoglu, Gel and
13 * Keskinocak, INFORMS J. Comput. 25(2), 2013).
14 *
15 * Port of matlab/src/api/qsys/qsys_mmc_prio_eta.m. For type "np", v is the
16 * total number of orders in the system and q the number of class <= r orders
17 * waiting (used when v >= c); for type "pr", v is the number of class <= r
18 * orders in the system and q is ignored. Classes with no higher-priority
19 * traffic use the closed form of Theorem 1; the others invert the transform of
20 * Theorem 2 ("np") or Theorem 4 and eq. (17) ("pr").
21 *
22 * ARITHMETIC: double.
23 */
24
25#include <cmath>
26#include <string>
27#include <vector>
28
30
31namespace line {
32namespace qsys {
33
34/** MATLAB's [Tard, Ptard, S] outputs, one entry of Tard and Ptard per due date. */
36 std::vector<double> Tard; ///< E[(T - d)^+]
37 std::vector<double> Ptard; ///< P(T > d)
38 double S = 0.0; ///< E[T]
39};
40
41/**
42 * @brief Expected tardiness at arrival of a class-r order.
43 *
44 * @param lambda per-class arrival rates, highest priority first
45 * @param mu common service rate
46 * @param c number of servers
47 * @param r class of the arriving order, 1-based as in MATLAB
48 * @param v orders in the system ("np") or class <= r orders in the system ("pr")
49 * @param q class <= r orders waiting ("np" only)
50 * @param d due dates
51 * @param type "np" or "pr"
52 * @param method Laplace inversion method
53 */
54inline MmcPrioEtaResult qsys_mmc_prio_eta(const std::vector<double>& lambda, double mu, unsigned c, unsigned r,
55 unsigned v, unsigned q, const std::vector<double>& d,
56 const std::string& type = "np", const std::string& method = "euler") {
57 using namespace tarddetail;
58 const char* fn = "qsys_mmc_prio_eta";
59 bool bad = lambda.empty() || !(mu > 0);
60 for (double l : lambda)
61 if (!(l >= 0)) bad = true;
62 if (bad) throw InputError(ErrorKind("Argument"), std::string(fn) + ": lambda must be nonnegative and mu a positive scalar");
63 if (c < 1) throw InputError(ErrorKind("Argument"), std::string(fn) + ": c must be a positive integer");
64 if (r < 1 || r > lambda.size()) throw InputError(ErrorKind("Argument"), std::string(fn) + ": r must be a class index of lambda");
65 for (double x : d)
66 if (std::isnan(x)) throw InputError(ErrorKind("Argument"), std::string(fn) + ": d must not be NaN");
67 const bool preemptive = is_preemptive(type, fn);
69 double lb = 0;
70 for (unsigned j = 0; j + 1 < r; ++j) lb += lambda[j];
71 const double cmu = c * mu;
72 if (lb >= cmu) resdetail::throw_unstable(fn, "higher-priority load", lb / cmu);
73 unsigned K;
74 if (preemptive)
75 K = v + 1 > c ? v - c + 1 : 0;
76 else
77 K = v + 1 <= c ? 0 : q + 1;
79 out.Tard.assign(d.size(), 0.0);
80 out.Ptard.assign(d.size(), 0.0);
81 if (lb == 0 || (K == 0 && !preemptive)) {
82 out.S = 1 / mu + K / (cmu - lb);
83 for (std::size_t n = 0; n < d.size(); ++n) hypo_tard(K, mu, cmu, d[n], out.S, out.Tard[n], out.Ptard[n]);
84 return out;
85 }
87 if (preemptive) {
88 const std::vector<double> Sv = pr_means(lb, mu, c);
89 if (v + 1 <= c) {
90 out.S = Sv[v];
91 F = [lb, mu, c, v](Cplx s) { return pr_state_lst(s, lb, mu, c)[v]; };
92 } else {
93 out.S = Sv[c - 1] + K / (cmu - lb);
94 F = [lb, mu, c, cmu, K](Cplx s) { return pr_state_lst(s, lb, mu, c)[c - 1] * ipow(busy_lst(s, lb, cmu), K); };
95 }
96 } else {
97 out.S = 1 / mu + K / (cmu - lb);
98 F = [lb, mu, cmu, K](Cplx s) { return mu / (s + mu) * ipow(busy_lst(s, lb, cmu), K); };
99 }
100 for (std::size_t n = 0; n < d.size(); ++n) invert_tard(F, out.S, d[n], m, out.Tard[n], out.Ptard[n]);
101 return out;
102}
103
104} // namespace qsys
105} // namespace line
106
107#endif // LINE_API_QSYS_QSYS_MMC_PRIO_ETA_H
InputError(const std::string &what)
Definition error.h:105
LaplaceMethod
The methods laplace_invert accepts.
LaplaceMethod laplace_method(const std::string &s)
Parse the reference's method names, including its two Gaver spellings.
std::function< Cplx(Cplx)> LaplaceFn
The transform, evaluated at complex argument.
void throw_unstable(const char *fn, const char *what, double v)
A LINE:input:Unstable refusal "fn: unstable system: <what> = %g >= 1".
Definition qsys_res.h:213
std::complex< double > Cplx
Definition qsys_mg1_ps.h:89
MmcPrioEtaResult qsys_mmc_prio_eta(const std::vector< double > &lambda, double mu, unsigned c, unsigned r, unsigned v, unsigned q, const std::vector< double > &d, const std::string &type="np", const std::string &method="euler")
Expected tardiness at arrival of a class-r order.
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52
Exact stationary expected tardiness in a multiclass priority M/M/c queue (Hafizoglu,...
ErrorKind(std::string n)
Definition error.h:39
MATLAB's [Tard, Ptard, S] outputs, one entry of Tard and Ptard per due date.
std::vector< double > Ptard
P(T > d).
std::vector< double > Tard
E[(T - d)^+].