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)
4% Estimate limiting distribution
for a DTMC
P that may have reducible
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
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
18% -
if there are multiple transient SCCs then pi
is the average
19% of the limiting distributions in pis
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
29% WARNING: the script does not consider explicitly periodic SCCs
31[scc, isrec] = stronglyconncomp(
P);
46 % Lump states according to SCCs
47 scc_idx = cell(1,numSCC);
49 scc_idx{i} = scc == i;
57 Pl(i,j) = sum(
P(scc_i, scc_j),
"all");
62 Pl = dtmc_makestochastic(Pl);
64 % Ensure that recurrent SCCs have self-loops
71 % acompute pinl(i), the probability of starting in scc i
72 if nargin<2 || isempty(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
81 pinl = pinl / sum(pinl);
83 % in
this case, an initial state vector
is provided
85 pinl = zeros(1,numSCC);
87 pinl(i) = sum(pin(scc_idx{i}));
91 %
using pinl, compute all limiting probabilities and average them
92 pi = zeros(1,length(
P));
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
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
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);
118 PI = zeros(size(projectors{1}));
121 PI = PI + projectors{e};
124 % Check
if PI has NaN values (spectd failed on singular matrix)
126 PI = compute_limiting_matrix_power(Pl);
129 % Fallback to power method
if spectd fails
130 PI = compute_limiting_matrix_power(Pl);
133 % Use power method
for numerically degenerate matrices
134 PI = compute_limiting_matrix_power(Pl);
136 pi0 = zeros(numSCC,numSCC);
137 pil = zeros(numSCC,numSCC);
138 pis = zeros(numSCC,length(
P));
141 pi0(i,:) = zeros(1,numSCC);
143 pil(i,:) = pi0(i,:)*PI;
144 pis(i,1:length(
P)) = 0;
148 pis(i, scc_j) = pil(i,j)*dtmc_solve(
P(scc_j, scc_j));
150 pis(i, scc_j) = pil(i,j)*dtmc_solve(
P(scc_j, scc_j), options);
153 pi = pi + pis(i,:) * pinl(i);
157 transient_states = find(isrec==
false);
158 if isscalar(transient_states) && isempty(pin)
159 pi = pis(transient_states,:);
166function PI = compute_limiting_matrix_power(
P)
167% COMPUTE_LIMITING_MATRIX_POWER Compute limiting matrix
using power iteration
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.
182 maxDiff = max(abs(Pk1(:) - Pk(:)));