5#ifndef LINE_API_MAM_CME_H
6#define LINE_API_MAM_CME_H
64 std::vector<std::size_t> orders;
66 orders.push_back(
static_cast<std::size_t
>(2 *
iltcme::kTable[i].n + 1));
67 std::sort(orders.begin(), orders.end());
68 orders.erase(std::unique(orders.begin(), orders.end()), orders.end());
79 if (order < 3 || order % 2 == 0)
80 throw InputError(
"cme_table_entry: the order must be an odd integer 2n+1 with n >= 1");
82 const int n =
static_cast<int>((order - 1) / 2);
88 throw InputError(
"cme_table_entry: no tabulated CME of order " + std::to_string(order));
102 const std::size_t n =
static_cast<std::size_t
>(e.
n), sz = 2 * n + 1;
108 r.
alpha.assign(sz, zero);
110 const double mu1 = e.
mu1, w = e.
omega;
113 for (std::size_t k = 1; k <= n; ++k) {
114 const std::size_t i = 2 * k - 1;
115 const double wk =
static_cast<double>(k) * w;
120 const double d = 2.0 * (1.0 + wk * wk);
125 for (std::size_t i = 0; i < sz; ++i) s += r.
alpha[i];
127 throw NumericError(
"cme_representation: the entry law does not normalize");
128 for (std::size_t i = 0; i < sz; ++i) r.
alpha[i] = T(r.
alpha[i] / s);
135 const std::size_t n = A.
rows();
140 for (std::size_t i = 0; i < n; ++i) {
142 for (std::size_t j = 0; j < n; ++j) rowsum += A(i, j);
143 for (std::size_t j = 0; j < n; ++j) m.
D1(i, j) = T(-rowsum * alpha[j]);
170 "dist_fit_me takes a square root of the moment discriminant");
171 if (!std::isfinite(mean) || mean <= 0.0)
172 throw InputError(
"dist_fit_me: the mean must be a positive finite number");
173 if (!std::isfinite(scv) || scv <= 0.0 || scv >= 1.0)
175 "dist_fit_me: requires 0 < scv < 1; use a hyperexponential for scv >= 1 and a CME "
179 std::size_t bestOrder = 0;
180 for (std::size_t i = 0; i < orders.size(); ++i) {
181 const std::size_t order = orders[i];
182 if (maxPhases > 0 && order + 1 > maxPhases)
continue;
185 if (sY / (1.0 + sY) <= scv)
break;
188 throw InputError(
"dist_fit_me: no CME order fits a budget of " + std::to_string(maxPhases) +
189 " phases; the smallest is 3 phases plus one exponential");
192 const double sY = rep.
scv;
193 const double reach = sY / (1.0 + sY);
194 const double c = scv < reach ? mean / (1.0 + sY)
195 : mean * (1.0 - std::sqrt(1.0 - (1.0 + sY) * (1.0 - scv))) /
197 const double d = mean - c;
198 const std::size_t n = rep.
alpha.size();
201 if (d <= mean * 1e-12) {
204 for (std::size_t i = 0; i < n; ++i)
205 for (std::size_t j = 0; j < n; ++j) A(i, j) = T(A(i, j) * inv);
208 if (c <= mean * 1e-12) {
216 std::vector<T> alpha(n + 1, zero);
218 for (std::size_t i = 0; i < n; ++i) {
219 alpha[i] = rep.
alpha[i];
221 for (std::size_t j = 0; j < n; ++j) {
222 A(i, j) = T(rep.
A(i, j) * invc);
NumericError(const std::string &what)
The exception types the port throws.
The vendored concentrated-matrix-exponential (CME) coefficient table that matlab_ilt reads from iltcm...
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
Dense matrix and non-owning view.
const CmeEntry kTable[]
The reachable entries, in table order.
const std::size_t kTableSize
std::vector< std::size_t > cme_supported_orders()
Every phase count 2n+1 the vendored table realizes, ascending.
const iltcme::CmeEntry & cme_table_entry(std::size_t order)
The most concentrated table entry realizing order phases.
CmeRepresentation< T > cme_representation(std::size_t order)
Map< T > dist_fit_me(double mean, double scv, std::size_t maxPhases=0)
Two-moment matrix-exponential fit for 0 < scv < 1, a port of dist_fit_me.m.
Map< T > me_to_map(const std::vector< T > &alpha, const Matrix< T > &A)
Assemble the renewal (D0, D1) of a matrix-exponential law (alpha, A).
double cme_min_scv(std::size_t order)
The minimal SCV a CME of this order attains.
Number-type abstraction for the templated API port.
The unit-mean (alpha, A) form of a CME, with the SCV it attains.
double scv
the tabulated cv2 of this order
std::vector< T > alpha
entry law, sums to one
Matrix< T > A
(2n+1) square, generator-shaped but not a generator
A MAP as the pair of matrices (D0, D1).
One CME entry, carrying only the fields matlab_ilt reads.
double omega
angular frequency
const double * a
cosine coefficients, length n
int n
number of cosine/sine terms; the transform costs n+1 evaluations
double mu1
first moment scale
double cv2
squared coefficient of variation; smaller is steeper
const double * b
sine coefficients, length n