LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
aph2_fitall.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_MAM_APH2_FITALL_H
6
#define LINE_API_MAM_APH2_FITALL_H
7
8
/**
9
* @file
10
* @ingroup api_mam
11
* All APH(2) representations matching three moments
12
* (matlab/lib/m3a/m3a/aph2/aph2_fitall.m).
13
*
14
* The two phase means solve a quadratic whose discriminant is
15
* tmp0 = M3^2/9 + (8 M1^3/3 - 2 M1 M2) M3 - 3 M1^2 M2^2 + 2 M2^3,
16
* giving one solution when tmp0 vanishes (identical diagonal entries of D0)
17
* and two otherwise. Each is retained only when both phase means are positive
18
* and the branching probability lies in [0, 1] up to a degeneracy tolerance.
19
*
20
* As in the in-tree MATLAB (the "added by GC" branches), an infeasible
21
* discriminant or an empty feasible set falls back to a single aph_fit(M1, M2,
22
* M3, 2), so the result is never empty.
23
*
24
* Gated on transcendental arithmetic: the discriminant square root and the
25
* SCV <= 1 lower bound of the third moment.
26
*/
27
28
#include <vector>
29
30
#include "
line/api/mam/aph2_assemble.h
"
31
#include "
line/api/mam/aph_fit.h
"
32
#include "
line/api/mam/map_fit_detail.h
"
33
#include "
line/api/mam/map_moment.h
"
34
#include "
line/num/number.h
"
35
#include "
line/util/error.h
"
36
37
namespace
line
{
38
namespace
mam
{
39
40
/**
41
* All feasible APH(2) fits of (M1, M2, M3). degentol is the tolerance used
42
* both for the "M3 sits on its lower bound" degeneracy and for accepting a
43
* branching probability marginally outside [0, 1] (MATLAB uses 1e-8).
44
*/
45
template
<
class
T>
46
std::vector<Map<T>>
aph2_fitall
(
const
T& M1,
const
T& M2,
const
T& M3,
const
T& degentol) {
47
static_assert
(
num_traits<T>::has_transcendental
,
48
"aph2_fitall requires transcendental arithmetic"
);
49
using
fitdetail::num_sqrt;
50
using
fitdetail::pw;
51
52
const
T zero =
num_traits<T>::from_int
(0);
53
const
T one =
num_traits<T>::from_int
(1);
54
const
T two =
num_traits<T>::from_int
(2);
55
const
T three =
num_traits<T>::from_int
(3);
56
57
if
(M1 <= zero)
throw
InputError
(
"aph2_fitall: non-positive first moment"
);
58
59
const
T SCV = (M2 - M1 * M1) / (M1 * M1);
60
bool
degenerate =
false
;
61
if
(SCV <= one) {
62
const
T d = one - SCV;
63
const
T M3lb = three * pw(M1, 3) * (three * SCV - one + num_sqrt(two) * d * num_sqrt(d));
64
if
(
num_abs
(T(M3 - M3lb)) < degentol) degenerate =
true
;
65
}
66
67
T tmp0 = zero;
68
if
(!degenerate) {
69
tmp0 = M3 * M3 /
num_traits<T>::from_int
(9) +
70
((
num_traits<T>::from_int
(8) * pw(M1, 3)) / three - two * M2 * M1) * M3 -
71
three * M1 * M1 * M2 * M2 + two * pw(M2, 3);
72
if
(tmp0 < zero) {
73
std::vector<Map<T>> out;
74
out.push_back(
aph_fit
(M1, M2, M3, 2u).aph);
75
return
out;
76
}
77
}
78
79
const
T tmp1 = three * num_sqrt(tmp0);
80
const
T tmp2 = M3 - three * M1 * M2;
81
const
T tmp3 =
num_traits<T>::from_int
(6) * M2 -
num_traits<T>::from_int
(12) * M1 * M1;
82
// M2 == 2 M1^2 is SCV == 1: the EXPONENTIAL, and the commonest input there
83
// is, not a malformed moment set. The reference does not guard it -- at
84
// SCV <= 1 with M3 on its lower bound it takes the tmp0 == 0 path and
85
// evaluates tmp2/tmp3, which for an exponential is 0/0 and yields NaN that
86
// the caller later discards as unfeasible. Throwing was worse than the NaN,
87
// since it took down a Poisson split/merge that has an exact answer; but
88
// returning the NaN would be worse still. Both roots of this quadratic are
89
// unusable when tmp3 vanishes (0/0 when tmp2 does too, otherwise infinite),
90
// so hand the moments to the general n-phase fitter, exactly as the
91
// infeasible branch above already does.
92
if
(tmp3 == zero) {
93
std::vector<Map<T>> out;
94
out.push_back(
aph_fit
(M1, M2, M3, 2u).aph);
95
return
out;
96
}
97
98
const
std::size_t n = (tmp0 == zero) ? 1u : 2u;
99
std::vector<T> h1v(n, zero), h2v(n, zero);
100
if
(n == 1) {
101
h2v[0] = tmp2 / tmp3;
102
h1v[0] = h2v[0];
103
}
else
{
104
h2v[0] = (tmp2 + tmp1) / tmp3;
105
h2v[1] = (tmp2 - tmp1) / tmp3;
106
h1v[1] = h2v[0];
107
h1v[0] = h2v[1];
108
}
109
110
std::vector<Map<T>> out;
111
for
(std::size_t j = 0; j < n; ++j) {
112
const
T h1 = h1v[j];
113
const
T h2 = h2v[j];
114
if
(h2 == zero)
continue
;
115
T r1 = (M1 - h1) / h2;
116
if
(h1 > zero && h2 > zero && r1 >= -degentol && r1 <= one + degentol) {
117
if
(r1 > one) r1 = one;
118
if
(r1 < zero) r1 = zero;
119
out.push_back(
aph2_assemble
(h1, h2, r1));
120
}
121
}
122
if
(out.empty()) out.push_back(
aph_fit
(M1, M2, M3, 2u).aph);
123
return
out;
124
}
125
126
/** aph2_fitall with the MATLAB default degentol = 1e-8. */
127
template
<
class
T>
128
std::vector<Map<T>>
aph2_fitall
(
const
T& M1,
const
T& M2,
const
T& M3) {
129
return
aph2_fitall
(M1, M2, M3, T(
num_traits<T>::from_double
(1e-8)));
130
}
131
132
}
// namespace mam
133
}
// namespace line
134
135
#endif
// LINE_API_MAM_APH2_FITALL_H
aph2_assemble.h
Assemble an APH(2) from its canonical parameters (matlab/lib/m3a/m3a/aph2/aph2_assemble....
aph_fit.h
Minimal-order acyclic phase-type fit of the first three moments (matlab/lib/kpctoolbox/aph/aph_fit....
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
error.h
The exception types the port throws.
map_fit_detail.h
Scalar helpers shared by the MAP/PH moment-matching headers.
map_moment.h
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
line::mam
Definition
amap2_adjust_gamma.h:78
line::mam::aph2_fitall
std::vector< Map< T > > aph2_fitall(const T &M1, const T &M2, const T &M3, const T °entol)
All feasible APH(2) fits of (M1, M2, M3).
Definition
aph2_fitall.h:46
line::mam::aph2_assemble
Map< T > aph2_assemble(const T &l1, const T &l2, const T &p1)
APH(2) with phase means l1, l2 and continuation probability p1.
Definition
aph2_assemble.h:36
line::mam::aph_fit
AphFitResult< T > aph_fit(const T &e1, const T &e2, const T &e3, unsigned nmax, const T &tol)
Fit an APH(n) with n <= nmax to the raw moments e1, e2, e3.
Definition
aph_fit.h:176
line
Definition
aoi_dist2ph.h:52
line::num_abs
T num_abs(const T &v)
Definition
number.h:172
number.h
Number-type abstraction for the templated API port.
line::num_traits
Definition
number.h:111
include
line
api
mam
aph2_fitall.h
Generated by
1.18.0