5#ifndef LINE_API_MAM_MAMAP22_FIT_BS_H
6#define LINE_API_MAM_MAMAP22_FIT_BS_H
82 double denumtol, T* q1, T* q2, T* q3) {
83 const T den = T(c.
U[10] * vB1 * p1 + c.
U[11] * p1);
88 *q2 = T((c.
U[6] * vB1 * vB1 * p1 * p1 + c.
U[7] * vB1 * p1 * p1 + c.
U[8] * vS11 +
91 *q1 = T(-(c.
G[11] * p1 - vB1 * c.
G[2] * p1 +
92 (c.
G[2] * c.
G[10] - c.
G[1] * c.
G[11]) * (*q2)) /
94 *q3 = T((c.
G[9] * p1 - vB1 * c.
G[0] * p1 +
95 (c.
G[0] * c.
G[10] - c.
G[1] * c.
G[9]) * (*q2)) /
101void fit_can2(
const Mamap2mCoefficients<T>& c,
const T& p1,
const T& vB1,
const T& vS11,
102 double denumtol, T* q1, T* q2, T* q3) {
103 const T den = T(c.U[10] * vB1 * p1 + c.U[11] * p1);
105 *q1 = *q2 = *q3 = p1;
108 *q3 = T((c.U[6] * vB1 * vB1 * p1 * p1 + c.U[7] * vB1 * p1 * p1 + c.U[8] * p1 * p1 +
111 *q1 = T((c.G[9] * p1 - vB1 * c.G[1] * p1 +
112 (c.G[1] * c.G[10] - c.G[2] * c.G[9]) * (*q3)) /
114 *q2 = T(-(c.G[8] * p1 - vB1 * c.G[0] * p1 +
115 (c.G[0] * c.G[10] - c.G[2] * c.G[8]) * (*q3)) /
132 const std::vector<T>& B,
const Matrix<T>& S,
133 const std::vector<T>& classWeights = std::vector<T>(),
134 const std::vector<T>& bsWeights = std::vector<T>(),
135 bool adjust =
true) {
137 "mamap22_fit_bs_multiclass inverts a moment system");
140 if (map.
D0.rows() != 2)
141 throw InputError(
"mamap22_fit_bs_multiclass: the underlying MAP must be second order");
143 throw InputError(
"mamap22_fit_bs_multiclass: the underlying MAP must be acyclic");
145 if (map.
D1(0, 1) == zero) form = 1;
146 else if (map.
D1(0, 0) == zero) form = 2;
149 "mamap22_fit_bs_multiclass: the underlying MAP must be in canonical acyclic form");
152 "mamap22_fit_bs_multiclass: fitting the backward moment and the transition "
153 "probabilities supports two classes only");
155 throw InputError(
"mamap22_fit_bs_multiclass: one backward moment per class is required");
157 throw InputError(
"mamap22_fit_bs_multiclass: the transition matrix is empty");
159 std::vector<T> cw = classWeights;
160 if (cw.empty()) cw.assign(2, one);
161 std::vector<T> bw = bsWeights;
162 if (bw.empty()) bw.assign(2, one);
164 const double degentol = 1e-6, feastol = 1e-4, denumtol = 1e-12;
166 T h1 = T(-one / mp.
D0(0, 0)), h2 = T(-one / mp.
D0(1, 1));
167 T r1 = T(mp.
D0(0, 1) * h1), r2 = T(mp.
D1(1, 1) * h2);
175 auto finish = [&](T q1, T q2, T q3) {
176 auto fix = [&](
const T& q) {
178 if (v < zero) v = zero;
179 if (v > one) v = one;
186 out.
mmap.Dc[0](0, 0) = T(out.
mmap.D1(0, 0) * q1);
187 out.
mmap.Dc[0](1, 0) = T(out.
mmap.D1(1, 0) * q2);
188 out.
mmap.Dc[0](1, 1) = T(out.
mmap.D1(1, 1) * q3);
189 out.
mmap.Dc[1](0, 0) = T(out.
mmap.D1(0, 0) * (one - q1));
190 out.
mmap.Dc[1](1, 0) = T(out.
mmap.D1(1, 0) * (one - q2));
191 out.
mmap.Dc[1](1, 1) = T(out.
mmap.D1(1, 1) * (one - q3));
193 out.
mmap.Dc[0](0, 1) = T(out.
mmap.D1(0, 1) * q1);
194 out.
mmap.Dc[0](1, 0) = T(out.
mmap.D1(1, 0) * q2);
195 out.
mmap.Dc[0](1, 1) = T(out.
mmap.D1(1, 1) * q3);
196 out.
mmap.Dc[1](0, 1) = T(out.
mmap.D1(0, 1) * (one - q1));
197 out.
mmap.Dc[1](1, 0) = T(out.
mmap.D1(1, 0) * (one - q2));
198 out.
mmap.Dc[1](1, 1) = T(out.
mmap.D1(1, 1) * (one - q3));
200 const std::vector<unsigned> ord(1, 1u);
202 out.
fB.assign(2, zero);
203 for (std::size_t c = 0; c < 2; ++c) out.
fB[c] = bm[c][0];
206 auto feasible = [&](
const T& q) {
207 return dv(q) >= -feastol && dv(q) <= 1.0 + feastol;
211 const bool degen1 = form == 1 && (dv(r1) < degentol || dv(r2) > 1.0 - degentol ||
212 std::fabs(dv(h2) - dv(h1) * dv(r2)) < degentol);
214 form == 2 && (dv(r2) > 1.0 - degentol ||
215 std::fabs(dv(h1) - dv(h2) - dv(h1) * dv(r1) + dv(h1) * dv(r1) * dv(r2)) <
217 if (degen1 || degen2) {
220 if (form == 1 && std::fabs(dv(h2) - dv(h1) * dv(r2)) < degentol)
223 std::fabs(dv(h1) - dv(h2) - dv(h1) * dv(r1) + dv(h1) * dv(r1) * dv(r2)) < degentol)
227 mp.
D0(0, 0) = T(-one / h1);
228 mp.
D0(0, 1) = T(r1 / h1);
229 mp.
D0(1, 1) = T(-one / h2);
231 mp.
D1(0, 0) = T((one - r1) / h1);
232 mp.
D1(1, 0) = T(r2 / h2);
233 mp.
D1(1, 1) = T((one - r2) / h2);
235 mp.
D1(0, 1) = T((one - r1) / h1);
236 mp.
D1(1, 0) = T(r2 / h2);
237 mp.
D1(1, 1) = T((one - r2) / h2);
245 if (form == 2 && dv(r2) < degentol && std::fabs(1.0 - dv(r1)) < degentol) {
246 finish(p[0], p[0], p[0]);
249 if (form == 1 && dv(r2) < degentol) {
256 const std::vector<unsigned> ord(1, 1u);
258 out.
fB.assign(2, zero);
259 for (std::size_t c = 0; c < 2; ++c) out.
fB[c] = bm[c][0];
263 if (std::fabs(1.0 - dv(r1)) < degentol) {
268 const std::vector<unsigned> ord(1, 1u);
270 out.
fB.assign(2, zero);
271 for (std::size_t c = 0; c < 2; ++c) out.
fB[c] = bm[c][0];
275 if (form == 2 && dv(r2) < degentol) {
277 auto degen_backward = [&](
const T& vB1, T* q1, T* q2, T* q3) {
278 *q1 = T((p[0] * (r1 - two) * (h2 - vB1 + h1 * r1)) /
279 ((r1 - one) * (h2 - h1 + h1 * r1)));
280 *q2 = T(-(p[0] * (vB1 - h1) * (r1 - two)) / (h2 - h1 + h1 * r1));
283 T q1 = zero, q2 = zero, q3 = zero;
284 if (dv(bw[0]) > dv(bw[1])) {
285 degen_backward(B[0], &q1, &q2, &q3);
286 if (!(feasible(q1) && feasible(q2) && feasible(q3))) {
290 const T q1B = T(-p[0] * (r1 - two) / ((r1 - one) * (h2 - h1 + h1 * r1)));
291 const T q1_0 = T(p[0] * (r1 - two) * (h2 + h1 * r1) /
292 ((r1 - one) * (h2 - h1 + h1 * r1)));
293 const T q2B = T(-p[0] * (r1 - two) / (h2 - h1 + h1 * r1));
294 const T q2_0 = T(p[0] * (r1 - two) * h1 / (h2 - h1 + h1 * r1));
295 double lo = 1e-6, hi = 1e6;
296 const double coefs[2] = {dv(q1B), dv(q2B)};
297 const double offs[2] = {dv(q1_0), dv(q2_0)};
298 for (
int i = 0; i < 2; ++i) {
299 if (std::fabs(coefs[i]) < denumtol)
continue;
301 const double a = -offs[i] / coefs[i], b = (1.0 - offs[i]) / coefs[i];
302 lo = std::max(lo, std::min(a, b));
303 hi = std::min(hi, std::max(a, b));
307 "mamap22_fit_bs_multiclass: the degenerate backward fit has an empty "
308 "feasible interval for this (p, B)");
319 auto degen_transition = [&](
const T& vS11, T* a, T* b, T* c) {
320 const double root = dv(T(p[0] * p[0] - vS11));
322 *a = T(p[0] + s / (r1 - one));
327 const bool real = degen_transition(S(0, 0), &q1, &q2, &q3);
328 if (!real || !(feasible(q1) && feasible(q2) && feasible(q3))) {
330 const double safety = 1e-10;
331 const double p1 = dv(p[0]), rr1 = dv(r1);
332 const double lb = p1 * p1 * (1.0 - (1.0 - rr1) * (1.0 - rr1));
333 const double ub = p1 * p1 - (1.0 - p1) * (1.0 - p1);
334 double s11 = dv(S(0, 0));
335 if (s11 <= lb) s11 = lb + safety;
336 else if (s11 >= ub) s11 = ub - safety;
348 T q1 = zero, q2 = zero, q3 = zero;
350 bsdetail::fit_can1(c, p[0], B[0], S(0, 0), denumtol, &q1, &q2, &q3);
352 bsdetail::fit_can2(c, p[0], B[0], S(0, 0), denumtol, &q1, &q2, &q3);
354 if (feasible(q1) && feasible(q2) && feasible(q3)) {
364 "mamap22_fit_bs_multiclass: the closed-form backward-plus-sigma inverse is infeasible for "
365 "these targets, and the reference's repair solves a NONCONVEX bilinear program with "
366 "YALMIP's bmibnb, a spatial branch-and-bound returning a GLOBAL optimum. That solver is "
367 "not ported; a local method would report a different fit under the same name. Pass "
368 "adjust = false to take the clamped closed form, weight the forward moment above sigma so "
369 "mamap2m_fit_fb_multiclass applies, or relax the targets");
385 const std::vector<T>& p,
const std::vector<T>& B,
389 if (a.
amaps.size() == 1 && a.
amaps[0].order() == 1) {
392 const T ratio = T(M2a / M2);
398 for (std::size_t j = 0; j < alt.size(); ++j) a.
amaps.push_back(
map_normalize(alt[j]));
400 return mamapdetail::marked_poisson(M1, p);
405 double bestErr = 0.0;
407 for (std::size_t j = 0; j < a.
amaps.size(); ++j) {
411 }
catch (
const Error&) {
417 const double err = db * db + ds * ds;
418 if (!have || err < bestErr) {
426 "mamap22_fit_gamma_bs: no AMAP(2) form admits a feasible backward-plus-sigma "
427 "marking for these targets");
435 const std::vector<T> p =
mmap_pc(mm);
436 const std::vector<std::vector<T>> bm =
438 std::vector<T> B(p.size());
439 for (std::size_t c = 0; c < p.size(); ++c) B[c] = bm[c][0];
447 if (Tv.empty() || Tv.size() != A.size())
449 "mamap22_fit_gamma_bs_trace: the trace and its labels must agree in length");
451 T m1 = zero, m2 = zero, m3 = zero;
452 for (std::size_t i = 0; i < Tv.size(); ++i) {
462 std::vector<T> B(p.size(), zero);
463 for (std::size_t c = 0; c < p.size(); ++c) B[c] = bm(c, 0);
AMAP(2) fit of three moments and the autocorrelation decay rate (matlab/lib/m3a/m3a/amap2/amap2_fit_g...
Base error for the multiprecision C++ port.
NumericError(const std::string &what)
UnsupportedError(const std::string &what)
The exception types the port throws.
The m3a fitters driven from a process or from a trace rather than from moments.
The marking coefficients of a canonical AMAP(2), for the sigma fitters.
The marked Poisson process every MAMAP fitter falls back to.
Autocorrelation decay rate of a MAP: the gamma of the geometric model rho(k) = rho0 * gamma^k with rh...
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
Fit a MAPH(2,m): a second-order acyclic phase-type marked with m classes.
Dense matrix and non-owning view.
Compression of a marked MAP into a smaller representation, and the two M3A primitives it is built fro...
Marked MAP (MMAP) algebra: per-class rates, class probabilities, superposition, normalization and sca...
Marked MAP statistics: embedded chains, class-transition probabilities, forward and cross moments,...
Backward moments of a marked trace: the moments of the inter-arrival time that PRECEDES an event of e...
Class probabilities of a marked trace, p_c = count_c / N.
One-step class transition frequencies of a marked trace,.
Mamap2mCoefficients< T > mamap2m_can1_coefficients(const T &h1, const T &h2, const T &r1, const T &r2)
First canonical form, a positive autocorrelation decay.
Amap2FitGammaResult< T > amap2_fit_gamma(const T &M1, const T &M2, const T &M3, const T &GAMMA, const T &cvtol)
Fit an AMAP(2) to (M1, M2, M3, GAMMA).
Mmap< T > mamap22_fit_gamma_bs_trace(const std::vector< T > &Tv, const std::vector< int > &A)
mamap22_fit_gamma_bs driven from a marked trace.
Mamap2mCoefficients< T > mamap2m_can2_coefficients(const T &h1, const T &h2, const T &r1, const T &r2)
Second canonical form, a negative autocorrelation decay (E, V, Z).
Mmap< T > mamap22_fit_gamma_bs_mmap(const Mmap< T > &mm)
mamap22_fit_gamma_bs driven from an MMAP[2] of arbitrary order.
Aph2FitResult< T > aph2_fit_map(const Map< T > &m)
Fit an APH(2) to the first three moments of a MAP.
std::vector< std::vector< T > > mmap_backward_moment(const Mmap< T > &m, const std::vector< unsigned > &orders, bool normalized)
Class-conditional backward moments of an MMAP (mmap_backward_moment.m).
Mamap22FitResult< T > mamap22_fit_bs_multiclass(const Map< T > &map, const std::vector< T > &p, const std::vector< T > &B, const Matrix< T > &S, const std::vector< T > &classWeights=std::vector< T >(), const std::vector< T > &bsWeights=std::vector< T >(), bool adjust=true)
Matrix< T > mmap_sigma(const Mmap< T > &mm)
sigma(i,j) = pie E_i E_j 1, the probability that two consecutive marks are (i,j).
Mmap< T > mamap22_fit_gamma_bs(const T &M1, const T &M2, const T &M3, const T &GAMMA, const std::vector< T > &p, const std::vector< T > &B, const Matrix< T > &S)
mamap22_fit_gamma_bs: fit over every AMAP(2) form and keep the closest.
std::vector< T > mmap_pc(const Mmap< T > &m)
Class probabilities seen by an arriving job, pc = pie (-D0)^-1 D1^(c) e.
Map< T > map_normalize(const Map< T > &in)
Clamp negative off-diagonal entries of D0 and negative entries of D1 to zero, then rebuild the diagon...
std::vector< Map< T > > amap2_fitall_gamma(const T &M1, const T &M2, const T &M3, const T &GAMMA, const T °entol, const T &r12tol)
Every AMAP(2) matching (M1, M2, M3, GAMMA).
T map_moment(const Map< T > &m, unsigned k)
Raw moment of order k of the inter-arrival time: k!
Maph2mFitResult< T > maph2m_fit_multiclass(const Map< T > &aph, const std::vector< T > &p, const std::vector< T > &B, const std::vector< T > &classWeights=std::vector< T >())
Mark a canonical acyclic APH(2) with m classes.
T map_gamma(const Map< T > &m, long limit=1000)
Autocorrelation decay rate of a MAP (map_gamma.m).
Matrix< T > mtrace_backward_moment(const std::vector< T > &Tv, const std::vector< int > &A, const std::vector< unsigned > &orders, bool norm=true)
Backward moments of a marked trace: the moments of the inter-arrival time that PRECEDES an event of e...
TraceGammaResult< T > trace_gamma(const std::vector< T > &S, long limit=1000, const std::vector< T > &grid=std::vector< T >())
Autocorrelation decay rate of a trace: the gamma of the geometric model rho(k) = rho0 * gamma^k,...
std::vector< T > mtrace_pc(const std::vector< int > &A)
Class probabilities of a marked trace, p_c = count_c / N.
Matrix< T > mtrace_sigma(const std::vector< int > &L)
One-step class transition frequencies of a marked trace, sigma(i,j) = #{t : A_t = i,...
Number-type abstraction for the templated API port.
Result of amap2_fit_gamma.
std::vector< Map< T > > amaps
every exact solution found
The fitted MAMAP(2,2), what it achieved, and whether the fit was exact.
std::vector< T > fB
achieved per-class backward moments
Matrix< T > fS
achieved class transition probabilities
The three coefficient tables of one canonical form.
std::vector< T > G
15 entries for form 1, 14 for form 2 (there called E)
std::vector< T > Y
3 determinants (Z for form 2)
std::vector< T > U
12 entries (V for form 2)
A MAP as the pair of matrices (D0, D1).
The fitted MAPH and the backward moments it actually achieved.
An MMAP: the underlying MAP plus the per-class arrival matrices.
Autocorrelation decay rate of a trace: the gamma of the geometric model rho(k) = rho0 * gamma^k,...