LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
pfqn_sens_respt_validate.m
1function pfqn_sens_respt_validate()
2%{
3%{
4 % @file pfqn_sens_respt_validate.m
5 % @brief Validation harness for pfqn_sens_respt, the FCFS sojourn-time moment
6 % analysis of Strelen (1990), Theorem 4.1.
7 %
8 % Five references:
9 % A. brute-force enumeration. This is the strongest check because it
10 % shares none of Theorem 4.1's algebra. The equilibrium product
11 % form is enumerated to get the exact arrival-theorem marginals
12 % p_i(j, N-1_l); the sojourn time conditioned on finding j jobs is
13 % known in closed form (Exp(mu) if j < b, otherwise an
14 % Erlang(j-b+1, b*mu) queueing delay plus an Exp(mu) service), so
15 % its moments are formed directly and mixed over j. Neither the
16 % coefficients a_(t,tau)(0) nor the recursion (4.2) enter, so the
17 % agreement tests both.
18 % B. the published table of Example 3.4 (continued) of the reference,
19 % which prints E(W_i) and sigma^2_(W_i) for the Kobayashi model.
20 % C. the internal identity W(i,l) = w_i(l)/V(i,l): the t = 1 case of
21 % (4.5) must reproduce the MVA residence time divided by the visit
22 % ratio, which is a completely different expression.
23 % D. pfqn_mva for the base measures in the single-server case.
24 % E. the single-job network, where an arriving job always finds an
25 % empty station, so W is exactly Exp(mu) and every moment is known
26 % in closed form.
27 %
28 % Reference: J. C. Strelen, "Moment Analysis for Closed Queuing Networks
29 % and its Linearizer", Performance Evaluation 11:127-142, 1990.
30%}
31%}
32rng(5);
33tolBrute = 1e-9;
34tolPaper = 5e-4; % the paper prints 5 decimals on small sojourn times
35tolIdent = 1e-10;
36tolMva = 1e-10;
37tolExp = 1e-12;
38
39errBrute = 0; errIdent = 0; errMva = 0; errExp = 0;
40nBrute = 0;
41
42% =====================================================================
43% A/C/D. random models, single- and multi-server
44% =====================================================================
45for trial = 1:36
46 M = randi([1 3]);
47 R = randi([1 2]);
48 S = 0.2 + rand(M,1);
49 V = 0.3 + rand(M,R);
50 if mod(trial,4) == 0 && M > 1
51 V(1,1) = 0; % a class that skips a station
52 end
53 N = randi([1 3],1,R);
54 if mod(trial,2) == 0
55 Z = 0.3 + rand(1,R);
56 else
57 Z = zeros(1,R);
58 end
59 if mod(trial,3) == 0
60 b = randi([1 3],M,1);
61 else
62 b = ones(M,1);
63 end
64
65 res = pfqn_sens_respt(S,V,N,Z,b,3);
66
67 % ---- C. W = w/V ------------------------------------------------
68 for i = 1:M
69 for l = 1:R
70 if V(i,l) > 0 && N(l) > 0
71 errIdent = max(errIdent, relerr(res.W(i,l), res.Wresid(i,l)/V(i,l)));
72 end
73 end
74 end
75
76 % ---- D. base measures, single-server only ----------------------
77 if all(b == 1)
78 L = zeros(M,R);
79 for i = 1:M
80 L(i,:) = S(i) * V(i,:);
81 end
82 [XN,QN,UN] = pfqn_mva(L,N,Z);
83 errMva = max([errMva, relerr(res.X,XN), relerr(res.Q,QN), relerr(res.U,UN)]);
84 end
85
86 % ---- A. brute force --------------------------------------------
87 if prod(N+1) <= 24 && M <= 3
88 [Wb, pb] = brute_respt(S,V,N,Z,b,3);
89 errBrute = max(errBrute, relerr(res.WM, Wb));
90 % .p is ragged: station i only defines j = 0..b_i-1, the range the
91 % b-server recursion needs, and the rest of the row is zero padding out
92 % to max(b). Comparing the padding against the true marginal would be
93 % comparing against something the algorithm never claims to compute.
94 for i = 1:M
95 errBrute = max(errBrute, relerr(res.p(i,1:b(i)), pb(i,1:b(i))));
96 end
97 nBrute = nBrute + 1;
98 end
99end
100
101% =====================================================================
102% E. one job: the arriving job always finds the station empty, so W~Exp(mu)
103% =====================================================================
104S1 = [0.4; 0.25];
105V1 = [1; 2];
106r1 = pfqn_sens_respt(S1,V1,1,0.7,[1;1],3);
107for i = 1:2
108 mu = 1/S1(i);
109 errExp = max([errExp, relerr(r1.WM(i,1,1), 1/mu), ...
110 relerr(r1.WM(i,1,2), 2/mu^2), relerr(r1.WM(i,1,3), 6/mu^3), ...
111 relerr(r1.WVar(i,1), 1/mu^2)]);
112end
113
114% =====================================================================
115% B. Example 3.4 (continued): Kobayashi central-server model, n = 3
116% The paper prints E(W_i) and sigma^2_(W_i).
117% =====================================================================
118xs = [repmat(0.0215,1,9), 0.104, 0.104, 0.019]';
119es = [repmat(9.333,1,9), 10.5, 10.5, 105]';
120rk = pfqn_sens_respt(xs, es, 3, 0, ones(12,1), 3);
121paperW = [0.02275; 0.14178; 0.03322];
122paperWV = [0.00052; 0.01846; 0.00083];
123gotW = [rk.W(1,1); rk.W(10,1); rk.W(12,1)];
124gotWV = [rk.WVar(1,1); rk.WVar(10,1); rk.WVar(12,1)];
125errPaper = max(relerr(gotW,paperW), relerr(gotWV,paperWV));
126
127fprintf('\n=== pfqn_sens_respt validation (max relative error) ===\n');
128fprintf(' A. brute force, arrival theorem (%d models) : %.3e (tol %.1e)\n', nBrute, errBrute, tolBrute);
129fprintf(' B. Strelen Example 3.4 published sojourn : %.3e (tol %.1e)\n', errPaper, tolPaper);
130fprintf(' C. identity W(i,l) = w_i(l)/V(i,l) : %.3e (tol %.1e)\n', errIdent, tolIdent);
131fprintf(' D. pfqn_mva base measures (b=1) : %.3e (tol %.1e)\n', errMva, tolMva);
132fprintf(' E. single job, W ~ Exp(mu) exactly : %.3e (tol %.1e)\n', errExp, tolExp);
133fprintf(' (paper E(W_12)=%.5f got %.5f ; sigma2=%.5f got %.5f)\n', ...
134 paperW(3), gotW(3), paperWV(3), gotWV(3));
135
136ok = errBrute <= tolBrute && errPaper <= tolPaper && errIdent <= tolIdent && ...
137 errMva <= tolMva && errExp <= tolExp;
138if ~ok
139 error('pfqn_sens_respt_validate:mismatch','one or more checks exceeded tolerance');
140end
141fprintf(' ALL CHECKS PASSED\n');
142end
143
144% =========================================================================
145function e = relerr(a,b)
146a = a(:); b = b(:);
147d = abs(a-b);
148scale = max(1, max(abs(a),abs(b)));
149e = max(d ./ scale);
150if isempty(e)
151 e = 0;
152end
153end
154
155% =========================================================================
156function [WM, pN] = brute_respt(S,V,N,Z,b,tmax)
157% Sojourn-time moments from first principles: enumerate the product form to get
158% the exact arrival-theorem marginals p_i(j, N-e_l), then mix the conditional
159% sojourn-time moments over j. Uses none of Theorem 4.1.
160[M,R] = size(V);
161bmax = max(b);
162WM = zeros(M,R,tmax);
163for l = 1:R
164 if N(l) == 0
165 continue;
166 end
167 Nl = N; Nl(l) = Nl(l) - 1;
168 pj = brute_marginals(S,V,Nl,Z,b); % pj(i,1+j) at population N - e_l
169 for i = 1:M
170 if V(i,l) <= 0
171 continue;
172 end
173 mu = 1/S(i);
174 for t = 1:tmax
175 acc = 0;
176 for j = 0:(size(pj,2)-1)
177 acc = acc + pj(i,1+j) * cond_moment(j,b(i),mu,t);
178 end
179 WM(i,l,t) = acc;
180 end
181 end
182end
183pAll = brute_marginals(S,V,N,Z,b);
184pN = zeros(M,bmax);
185for i = 1:M
186 for j = 0:(bmax-1)
187 pN(i,1+j) = pAll(i,1+j);
188 end
189end
190end
191
192% =========================================================================
193function v = cond_moment(j,b,mu,t)
194% E[(W|j)^t] where a job arriving to find j jobs at an FCFS b-server station
195% waits an Erlang(max(0,j-b+1), b*mu) and is then served for an Exp(mu).
196k = max(0, j - b + 1);
197v = 0;
198for s = 0:t
199 % E[X^s] with X ~ Exp(mu)
200 EX = factorial(s) / mu^s;
201 p = t - s;
202 % E[Y^p] with Y ~ Erlang(k, b*mu), and Y = 0 when k = 0
203 if k == 0
204 if p == 0
205 EY = 1;
206 else
207 EY = 0;
208 end
209 else
210 theta = b*mu;
211 EY = 1;
212 for a = 0:(p-1)
213 EY = EY * (k + a);
214 end
215 EY = EY / theta^p;
216 end
217 v = v + nchoosek(t,s) * EX * EY;
218end
219end
220
221% =========================================================================
222function pj = brute_marginals(S,V,N,Z,b)
223% P[Q_i = j] for every station, by enumerating the closed product form of a
224% network of FCFS b-server stations:
225% f_i(q_i) = q_i! prod_l (a(i,l)^q_il / q_il!) prod_{j=1}^{q_i} 1/min(j,b_i)
226% with a(i,l) = S(i)*V(i,l), plus the delay term for the think times.
227[M,R] = size(V);
228a = zeros(M,R);
229for i = 1:M
230 a(i,:) = S(i) * V(i,:);
231end
232states = enumerate_states(N,M);
233K = size(states,1);
234w = zeros(K,1);
235tot = zeros(K,M);
236for k = 1:K
237 nir = reshape(states(k,:),R,M)';
238 lw = 0;
239 ok = true;
240 for i = 1:M
241 ni = sum(nir(i,:));
242 lw = lw + gammaln(ni+1);
243 for j = 1:ni
244 lw = lw - log(min(j,b(i)));
245 end
246 for r = 1:R
247 if nir(i,r) > 0
248 if a(i,r) <= 0
249 ok = false; break;
250 end
251 lw = lw + nir(i,r)*log(a(i,r)) - gammaln(nir(i,r)+1);
252 end
253 end
254 if ~ok, break; end
255 end
256 if ok
257 for r = 1:R
258 n0r = N(r) - sum(nir(:,r));
259 if n0r > 0
260 if Z(r) <= 0
261 ok = false; break;
262 end
263 lw = lw + n0r*log(Z(r)) - gammaln(n0r+1);
264 end
265 end
266 end
267 if ok
268 w(k) = exp(lw);
269 end
270 tot(k,:) = sum(nir,2)';
271end
272w = w / sum(w);
273maxj = max(sum(N),1);
274pj = zeros(M,1+maxj);
275for k = 1:K
276 for i = 1:M
277 pj(i,1+tot(k,i)) = pj(i,1+tot(k,i)) + w(k);
278 end
279end
280end
281
282% =========================================================================
283function states = enumerate_states(N,M)
284R = numel(N);
285per = cell(1,R);
286for r = 1:R
287 per{r} = compositions_leq(N(r),M);
288end
289states = zeros(0,R*M);
290idx = ones(1,R);
291while true
292 row = zeros(M,R);
293 for r = 1:R
294 row(:,r) = per{r}(idx(r),:)';
295 end
296 states(end+1,:) = reshape(row',1,[]); %#ok<AGROW>
297 r = R;
298 while r >= 1
299 idx(r) = idx(r) + 1;
300 if idx(r) <= size(per{r},1)
301 break;
302 end
303 idx(r) = 1;
304 r = r - 1;
305 end
306 if r == 0
307 break;
308 end
309end
310end
311
312% =========================================================================
313function C = compositions_leq(n,M)
314if M == 1
315 C = (0:n)';
316 return;
317end
318C = zeros(0,M);
319for first = 0:n
320 sub = compositions_leq(n-first,M-1);
321 C = [C; [repmat(first,size(sub,1),1), sub]]; %#ok<AGROW>
322end
323end
Definition Station.m:245