LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
pfqn_ca.m
1%{
2%{
3 % @file pfqn_ca.m
4 % @brief Convolution Algorithm for exact normalizing constant computation.
5%}
6%}
7
8function [Gn,lGn]=pfqn_ca(L,N,Z)
9%{
10%{
11 % @brief Convolution Algorithm for exact normalizing constant computation.
12 % @fn pfqn_ca(L, N, Z)
13 % @param L Service demand matrix.
14 % @param N Population vector.
15 % @param Z Think time vector.
16 % @return Gn Normalizing constant.
17 % @return lGn Logarithm of the normalizing constant.
18%}
19%}
20[M,R]=size(L);
21if nargin<3 || isempty(Z)
22 Z=zeros(1,R);
23end
24if M==0
25 lGn = - sum(factln(N)) + sum(N.*log(sum(Z,1)));
26 Gn = exp(lGn);
27 return
28end
29
30if min(N)<0
31 Gn=0;
32 lGn=-Inf;
33 return;
34end
35
36if sum(N)==0
37 Gn=1;
38 lGn=0;
39 return;
40end
41
42% see _kb/03-api-layer.md (pfqn/ family: scaling, log-domain switches, dispatch gates)
43Nt = sum(N);
44lGest = -Inf;
45for i = 1:M
46 t = 0; ok = true;
47 for r = 1:R
48 if N(r) > 0
49 if L(i,r) > 0
50 t = t + N(r)*log(L(i,r));
51 else
52 ok = false; break
53 end
54 end
55 end
56 if ok, lGest = max(lGest, t); end
57end
58if any(Z > 0) % all jobs at the delay
59 t = 0; ok = true;
60 for r = 1:R
61 if N(r) > 0
62 if sum(Z(:,r)) > 0
63 t = t + N(r)*log(sum(Z(:,r))) - factln(N(r));
64 else
65 ok = false; break
66 end
67 end
68 end
69 if ok, lGest = max(lGest, t); end
70end
71if ~isfinite(lGest)
72 kscale = 0;
73else
74 kscale = round(lGest/(Nt*log(2)));
75end
76cscale = pow2(kscale);
77L = L / cscale;
78Z = Z / cscale;
79
80G = ones(M+1,prod(N+1)); % stores G across recursion
81n = pprod(N);
82while sum(n)~=-1
83 idxn = hashpop(n,N);
84 G(1,idxn) = Fz(Z,n);
85 for m=2:M+1
86 G(m,idxn) = G(m-1,idxn); % norm constant with m-1 queues
87 for r=1:R
88 if n(r)>=1
89 n(r) = n(r)-1;
90 idxn_1r = hashpop(n,N);
91 n(r) = n(r)+1;
92 G(m,idxn) = G(m,idxn) + L(m-1,r)*G(m,idxn_1r);
93 end
94 end
95 end
96 n=pprod(n,N);
97end
98% Undo the scaling in log space: log G = log G_scaled + sum(N) log c. lGn is
99% therefore finite whenever log G itself is, even though Gn may legitimately
100% overflow to Inf (the true constant really is outside double range).
101lGn = log(G(M+1,end)) + sum(N)*kscale*log(2);
102% see _kb/03-api-layer.md (pfqn/ family: scaling, log-domain switches, dispatch gates)
103Gn = pow2(G(M+1,end), sum(N)*kscale);
104end
105
106function idx=hashpop(n,N,R,prods)
107% IDX=HASHPOP(N,N,R,PRODS)
108
109% hash a population vector in n: 0<=n<=N
110idx=1;
111if nargin==2
112 R=length(N);
113 for r=1:R
114 idx= idx + prod(N(1:r-1)+1)*n(r);
115 end
116 return
117else
118 for r=1:R
119 idx= idx + prods(r)*n(r);
120 end
121end
122end
123
124function [n]=pprod(n,N)
125% [N]=PPROD(N,N)
126
127% sequentially generate all vectors n: 0<=n<=N
128% n=pprod(N) - init
129% n=pprod(n,N) - next state
130if nargin==1
131 N=n;
132 n=zeros(size(N));
133 return;
134end
135
136R=length(N);
137if sum(n==N)==R
138 n=-1;
139 return
140end
141
142s=R;
143while s>0 && n(s)==N(s)
144 n(s)=0;
145 s=s-1;
146end
147if s==0
148 %n=-1*ones(1,R);
149 return
150end
151n(s)=n(s)+1;
152return;
153end
154
155function f=Fz(Z,n)
156% F=FZ(Z,N)
157
158R=length(n);
159if sum(n)==0
160 f=1;
161 return
162end
163f=0;
164for r=1:R
165 if Z(r)>0
166 f=f+log(Z(r))*n(r);
167 f=f-gammaln(1+n(r));
168 elseif n(r)>0
169 f = 0;
170 return
171 end
172end
173f=exp(f);
174end