5#ifndef LINE_API_MAM_MMAP_MODULATE_H
6#define LINE_API_MAM_MMAP_MODULATE_H
71 const std::vector<
Mmap<T>>& comps) {
72 const std::size_t J = HT.size();
73 if (comps.size() != J)
74 throw InputError(
"mmap_modulate: the holding-time and MMAP lists must have equal length");
75 if (J == 0)
throw InputError(
"mmap_modulate: no environments given");
77 throw InputError(
"mmap_modulate: P must be square of the environment count");
82 std::vector<Mmap<T>> M = comps;
83 for (std::size_t j = 0; j < J; ++j)
84 if (M[j].Dc.empty()) M[j].Dc.push_back(M[j].D1);
85 const std::size_t K = M[0].classes();
86 for (std::size_t j = 1; j < J; ++j)
87 if (M[j].classes() != K)
88 throw InputError(
"mmap_modulate: the MMAPs must have the same number of types");
90 std::vector<std::size_t> nh(J), nm(J), nq(J), off(J + 1, 0);
91 for (std::size_t j = 0; j < J; ++j) {
92 nh[j] = HT[j].D0.rows();
94 nq[j] = nh[j] * nm[j];
95 off[j + 1] = off[j] + nq[j];
97 const std::size_t N = off[J];
105 std::vector<std::vector<T>> entry(J);
106 for (std::size_t i = 0; i < J; ++i) {
107 const std::vector<T> a =
map_pie(HT[i]);
108 const std::vector<T> b =
map_pie(M[i].map());
109 entry[i].assign(nq[i], zero);
110 for (std::size_t p = 0; p < nh[i]; ++p)
111 for (std::size_t q = 0; q < nm[i]; ++q) entry[i][p * nm[i] + q] = T(a[p] * b[q]);
114 for (std::size_t j = 0; j < J; ++j) {
117 for (std::size_t r = 0; r < nq[j]; ++r)
118 for (std::size_t c = 0; c < nq[j]; ++c) out.
D0(off[j] + r, off[j] + c) = diag(r, c);
121 for (std::size_t k = 0; k < K; ++k) {
123 for (std::size_t r = 0; r < nq[j]; ++r)
124 for (std::size_t c = 0; c < nq[j]; ++c)
125 out.
Dc[k](off[j] + r, off[j] + c) = blk(r, c);
131 std::vector<T> exitRow(nq[j], zero);
132 for (std::size_t r = 0; r < nq[j]; ++r) {
134 for (std::size_t c = 0; c < nq[j]; ++c) s += exit(r, c);
137 for (std::size_t i = 0; i < J; ++i) {
138 if (i == j)
continue;
139 for (std::size_t r = 0; r < nq[j]; ++r)
140 for (std::size_t c = 0; c < nq[i]; ++c)
141 out.
D0(off[j] + r, off[i] + c) = T(P(j, i) * exitRow[r] * entry[i][c]);
157 const std::size_t m = PHs.size();
158 if (m == 0)
throw InputError(
"mmap_mixture_order2: no components given");
159 for (std::size_t i = 0; i < m; ++i)
160 if (PHs[i].size() != m)
161 throw InputError(
"mmap_mixture_order2: the component table must be square");
162 if (P2.
rows() != m || P2.
cols() != m)
163 throw InputError(
"mmap_mixture_order2: P2 must be square of the component count");
165 for (std::size_t i = 0; i < m; ++i)
166 for (std::size_t j = 0; j < m; ++j)
167 if (PHs[i][j].D0.rows() != 2)
168 throw InputError(
"mmap_mixture_order2: every component must be of order two");
171 const std::size_t N = 2 * m * m;
178 for (std::size_t i = 0; i < m; ++i)
179 for (std::size_t j = 0; j < m; ++j) {
180 const std::size_t k = i * m + j, base = 2 * k;
181 for (std::size_t r = 0; r < 2; ++r)
182 for (std::size_t c = 0; c < 2; ++c) out.
D0(base + r, base + c) = PHs[i][j].D0(r, c);
187 for (std::size_t i1 = 0; i1 < m; ++i1)
188 for (std::size_t j1 = 0; j1 < m; ++j1) {
189 const std::size_t k1 = i1 * m + j1;
190 for (std::size_t i2 = 0; i2 < m; ++i2)
191 for (std::size_t j2 = 0; j2 < m; ++j2) {
192 if (j1 != i2)
continue;
193 const std::size_t k2 = i2 * m + j2;
194 const std::vector<T> pie =
map_pie(PHs[i2][j2]);
195 for (std::size_t r = 0; r < 2; ++r) {
197 for (std::size_t c = 0; c < 2; ++c) ex += -PHs[i1][j1].D0(r, c);
198 for (std::size_t c = 0; c < 2; ++c) {
199 const T v = T(P2(i1, i2) * ex * pie[c]);
200 out.
Dc[j1](2 * k1 + r, 2 * k2 + c) = v;
233 "mmap_mixture_fit fits an APH(2) per class pair");
234 const std::size_t m = M1.
rows();
235 if (m == 0)
throw InputError(
"mmap_mixture_fit: no classes given");
237 throw InputError(
"mmap_mixture_fit: the cross-moment tables must be square and equal");
238 if (P2.
rows() != m || P2.
cols() != m * m)
239 throw InputError(
"mmap_mixture_fit: P2 must be (C x C*C), the flattened triple sigma");
245 std::vector<std::vector<Map<T>>> PHs(m, std::vector<
Map<T>>(m));
246 for (std::size_t i = 0; i < m; ++i)
247 for (std::size_t j = 0; j < m; ++j) {
250 "mmap_mixture_fit: the cross moment of class pair (" + std::to_string(i + 1) +
251 ", " + std::to_string(j + 1) +
252 ") is not positive, so that pair was never observed and its component cannot "
253 "be fitted. Supply a trace in which every ordered class pair occurs, or fit "
255 PHs[i][j] =
aph2_fit(M1(i, j), M2(i, j), M3(i, j)).aph;
258 const std::size_t N = 2 * m * m;
264 for (std::size_t i = 0; i < m; ++i)
265 for (std::size_t j = 0; j < m; ++j) {
266 const std::size_t base = 2 * (i * m + j);
267 for (std::size_t r = 0; r < 2; ++r)
268 for (std::size_t c = 0; c < 2; ++c) out.
D0(base + r, base + c) = PHs[i][j].D0(r, c);
271 for (std::size_t i1 = 0; i1 < m; ++i1)
272 for (std::size_t j1 = 0; j1 < m; ++j1) {
273 const std::size_t k1 = i1 * m + j1;
276 for (std::size_t h = 0; h < m; ++h) rowtot += P2(i1, j1 * m + h);
277 for (std::size_t i2 = 0; i2 < m; ++i2)
278 for (std::size_t j2 = 0; j2 < m; ++j2) {
279 if (j1 != i2)
continue;
281 const T pr = T(P2(i1, i2 * m + j2) / rowtot);
282 const std::size_t k2 = i2 * m + j2;
283 const std::vector<T> pie =
map_pie(PHs[i2][j2]);
284 for (std::size_t r = 0; r < 2; ++r) {
286 for (std::size_t c = 0; c < 2; ++c) ex += -PHs[i1][j1].D0(r, c);
287 for (std::size_t c = 0; c < 2; ++c)
288 out.
Dc[j1](2 * k1 + r, 2 * k2 + c) = T(pr * ex * pie[c]);
304 if (Tv.empty() || Tv.size() != A.size())
305 throw InputError(
"mmap_mixture_fit_trace: the trace and its labels must agree in length");
APH(2) fit of three moments, with a fallback to adjusted moments (matlab/lib/m3a/m3a/aph2/aph2_fit....
The exception types the port throws.
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
Dense matrix and non-owning view.
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,...
Class-pair cross moments of a marked trace: the k-th moment of the interval that separates an event o...
Two-step class transition frequencies of a marked trace,.
Mmap< T > mmap_normalize(const Mmap< T > &in)
Clamp negative off-diagonal and per-class entries to zero and rebuild D1 and the diagonal of D0 from ...
Aph2FitResult< T > aph2_fit(const T &M1, const T &M2, const T &M3)
Fit an APH(2) to (M1, M2, M3), relaxing the moments if necessary.
Mmap< T > mmap_mixture_fit_trace(const std::vector< T > &Tv, const std::vector< int > &A)
mmap_mixture_fit driven from a marked trace: the triple sigma and the cross moments are measured on t...
Mmap< T > mmap_mixture_fit(const Matrix< T > &P2, const Matrix< T > &M1, const Matrix< T > &M2, const Matrix< T > &M3)
Second-order mixture FITTED from cross moments and a triple sigma, the reference's mmap_mixture_fit.
Matrix< T > krons(const Matrix< T > &A, const Matrix< T > &B)
Kronecker sum, MATLAB's krons: kron(A, I_nb) + kron(I_na, B).
Mmap< T > mmap_mixture_order2(const std::vector< std::vector< Map< T > > > &PHs, const Matrix< T > &P2)
Second-order mixture: the state records the previous and the current class.
Matrix< T > kron(const Matrix< T > &A, const Matrix< T > &B)
Kronecker product.
Mmap< T > mmap_modulate(const Matrix< T > &P, const std::vector< Map< T > > &HT, const std::vector< Mmap< T > > &comps)
Modulate a family of marked MAPs by an environment chain.
std::vector< T > map_pie(const Map< T > &m)
Phase distribution seen by an arriving job, pie = pi D1 / (pi D1 e).
MtraceCrossMomentResult< T > mtrace_cross_moment(const std::vector< T > &Tv, const std::vector< int > &L, unsigned k)
Class-pair cross moments of a marked trace: the k-th moment of the interval that separates an event o...
Matrix< T > mtrace_sigma2(const std::vector< int > &L)
Two-step class transition frequencies of a marked trace, sigma(i,j,h) = #{t : A_t = i,...
Matrix< T > eye(std::size_t n)
Identity of order n.
Number-type abstraction for the templated API port.
A MAP as the pair of matrices (D0, D1).
An MMAP: the underlying MAP plus the per-class arrival matrices.
std::vector< Matrix< T > > Dc
per-class matrices, sum_c Dc = D1