LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
snc_env_map.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_SNC_ENV_MAP_H
6#define LINE_API_SNC_ENV_MAP_H
7
8/**
9 * @file
10 * @ingroup api_snc
11 * MGF arrival envelope of a MAP/MMPP flow with unit-size jobs.
12 *
13 * For a Markovian arrival process (D0,D1) counting N(0,t) unit-work jobs,
14 * `E[exp(theta*N(0,t))] = pi*expm((D0+D1*exp(theta))*t)*1`. With lstar the
15 * eigenvalue of maximal real part of `A(theta)=D0+D1*e^theta` and v > 0 its
16 * right Perron eigenvector, bounding `1 <= v/min(v)` entrywise gives
17 *
18 * rho(theta) = lstar/theta,
19 * sigma(theta) = log(max(v)/min(v))/theta,
20 *
21 * the standard exponential-form envelope of a Markov-modulated source. The burst
22 * term is what the modulating chain contributes: 0 for a one-phase MAP, where
23 * this reproduces `snc_env_poisson` exactly, and positive for an MMPP.
24 *
25 * THE PERRON PAIR IS COMPUTED BY POWER ITERATION ON THE SHIFTED MATRIX `A+cI`,
26 * not by a general eigensolver. A(theta) is essentially nonnegative, so the
27 * shift makes it nonnegative with a positive diagonal, hence primitive whenever
28 * the MAP is irreducible, and the iteration converges to the pair the bound
29 * needs without asking a general solver which of its eigenvectors is the
30 * positive one. The MATLAB reference uses `eig` and agrees to machine
31 * precision; the JAR port iterates the same way.
32 *
33 * Port of matlab/src/api/snc/snc_env_map.m. Reference: C.-S. Chang, Performance
34 * Guarantees in Communication Networks, Springer 2000, Ch. 7.
35 */
36
37#include <algorithm>
38#include <cmath>
39#include <cstddef>
40#include <limits>
41#include <vector>
43#include "line/util/error.h"
44#include "line/util/matrix.h"
45
46namespace line {
47namespace snc {
48
49/**
50 * @brief MGF arrival envelope of a MAP/MMPP flow with unit-size jobs.
51 *
52 * @param D0 hidden-transition generator block of the MAP
53 * @param D1 arrival-transition block of the MAP
54 * @param theta Chernoff parameter, theta > 0
55 */
56inline Env snc_env_map(const Matrix<double>& D0, const Matrix<double>& D1, double theta) {
57 if (theta <= 0) throw UnsupportedError("snc_env_map: theta must be positive");
58 const std::size_t n = D0.rows();
59 if (D0.cols() != n || D1.rows() != n || D1.cols() != n)
60 throw UnsupportedError("snc_env_map: D0 and D1 must be square and of equal size");
61
62 std::vector<std::vector<double>> A(n, std::vector<double>(n, 0.0));
63 const double etheta = std::exp(theta);
64 double shift = 0.0;
65 for (std::size_t i = 0; i < n; ++i) {
66 for (std::size_t j = 0; j < n; ++j) A[i][j] = D0(i, j) + D1(i, j) * etheta;
67 shift = std::max(shift, -A[i][i]);
68 }
69 shift += 1.0;
70 for (std::size_t i = 0; i < n; ++i) A[i][i] += shift;
71
72 std::vector<double> v(n, 1.0), w(n, 0.0);
73 double lambdaShift = 0.0;
74 for (int it = 0; it < 100000; ++it) {
75 for (std::size_t i = 0; i < n; ++i) {
76 double acc = 0.0;
77 for (std::size_t j = 0; j < n; ++j) acc += A[i][j] * v[j];
78 w[i] = acc;
79 }
80 double norm = 0.0;
81 for (std::size_t i = 0; i < n; ++i) norm = std::max(norm, std::fabs(w[i]));
82 if (!(norm > 0))
83 throw UnsupportedError(
84 "snc_env_map: MAP is not irreducible: the Perron eigenvector is not positive");
85 double delta = 0.0;
86 for (std::size_t i = 0; i < n; ++i) {
87 w[i] /= norm;
88 delta = std::max(delta, std::fabs(w[i] - v[i]));
89 }
90 v = w;
91 lambdaShift = norm;
92 if (delta < 1e-14) break;
93 }
94 double vmin = std::numeric_limits<double>::infinity(), vmax = 0.0;
95 for (std::size_t i = 0; i < n; ++i) {
96 vmin = std::min(vmin, v[i]);
97 vmax = std::max(vmax, v[i]);
98 }
99 if (!(vmin > 0))
100 throw UnsupportedError(
101 "snc_env_map: MAP is not irreducible: the Perron eigenvector is not positive");
102 return Env{std::log(vmax / vmin) / theta, (lambdaShift - shift) / theta};
103}
104
105/** The same envelope as a function of theta. */
107 return [D0, D1](double theta) { return snc_env_map(D0, D1, theta); };
108}
109
110} // namespace snc
111} // namespace line
112
113#endif // LINE_API_SNC_ENV_MAP_H
std::size_t cols() const
Definition matrix.h:90
std::size_t rows() const
Definition matrix.h:89
UnsupportedError(const std::string &what)
Definition error.h:51
The exception types the port throws.
Dense matrix and non-owning view.
Envelope snc_env_map_fn(const Matrix< double > &D0, const Matrix< double > &D1)
The same envelope as a function of theta.
Env snc_env_map(const Matrix< double > &D0, const Matrix< double > &D1, double theta)
MGF arrival envelope of a MAP/MMPP flow with unit-size jobs.
Definition snc_env_map.h:56
std::function< Env(double)> Envelope
An envelope as a function of the Chernoff parameter.
Definition snc_types.h:48
Shared types of the stochastic network calculus domain.
The pair (sigma, rho) of an envelope evaluated at one theta.
Definition snc_types.h:42