1function [G,R,U]=QBD_FI(A0,A1,A2,varargin)
2%QBD_FI Functional Iterations
for Quasi-Birth-Death Markov Chains [Neuts]
6% G=QBD_FI(A0,A1,A2) computes the minimal nonnegative solution to the
7% matrix equation G = A0 + A1 G + A2 G^2, where A,B and C are square
8% nonnegative matrices, with (A0+A1+A2) irreducible and stochastic
10% [G,R]=QBD_FI(A0,A1,A2) also provides the minimal nonnegative solution
11% to the matrix equation R = A2 + R A1 + R^2 A0
13% [G,R,U]=QBD_FI(A0,A1,A2) also provides the minimal nonnegative solution
14% to the matrix equation U = A1 + A2 (I-U)^(-1) A0
16% CONTINUOUS TIME CASE:
18% G=QBD_FI(A0,A1,A2) computes the minimal nonnegative solution to the
19% matrix equation 0 = A0 + A1 G + A2 G^2, where A,B and C are square
20% nonnegative matrices, with (A0+A1+A2) having row sums equal to zero
22% [G,R]=QBD_FI(A0,A1,A2) also provides the minimal nonnegative solution
23% to the matrix equation 0 = A2 + R A1 + R^2 A0
25% [G,R,U]=QBD_FI(A0,A1,A2) also provides the minimal nonnegative solution
26% to the matrix equation U = A1 + A2 (-U)^(-1) A0
30% MaxNumIt: Maximum number of iterations (default: 10000)
31% Mode:
'Traditional': G(n+1) = (I-A1)^(-1) * (A0 + A2 * G^2)
32%
'Natural': G(n+1) = A0 + (A1 + A2*G(n))*G(n)
33%
'U-Based': G(n+1) = (I-A1-A2*G(n))^(-1)*A0
34%
'Shift<Mode>': where <Mode>
is Traditional, Natural or
35% U-Based uses the Shift Technique
37% Verbose: When set to k, the residual error
is printed every
39% StartValue: Starting value for iteration (default: 0)
49OptionValues{1}=[
'Traditional ';
57for i=1:size(OptionNames,1)
58 options.(deblank(OptionNames(i,:)))=[];
62options.Mode='U-Based';
63options.MaxNumIt=10000;
66options.StartValue=zeros(m,m);
68% Convert to discrete time problem, if needed
71if (sum(diag(A1)<0)) % continues time
80QBD_ParsePara(A0,A1,A2);
82% Parse Optional Parameters
83options=ParseOptPara(options,OptionNames,OptionTypes,OptionValues,varargin);
85% check whether G
is known explicitly
86[G,R,U]=QBD_EG(A0,A1,A2,options.Verbose,nargout);
96if (strfind(options.Mode,'Shift')>0)
97 theta=statvec(A0+A1+A2);
98 drift=theta*sum(A0,2)-theta*sum(A2,2);
99 if (drift < 0) % MC
is transient -> use the dual MC
100 if (nargout > 1 | options.Verbose>0)
103 A2=A2-ones(m,1)*(theta*A2);
104 A1=A1+ones(m,1)*(theta*A0);
108 if (nargout > 2 | options.Verbose>0) % store A0old to compute U
116if (strfind(options.Mode,'Natural')>0)
117 while(check > 10^(-14) & numit < options.MaxNumIt)
120 check=norm(G-Gold,inf);
122 if (~mod(numit,options.Verbose))
123 fprintf('Check after %d iterations: %d\n',numit,check);
129if (strfind(options.Mode,'Traditional')>0)
130 invA1=(eye(m)-A1)^(-1);
131 while(check > 10^(-14) & numit < options.MaxNumIt)
134 check=norm(G-Gold,inf);
136 if (~mod(numit,options.Verbose))
137 fprintf('Check after %d iterations: %d\n',numit,check);
143if (strfind(options.Mode,'U-Based')>0)
144 while(check > 10^(-14) & numit < options.MaxNumIt)
146 G=(eye(m)-A1-A2*G)^(-1)*A0;
147 check=norm(G-Gold,inf);
149 if (~mod(numit,options.Verbose))
150 fprintf('Check after %d iterations: %d\n',numit,check);
155if (numit == options.MaxNumIt)
156 warning('Maximum Number of Iterations %d reached',numit);
159if (strfind(options.Mode,'Shift')>0)
160 if (drift < 0) % transient
161 if (nargout > 1 | options.Verbose >0)
162 A1=A1-ones(m,1)*theta*A0; % restore original A1
163 A2=A2old; % restore original A2
167 if (nargout > 1 | options.Verbose >0)
168 A1=A1-sum(A2,2)*uT; % restore original A1
170 if (nargout > 2 | options.Verbose >0)
171 A0=A0old; % restore original A0
176if (options.Verbose>0)
177 res_norm=norm(G-A0-(A1+A2*G)*G,inf);
178 fprintf('Final Residual Error for G: %d\n',res_norm);
183 R=A2*(eye(m)-(A1+A2*G))^(-1);
184 if (options.Verbose>0)
185 res_norm=norm(R-A2-R*(A1+R*A0),inf);
186 fprintf('Final Residual Error for R: %d\n',res_norm);
193 if (options.Verbose>0)
194 res_norm=norm(U-A1-A2*(eye(m)-U)^(-1)*A0,inf);
195 fprintf('Final Residual Error for U: %d\n',res_norm);