LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
qsys_mg1_conservation.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_MG1_CONSERVATION_H
6#define LINE_API_QSYS_QSYS_MG1_CONSERVATION_H
7
8/**
9 * @file
10 * @ingroup api_qsys
11 * Kleinrock's conservation law for work-conserving non-preemptive M/G/1
12 * disciplines.
13 *
14 * Port of matlab/src/api/qsys/qsys_mg1_conservation.m. For any such
15 * discipline sum_i rho_i Wq_i is invariant and equals
16 *
17 * V = rho sum_i lambda_i E[S_i^2] / (2 (1 - rho)),
18 *
19 * so V/rho is the FCFS waiting time; given per-class waiting times W the
20 * residual sum_i rho_i W_i - V checks a discipline against the law.
21 *
22 * ARITHMETIC: field; exact for T = Rational. A residual not asked for is NaN
23 * in MATLAB, which the exact field cannot hold, so `hasResidual` flags it and
24 * the res field is set only when W was given.
25 */
26
27#include <cstddef>
28#include <limits>
29#include <vector>
30
32#include "line/num/number.h"
33#include "line/util/error.h"
34
35namespace line {
36namespace qsys {
37
38/** MATLAB's [V, res] outputs. */
39template <class T>
41 T V; ///< the invariant
42 T fcfsWaitingTime; ///< V/rho
43 T residual; ///< sum_i rho_i W_i - V, when W was given
44 bool hasResidual = false; ///< false: MATLAB's residual = NaN
45};
46
47/**
48 * @brief The M/G/1 conservation-law invariant.
49 *
50 * @param lambda per-class arrival rates
51 * @param mu per-class service rates
52 * @param cs per-class coefficients of variation of the service time
53 * @param W per-class mean waiting times to check; empty when not given
54 */
55template <class T>
56Mg1ConservationResult<T> qsys_mg1_conservation(const std::vector<T>& lambda, const std::vector<T>& mu,
57 const std::vector<T>& cs,
58 const std::vector<T>& W = std::vector<T>()) {
59 const T zero = num_traits<T>::from_int(0), one = num_traits<T>::from_int(1);
60 const T two = num_traits<T>::from_int(2);
61 const std::size_t R = lambda.size();
62 bool bad = mu.size() != R || cs.size() != R;
63 for (std::size_t i = 0; !bad && i < R; ++i)
64 if (lambda[i] <= zero || mu[i] <= zero || cs[i] < zero) bad = true;
65 if (bad)
66 throw InputError(ErrorKind("Argument"),
67 "qsys_mg1_conservation: lambda, mu, cs must be equal-length, lambda and mu positive, "
68 "cs non-negative");
69 std::vector<T> rho_i(R);
70 T rho = zero, lES2 = zero;
71 for (std::size_t i = 0; i < R; ++i) {
72 rho_i[i] = T(lambda[i] / mu[i]);
73 rho += rho_i[i];
74 lES2 += T(lambda[i] * (one + cs[i] * cs[i]) / (mu[i] * mu[i]));
75 }
76 if (rho >= one) resdetail::throw_unstable("qsys_mg1_conservation", "rho", num_traits<T>::to_double(rho));
78 r.V = T(rho * lES2 / (two * (one - rho)));
79 r.fcfsWaitingTime = T(r.V / rho);
80 r.residual = zero;
81 if (!W.empty()) {
82 if (W.size() != R)
83 throw InputError(ErrorKind("Argument"), "qsys_mg1_conservation: W must have one entry per class");
84 T s = zero;
85 for (std::size_t i = 0; i < R; ++i) s += T(rho_i[i] * W[i]);
86 r.residual = T(s - r.V);
87 r.hasResidual = true;
88 }
89 return r;
90}
91
92} // namespace qsys
93} // namespace line
94
95#endif // LINE_API_QSYS_QSYS_MG1_CONSERVATION_H
InputError(const std::string &what)
Definition error.h:105
The exception types the port throws.
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
Mg1ConservationResult< T > qsys_mg1_conservation(const std::vector< T > &lambda, const std::vector< T > &mu, const std::vector< T > &cs, const std::vector< T > &W=std::vector< T >())
The M/G/1 conservation-law invariant.
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52
Number-type abstraction for the templated API port.
The res struct the exact queueing-system functions return, and the numeric helpers those functions sh...
ErrorKind(std::string n)
Definition error.h:39
bool hasResidual
false: MATLAB's residual = NaN
T residual
sum_i rho_i W_i - V, when W was given