LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
dtmc_solve_reducible.m
1function [pi,pis,pi0,scc,isrec,Pl,pil] = dtmc_solve_reducible(P, pin, options)
2% [PI,PIS,PI0,SCC,ISREC,PL,PIL] = DTMC_SOLVE_REDUCIBLE(P, PIN, OPTIONS)
3%
4% Estimate limiting distribution for a DTMC P that may have reducible
5% components
6%
7% Input:
8% P: dtmc transition matrix
9% pin: initial vector, to be set to [] if not available
10% options: struct where options.tol sets the tolerance
11%
12% Output:
13% pi: - For an ergodic DTMC, this is the unique limiting distribution.
14% - For a reducible DTMC:
15% - if there is a single transient SCC then this
16% is assumed to be the starting state with uniform probability
17% across its states.
18% - if there are multiple transient SCCs then pi is the average
19% of the limiting distributions in pis
20%
21% pis: limiting distribution given initialization pi0 in a single SCC
22% pi0: start vector of the lumped DTMC for each row of pis. For ergodic
23% DTMCs, this is the empty vector.
24% scc: mapping of state of P to SCCs
25% isrec: element i is true if SCC i is recurrent or false otherwise
26% Pl: lumped DTMC where each SCC is replaced by a single state
27% pil: limiting distribution of the lumped DTMC
28%
29% WARNING: the script does not consider explicitly periodic SCCs
30
31[scc, isrec] = stronglyconncomp(P);
32
33% Number of SCCs
34numSCC = max(scc);
35if numSCC==1
36 pi = dtmc_solve(P);
37 pis = pi;
38 pi0 = [];
39 Pl = P;
40 pil = pi;
41 return
42else
43 % Lump SCCs
44 Pl = zeros(numSCC);
45
46 % Lump states according to SCCs
47 scc_idx = cell(1,numSCC);
48 for i = 1:numSCC
49 scc_idx{i} = scc == i;
50 end
51
52 for i = 1:numSCC
53 scc_i = scc_idx{i};
54 for j = 1:numSCC
55 if i ~= j
56 scc_j = scc_idx{j};
57 Pl(i,j) = sum(P(scc_i, scc_j),"all");
58 end
59 end
60 end
61
62 Pl = dtmc_makestochastic(Pl);
63
64 % Ensure that recurrent SCCs have self-loops
65 for i = 1:numSCC
66 if isrec(i)
67 Pl(i,i) = 1;
68 end
69 end
70
71 % acompute pinl(i), the probability of starting in scc i
72 if nargin<2 || isempty(pin)
73 pin = [];
74 pinl = ones(1,numSCC);
75 % Find columns (states) with near-zero column sums (absorbing states)
76 z_cols = find(sum(P,1) < 1e-12);
77 % Map state indices to SCC indices for zeroing pinl
78 for j = z_cols
79 pinl(scc(j)) = 0;
80 end
81 pinl = pinl / sum(pinl);
82 else
83 % in this case, an initial state vector is provided
84 % lump initial vector
85 pinl = zeros(1,numSCC);
86 for i = 1:numSCC
87 pinl(i) = sum(pin(scc_idx{i}));
88 end
89 end
90
91 % using pinl, compute all limiting probabilities and average them
92 pi = zeros(1,length(P));
93
94 % Compute limiting matrix PI via spectral decomposition
95 % First check if matrix is numerically stable for spectral decomposition
96 % by examining the eigenvector matrix condition number
97 useSpectral = true;
98 try
99 [V, ~] = eig(Pl);
100 condV = cond(V);
101 if condV > 1e10 || isnan(condV) || isinf(condV)
102 % Matrix has repeated eigenvalues or is numerically degenerate
103 % Use power method directly to avoid slow/failing spectd
104 useSpectral = false;
105 end
106 catch
107 useSpectral = false;
108 end
109
110 if useSpectral
111 try
112 % Suppress singular matrix warnings during spectd call
113 warnState = warning('off', 'MATLAB:singularMatrix');
114 warnState2 = warning('off', 'MATLAB:nearlySingularMatrix');
115 [eigs,projectors]=spectd(Pl);
116 warning(warnState);
117 warning(warnState2);
118 PI = zeros(size(projectors{1}));
119 for e=1:length(eigs)
120 if eigs(e)>1-1e-12
121 PI = PI + projectors{e};
122 end
123 end
124 % Check if PI has NaN values (spectd failed on singular matrix)
125 if any(isnan(PI(:)))
126 PI = compute_limiting_matrix_power(Pl);
127 end
128 catch
129 % Fallback to power method if spectd fails
130 PI = compute_limiting_matrix_power(Pl);
131 end
132 else
133 % Use power method for numerically degenerate matrices
134 PI = compute_limiting_matrix_power(Pl);
135 end
136 pi0 = zeros(numSCC,numSCC);
137 pil = zeros(numSCC,numSCC);
138 pis = zeros(numSCC,length(P));
139 for i = 1:numSCC
140 if pinl(i)>0
141 pi0(i,:) = zeros(1,numSCC);
142 pi0(i,i) = 1;
143 pil(i,:) = pi0(i,:)*PI;
144 pis(i,1:length(P)) = 0;
145 for j=1:numSCC
146 scc_j = scc_idx{j};
147 if nargin<3
148 pis(i, scc_j) = pil(i,j)*dtmc_solve(P(scc_j, scc_j));
149 else
150 pis(i, scc_j) = pil(i,j)*dtmc_solve(P(scc_j, scc_j), options);
151 end
152 end
153 pi = pi + pis(i,:) * pinl(i);
154 end
155 end
156
157 transient_states = find(isrec==false);
158 if isscalar(transient_states) && isempty(pin)
159 pi = pis(transient_states,:);
160 else
161 % leave pi as it is
162 end
163end
164end
165
166function PI = compute_limiting_matrix_power(P)
167% COMPUTE_LIMITING_MATRIX_POWER Compute limiting matrix using power iteration
168%
169% For ergodic DTMCs, P^n converges to a matrix where each row is the
170% stationary distribution. This function serves as a fallback when
171% spectral decomposition fails due to singular or defective matrices.
172
173n = size(P, 1);
174Pk = P;
175maxIter = 1000;
176tol = 1e-10;
177
178for iter = 1:maxIter
179 Pk1 = Pk * P;
180
181 % Check convergence
182 maxDiff = max(abs(Pk1(:) - Pk(:)));
183 Pk = Pk1;
184
185 if maxDiff < tol
186 break
187 end
188end
189
190PI = Pk;
191end