5#ifndef LINE_API_MAM_DMAP_H
6#define LINE_API_MAM_DMAP_H
59std::vector<T> vec_colmajor(
const Matrix<T>& A) {
60 std::vector<T> v(A.
rows() * A.
cols());
61 for (std::size_t j = 0; j < A.
cols(); ++j)
62 for (std::size_t i = 0; i < A.
rows(); ++i) v[j * A.
rows() + i] = A(i, j);
68Matrix<T> stein_solve(
const Matrix<T>& A,
const Matrix<T>& B,
const Matrix<T>& C) {
69 const std::size_t m = A.rows(), n = B.cols();
70 if (A.cols() != m || B.rows() != n)
71 throw InputError(
"stein_solve: A and B must be square");
72 if (C.rows() != m || C.cols() != n)
73 throw InputError(
"stein_solve: the right-hand side is not conformable");
74 const std::size_t N = m * n;
75 Matrix<T> M(N, N, num_traits<T>::from_int(0));
77 for (std::size_t jb = 0; jb < n; ++jb)
78 for (std::size_t ib = 0; ib < n; ++ib)
79 for (std::size_t ia = 0; ia < m; ++ia)
80 for (std::size_t ja = 0; ja < m; ++ja)
81 M(jb * m + ia, ib * m + ja) = -B(ib, jb) * A(ia, ja);
82 for (std::size_t k = 0; k < N; ++k) M(k, k) += num_traits<T>::from_int(1);
83 const std::vector<T> x =
solve(M, vec_colmajor(C));
84 Matrix<T> X(m, n, num_traits<T>::from_int(0));
85 for (std::size_t j = 0; j < n; ++j)
86 for (std::size_t i = 0; i < m; ++i) X(i, j) = x[j * m + i];
92Matrix<T> dmap_embedded_chain(
const Matrix<T>& D0,
const Matrix<T>& D1) {
93 const std::size_t n = D0.rows();
95 for (std::size_t i = 0; i < n; ++i)
96 for (std::size_t j = 0; j < n; ++j) A(i, j) -= D0(i, j);
111 const std::size_t n = d.
order();
112 const std::vector<T> al =
dmap_pie(d);
114 for (std::size_t i = 0; i < n; ++i)
115 for (std::size_t j = 0; j < n; ++j) IA(i, j) -= d.
D0(i, j);
117 const std::vector<T> e =
ones<T>(n);
118 const std::vector<T> Ae =
mulvec(A, e);
120 for (std::size_t i = 0; i < n; ++i) m1 += al[i] * Ae[i];
121 const std::vector<T> alA =
vecmul(al, A);
122 const std::vector<T> alAA =
vecmul(alA, A);
124 for (std::size_t i = 0; i < n; ++i) {
125 alAe += alA[i] * Ae[i];
126 alAAe += alAA[i] * Ae[i];
129 for (std::size_t t = 0; t < orders.size(); ++t) {
142 throw InputError(
"dmap_moment: raw moments of order > 3 are not implemented");
151 const std::size_t n = d.
D0.rows();
152 if (d.
D0.cols() != n || d.
D1.rows() != n || d.
D1.cols() != n)
return false;
155 for (std::size_t i = 0; i < n; ++i) {
157 for (std::size_t j = 0; j < n; ++j) {
158 if (d.
D0(i, j) < negtol || d.
D1(i, j) < negtol)
return false;
159 rs += d.
D0(i, j) + d.
D1(i, j);
163 if (d1rs < negtol)
return false;
171 const std::vector<T>& alB) {
172 const std::size_t NA = a.
order(), NB = b.
order();
174 for (std::size_t i = 0; i < NB; ++i)
175 for (std::size_t j = 0; j < NA; ++j) C(i, j) = alB[i] * alA[j];
176 if (L == 0)
throw InputError(
"dmap_exp_mul_int: the truncation lag L must be positive");
177 Matrix<T> Z = detail::stein_solve(b.
D0.transpose(), a.
D0, C);
178 for (
unsigned i = 1; i <= L - 1; ++i) {
180 Z = detail::stein_solve(b.
D0.transpose(), a.
D0, R);
183 for (std::size_t i = 0; i < NA; ++i) {
185 for (std::size_t j = 0; j < NA; ++j) dA[i] -= a.
D0(i, j);
187 for (std::size_t i = 0; i < NB; ++i) {
189 for (std::size_t j = 0; j < NB; ++j) dB[i] -= b.
D0(i, j);
191 const std::vector<T> t =
vecmul(dB, Z);
193 for (std::size_t i = 0; i < NA; ++i) out += t[i] * dA[i];
206 const std::vector<T>& alB) {
226 const std::vector<T>& alB) {
227 const std::size_t NA = a.
order(), NB = b.
order();
229 for (std::size_t i = 0; i < NA; ++i)
230 for (std::size_t j = 0; j < NA; ++j) IA(i, j) -= a.
D0(i, j);
231 for (std::size_t i = 0; i < NB; ++i)
232 for (std::size_t j = 0; j < NB; ++j) IB(i, j) -= b.
D0(i, j);
235 for (std::size_t i = 0; i < NA; ++i)
236 for (std::size_t j = 0; j < NA; ++j) PAh(i, j) -= alA[j];
237 for (std::size_t i = 0; i < NB; ++i)
238 for (std::size_t j = 0; j < NB; ++j) PBh(i, j) -= alB[j];
240 for (std::size_t i = 0; i < NA; ++i)
241 for (std::size_t j = 0; j < NA; ++j) rowA[i] += D0Ai(i, j);
242 const std::vector<T> alBD0Bi =
vecmul(alB, D0Bi);
244 for (std::size_t i = 0; i < NA; ++i)
245 for (std::size_t j = 0; j < NB; ++j) C(i, j) = rowA[i] * alBD0Bi[j];
246 const Matrix<T> X = detail::stein_solve(PAh, PBh, C);
249 for (std::size_t i = 0; i < NB; ++i) out += v[i];
262 const std::vector<T>& alB) {
263 std::vector<unsigned> ord;
268 const T varA = momA[1] - momA[0] * momA[0];
269 const T varB = momB[1] - momB[0] * momB[0];
271 return (
dmap_geo_mul_sum(a, a, alA, alA) - momA[1] * momA[1] / four) / (varA * varA) -
273 (
dmap_geo_mul_sum(a, b, alA, alB) - momA[1] * momB[1] / four) / (varA * varB) +
274 (
dmap_geo_mul_sum(b, b, alB, alB) - momB[1] * momB[1] / four) / (varB * varB);
286 const std::vector<T>& alB) {
287 const std::size_t NA = a.
order(), NB = b.
order();
289 for (std::size_t i = 0; i < NA; ++i) {
291 for (std::size_t j = 0; j < NA; ++j) ea[i] -= a.
D0(i, j);
293 for (std::size_t i = 0; i < NB; ++i) {
295 for (std::size_t j = 0; j < NB; ++j) eb[i] -= b.
D0(i, j);
299 for (std::size_t i = 0; i < NA; ++i)
300 for (std::size_t j = 0; j < NB; ++j) Cab(i, j) = alA[i] * alB[j];
301 for (std::size_t i = 0; i < NA; ++i)
302 for (std::size_t j = 0; j < NA; ++j) Caa(i, j) = alA[i] * alA[j];
303 for (std::size_t i = 0; i < NB; ++i)
304 for (std::size_t j = 0; j < NB; ++j) Cbb(i, j) = alB[i] * alB[j];
305 const Matrix<T> Z_AB = detail::stein_solve(a.
D0.transpose(), b.
D0, Cab);
306 const Matrix<T> Z_AA = detail::stein_solve(a.
D0.transpose(), a.
D0, Caa);
307 const Matrix<T> Z_BB = detail::stein_solve(b.
D0.transpose(), b.
D0, Cbb);
310 for (std::size_t i = 0; i < NA; ++i)
311 for (std::size_t j = 0; j < NB; ++j) Rab(i, j) = ea[i] * eb[j];
312 for (std::size_t i = 0; i < NA; ++i)
313 for (std::size_t j = 0; j < NA; ++j) Raa(i, j) = ea[i] * ea[j];
314 for (std::size_t i = 0; i < NB; ++i)
315 for (std::size_t j = 0; j < NB; ++j) Rbb(i, j) = eb[i] * eb[j];
316 const Matrix<T> X_AB = detail::stein_solve(a.
D0, b.
D0.transpose(), Rab);
317 const Matrix<T> X_AA = detail::stein_solve(a.
D0, a.
D0.transpose(), Raa);
318 const Matrix<T> X_BB = detail::stein_solve(b.
D0, b.
D0.transpose(), Rbb);
319 const std::vector<T> vA = detail::vec_colmajor(a.
D1);
320 const std::vector<T> vB = detail::vec_colmajor(b.
D1);
324 for (std::size_t p = 0; p < NB; ++p)
325 for (std::size_t q = 0; q < NB; ++q)
326 for (std::size_t r = 0; r < NB; ++r)
327 for (std::size_t s = 0; s < NB; ++s)
328 sBB += vB[p * NB + q] * X_BB(p, r) * Z_BB(q, s) * vB[r * NB + s];
329 for (std::size_t p = 0; p < NA; ++p)
330 for (std::size_t q = 0; q < NA; ++q)
331 for (std::size_t r = 0; r < NA; ++r)
332 for (std::size_t s = 0; s < NA; ++s)
333 sAA += vA[p * NA + q] * X_AA(p, r) * Z_AA(q, s) * vA[r * NA + s];
334 for (std::size_t p = 0; p < NA; ++p)
335 for (std::size_t q = 0; q < NA; ++q)
336 for (std::size_t r = 0; r < NB; ++r)
337 for (std::size_t s = 0; s < NB; ++s)
338 sAB += vA[p * NA + q] * X_AB(p, r) * Z_AB(q, s) * vB[r * NB + s];
349template <
class T,
class Gen>
351 const std::size_t N = d.
order();
352 const std::vector<T> al =
dmap_pie(d);
353 std::uniform_real_distribution<double> unif(0.0, 1.0);
354 std::size_t phase = 0;
355 double u = unif(gen), acc = 0.0;
356 for (std::size_t i = 0; i < N; ++i) {
363 std::vector<unsigned> X(n, 0);
364 for (std::size_t i = 0; i < n; ++i) {
368 const double v = unif(gen);
370 std::size_t next = 2 * N - 1;
371 for (std::size_t j = 0; j < 2 * N; ++j) {
Equilibrium distribution of a discrete-time Markov chain, and stochastic complementation.
The exception types the port throws.
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
LU factorization with partial pivoting, templated on the number type.
Dense matrix and non-owning view.
Marked MAP (MMAP) algebra: per-class rates, class probabilities, superposition, normalization and sca...
T dmap_dist_acf(const Dmap< T > &a, const Dmap< T > &b, const std::vector< T > &alA, const std::vector< T > &alB)
Squared distance between the autocorrelation structures of two D-MAPs.
T dmap_dist(const Dmap< T > &a, const Dmap< T > &b, unsigned L, const std::vector< T > &alA, const std::vector< T > &alB)
Squared L2 distance between the interarrival densities truncated at lag L.
bool dmap_isfeasible(const Dmap< T > &d)
True when D0 and D1 are nonnegative and D0 + D1 is stochastic.
std::vector< unsigned > dmap_sample(const Dmap< T > &d, std::size_t n, Gen &gen)
n interarrival times in slots, drawn by walking the phase process.
T dmap_dist_lag1(const Dmap< T > &a, const Dmap< T > &b, const std::vector< T > &alA, const std::vector< T > &alB)
Squared distance between the lag-1 joint densities of two D-MAPs.
std::vector< T > dmap_pie(const Dmap< T > &d)
Stationary phase distribution at arrival epochs.
T dmap_geo_mul_sum(const Dmap< T > &a, const Dmap< T > &b, const std::vector< T > &alA, const std::vector< T > &alB)
Geometrically weighted sum of the lagged joint moments, the building block of the autocorrelation dis...
T dmap_exp_mul_int(const Dmap< T > &a, const Dmap< T > &b, unsigned L, const std::vector< T > &alA, const std::vector< T > &alB)
Inner product of the two interarrival densities truncated at lag L.
std::vector< T > dmap_moment(const Dmap< T > &d, const std::vector< unsigned > &orders)
Raw moments of the interarrival time in slots, for orders 1, 2 and 3 only.
std::vector< T > dtmc_solve(const Matrix< T > &P)
Stationary distribution of a stochastic matrix P.
std::vector< T > vecmul(const std::vector< T > &v, const Matrix< T > &A)
Row vector times matrix, v A.
Matrix< T > inverse(const Matrix< T > &A)
Inverse by LU with one factorization and n back substitutions.
Matrix< T > matmul(const Matrix< T > &A, const Matrix< T > &B)
Matrix product A B.
std::vector< T > mulvec(const Matrix< T > &A, const std::vector< T > &v)
Matrix times column vector, A v.
std::vector< T > solve(const Matrix< T > &A, const std::vector< T > &b)
Convenience: solve Ax = b, leaving A and b untouched.
std::vector< T > ones(std::size_t n)
Column vector of ones, the ubiquitous e in MAP algebra.
Matrix< T > eye(std::size_t n)
Identity of order n.
Number-type abstraction for the templated API port.
A discrete-time MAP: substochastic D0 (no arrival) and D1 (one arrival).
std::size_t order() const