LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
ldqbd_pi.m
1%{ @file ldqbd_pi.m
2 % @brief Computes stationary distribution for level-dependent QBD processes
3 %
4 % @author QORE Lab, Imperial College London (Algorithm by Phung-Duc et al.)
5%}
6
7%{
8 % @brief Computes the stationary distribution for a level-dependent QBD
9 %
10 % @details
11 % This function implements Algorithm 3 from the Phung-Duc et al. paper for
12 % computing the stationary distribution of level-dependent QBD processes.
13 %
14 % The algorithm uses:
15 % 1. Boundary equation: pi_0 * (Q1^(0) + R^(1)*Q2^(1)) = 0
16 % 2. Forward recursion: pi_n = pi_{n-1} * R^(n)
17 % 3. Normalize: sum(pi) = 1
18 %
19 % @par Syntax:
20 % @code
21 % pi = ldqbd_pi(R, Q0, Q1, Q2)
22 % pi = ldqbd_pi(R, Q0, Q1, Q2, options)
23 % @endcode
24 %
25 % @par Parameters:
26 % <table>
27 % <tr><th>Name<th>Description
28 % <tr><td>R<td>Cell array {R^(1), R^(2), ..., R^(N)} - rate matrices from ldqbd_R
29 % <tr><td>Q0<td>Cell array {Q0^(0), Q0^(1), ..., Q0^(N-1)} - upward transitions
30 % <tr><td>Q1<td>Cell array {Q1^(0), Q1^(1), ..., Q1^(N)} - local transitions
31 % <tr><td>Q2<td>Cell array {Q2^(1), Q2^(2), ..., Q2^(N)} - downward transitions
32 % <tr><td>options<td>Optional struct with fields: verbose (default false)
33 % </table>
34 %
35 % @par Returns:
36 % <table>
37 % <tr><th>Name<th>Description
38 % <tr><td>pi<td>Row vector [pi_0, pi_1, ..., pi_N] - stationary distribution
39 % (aggregated over phases at each level)
40 % <tr><td>pi_cell<td>(Optional) Cell array with full phase-level distributions
41 % </table>
42 %
43 % @par Reference:
44 % T. Phung-Duc, H. Masuyama, S. Kasahara, Y. Takahashi, "A Simple Algorithm
45 % for the Rate Matrices of Level-Dependent QBD Processes", QTNA 2010.
46%}
47function [pi, pi_cell] = ldqbd_pi(R, Q0, Q1, Q2, varargin)
48
49% Parse options
50if nargin >= 5 && ~isempty(varargin{1})
51 options = varargin{1};
52else
53 options = struct();
54end
55
56if ~isfield(options, 'verbose'), options.verbose = false; end
57
58% Determine number of levels
59N = length(Q1) - 1; % Maximum level
60
61if options.verbose
62 fprintf('LD-QBD Stationary Distribution: N=%d levels\n', N);
63end
64
65% Check if all levels have same dimension (homogeneous)
66isScalar = all(cellfun(@(x) numel(x) == 1, Q1));
67dims = cellfun(@(x) size(x, 1), Q1);
68isHomogeneous = (length(unique(dims)) == 1);
69
70if isScalar && isHomogeneous
71 % Scalar case: direct computation
72 pi = zeros(1, N+1);
73 pi_cell = cell(N+1, 1);
74
75 % Start with pi_0 = 1 (will normalize later)
76 pi_cell{1} = 1;
77
78 % Forward recursion: pi_n = pi_{n-1} * R^(n)
79 for n = 1:N
80 if ~isempty(R{n})
81 pi_cell{n+1} = pi_cell{n} * R{n};
82 else
83 pi_cell{n+1} = 0;
84 end
85 end
86
87 % Convert to vector and normalize
88 for n = 0:N
89 pi(n+1) = pi_cell{n+1};
90 end
91 pi = pi / sum(pi);
92
93 % Update pi_cell with normalized values
94 for n = 0:N
95 pi_cell{n+1} = pi(n+1);
96 end
97else
98 % Heterogeneous or matrix case: use cell array for pi with varying dimensions
99 pi_cell = cell(N+1, 1);
100
101 % Initialize pi_0 based on its dimension
102 if numel(Q1{1}) == 1
103 % Scalar level 0: start with pi_0 = 1
104 pi_cell{1} = 1;
105 else
106 % Matrix level 0: solve boundary equation
107 Q1_0 = Q1{1};
108 Q2_1 = Q2{1};
109 A = Q1_0 + R{1} * Q2_1;
110
111 % Find null space of A' (left null space of A)
112 [V, D] = eig(A');
113 [~, idx] = min(abs(diag(D)));
114 pi0 = real(V(:, idx))';
115
116 % Ensure positive and normalize
117 if sum(pi0) < 0
118 pi0 = -pi0;
119 end
120 pi0 = abs(pi0);
121 pi0 = pi0 / sum(pi0);
122 pi_cell{1} = pi0;
123 end
124
125 % Forward recursion: pi_n = pi_{n-1} * R^(n)
126 for n = 1:N
127 pi_cell{n+1} = pi_cell{n} * R{n};
128 end
129
130 % Normalize and convert to vector (sum over phases at each level)
131 total = sum(cellfun(@sum, pi_cell));
132 pi = zeros(1, N+1);
133 for n = 0:N
134 pi_cell{n+1} = pi_cell{n+1} / total;
135 pi(n+1) = sum(pi_cell{n+1}); % Sum over phases if vector
136 end
137end
138
139if options.verbose
140 fprintf(' Stationary distribution computed, sum = %.6f\n', sum(pi));
141end
142
143end