1function pfqn_sens_respt_validate()
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.
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
28 % Reference: J. C. Strelen,
"Moment Analysis for Closed Queuing Networks
29 % and its Linearizer", Performance Evaluation 11:127-142, 1990.
34tolPaper = 5e-4; %
the paper prints 5 decimals on small sojourn times
39errBrute = 0; errIdent = 0; errMva = 0; errExp = 0;
42% =====================================================================
43% A/C/D. random models, single- and multi-server
44% =====================================================================
50 if mod(trial,4) == 0 && M > 1
51 V(1,1) = 0; % a
class that skips a station
65 res = pfqn_sens_respt(S,V,N,Z,b,3);
67 % ---- C. W = w/V ------------------------------------------------
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)));
76 % ---- D. base measures, single-server only ----------------------
80 L(i,:) = S(i) * V(i,:);
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)]);
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.
95 errBrute = max(errBrute, relerr(res.p(i,1:b(i)), pb(i,1:b(i))));
101% =====================================================================
102% E. one job:
the arriving job always finds
the station empty, so W~Exp(mu)
103% =====================================================================
106r1 = pfqn_sens_respt(S1,V1,1,0.7,[1;1],3);
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)]);
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));
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));
136ok = errBrute <= tolBrute && errPaper <= tolPaper && errIdent <= tolIdent && ...
137 errMva <= tolMva && errExp <= tolExp;
139 error('pfqn_sens_respt_validate:mismatch','one or more checks exceeded tolerance');
141fprintf(' ALL CHECKS PASSED\n');
144% =========================================================================
145function e = relerr(a,b)
148scale = max(1, max(abs(a),abs(b)));
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.
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
176 for j = 0:(size(pj,2)-1)
177 acc = acc + pj(i,1+j) * cond_moment(j,b(i),mu,t);
183pAll = brute_marginals(S,V,N,Z,b);
187 pN(i,1+j) = pAll(i,1+j);
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);
199 % E[X^s] with X ~ Exp(mu)
200 EX = factorial(s) / mu^s;
202 % E[Y^p] with Y ~ Erlang(k, b*mu), and Y = 0 when k = 0
217 v = v + nchoosek(t,s) * EX * EY;
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.
230 a(i,:) = S(i) * V(i,:);
232states = enumerate_states(N,M);
237 nir = reshape(states(k,:),R,M)
';
242 lw = lw + gammaln(ni+1);
244 lw = lw - log(min(j,b(i)));
251 lw = lw + nir(i,r)*log(a(i,r)) - gammaln(nir(i,r)+1);
258 n0r = N(r) - sum(nir(:,r));
263 lw = lw + n0r*log(Z(r)) - gammaln(n0r+1);
270 tot(k,:) = sum(nir,2)';
277 pj(i,1+tot(k,i)) = pj(i,1+tot(k,i)) + w(k);
282% =========================================================================
283function states = enumerate_states(N,M)
287 per{r} = compositions_leq(N(r),M);
289states = zeros(0,R*M);
294 row(:,r) = per{r}(idx(r),:)
';
296 states(end+1,:) = reshape(row',1,[]); %#ok<AGROW>
300 if idx(r) <= size(per{r},1)
312% =========================================================================
313function C = compositions_leq(n,M)
320 sub = compositions_leq(n-first,M-1);
321 C = [C; [repmat(first,size(sub,1),1), sub]]; %#ok<AGROW>