LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
fj_xmax_moments_het.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_FJ_XMAX_MOMENTS_HET_H
6#define LINE_API_FJ_XMAX_MOMENTS_HET_H
7
8/**
9 * @file
10 * @ingroup api_fj
11 * Moments of the maximum of heterogeneous exponentials by recurrence.
12 *
13 * Templated port of matlab/src/api/fj/fj_xmax_moments_het.m.
14 *
15 * M_m(lambda, n) = [ n M_m(lambda, n-1)
16 * + sum_{j=1..m} lambda_j M_{m-1}(lambda \ j, n) ]
17 * / sum_{j=1..m} lambda_j
18 *
19 * with M_m(lambda, 0) = 1 and M_0(., n) = 0 for n >= 1, which is the n-th
20 * derivative of the transform recurrence of fj_lst_max_het at the origin.
21 *
22 * Eq. (30) of the survey prints the second sum WITHOUT the lambda_j weight;
23 * that form is not the derivative of Eq. (29) and misses the textbook
24 * two-variable answer, so the weight is restored here. fj_xmax_het is the
25 * independent inclusion-exclusion check.
26 */
27
28#include <cstddef>
29#include <vector>
30
32#include "line/num/number.h"
33#include "line/util/error.h"
34
35namespace line {
36namespace fj {
37
38/**
39 * @brief Moments of the maximum of heterogeneous exponentials by recurrence.
40 *
41 * @param lambda the K positive exponential rates
42 * @param n highest moment order, n >= 1
43 * @return moments of orders 1..n of the maximum
44 */
45template <class T>
46std::vector<T> fj_xmax_moments_het(const std::vector<T>& lambda, unsigned n = 1) {
47 const std::size_t K = lambda.size();
48 if (K < 1) throw InputError("fj_xmax_moments_het: at least one rate is required");
49 if (n < 1) throw InputError("fj_xmax_moments_het: the moment order must be a positive integer");
50 if (K > 22)
51 throw InputError("fj_xmax_moments_het: the recurrence enumerates 2^K sub-collections");
52 const T zero = num_traits<T>::from_int(0), one = num_traits<T>::from_int(1);
53 for (std::size_t i = 0; i < K; ++i)
54 if (!(lambda[i] > zero))
55 throw InputError("fj_xmax_moments_het: all exponential rates must be positive");
56
57 const std::size_t nmask = static_cast<std::size_t>(1) << K;
58 // tab[mask][k] is the k-th moment over the sub-collection selected by mask
59 std::vector<std::vector<T> > tab(nmask, std::vector<T>(n + 1, zero));
60 for (std::size_t mask = 0; mask < nmask; ++mask) tab[mask][0] = one;
61
62 for (unsigned order = 1; order <= n; ++order) {
63 // The empty sub-collection has a zero maximum, so all its moments vanish
64 tab[0][order] = zero;
65 for (std::size_t mask = 1; mask < nmask; ++mask) {
66 T tot = zero;
67 T acc = num_traits<T>::from_int(static_cast<long>(order)) * tab[mask][order - 1];
68 for (std::size_t j = 0; j < K; ++j)
69 if (mask & (static_cast<std::size_t>(1) << j)) {
70 tot += lambda[j];
71 acc += lambda[j] * tab[mask ^ (static_cast<std::size_t>(1) << j)][order];
72 }
73 tab[mask][order] = acc / tot;
74 }
75 }
76
77 std::vector<T> out(n);
78 for (unsigned k = 1; k <= n; ++k) out[k - 1] = tab[nmask - 1][k];
79 return out;
80}
81
82} // namespace fj
83} // namespace line
84
85#endif // LINE_API_FJ_XMAX_MOMENTS_HET_H
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
Shared return types and arithmetic helpers for the templated fork-join port.
std::vector< T > fj_xmax_moments_het(const std::vector< T > &lambda, unsigned n=1)
Moments of the maximum of heterogeneous exponentials by recurrence.
Number-type abstraction for the templated API port.