LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
moment_cumulant.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_MOMENT_MOMENT_CUMULANT_H
6#define LINE_API_MOMENT_MOMENT_CUMULANT_H
7
8/**
9 * @file
10 * @ingroup api_moment
11 * Cumulants from raw moments and the inverse, plus the factorial-cumulant pair.
12 *
13 * Templated port of matlab/src/api/moment/moment_cumulant_from_raw.m,
14 * moment_raw_from_cumulant.m, moment_factcumulant_from_factorial.m and
15 * moment_factorial_from_factcumulant.m. The recurrence is the one obtained by
16 * differentiating log M(t) once, so it is triangular and every operation is
17 * integer or rational.
18 *
19 * The factorial-cumulant pair is the SAME recurrence read on the factorial
20 * sequence, which is why MATLAB delegates rather than duplicating it.
21 *
22 * Entry 0 of the cumulant vector is always 0 by convention, and entry 0 of the
23 * raw vector is always 1, whatever the caller passes in.
24 */
25
26#include <vector>
27
28#include "line/num/number.h"
29#include "line/util/error.h"
30#include "line/util/matrix.h"
32
33namespace line {
34namespace moment {
35
36/** kappa_i = m_i - sum_{k=1}^{i-1} C(i-1,k-1) kappa_k m_{i-k}. */
37template <class T>
38std::vector<T> moment_cumulant_from_raw(const std::vector<T>& m) {
39 if (m.empty()) throw InputError("moment_cumulant_from_raw: m must be nonempty");
40 const int n = static_cast<int>(m.size()) - 1;
41 std::vector<T> kappa(m.size(), num_traits<T>::from_int(0));
42 for (int i = 1; i <= n; ++i) {
43 T acc = num_traits<T>::from_int(0);
44 for (int k = 1; k <= i - 1; ++k) acc += num_nck<T>(i - 1, k - 1) * kappa[k] * m[i - k];
45 kappa[i] = m[i] - acc;
46 }
47 return kappa;
48}
49
50/** m_i = sum_{k=1}^{i} C(i-1,k-1) kappa_k m_{i-k}, with m_0 = 1. */
51template <class T>
52std::vector<T> moment_raw_from_cumulant(const std::vector<T>& kappa) {
53 if (kappa.empty()) throw InputError("moment_raw_from_cumulant: kappa must be nonempty");
54 const int n = static_cast<int>(kappa.size()) - 1;
55 std::vector<T> m(kappa.size(), num_traits<T>::from_int(0));
57 for (int i = 1; i <= n; ++i) {
58 T acc = num_traits<T>::from_int(0);
59 for (int k = 1; k <= i; ++k) acc += num_nck<T>(i - 1, k - 1) * kappa[k] * m[i - k];
60 m[i] = acc;
61 }
62 return m;
63}
64
65/** Factorial cumulants from factorial moments. */
66template <class T>
67std::vector<T> moment_factcumulant_from_factorial(const std::vector<T>& f) {
69}
70
71/** Factorial moments from factorial cumulants. */
72template <class T>
73std::vector<T> moment_factorial_from_factcumulant(const std::vector<T>& kappa) {
74 return moment_raw_from_cumulant<T>(kappa);
75}
76
77} // namespace moment
78} // namespace line
79
80#endif
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
Dense matrix and non-owning view.
std::vector< T > moment_raw_from_cumulant(const std::vector< T > &kappa)
mi = sum{k=1}^{i} C(i-1,k-1) kappa_k m_{i-k}, with m_0 = 1.
std::vector< T > moment_factorial_from_factcumulant(const std::vector< T > &kappa)
Factorial moments from factorial cumulants.
std::vector< T > moment_cumulant_from_raw(const std::vector< T > &m)
kappa_i = m_i - sum_{k=1}^{i-1} C(i-1,k-1) kappa_k m_{i-k}.
std::vector< T > moment_factcumulant_from_factorial(const std::vector< T > &f)
Factorial cumulants from factorial moments.
T num_nck(int n, int k)
Binomial coefficient as a value of T, by the Pascal recurrence.
Definition population.h:87
Number-type abstraction for the templated API port.
Population-vector enumeration and combinatorics.