LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
infer_qmle.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_INFER_INFER_QMLE_H
6#define LINE_API_INFER_INFER_QMLE_H
7
8/**
9 * @file
10 * @ingroup api_infer
11 * Queue-length-based maximum-likelihood estimator of the service demands of a
12 * closed queueing network.
13 *
14 * Templated port of matlab/src/api/infer/infer_qmle.m. The JAR has no
15 * counterpart: jline/api/infer/ carries the LQN identification classes only,
16 * so MATLAB is the sole reference.
17 *
18 * From the observed mean queue lengths Q, the populations N and the think
19 * times Z, the demand of class j at station i is estimated by
20 *
21 * D(i,j) = Q(i,j) / (N_j - sum_k Q(k,j)) * Z_j / (1 + sum_s Q(i,s) - Q(i,j)/N_j)
22 *
23 * i.e. the arrival-theorem residence time inverted for the demand, with the
24 * think-time population N_j - sum_k Q(k,j) supplying the class throughput.
25 *
26 * ARITHMETIC: additions, multiplications and divisions of the inputs only, so
27 * a finite field computation, exact in the exact instantiation.
28 */
29
30#include <cstddef>
31#include <vector>
32
33#include "line/num/number.h"
34#include "line/util/error.h"
35#include "line/util/matrix.h"
36
37namespace line {
38namespace infer {
39
40/**
41 * @brief Queue-length-based maximum-likelihood estimator of the service
42 * demands of a closed queueing network.
43 *
44 * @param Q (M x R) mean queue lengths
45 * @param N (R) population per class
46 * @param Z (R) think time per class
47 * @return (M x R) estimated service demands
48 */
49template <class T>
50Matrix<T> infer_qmle(const Matrix<T>& Q, const std::vector<T>& N, const std::vector<T>& Z) {
51 const std::size_t M = Q.rows(), R = Q.cols();
52 if (N.size() != R) throw InputError("infer_qmle: Q and N disagree on the class count");
53 if (Z.size() != R) throw InputError("infer_qmle: Q and Z disagree on the class count");
54 const T one = num_traits<T>::from_int(1);
55 const T zero = num_traits<T>::from_int(0);
56
57 // column sums of Q, the in-network population of each class
58 std::vector<T> colsum(R, zero);
59 for (std::size_t i = 0; i < M; ++i)
60 for (std::size_t j = 0; j < R; ++j) colsum[j] += Q(i, j);
61
62 Matrix<T> D(M, R, zero);
63 for (std::size_t i = 0; i < M; ++i) {
64 T rowsum = zero;
65 for (std::size_t s = 0; s < R; ++s) rowsum += Q(i, s);
66 for (std::size_t j = 0; j < R; ++j) {
67 const T think_pop = N[j] - colsum[j];
68 if (think_pop == zero)
69 throw NumericError("infer_qmle: a class has its whole population in the queues");
70 if (N[j] == zero) throw InputError("infer_qmle: zero population");
71 const T den = one + rowsum - Q(i, j) / N[j];
72 if (den == zero) throw NumericError("infer_qmle: singular arrival-theorem denominator");
73 D(i, j) = Q(i, j) / think_pop * Z[j] / den;
74 }
75 }
76 return D;
77}
78
79} // namespace infer
80} // namespace line
81
82#endif // LINE_API_INFER_INFER_QMLE_H
InputError(const std::string &what)
Definition error.h:39
std::size_t cols() const
Definition matrix.h:90
std::size_t rows() const
Definition matrix.h:89
NumericError(const std::string &what)
Definition error.h:45
The exception types the port throws.
Dense matrix and non-owning view.
Matrix< T > infer_qmle(const Matrix< T > &Q, const std::vector< T > &N, const std::vector< T > &Z)
Queue-length-based maximum-likelihood estimator of the service demands of a closed queueing network.
Definition infer_qmle.h:50
Number-type abstraction for the templated API port.