1function [p,p_1,Qperm,eps,epsMAX,pcourt]=ctmc_kms(Q,MS,numSteps)
2% CTMC_KMS - Koury-McAllister-Stewart aggregation-disaggregation method
3% [p,p_1,Qperm,eps,epsMAX,pcourt] = CTMC_KMS(Q,MS,numSteps)
5% Q : infinitesimal generator matrix
6% MS : cell array where MS{i}
is the set of rows of Q in macrostate i
7% numSteps: number of iterative steps
9% p : estimated steady-state probability vector
11% Qperm : permuted Q matrix w.r.t MS as returned by ctmc_courtois
12% eps : NCD index as returned by ctmc_courtois
13% epsMAX : max acceptable value
for eps (otherwise Q
is not NCD)
14% pcourt : steady-state probability vector estimated by ctmc_courtois
16% * The initial approximate solutions
is obtained by calling CTMC_COURTOIS(Q,MS)
17% * No convergence stop criterion
is currently implented
20nMacroStates = size(MS,1); % Number of macro-states
22%% START FROM COURTOIS DECOMPOSITION SOLUTION
23[pcourt,Qperm,Qdec,eps,epsMAX,
P,B,C]=ctmc_courtois(Q,MS);
25% see _kb/03-api-layer.md (CTMC aggregation-disaggregation)
for the ordering rationale
31p_1=pn(:); % defined even when numSteps==0
34 pn_1=pn(:); % canonical
column orientation regardless of iteration
38 procRows=0; %processed rows
39 for I = 1:nMacroStates %
for each macro-state
40 if sum(pn_1((procRows + 1):(procRows + length(MS{I}))))>0
41 pcondn_1((procRows + 1):(procRows + length(MS{I})))=pn_1((procRows + 1):(procRows + length(MS{I})))/sum(pn_1((procRows + 1):(procRows + length(MS{I}))));
43 procRows = procRows + length(MS{I});
46 G=zeros(nMacroStates,nMacroStates);
47 procCols=0; %processed rows
48 for I = 1:nMacroStates %
for each source macro-state
49 procRows=0; %processed rows
50 for J = 1:nMacroStates %
for each dest macro-state
52 %size(pcondn_1((procRows + 1):(procRows + length(MS{J})))
')
53 %size(P((procRows + 1):(procRows + length(MS{J})),(procCols + 1):(procCols + length(MS{I}))))
54 %size(ones(length(MS{I}),1))
55 G(I,J)=pcondn_1((procRows + 1):(procRows + length(MS{J})))'*
P((procRows + 1):(procRows + length(MS{J})),(procCols + 1):(procCols + length(MS{I})))*ones(length(MS{I}),1);
56 procRows = procRows + length(MS{J});
58 procCols = procCols + length(MS{I});
62 %% DISAGGREGATION STEP
64 zn=zeros(1,nStates); % row: zn*L below requires row orientation
65 L=zeros(nStates,nStates);
66 D=zeros(nStates,nStates);
67 U=zeros(nStates,nStates);
68 procRows=0; %processed rows
69 for I = 1:nMacroStates % for each macro-state
70 zn((procRows + 1):(procRows + length(MS{I})))=w(I)*z((procRows + 1):(procRows + length(MS{I})))';
71 procCols=0; %processed rows
72 for J = 1:nMacroStates
74 L((procRows + 1):(procRows + length(MS{I})),(procCols + 1):(procCols + length(MS{J})))=
P((procRows + 1):(procRows + length(MS{I})),(procCols + 1):(procCols + length(MS{J})));
77 D((procRows + 1):(procRows + length(MS{I})),(procCols + 1):(procCols + length(MS{J})))=eye(length(MS{I}))-
P((procRows + 1):(procRows + length(MS{I})),(procCols + 1):(procCols + length(MS{J})));
80 U((procRows + 1):(procRows + length(MS{I})),(procCols + 1):(procCols + length(MS{J})))=
P((procRows + 1):(procRows + length(MS{I})),(procCols + 1):(procCols + length(MS{J})));
82 procCols = procCols + length(MS{J});
84 procRows = procRows + length(MS{I});
87 % Block Gauss-Seidel sweep: solve pn*(D-U) = zn*L directly. The former
88 % 2-block inverse [invA,-invA*B*invC;0,invC] split M at an arbitrary
89 % midpoint rather than a macro-block boundary, which
is invalid.
93 [xg,gflag]=ctmc_gmres(M',rhs);
104% Map back from permuted (macrostate-major) to original state ordering.
107pback=zeros(nStates,1);