LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
pfqn_comom.m
1%{
2%{
3 % @file pfqn_comom.m
4 % @brief CoMoM algorithm for computing the normalizing constant.
5%}
6%}
7
8function lG=pfqn_comom(L,N,Z,atol)
9%{
10%{
11 % @brief CoMoM algorithm for computing the normalizing constant.
12 % @fn pfqn_comom(L, N, Z, atol)
13 % @param L Service demand matrix.
14 % @param N Population vector.
15 % @param Z Think time vector.
16 % @param atol Tolerance.
17 % @return lG Logarithm of the normalizing constant.
18%}
19%}
20if nargin<3
21 Z=0*N;
22end
23% atol has no other default in this family; 1e-14 matches the sibling
24% pfqn_procomom. Without this the 3-argument form advertised in the header
25% died on an undefined atol at the Lmax rescaling below.
26if nargin<4
27 atol=1e-14;
28end
29[M,R]=size(L);
30if M>1
31 line_error(mfilename,'pfqn_comom supports at most one queueing station (repairman models with a delay); use pfqn_ca or pfqn_recal for M>1.');
32end
33% rescale demands
34Lmax = L; % use L
35Lmax(Lmax<atol)=Z(Lmax<atol); % unless zero
36Lmax = max(Lmax,[],1);
37L = L./repmat(Lmax,M,1);
38Z = Z./repmat(Lmax,M,1);
39% sort from smallest to largest
40%[~,rsort] = sort(Z,'ascend');
41%L=L(:,rsort);
42%Z=Z(:,rsort);
43% prepare comom data structures
44Dn=multichoose(R,M);
45Dn(:,R)=0;
46Dn=sortbynnzpos(Dn);
47% initialize
48nvec=zeros(1,R);
49h=ginit(L);
50lh=log(h) + factln(sum(nvec)+M-1) - sum(factln(nvec));
51h=exp(lh);
52scale=zeros(1,sum(N));
53matrixDim = nchoosek(M+R-1,M)*(M+1);
54A = zeros(matrixDim);
55B = zeros(matrixDim);
56DA = zeros(matrixDim);
57% iterate
58for r=1:R
59 for Nr=1:N(r)
60 nvec(r)=nvec(r)+1;
61 if Nr==1
62 [A,B,DA]=genmatrix(L,nvec,Z,r);
63 else
64 A=A+DA;
65 end
66 b = B*h*nvec(r)/(sum(nvec)+M-1);
67 h = A\b;
68 nt=sum(nvec);
69 scale(nt)=abs(sum(sort(h)));
70 h = abs(h)/scale(nt); % rescale so that |h|=1
71 end
72end
73% unscale and return the log of the normalizing constant
74lG=log(h(end-(R-1))) + factln(sum(N)+M-1) - sum(factln(N)) + N*log(Lmax)' + sum(log(scale));
75
76 function [A,B,DA]=genmatrix(L,N,Z,r)
77 [M,R]=size(L);
78 A=zeros(nchoosek(M+R-1,M)*(M+1));
79 DA=zeros(nchoosek(M+R-1,M)*(M+1));
80 B=zeros(nchoosek(M+R-1,M)*(M+1));
81 row=0;
82 lastnnz=0;
83 for d=1:length(Dn)
84 hnnz=hashnnz(Dn(d,:),R);
85 if hnnz~=lastnnz
86 lastnnz=hnnz;
87 end
88 end
89 for d=1:length(Dn)
90 if sum(Dn(d,(r):R-1))>0
91 % dummy rows for unused norm consts
92 for k=0:M
93 row=row+1;
94 col = hash(N,N-Dn(d,:),k+1);
95 A(row,col)=1;
96 if sum(Dn(d,(r+1):R-1))>0
97 col = hash(N,N-Dn(d,:),k+1);
98 B(row,col)=1;
99 else
100 er=zeros(1,R); er(r)=1;
101 col = hash(N,N-Dn(d,:)+er,k+1);
102 B(row,col)=1;
103 end
104 end
105 else
106 if sum(Dn(d,1:r))<M
107 for k=1:M
108 % add CE
109 row=row+1;
110 A(row,hash(N,N-Dn(d,:),k+1))=1;
111 A(row,hash(N,N-Dn(d,:),0+1))=-1;
112 for s=1:r-1
113 A(row,hash(N,oner(N-Dn(d,:),s),k+1))=-L(k,s);
114 end
115 B(row,hash(N,N-Dn(d,:),k+1))=L(k,r);
116 end
117 for s=1:(r-1)
118 % add PC to A
119 row=row+1;
120 n=N-Dn(d,:);
121 A(row,hash(N,n,0+1))=n(s);
122 A(row,hash(N,oner(n,s),0+1))=-Z(s);
123 for k=1:M
124 A(row,hash(N,oner(n,s),k+1))=-L(k,s);
125 end
126 B(row,:)=0;
127 end
128 end
129 end
130 end
131 %add PC of class R
132 for d=1:length(Dn)
133 if sum(Dn(d,(r):R-1))<=0
134 row=row+1;
135 n=N-Dn(d,:);
136 A(row,hash(N,n,0+1))=n(r);
137 DA(row,hash(N,n,0+1))=1;
138 B(row,hash(N,n,0+1))=Z(r);
139 for k=1:M
140 B(row,hash(N,n,k+1))=L(k,r);
141 end
142 end
143 end
144 end
145
146 function val=hashnnz(dn,R)
147 val=0;
148 for t=1:R
149 if dn(t)==0
150 val=val+2^(t-1);
151 end
152 end
153 end
154
155 function col=hash(N,n,i)
156 if i==1
157 col=size(Dn,1)*M+matchrow(Dn,N-n);
158 else
159 col=(matchrow(Dn,N-n)-1)*M+i-1;
160 end
161 end
162
163 function g=ginit(L)
164 e1=zeros(1,R);
165 g=zeros(size(Dn,1)*(M+1),1);
166 for i=0:M
167 g(hash(N,N,i+1))=1;
168 end
169 g=g(:);
170 end
171
172 function I=sortbynnzpos(I)
173 % sorts a set of combinations with repetition according to the number of
174 % nonzeros
175 for i=1:size(I,1)-1
176 for j=i+1:size(I,1)
177 if nnzcmp(I(i,:),I(j,:))==1
178 v=I(i,:);
179 I(i,:)=I(j,:);
180 I(j,:)=v;
181 end
182 end
183 end
184 end
185
186 function r=nnzcmp(i1,i2) % return 1 if i1<i2
187 nnz1=nnz(i1);
188 nnz2=nnz(i2);
189 if(nnz1>nnz2)
190 r=1; % i2 has more zeros and is thus greater
191 elseif(nnz1<nnz2)
192 r=0; % i1 has more zeros and is thus greater
193 else %nnz1==nnz2
194 for j=1:length(i1)
195 if i1(j)==0 & i2(j)>0
196 r=1; % i2 has the left-most zero
197 return
198 elseif i1(j)>0 & i2(j)==0
199 r=0;
200 return
201 end
202 end
203 r=0;
204 end
205 end
206
207end