3 % @file pfqn_procomom.m
4 % @brief ProCoMoM algorithm
for computing marginal queue-length probabilities.
8function [Pr,Q]=pfqn_procomom(L,N,Z,atol)
11 % @brief ProCoMoM algorithm
for computing marginal queue-length probabilities.
12 % @fn pfqn_procomom(L, N, Z, atol)
13 % @param L Service demand matrix (M x R).
14 % @param N Population vector (1 x R).
15 % @param Z Think time vector (1 x R).
16 % @param atol Tolerance.
17 % @
return Pr Marginal probability matrix (M x sumN+1), Pr(k,j+1) =
P(n_k = j).
18 % @
return Q Mean queue length vector (M x 1).
21if nargin<3 || isempty(Z)
30% rescale demands per
class for numerical stability
31% normalized probabilities are invariant to per-
class demand scaling
37% build Dn basis: multichoose(R,M) with column R zeroed, sorted by nnzpos
44% solve with
auto-perturbation on rank deficiency
45[Pr,rankdef]=solve_all(L,Z);
47 %
try progressively larger perturbations
49 Lscale=max(abs(L(:)));
50 if Lscale<atol; Lscale=1; end
51 for delta_exp = [-10 -8 -6 -4]
52 delta=Lscale*10^delta_exp;
54 Lp=L+delta*(1+rand(M,R));
55 Zp=Z+delta*(1+rand(1,R));
56 [Pr_try,rd]=solve_all(Lp,Zp);
57 if ~rd && all(Pr_try(:)>=-1e-6) && all(abs(sum(Pr_try,2)-1)<0.01)
66 function [Pr,rankdef]=solve_all(Ls_in,Zs_in)
73 Lrot([station M],:)=Lrot([M station],:);
74 [dist,rd]=solve_station(Lrot);
80 Pr(station,:)=dist/total;
86 function [dist,rankdef]=solve_station(Ls)
88 % pk(:,j+1) holds basis coefficients for queue length n=j
89 pk=zeros(basisSize,sumN+1);
90 % pexact: for empty network, all stations have probability 1 at n=0
93 pk(phash(zero_dn,kk),1)=1;
100 pk=zeros(basisSize,sumN+1);
101 [Ag,Bg,DCg,DDg]=genpmatrix(Ls,Ncur,r);
102 % SVD for rank-revealing decomposition
105 tol=max(size(Ag))*eps(max(sv));
109 % use minimum-norm solution via truncated SVD
112 Si=diag(1./sv(1:rk));
114 pDC=Vr*(Si*(Ur
'*DCg));
115 pDD=Vr*(Si*(Ur'*DDg));
117 pk(:,1)=pB*pklast(:,1);
119 pk(:,n+1)=pB*pklast(:,n+1)+n*pDC*pk(:,n)+n*pDD*pklast(:,n);
122 % full rank: use QR
for speed and accuracy
128 pk(:,1)=Rg\(QtB*pklast(:,1));
130 rhs=QtB*pklast(:,n+1)+n*QtDC*pk(:,n)+n*QtDD*pklast(:,n);
134 % rescale to prevent overflow
135 smax=max(abs(pk(:)));
136 if smax>0 && isfinite(smax)
141 % extract result: first basis element at zero Dn entry
142 dist=pk(phash(zero_dn,1),:);
145 function [A,B,DC,DD]=genpmatrix(Ls,Ncur,r)
146 numRows=countrows(r);
147 A=zeros(numRows,basisSize);
148 B=zeros(numRows,basisSize);
149 DC=zeros(numRows,basisSize);
150 DD=zeros(numRows,basisSize);
153 if r<=R-1 && sum(Dn(d,r:R-1))>0
154 % Branch A: propagation through class boundaries
157 colA=phash(Dn(d,:),k);
159 if r+1<=R-1 && sum(Dn(d,r+1:R-1))>0
163 shifted(r)=shifted(r)-1;
164 colB=phash(shifted,k);
165 if colB>0 && colB<=basisSize
171 % Branch B: CE, PC, and extra PC equations
173 % CE equations: k=1..M-1
176 A(row,phash(Dn(d,:),k+1))=1;
177 A(row,phash(Dn(d,:),1))=-1;
180 shifted(s)=shifted(s)+1; % UP shift
181 col=phash(shifted,k+1);
182 if col>0 && col<=basisSize
186 B(row,phash(Dn(d,:),k+1))=Ls(k,r);
188 % PC equations: s=1..r-1
191 nd_s=Ncur(s)-Dn(d,s);
192 A(row,phash(Dn(d,:),1))=nd_s;
194 shifted(s)=shifted(s)+1; % UP shift
195 colBase=phash(shifted,1);
196 if colBase>0 && colBase<=basisSize
197 A(row,colBase)=-Z(s);
198 DC(row,colBase)=Ls(M,s);
201 col=phash(shifted,k+1);
202 if col>0 && col<=basisSize
208 % Extra PC for class r (always in Branch B)
210 nd_r=Ncur(r)-Dn(d,r);
211 A(row,phash(Dn(d,:),1))=nd_r;
212 B(row,phash(Dn(d,:),1))=Z(r);
214 B(row,phash(Dn(d,:),k+1))=Ls(k,r);
216 DD(row,phash(Dn(d,:),1))=Ls(M,r);
221 function numRows=countrows(r)
224 if r<=R-1 && sum(Dn(d,r:R-1))>0
228 numRows=numRows+M+r-1;
236 function col=phash(dn,i)
245 function I=sortbynnzpos(I)
247 for jj=ii+1:size(I,1)
248 if nnzcmp(I(ii,:),I(jj,:))==1
257 function r=nnzcmp(i1,i2)
266 if i1(jj)==0 && i2(jj)>0
269 elseif i1(jj)>0 && i2(jj)==0