1function pi=QBD_pi(B0,B1,R,varargin)
2%QBD_pi Stationary vector of a Quasi-Birth-Death Markov Chains [Neuts]
6% pi=QBD_pi(B0,B1,R) computes
the stationary vector of a Quasi-Birth-Death
7% Markov chain with a transition matrix of
the form
15%
the input matrix R
is the minimal nonnegative solution to
the matrix
16% equation R = A2 + R A1 + R^2 A0
18% CONTINUOUS TIME CASE:
20% pi=QBD_pi(B0,B1,R) computes
the stationary vector of a Quasi-Birth-Death
21% Markov chain with a rate matrix of
the form
29%
the input matrix R
is the minimal nonnegative solution to
the matrix
30% equation 0 = A2 + R A1 + R^2 A0
34% MaxNumComp: Maximum number of components (
default: 500)
35% Verbose: The accumulated probability mass
is printed at every
36% n steps when set to n (default:0)
37% Boundary: Allows solving
the QBD with a more general boundary
41%
P (or Q) = 0 A0 A1 A2 0 ...
45%
the parameter value contains
the matrix [B2; A1+R*A0].
46% The matrices B0 and B2 need not to be square.
48% RAPComp: set to 1 if
the QBD has RAP components
64for i=1:size(OptionNames,1)
65 options.(deblank(OptionNames(i,:)))=[];
70options.MaxNumComp=500;
75options=ParseOptPara(options,OptionNames,OptionTypes,OptionValues,varargin);
79% Convert to discrete time problem, if needed
80if (sum(diag(B1)<0) || options.RAPComp) % continuous time
82 if (~isempty(options.Boundary))
84 lamb=max(lamb,max(-diag(options.Boundary(mb+1:end,:))));
85 options.Boundary=options.Boundary/lamb;
86 options.Boundary(mb+1:end,:)=options.Boundary(mb+1:end,:)+eye(m);
95% Positive recurrence
is sp(R)<1. For a Markovian QBD, R
is nonnegative and
96% sp(R)<1
is equivalent to (eye(m)-R)^(-1)>=0,
the entrywise test used here
97% originally; with RAP components R may have negative entries, (eye(m)-R)^(-1)
98% then legitimately has negative entries too, and
the entrywise test rejects
99% stable RAP/RAP/1 queues. The eigenvalue test
is the condition itself.
100if( max(abs(eig(R))) >= 1 )
101 error('MATLAB:QBD_pi:InvalidRInput',...
102 'The spectral radius of R
is not below 1: QBD
is not pos. recurrent');
105if (isempty(options.Boundary))
106 pi=stat(B1+R*B0); % compute pi_0
107 pi=pi/(pi*temp*ones(m,1)); % normalize pi_0
110 while (sumpi < 1-10^(-10) && numit < 1+options.MaxNumComp)
111 pi(numit+1,1:m)=pi(numit,:)*R; % compute pi_(numit+1)
113 sumpi=sumpi+sum(pi(numit,:));
114 if (~mod(numit,options.Verbose))
115 fprintf('Accumulated mass after %d iterations: %d\n',numit,sumpi);
119 pi=reshape(pi',1,[]);
122 pi0=stat([[B1; B0] options.Boundary]); % compute pi_0 and pi_1
123 pi0=pi0/(pi0(1:mb)*ones(mb,1)+pi0(mb+1:end)*temp*ones(m,1)); % normalize
126 sumpi=sum(pi0)+sum(pi);
128 while (sumpi < 1-10^(-10) && numit < options.MaxNumComp)
129 pi(numit+1,1:m)=pi(numit,:)*R; % compute pi_(numit+1)
131 sumpi=sumpi+sum(pi(numit,:));
132 if (~mod(numit,options.Verbose))
133 fprintf('Accumulated mass after %d iterations: %d\n',numit,sumpi);
137 pi=[pi0 reshape(pi',1,[])];
141if (numit == 1+options.MaxNumComp)
142 warning('Maximum Number of Components %d reached',numit-1);