LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
fes_beta_handle.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_FES_BETA_HANDLE_H
6#define LINE_API_FES_BETA_HANDLE_H
7
8/**
9 * @file
10 * @ingroup api_fes
11 * Wraps a flow-equivalent-server throughput table as a per-class
12 * class-dependence function beta_{i,r}(n).
13 *
14 * Templated port of matlab/src/api/fes/fes_beta_handle.m. The returned
15 * callable takes the per-class population n at the FES station and returns
16 *
17 * beta_r(n) = X_r(n) |n| / n_r,
18 *
19 * the DIMENSIONLESS scaling relative to the nominal rate-1 service of the FES
20 * station. The |n|/n_r factor cancels the processor-sharing share that the
21 * convolution applies (Sauer 1983, eq. (40), with mu_{r,i}(n) = (n_r/|n|)
22 * beta_r(n)), leaving the aggregate completing class r at exactly the
23 * subnetwork throughput X_r(n). The population is clamped to the cutoffs, so
24 * the scaling saturates beyond the tabulated range as the table intends;
25 * entries with n_r = 0 are never consulted by the recurrence and are returned
26 * as 1.
27 *
28 * Arithmetic. One table lookup, one multiplication and one division, so this
29 * is exact at T = Rational.
30 *
31 * Deviation from MATLAB, mechanical: the MATLAB handle is a closure over the
32 * table; here it is a std::function that owns copies of the table and the
33 * cutoffs, so the returned callable outlives its arguments.
34 */
35
36#include <cstddef>
37#include <functional>
38#include <vector>
39
41#include "line/num/number.h"
42#include "line/util/error.h"
43
44namespace line {
45namespace fes {
46
47/** Class-dependence handle: population vector -> per-class beta. */
48template <class T>
49using FesBetaFun = std::function<std::vector<T>(const std::vector<int>&)>;
50
51/**
52 * @brief Wraps a flow-equivalent-server throughput table as a per-class
53 * class-dependence function beta_{i,r}(n).
54 *
55 * @param scalingTable (K) linearized per-class throughput vectors, as produced
56 * by fes_compute_throughputs
57 * @param cutoffs (K) the population vector the table was tabulated on
58 */
59template <class T>
60FesBetaFun<T> fes_beta_handle(const std::vector<std::vector<T>>& scalingTable,
61 const std::vector<int>& cutoffs) {
62 const std::vector<std::vector<T>> table = scalingTable;
63 const std::vector<int> cut = cutoffs;
64 return [table, cut](const std::vector<int>& nin) -> std::vector<T> {
65 const std::size_t K = table.size();
66 const T one = num_traits<T>::from_int(1);
67 std::vector<T> v(K, one);
68
69 // pad with zeros or truncate to the length of the cutoff vector
70 std::vector<int> n(cut.size(), 0);
71 for (std::size_t k = 0; k < cut.size() && k < nin.size(); ++k) n[k] = nin[k];
72
73 std::vector<int> nClamped(cut.size(), 0);
74 for (std::size_t k = 0; k < cut.size(); ++k) {
75 int x = n[k] < cut[k] ? n[k] : cut[k];
76 nClamped[k] = x < 0 ? 0 : x;
77 }
78 const std::size_t idx = ljd_linearize(nClamped, cut);
79
80 int tot = 0;
81 for (int x : n) tot += x;
82
83 for (std::size_t r = 0; r < K; ++r) {
84 if (r >= n.size()) break;
85 const std::vector<T>& tbl = table[r];
86 if (!tbl.empty() && idx >= 1 && idx <= tbl.size() && n[r] > 0) {
87 // FES station rate-sharing rationale: see _kb/03-api-layer.md (cpp port notes: fes)
88 v[r] = tbl[idx - 1] * num_traits<T>::from_int(tot) / num_traits<T>::from_int(n[r]);
89 }
90 }
91 return v;
92 };
93}
94
95} // namespace fes
96} // namespace line
97
98#endif // LINE_API_FES_BETA_HANDLE_H
The exception types the port throws.
Linearized index of a per-class population vector, for Limited Joint Dependence (LJD) tables.
FesBetaFun< T > fes_beta_handle(const std::vector< std::vector< T > > &scalingTable, const std::vector< int > &cutoffs)
Wraps a flow-equivalent-server throughput table as a per-class class-dependence function beta_{i,...
std::function< std::vector< T >(const std::vector< int > &)> FesBetaFun
Class-dependence handle: population vector -> per-class beta.
std::size_t ljd_linearize(const std::vector< int > &nvec, const std::vector< int > &cutoffs)
Linearized index of a per-class population vector, for Limited Joint Dependence (LJD) tables.
Number-type abstraction for the templated API port.