LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
pfqn_mu_ms.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_PFQN_MU_MS_H
6#define LINE_API_PFQN_MU_MS_H
7
8/**
9 * @file
10 * @ingroup api_pfqn
11 * Aggregate load-dependent rate of m identical c-server FCFS stations.
12 *
13 * Templated port of matlab/src/api/pfqn/pfqn_mu_ms.m.
14 *
15 * A single c-server station holding k jobs has balance function
16 * beta_1(k) = 1 / prod_{j=1}^{k} min(j, c). The flow-equivalent aggregate of m
17 * such stations in parallel has the convolution
18 *
19 * beta_m(n) = sum_{k=0}^{n} beta_1(k) beta_{m-1}(n - k), beta_m(0) = 1,
20 *
21 * and the load-dependent rate of the aggregate is the ratio of consecutive
22 * balance-function values,
23 *
24 * mu(n) = beta_m(n - 1) / beta_m(n), n = 1, ..., N.
25 *
26 * The reference writes the inner term as 1/(prod(a) * prod(b)) with
27 * b = 1/beta_{m-1}(n-k), i.e. as beta_{m-1}(n-k)/prod_{j<=k} min(j,c), which is
28 * the convolution above; the MATLAB idiom relies on prod([]) = 1 to cover
29 * k = 0. It also fills the table with the population outermost and the station
30 * count innermost, so beta_{m-1}(n) is available at the same n; that ordering
31 * is preserved here even though the port could iterate either way.
32 *
33 * Arithmetic: EXACT-CAPABLE. Only additions, multiplications and divisions in
34 * the field of the inputs, all of them on values built from the integers, so
35 * at T = Rational the returned rates are exact rationals.
36 */
37
38#include <cstddef>
39#include <vector>
40
41#include "line/num/number.h"
42#include "line/util/error.h"
43
44namespace line {
45namespace pfqn {
46
47/**
48 * @brief Aggregate load-dependent rate of m identical c-server FCFS stations.
49 *
50 * @param N maximum population
51 * @param m number of identical stations
52 * @param c number of servers per station
53 * @return (N) rates mu(1), ..., mu(N)
54 */
55template <class T>
56std::vector<T> pfqn_mu_ms(int N, int m, int c) {
57 if (N < 0) throw InputError("pfqn_mu_ms: negative population");
58 if (m < 1) throw InputError("pfqn_mu_ms: the station count must be at least one");
59 if (c < 1) throw InputError("pfqn_mu_ms: the server count must be at least one");
60
61 const T one = num_traits<T>::from_int(1);
62 const T zero = num_traits<T>::from_int(0);
63
64 // beta_1(k) = 1 / prod_{j=1}^{k} min(j, c), tabulated once.
65 std::vector<T> beta1(static_cast<std::size_t>(N) + 1, one);
66 for (int k = 1; k <= N; ++k) {
67 const int mn = k < c ? k : c;
68 beta1[static_cast<std::size_t>(k)] =
69 beta1[static_cast<std::size_t>(k - 1)] / num_traits<T>::from_int(mn);
70 }
71
72 // g[i][n] = beta_{i+1}(n); population outermost, as in the reference.
73 std::vector<std::vector<T>> g(static_cast<std::size_t>(m),
74 std::vector<T>(static_cast<std::size_t>(N) + 1, zero));
75 for (int n = 0; n <= N; ++n) {
76 for (int i = 1; i <= m; ++i) {
77 if (n == 0) {
78 g[static_cast<std::size_t>(i - 1)][0] = one;
79 } else if (i == 1) {
80 g[0][static_cast<std::size_t>(n)] = beta1[static_cast<std::size_t>(n)];
81 } else {
82 T s = zero;
83 for (int k = 0; k <= n; ++k)
84 s += beta1[static_cast<std::size_t>(k)] *
85 g[static_cast<std::size_t>(i - 2)][static_cast<std::size_t>(n - k)];
86 g[static_cast<std::size_t>(i - 1)][static_cast<std::size_t>(n)] = s;
87 }
88 }
89 }
90
91 std::vector<T> mu(static_cast<std::size_t>(N), one);
92 for (int n = 1; n <= N; ++n) {
93 const T& den = g[static_cast<std::size_t>(m - 1)][static_cast<std::size_t>(n)];
94 if (den == zero) throw NumericError("pfqn_mu_ms: zero balance function");
95 mu[static_cast<std::size_t>(n - 1)] =
96 g[static_cast<std::size_t>(m - 1)][static_cast<std::size_t>(n - 1)] / den;
97 }
98 return mu;
99}
100
101} // namespace pfqn
102} // namespace line
103
104#endif // LINE_API_PFQN_MU_MS_H
InputError(const std::string &what)
Definition error.h:39
NumericError(const std::string &what)
Definition error.h:45
The exception types the port throws.
std::vector< T > pfqn_mu_ms(int N, int m, int c)
Aggregate load-dependent rate of m identical c-server FCFS stations.
Definition pfqn_mu_ms.h:56
Number-type abstraction for the templated API port.