-
Notifications
You must be signed in to change notification settings - Fork 0
/
QBD_pi.m
138 lines (128 loc) · 4.41 KB
/
QBD_pi.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
function pi=QBD_pi(B0,B1,R,varargin)
%QBD_pi Stationary vector of a Quasi-Birth-Death Markov Chains [Neuts]
%
% DISCRETE TIME CASE:
%
% pi=QBD_pi(B0,B1,R) computes the stationary vector of a Quasi-Birth-Death
% Markov chain with a transition matrix of the form
%
% B1 A2 0 0 0 ...
% B0 A1 A2 0 0 ...
% P = 0 A0 A1 A2 0 ...
% 0 0 A0 A1 A2 ...
% ...
%
% the input matrix R is the minimal nonnegative solution to the matrix
% equation R = A2 + R A1 + R^2 A0
%
% CONTINUOUS TIME CASE:
%
% pi=QBD_pi(B0,B1,R) computes the stationary vector of a Quasi-Birth-Death
% Markov chain with a rate matrix of the form
%
% B1 A2 0 0 0 ...
% B0 A1 A2 0 0 ...
% Q = 0 A0 A1 A2 0 ...
% 0 0 A0 A1 A2 ...
% ...
%
% the input matrix R is the minimal nonnegative solution to the matrix
% equation 0 = A2 + R A1 + R^2 A0
%
% Optional Parameters:
%
% MaxNumComp: Maximum number of components (default: 500)
% Verbose: The accumulated probability mass is printed at every
% n steps when set to n (default:0)
% Boundary: Allows solving the QBD with a more general boundary
%
% B1 B2 0 0 0 ...
% B0 A1 A2 0 0 ...
% P (or Q) = 0 A0 A1 A2 0 ...
% 0 0 A0 A1 A2 ...
% ...
%
% the parameter value contains the matrix [B2; A1+R*A0].
% The matrices B0 and B2 need not to be square.
% (default: B2=A2)
% RAPComp: set to 1 if the QBD has RAP components
OptionNames=[
'Boundary ';
'MaxNumComp ';
'Verbose ';
'RAPComp '];
OptionTypes=[
'numeric';
'numeric';
'numeric';
'numeric'];
OptionValues=[];
options=[];
for i=1:size(OptionNames,1)
options.(deblank(OptionNames(i,:)))=[];
end
% Default settings
options.Boundary=[];
options.MaxNumComp=500;
options.Verbose=0;
options.RAPComp=0;
% Parse Optional Parameters
options=ParseOptPara(options,OptionNames,OptionTypes,OptionValues,varargin);
m=size(R,1);
% Convert to discrete time problem, if needed
if (sum(diag(B1)<0) || options.RAPComp) % continuous time
lamb=max(-diag(B1));
if (~isempty(options.Boundary))
mb=size(B1,1);
lamb=max(lamb,max(-diag(options.Boundary(mb+1:end,:))));
options.Boundary=options.Boundary/lamb;
options.Boundary(mb+1:end,:)=options.Boundary(mb+1:end,:)+eye(m);
B1=B1/lamb+eye(mb);
else
B1=B1/lamb+eye(m);
end
B0=B0/lamb;
end
temp=(eye(m)-R)^(-1);
if( max(temp<-100*eps) )
error('MATLAB:QBD_pi:InvalidRInput',...
'The spectral radius of R is not below 1: QBD is not pos. recurrent');
end
if (isempty(options.Boundary))
pi=stat(B1+R*B0); % compute pi_0
pi=pi/(pi*temp*ones(m,1)); % normalize pi_0
sumpi=sum(pi);
numit=1;
while (sumpi < 1-10^(-10) && numit < 1+options.MaxNumComp)
pi(numit+1,1:m)=pi(numit,:)*R; % compute pi_(numit+1)
numit=numit+1;
sumpi=sumpi+sum(pi(numit,:));
if (~mod(numit,options.Verbose))
fprintf('Accumulated mass after %d iterations: %d\n',numit,sumpi);
drawnow;
end
end
pi=reshape(pi',1,[]);
else
mb=size(B1,1);
pi0=stat([[B1; B0] options.Boundary]); % compute pi_0 and pi_1
pi0=pi0/(pi0(1:mb)*ones(mb,1)+pi0(mb+1:end)*temp*ones(m,1)); % normalize
pi=pi0(mb+1:end);
pi0=pi0(1:mb);
sumpi=sum(pi0)+sum(pi);
numit=1;
while (sumpi < 1-10^(-10) && numit < options.MaxNumComp)
pi(numit+1,1:m)=pi(numit,:)*R; % compute pi_(numit+1)
numit=numit+1;
sumpi=sumpi+sum(pi(numit,:));
if (~mod(numit,options.Verbose))
fprintf('Accumulated mass after %d iterations: %d\n',numit,sumpi);
drawnow;
end
end
pi=[pi0 reshape(pi',1,[])];
numit=numit+1;
end
if (numit == 1+options.MaxNumComp)
warning('Maximum Number of Components %d reached',numit-1);
end