LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
pfqn_jdfun.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_JDFUN_H
6#define LINE_API_PFQN_JDFUN_H
7
8/**
9 * @file
10 * @ingroup api_pfqn
11 * AMVA joint-dependence function for non-product-form scaling.
12 *
13 * Templated port of matlab/src/api/pfqn/pfqn_jdfun.m.
14 *
15 * Returns, for every station i, the reciprocal of the joint-dependent scaling
16 * eta_i(n_{i1}, ..., n_{iR}) evaluated at the per-station population row
17 * nvec(i,:), for the requested class.
18 *
19 * jdscaling[i] is a callable of that row. It may return a single value, i.e. a
20 * scaling eta_i(n) shared by every class (broadcast, as in the flagship
21 * min(n_i1, c)), or R values, i.e. the per-class scalings eta_{i,r}(n), of
22 * which element classIdx is taken (Sauer chain-dependent rate mu_{r,i}(n)).
23 *
24 * Unlike pfqn_cdfun -- whose beta_{i,r} is a product-form scaling reading only
25 * the own-class marginal n_{i,r} -- eta may read the joint vector arbitrarily
26 * and is therefore NON-product-form: the AMVA result is an approximation with
27 * no exactness or uniqueness guarantee. The numerical evaluation is identical
28 * to pfqn_cdfun; the distinction is semantic and is carried by the separate
29 * sn.jdscaling field.
30 *
31 * Arithmetic: EXACT-CAPABLE. One reciprocal per station and nothing else, so
32 * no transcendental gate; exactness is a property of the supplied callables.
33 */
34
35#include <cstddef>
36#include <functional>
37#include <vector>
38
39#include "line/num/number.h"
40#include "line/util/error.h"
41#include "line/util/matrix.h"
42
43namespace line {
44namespace pfqn {
45
46/** A per-station joint-dependence callable: the population row -> 1 or R rates. */
47template <class T>
48using JdScaling = std::function<std::vector<T>(const std::vector<T>&)>;
49
50/**
51 * @brief AMVA joint-dependence function for non-product-form scaling.
52 *
53 * @param nvec (M x R) per-station, per-class populations
54 * @param jdscaling (M) callables; entries may be empty for "no scaling"
55 * @param classIdx 0-based class whose scaling is selected from a vector result
56 * @return (M) reciprocals of the scalings
57 */
58template <class T>
59std::vector<T> pfqn_jdfun(const Matrix<T>& nvec, const std::vector<JdScaling<T>>& jdscaling,
60 std::size_t classIdx) {
61 const std::size_t M = nvec.rows();
62 const std::size_t R = nvec.cols();
63 const T one = num_traits<T>::from_int(1);
64 std::vector<T> r(M, one);
65 if (jdscaling.empty()) return r;
66 if (jdscaling.size() != M)
67 throw InputError("pfqn_jdfun: scaling vector has the wrong station count");
68 for (std::size_t i = 0; i < M; ++i) {
69 if (!jdscaling[i]) continue;
70 std::vector<T> row(R);
71 for (std::size_t s = 0; s < R; ++s) row[s] = nvec(i, s);
72 const std::vector<T> v = jdscaling[i](row);
73 if (v.empty()) throw InputError("pfqn_jdfun: a scaling callable returned nothing");
74 const T& chosen = v.size() > 1 ? v.at(classIdx) : v[0];
75 if (chosen == num_traits<T>::from_int(0))
76 throw NumericError("pfqn_jdfun: a joint-dependent scaling is zero");
77 r[i] = one / chosen;
78 }
79 return r;
80}
81
82/** MATLAB default: classIdx = 1, i.e. the first class. */
83template <class T>
84std::vector<T> pfqn_jdfun(const Matrix<T>& nvec, const std::vector<JdScaling<T>>& jdscaling) {
85 return pfqn_jdfun(nvec, jdscaling, static_cast<std::size_t>(0));
86}
87
88} // namespace pfqn
89} // namespace line
90
91#endif // LINE_API_PFQN_JDFUN_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.
std::vector< T > pfqn_jdfun(const Matrix< T > &nvec, const std::vector< JdScaling< T > > &jdscaling, std::size_t classIdx)
AMVA joint-dependence function for non-product-form scaling.
Definition pfqn_jdfun.h:59
std::function< std::vector< T >(const std::vector< T > &)> JdScaling
A per-station joint-dependence callable: the population row -> 1 or R rates.
Definition pfqn_jdfun.h:48
Number-type abstraction for the templated API port.