LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
trace_summary.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_TRACE_TRACE_SUMMARY_H
6#define LINE_API_TRACE_TRACE_SUMMARY_H
7
8/**
9 * @file
10 * @ingroup api_trace
11 * Descriptive summary of a trace: moments, shape, order statistics,
12 * autocorrelation and burstiness.
13 *
14 * Templated port of `jar/src/main/java/jline/api/trace/Trace_var.java#trace_summary`,
15 * cross-checked against matlab/lib/kpctoolbox/trace/trace_summary.m. The
16 * MATLAB version prints its result to a file id and returns the same
17 * quantities as separate outputs; the JAR returns them packed in a vector.
18 * This port returns a struct, so nothing is printed and nothing is positional.
19 *
20 * DIVERGENCES, MATLAB vs JAR, resolved as follows:
21 * - MAD: MATLAB uses mad(m,1), the median absolute deviation about the
22 * median. The JAR sorts the absolute deviations and takes element n/2,
23 * which is the upper median for even n and is not the median at all when
24 * n is even. MATLAB is the reference; the true median is used here.
25 * - KURT: the JAR subtracts 3, MATLAB's kurtosis does not. The field is
26 * named kurt_excess to make the convention explicit; add 3 for MATLAB.
27 * - SCV / IDC: the JAR uses the population variance everywhere, MATLAB the
28 * unbiased one; MATLAB is the reference (see trace_var.h).
29 * - percentiles: the linear-interpolation ("type 7") rule of the JAR is
30 * used. MATLAB's prctile interpolates on the (i-0.5)/n grid ("type 5")
31 * and gives different values on short traces; both agree in the limit.
32 *
33 * ARITHMETIC: the skewness and the standard deviation take square roots.
34 * static_assert(num_traits<T>::has_transcendental)
35 */
36
37#include <algorithm>
38#include <cstddef>
39#include <vector>
40
48#include "line/num/number.h"
49#include "line/util/error.h"
50
51namespace line {
52namespace trace {
53
54namespace detail {
55
56/** Median of an already sorted sample. */
57template <class T>
58inline T sorted_median(const std::vector<T>& x) {
59 const std::size_t n = x.size();
60 if (n % 2 == 1) return x[n / 2];
61 return (x[n / 2 - 1] + x[n / 2]) / num_traits<T>::from_int(2);
62}
63
64/** Linear-interpolation percentile of an already sorted sample. */
65template <class T>
66inline T sorted_percentile(const std::vector<T>& x, long p_num, long p_den) {
67 const long n = static_cast<long>(x.size());
68 if (n == 1) return x[0];
69 // index = (p/100) * (n-1), kept as an exact rational position
70 const long num = p_num * (n - 1);
71 const long lower = num / (p_den * 100);
72 const long rem = num - lower * p_den * 100;
73 if (rem == 0) return x[static_cast<std::size_t>(lower)];
74 const T w = num_traits<T>::from_rational(rem, p_den * 100);
75 return x[static_cast<std::size_t>(lower)] * (num_traits<T>::from_int(1) - w) +
76 x[static_cast<std::size_t>(lower + 1)] * w;
77}
78
79} // namespace detail
80
81/** Return value of trace_summary. */
82template <class T>
85 T scv;
86 T mad; ///< median absolute deviation about the median
87 T skew; ///< bias-corrected skewness, see trace_skew
88 T kurt_excess; ///< population kurtosis minus 3
89 T q25, q50, q75, p95;
90 T min, max, iqr;
91 std::vector<T> acf; ///< lags 1..4
92 T idc;
94};
95
96/**
97 * @brief Descriptive summary of a trace: moments, shape, order statistics,
98 * autocorrelation and burstiness.
99 *
100 * @param S the trace, at least 6 samples so that the lag-4 acf exists.
101 */
102template <class T>
103TraceSummary<T> trace_summary(const std::vector<T>& S) {
105 "trace_summary requires transcendental arithmetic");
106 detail::require_nonempty(S, "trace_summary");
107 if (S.size() < 6) throw InputError("trace_summary: at least six samples are required");
108
109 TraceSummary<T> out;
110 out.mean = trace_mean(S);
111 out.scv = trace_scv(S);
112
113 std::vector<T> x = S;
114 std::sort(x.begin(), x.end());
115 out.min = x.front();
116 out.max = x.back();
117 out.q25 = detail::sorted_percentile(x, 25, 1);
118 out.q50 = detail::sorted_percentile(x, 50, 1);
119 out.q75 = detail::sorted_percentile(x, 75, 1);
120 out.p95 = detail::sorted_percentile(x, 95, 1);
121 out.iqr = out.q75 - out.q25;
122
123 std::vector<T> dev(S.size());
124 for (std::size_t i = 0; i < S.size(); ++i) dev[i] = num_abs(T(S[i] - out.q50));
125 std::sort(dev.begin(), dev.end());
126 out.mad = detail::sorted_median(dev);
127
128 out.skew = trace_skew(S);
129
130 const T varp = trace_var(S, false);
131 if (varp == num_traits<T>::from_int(0))
132 throw NumericError("trace_summary: the trace is constant");
133 T k4 = num_traits<T>::from_int(0);
134 for (std::size_t i = 0; i < S.size(); ++i) {
135 const T d = S[i] - out.mean;
136 k4 += d * d * d * d;
137 }
138 k4 /= num_traits<T>::from_int(static_cast<long>(S.size()));
139 out.kurt_excess = k4 / (varp * varp) - num_traits<T>::from_int(3);
140
141 std::vector<int> lags;
142 for (int l = 1; l <= 4; ++l) lags.push_back(l);
143 out.acf = trace_acf(S, lags);
144
145 out.idc = trace_idc(S);
146 out.idc_scv_ratio = out.idc / out.scv;
147 return out;
148}
149
150} // namespace trace
151} // namespace line
152
153#endif // LINE_API_TRACE_TRACE_SUMMARY_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.
T trace_skew(const std::vector< T > &S)
Bias-corrected sample skewness (MATLAB's skewness(S,0), equivalently the G1 estimator).
Definition trace_skew.h:48
T trace_idc(const std::vector< T > &S)
Index of dispersion for counts, estimated by its asymptotic equality with the index of dispersion for...
Definition trace_idc.h:44
T trace_mean(const std::vector< T > &S)
(1/n) sum_i S(i).
Definition trace_mean.h:31
TraceSummary< T > trace_summary(const std::vector< T > &S)
Descriptive summary of a trace: moments, shape, order statistics, autocorrelation and burstiness.
T trace_var(const std::vector< T > &S, bool unbiased=true)
Sample variance of a trace.
Definition trace_var.h:45
T trace_scv(const std::vector< T > &S, bool unbiased=true)
Squared coefficient of variation of a trace, var/mean^2.
Definition trace_scv.h:39
std::vector< T > trace_acf(const std::vector< T > &S, const std::vector< int > &lags)
Autocorrelation coefficients of a trace at the requested lags.
Definition trace_acf.h:57
T num_abs(const T &v)
Definition number.h:172
Number-type abstraction for the templated API port.
Return value of trace_summary.
T mad
median absolute deviation about the median
T kurt_excess
population kurtosis minus 3
std::vector< T > acf
lags 1..4
T skew
bias-corrected skewness, see trace_skew
Autocorrelation coefficients of a trace at the requested lags.
Index of dispersion for counts, estimated by its asymptotic equality with the index of dispersion for...
Sample mean of a trace.
Squared coefficient of variation of a trace, var/mean^2.
Bias-corrected sample skewness (MATLAB's skewness(S,0), equivalently the G1 estimator).
Shared declarations for the empirical trace statistics domain.
Sample variance of a trace.