2 % @brief Computes rate matrices
for level-dependent QBD processes
4 % @author QORE Lab, Imperial College London (Algorithm by Phung-Duc et al.)
8 % @brief Computes all rate matrices R^(n)
for a level-dependent QBD
11 % This function implements the backward recursion algorithm
for computing
12 % rate matrices of level-dependent QBD processes with heterogeneous dimensions.
14 % For a level-dependent QBD with levels 0, 1, ..., N:
15 % R^(N) = Q0^(N-1) * (-Q1^(N))^{-1}
16 % R^(n) = Q0^(n-1) * (-Q1^(n) - R^(n+1) * Q2^(n+1))^{-1}
for n = N-1,...,1
19 % R^(n)
is (states at level n-1) x (states at level n)
20 % Q0^(n-1)
is (states at level n-1) x (states at level n)
21 % Q1^(n)
is (states at level n) x (states at level n)
22 % Q2^(n)
is (states at level n) x (states at level n-1)
26 % R = ldqbd_R(Q0, Q1, Q2)
27 % R = ldqbd_R(Q0, Q1, Q2, options)
32 % <tr><th>Name<th>Description
33 % <tr><td>Q0<td>Cell array {Q0^(0), Q0^(1), ..., Q0^(N-1)} - upward transitions
34 % <tr><td>Q1<td>Cell array {Q1^(0), Q1^(1), ..., Q1^(N)} - local transitions
35 % <tr><td>Q2<td>Cell array {Q2^(1), Q2^(2), ..., Q2^(N)} - downward transitions
36 % <tr><td>options<td>Optional
struct with fields: verbose (default false)
41 % <tr><th>Name<th>Description
42 % <tr><td>R<td>Cell array {R^(1), R^(2), ..., R^(N)} - rate matrices
46 % T. Phung-Duc, H. Masuyama, S. Kasahara, Y. Takahashi,
"A Simple Algorithm
47 % for the Rate Matrices of Level-Dependent QBD Processes", QTNA 2010.
49function R = ldqbd_R(Q0, Q1, Q2, varargin)
52if nargin >= 4 && ~isempty(varargin{1})
53 options = varargin{1};
58if ~isfield(options,
'verbose'), options.verbose =
false; end
60% Determine number of levels
61N = length(Q1) - 1; % Maximum level
64 fprintf(
'LD-QBD Rate Matrix Computation: N=%d levels\n', N);
67% Initialize R cell array
70% Start at level N (boundary): R^(N) = Q0^(N-1) * (-Q1^(N))^{-1}
71Q0_Nminus1 = Q0{N}; % Q0^(N-1)
72Q1_N = Q1{N+1}; % Q1^(N)
77 R{N} = Q0_Nminus1 / U;
79 R{N} = Q0_Nminus1 * 0;
82 if abs(det(U)) > 1e-14
83 R{N} = Q0_Nminus1 / U;
85 R{N} = Q0_Nminus1 * pinv(U);
89% Backward recursion
for n = N-1 down to 1
91 % R^(n) = Q0^(n-1) * (-Q1^(n) - R^(n+1) * Q2^(n+1))^{-1}
92 Q0_nminus1 = Q0{n}; % Q0^(n-1): (states at n-1) x (states at n)
93 Q1_n = Q1{n+1}; % Q1^(n): (states at n) x (states at n)
94 Q2_nplus1 = Q2{n+1}; % Q2^(n+1): (states at n+1) x (states at n)
95 R_nplus1 = R{n+1}; % R^(n+1): (states at n) x (states at n+1)
97 % Compute R^(n+1) * Q2^(n+1): (states at n) x (states at n)
98 RQ2 = R_nplus1 * Q2_nplus1;
100 % Compute U = -Q1^(n) - R^(n+1) * Q2^(n+1)
103 % Compute R^(n) = Q0^(n-1) * U^{-1}
106 R{n} = Q0_nminus1 / U;
108 R{n} = Q0_nminus1 * 0;
111 if abs(det(U)) > 1e-14
112 R{n} = Q0_nminus1 / U;
114 R{n} = Q0_nminus1 * pinv(U);
121 fprintf(
' R^(%d) computed (%dx%d)\n', n, size(R{n}, 1), size(R{n}, 2));