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[M,R]=size(L);
24% rescale demands
25Lmax = L; % use L
26Lmax(Lmax<atol)=Z(Lmax<atol); % unless zero
27Lmax = max(Lmax,[],1);
28L = L./repmat(Lmax,M,1);
29Z = Z./repmat(Lmax,M,1);
30% sort from smallest to largest
31%[~,rsort] = sort(Z,'ascend');
32%L=L(:,rsort);
33%Z=Z(:,rsort);
34% prepare comom data structures
35Dn=multichoose(R,M);
36Dn(:,R)=0;
37Dn=sortbynnzpos(Dn);
38% initialize
39nvec=zeros(1,R);
40h=ginit(L);
41lh=log(h) + factln(sum(nvec)+M-1) - sum(factln(nvec));
42h=exp(lh);
43scale=zeros(1,sum(N));
44matrixDim = nchoosek(M+R-1,M)*(M+1);
45A = zeros(matrixDim);
46B = zeros(matrixDim);
47DA = zeros(matrixDim);
48% iterate
49for r=1:R
50 for Nr=1:N(r)
51 nvec(r)=nvec(r)+1;
52 if Nr==1
53 [A,B,DA]=genmatrix(L,nvec,Z,r);
54 else
55 A=A+DA;
56 end
57 b = B*h*nvec(r)/(sum(nvec)+M-1);
58 h = A\b;
59 nt=sum(nvec);
60 scale(nt)=abs(sum(sort(h)));
61 h = abs(h)/scale(nt); % rescale so that |h|=1
62 end
63end
64% unscale and return the log of the normalizing constant
65lG=log(h(end-(R-1))) + factln(sum(N)+M-1) - sum(factln(N)) + N*log(Lmax)' + sum(log(scale));
66
67 function [A,B,DA]=genmatrix(L,N,Z,r)
68 [M,R]=size(L);
69 A=zeros(nchoosek(M+R-1,M)*(M+1));
70 DA=zeros(nchoosek(M+R-1,M)*(M+1));
71 B=zeros(nchoosek(M+R-1,M)*(M+1));
72 row=0;
73 lastnnz=0;
74 for d=1:length(Dn)
75 hnnz=hashnnz(Dn(d,:),R);
76 if hnnz~=lastnnz
77 lastnnz=hnnz;
78 end
79 end
80 for d=1:length(Dn)
81 if sum(Dn(d,(r):R-1))>0
82 % dummy rows for unused norm consts
83 for k=0:M
84 row=row+1;
85 col = hash(N,N-Dn(d,:),k+1);
86 A(row,col)=1;
87 if sum(Dn(d,(r+1):R-1))>0
88 col = hash(N,N-Dn(d,:),k+1);
89 B(row,col)=1;
90 else
91 er=zeros(1,R); er(r)=1;
92 col = hash(N,N-Dn(d,:)+er,k+1);
93 B(row,col)=1;
94 end
95 end
96 else
97 if sum(Dn(d,1:r))<M
98 for k=1:M
99 % add CE
100 row=row+1;
101 A(row,hash(N,N-Dn(d,:),k+1))=1;
102 A(row,hash(N,N-Dn(d,:),0+1))=-1;
103 for s=1:r-1
104 A(row,hash(N,oner(N-Dn(d,:),s),k+1))=-L(k,s);
105 end
106 B(row,hash(N,N-Dn(d,:),k+1))=L(k,r);
107 end
108 for s=1:(r-1)
109 % add PC to A
110 row=row+1;
111 n=N-Dn(d,:);
112 A(row,hash(N,n,0+1))=n(s);
113 A(row,hash(N,oner(n,s),0+1))=-Z(s);
114 for k=1:M
115 A(row,hash(N,oner(n,s),k+1))=-L(k,s);
116 end
117 B(row,:)=0;
118 end
119 end
120 end
121 end
122 %add PC of class R
123 for d=1:length(Dn)
124 if sum(Dn(d,(r):R-1))<=0
125 row=row+1;
126 n=N-Dn(d,:);
127 A(row,hash(N,n,0+1))=n(r);
128 DA(row,hash(N,n,0+1))=1;
129 B(row,hash(N,n,0+1))=Z(r);
130 for k=1:M
131 B(row,hash(N,n,k+1))=L(k,r);
132 end
133 end
134 end
135 end
136
137 function val=hashnnz(dn,R)
138 val=0;
139 for t=1:R
140 if dn(t)==0
141 val=val+2^(t-1);
142 end
143 end
144 end
145
146 function col=hash(N,n,i)
147 if i==1
148 col=size(Dn,1)*M+matchrow(Dn,N-n);
149 else
150 col=(matchrow(Dn,N-n)-1)*M+i-1;
151 end
152 end
153
154 function g=ginit(L)
155 e1=zeros(1,R);
156 g=zeros(size(Dn,1)*(M+1),1);
157 for i=0:M
158 g(hash(N,N,i+1))=1;
159 end
160 g=g(:);
161 end
162
163 function I=sortbynnzpos(I)
164 % sorts a set of combinations with repetition according to the number of
165 % nonzeros
166 for i=1:size(I,1)-1
167 for j=i+1:size(I,1)
168 if nnzcmp(I(i,:),I(j,:))==1
169 v=I(i,:);
170 I(i,:)=I(j,:);
171 I(j,:)=v;
172 end
173 end
174 end
175 end
176
177 function r=nnzcmp(i1,i2) % return 1 if i1<i2
178 nnz1=nnz(i1);
179 nnz2=nnz(i2);
180 if(nnz1>nnz2)
181 r=1; % i2 has more zeros and is thus greater
182 elseif(nnz1<nnz2)
183 r=0; % i1 has more zeros and is thus greater
184 else %nnz1==nnz2
185 for j=1:length(i1)
186 if i1(j)==0 & i2(j)>0
187 r=1; % i2 has the left-most zero
188 return
189 elseif i1(j)>0 & i2(j)==0
190 r=0;
191 return
192 end
193 end
194 r=0;
195 end
196 end
197
198end