LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
mfq_fluflu_sojourn.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_MFQ_FLUFLU_SOJOURN_H
6#define LINE_API_MAM_MFQ_FLUFLU_SOJOURN_H
7
8/**
9 * @file
10 * @ingroup api_mam
11 * Sojourn-time distribution of a fluid queue whose SERVICE is itself a
12 * Markov-modulated fluid flow, as an ME or PH representation (alpha, A).
13 *
14 * Port of matlab/src/api/mam/mfq_fluflu_sojourn.m and the BUTools FluFluSTD it
15 * wraps. Arrivals are a fluid flow modulated by (Qin, Rin) and the server
16 * drains fluid at a rate modulated by an independent (Qout, Rout).
17 *
18 * CONSTRUCTION. The two modulating chains are combined on the product space,
19 * but NOT as a plain Kronecker sum: because the two flows run on different
20 * clocks, the combined model is the TIME-CHANGED fluid queue
21 *
22 * Rh = kron(Rin, I) - kron(I, Rout),
23 * Qh = kron(Qin, Rout) + kron(Rin, Qout),
24 *
25 * in which each chain's generator is weighted by the OTHER flow's rate. Qh is
26 * therefore not a generator, and mfq_general_solve does not require it to be:
27 * its algebra is generic. Solving that fluid model gives the level law of the
28 * queue, and the sojourn-time representation follows from it exactly as in
29 * mfq_sojourn, with the closing vector weighted by kron(Rin, I) when service
30 * continues while the server's own fluid level is at zero, and by
31 * kron(Rin, Rout)/mu when service stops there. That is the srv0stop flag, and
32 * it is the only place where the two conventions differ.
33 *
34 * ARITHMETIC. Gated on num_traits<T>::has_transcendental through
35 * mfq_general_solve.
36 */
37
38#include <cstddef>
39#include <vector>
40
45#include "line/num/number.h"
46#include "line/util/error.h"
47#include "line/util/linalg.h"
48#include "line/util/matrix.h"
49
50namespace line {
51namespace mam {
52
53/**
54 * Sojourn time of a drop in a fluid queue with fluid-modulated service.
55 *
56 * @param Qin generator of the arrival-modulating chain, Na x Na
57 * @param Rin diagonal arrival fluid rate matrix, Na x Na
58 * @param Qout generator of the service-modulating chain, Ns x Ns
59 * @param Rout diagonal service fluid rate matrix, Ns x Ns
60 * @param srv0stop true if service stops when the server fluid level hits zero
61 * @param transToPH true for a phase-type representation, false for ME
62 * @param prec tolerance handed to mfq_general_solve
63 */
64template <class T>
66 const Matrix<T>& Qout, const Matrix<T>& Rout,
67 bool srv0stop, bool transToPH, const T& prec) {
69 "mfq_fluflu_sojourn requires transcendental arithmetic");
70 using namespace mfq_detail;
71 const T zero = num_traits<T>::from_int(0), one = num_traits<T>::from_int(1);
72 const std::size_t Na = Qin.rows(), Ns = Qout.rows();
73 if (Qin.cols() != Na || Rin.rows() != Na || Rin.cols() != Na)
74 throw InputError("mfq_fluflu_sojourn: Qin and Rin must be square and of equal order");
75 if (Qout.cols() != Ns || Rout.rows() != Ns || Rout.cols() != Ns)
76 throw InputError("mfq_fluflu_sojourn: Qout and Rout must be square and of equal order");
77
78 const Matrix<T> Iin = eye<T>(Na);
79 const Matrix<T> Iout = eye<T>(Ns);
80 const Matrix<T> KRinI = kron(Rin, Iout);
81 const Matrix<T> Rh = sub(KRinI, kron(Iin, Rout));
82 const Matrix<T> Qh = add(kron(Qin, Rout), kron(Rin, Qout));
83
84 const GeneralFluidSolution<T> s = mfq_general_solve(Qh, Rh, Matrix<T>(0, 0), prec);
85 const std::size_t Np = s.ini.size();
86 if (Np == 0) throw NumericError("mfq_fluflu_sojourn: the combined model has no up-drift state");
87
88 // lambda and mu, the mean fluid rates of the two flows.
89 T lambda = zero, mu = zero;
90 {
91 const std::vector<T> pin = mc::ctmc_solve(Qin);
92 for (std::size_t i = 0; i < Na; ++i) lambda += pin[i] * Rin(i, i);
93 const std::vector<T> pout = mc::ctmc_solve(Qout);
94 for (std::size_t i = 0; i < Ns; ++i) mu += pout[i] * Rout(i, i);
95 }
96 if (lambda <= zero) throw NumericError("mfq_fluflu_sojourn: non-positive arrival fluid rate");
97 if (srv0stop && mu <= zero)
98 throw NumericError("mfq_fluflu_sojourn: non-positive service fluid rate");
99
100 // The closing weight: kron(Rin, I)/lambda, or kron(Rin, Rout)/(lambda mu)
101 // when service stops at a zero server level.
102 Matrix<T> Wt = srv0stop ? kron(Rin, Rout) : KRinI;
103 const T denom = srv0stop ? T(lambda * mu) : lambda;
104 Wt = scale(Wt, T(one / denom));
105 const Matrix<T> cloW = matmul(s.clo, Wt); // Np x (Na Ns)
106
107 const Matrix<T> negKinv = inverse(scale(s.K, T(-one)));
109 if (transToPH) {
110 const std::vector<T> delta = vecmul(s.ini, negKinv);
111 for (std::size_t i = 0; i < Np; ++i)
112 if (delta[i] == zero)
113 throw NumericError(
114 "mfq_fluflu_sojourn: the PH similarity is singular on this model; ask for the "
115 "ME representation instead");
116 // A = Delta^-1 Kh' Delta.
117 out.A = Matrix<T>(Np, Np, zero);
118 for (std::size_t i = 0; i < Np; ++i)
119 for (std::size_t k = 0; k < Np; ++k) out.A(i, k) = s.K(k, i) * delta[k] / delta[i];
120 // alpha = row sums of Delta cloW.
121 out.alpha.assign(Np, zero);
122 for (std::size_t i = 0; i < Np; ++i) {
123 T acc = zero;
124 for (std::size_t j = 0; j < cloW.cols(); ++j) acc += delta[i] * cloW(i, j);
125 out.alpha[i] = acc;
126 }
127 } else {
128 std::vector<T> clovec(Np, zero);
129 for (std::size_t i = 0; i < Np; ++i)
130 for (std::size_t j = 0; j < cloW.cols(); ++j) clovec[i] += cloW(i, j);
131 const Matrix<T> B = mfq_transform_to_ones(clovec);
132 const Matrix<T> Bi = inverse(B);
133 out.A = matmul(matmul(B, s.K), Bi);
134 out.alpha = vecmul(vecmul(s.ini, negKinv), Bi);
135 }
136 return out;
137}
138
139/** mfq_fluflu_sojourn with an ME representation and prec = 1e-14. */
140template <class T>
142 const Matrix<T>& Qout, const Matrix<T>& Rout,
143 bool srv0stop) {
144 return mfq_fluflu_sojourn(Qin, Rin, Qout, Rout, srv0stop, false,
146}
147
148} // namespace mam
149} // namespace line
150
151#endif // LINE_API_MAM_MFQ_FLUFLU_SOJOURN_H
InputError(const std::string &what)
Definition error.h:39
std::size_t cols() const
Definition matrix.h:90
std::size_t rows() const
Definition matrix.h:89
NumericError(const std::string &what)
Definition error.h:45
Steady-state distribution of a continuous-time Markov chain.
The exception types the port throws.
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
Dense matrix and non-owning view.
Sojourn-time distribution of a Markov-modulated fluid queue, as a matrix-exponential or phase-type re...
Core of the Markovian fluid queue: the fundamental matrices Psi, K, U and the matrix-exponential stat...
Marked MAP (MMAP) algebra: per-class rates, class probabilities, superposition, normalization and sca...
MeRepresentation< T > mfq_fluflu_sojourn(const Matrix< T > &Qin, const Matrix< T > &Rin, const Matrix< T > &Qout, const Matrix< T > &Rout, bool srv0stop, bool transToPH, const T &prec)
Sojourn time of a drop in a fluid queue with fluid-modulated service.
Matrix< T > kron(const Matrix< T > &A, const Matrix< T > &B)
Kronecker product.
Definition mmap_lambda.h:57
GeneralFluidSolution< T > mfq_general_solve(const Matrix< T > &Q, const Matrix< T > &R, const Matrix< T > &Q0, const T &prec)
Stationary law of a general Markovian fluid model, pi(x) = ini exp(K x) clo above level zero plus the...
Definition mfq_solve.h:299
Matrix< T > mfq_transform_to_ones(const std::vector< T > &v)
The similarity transformation B with B v = e, for a non-negative column vector v.
Definition mfq_solve.h:506
std::vector< T > ctmc_solve(const Matrix< T > &Qin)
Steady-state distribution of a continuous-time Markov chain.
Definition ctmc_solve.h:122
std::vector< T > vecmul(const std::vector< T > &v, const Matrix< T > &A)
Row vector times matrix, v A.
Definition linalg.h:50
Matrix< T > inverse(const Matrix< T > &A)
Inverse by LU with one factorization and n back substitutions.
Definition linalg.h:72
Matrix< T > matmul(const Matrix< T > &A, const Matrix< T > &B)
Matrix product A B.
Definition linalg.h:36
Matrix< T > eye(std::size_t n)
Identity of order n.
Definition linalg.h:28
Number-type abstraction for the templated API port.
Stationary matrix-exponential solution of a general Markovian fluid model.
Definition mfq_solve.h:280
Matrix< T > K
matrix exponent of the density, Np x Np
Definition mfq_solve.h:283
std::vector< T > ini
initial vector of the density, length Np
Definition mfq_solve.h:282
Matrix< T > clo
closing matrix of the density, Np x N
Definition mfq_solve.h:284
A matrix-exponential or phase-type representation (alpha, A).
Definition mfq_sojourn.h:70
Matrix< T > A
generator-like matrix exponent
Definition mfq_sojourn.h:72
std::vector< T > alpha
initial row vector
Definition mfq_sojourn.h:71