LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
pfqn_sens_linearizer.m
1%{
2%{
3 % @file pfqn_sens_linearizer.m
4 % @brief Approximate higher moments of the queue lengths of a closed
5 % product-form queueing network, by differentiating the Linearizer
6 % fixed point. Polynomial in the population, unlike the exact
7 % pfqn_sens_mom.
8%}
9%}
10
11function res = pfqn_sens_linearizer(L,N,Z,tol,maxiter)
12%{
13%{
14 % @brief Approximate moments E[Q_i], Var[Q_i], Cov[Q_i,Q_j], E[Q_i^2] and
15 % E[Q_i^3] of the per-station total queue lengths of a closed
16 % product-form queueing network, by the LINEARIZER-2 / LINEARIZER-3
17 % algorithms of the reference (Section 5).
18 %
19 % Motivation. The exact moment analysis of pfqn_sens_mom evaluates the
20 % MVA recursion on the whole population lattice, so it costs
21 % O(prod(N+1)) and is unusable once the populations are large. The
22 % Linearizer replaces that lattice by a fixed point over a handful of
23 % populations, and the reference observes that the same trick applies to
24 % the derivatives: differentiate the Linearizer equations, append the
25 % differentiated equations to the originals, and iterate all of them
26 % together. This routine does that, carrying both the first and the
27 % second derivative, so it returns everything (3.2) needs, including the
28 % third moment. Carrying only the first derivative is the reference's
29 % LINEARIZER-2; carrying the second as well is its LINEARIZER-3.
30 %
31 % The approximation. CORE (equations (5.1)-(5.2)) estimates the queue
32 % lengths at population n - 1_l from those at n by
33 %
34 % v_i(l) = m_i^(n)(l) / n(l)
35 % m_i^(n-1_l')(l) = (n - 1_l')_l * ( v_i(l) + delta_i(l',l) )
36 %
37 % and substitutes them into the exact MVA equations. Setting the delta
38 % terms to zero gives Bard-Schweitzer; Linearizer instead estimates them
39 % from (5.3), delta_i^(N)(l',l) = v_i^(N-1_l')(l) - v_i^(N)(l), by
40 % running CORE at each of the N - 1_l populations, and holds them fixed
41 % across populations (the heuristic (5.4)). Differentiating (5.1)-(5.3)
42 % gives (5.5)-(5.8), which are carried alongside.
43 %
44 % Accuracy. The reference reports, over 51 networks including 34 stress
45 % cases, relative errors below 2.1% on E[Q], 4.1% on E[Q^2] and 6.2% on
46 % E[Q^3]. pfqn_sens_linearizer_validate measures the error against the
47 % exact pfqn_sens_mom on models small enough for both, and asserts
48 % bands of that order rather than machine precision: this routine is an
49 % approximation and is expected to disagree with the exact answer.
50 %
51 % Reference: J. C. Strelen, "Moment Analysis for Closed Queuing Networks
52 % and its Linearizer", Performance Evaluation 11:127-142, 1990,
53 % Section 5, equations (5.1)-(5.8), the CORE-2 and LINEARIZER-2
54 % algorithms. The delta definition follows the standard Chandy-Neuse
55 % Linearizer, v_i^(N-1_l')(l) - v_i^(N)(l), which is what LINE's
56 % pfqn_linearizer implements.
57 %
58 % @fn pfqn_sens_linearizer(L, N, Z, tol, maxiter)
59 % @param L Service demand matrix (M x R), L(i,r) = visits_ir / rate_ir.
60 % @param N Population vector (1 x R).
61 % @param Z Think time vector (1 x R). Default: zeros.
62 % @param tol (Optional) Convergence tolerance of the CORE fixed point on the
63 % mean queue lengths. Default: the test of the reference,
64 % 1/(4000+16*sum(n)), which is also applied to the variances at 1e-3.
65 % @param maxiter (Optional) Maximum CORE iterations. Default: 200.
66 % @return res A struct with:
67 % .X (1 x R), .Q (M x R), .U (M x R), .W (M x R) approximate base measures.
68 % .m (M x 1) approximate E[Q_i], the total queue length at station i.
69 % .dm (M x M) dm(i,h) = x_h dm_i/dx_h, the scaled first derivative.
70 % .d2m (M x 1) d2m(i) = x_i^2 d^2m_i/dx_i^2.
71 % .Var (M x 1), .Cov (M x M), .M2 (M x 1), .M3 (M x 1), .Skew (M x 1)
72 % the moments of (3.2), formed exactly as in pfqn_sens_mom but from the
73 % approximate derivatives.
74 % .CovAsym (scalar) raw asymmetry of Cov before symmetrization. Unlike the
75 % exact routines, this is NOT expected to sit at roundoff: the Linearizer
76 % fixed point does not enforce the symmetry that the product form
77 % guarantees, so this is a useful measure of the approximation error.
78 % .iter (scalar) total CORE iterations performed.
79 %
80 % Notes:
81 % - Single-server stations plus an optional delay Z, matching pfqn_linearizer.
82 % - The exact counterpart is pfqn_sens_mom; the per-class exact second moments
83 % are in pfqn_sens_mva.
84%}
85%}
86[M,R] = size(L);
87N = ceil(N(:)');
88if nargin < 3 || isempty(Z)
89 Z = zeros(1,R);
90end
91Z = Z(:)';
92if nargin < 4 || isempty(tol)
93 tol = [];
94end
95if nargin < 5 || isempty(maxiter)
96 maxiter = 200;
97end
98if length(N) ~= R
99 line_error(mfilename,'demand matrix and population vector have different number of classes');
100end
101if any(isinf(N))
102 line_error(mfilename,'pfqn_sens_linearizer requires a closed population');
103end
104
105if ~any(N > 0)
106 res = pack(zeros(1,R),zeros(M,R),zeros(M,R),zeros(M,R),zeros(M,1), ...
107 zeros(M,M),zeros(M,1),0);
108 return;
109end
110
111% ---- Linearizer state ----------------------------------------------------
112% pops: index 1 = N, index 1+l = N - e_l
113npops = 1 + R;
114pv = zeros(npops,R);
115pv(1,:) = N;
116for l = 1:R
117 pv(1+l,:) = N;
118 if N(l) > 0
119 pv(1+l,l) = N(l) - 1;
120 end
121end
122
123% m{p}(i,l) = estimate of m_i^{(pv(p,:))}(l), and its derivatives w.r.t. y_h
124mE = cell(npops,1); dmE = cell(npops,1); d2mE = cell(npops,1);
125for p = 1:npops
126 mE{p} = zeros(M,R);
127 for l = 1:R
128 mE{p}(:,l) = pv(p,l)/M; % initialization of the reference
129 end
130 dmE{p} = zeros(M,R,M);
131 d2mE{p} = zeros(M,R,M);
132end
133% delta(i,l',l), indexed by the removed class l' and the class l
134delta = zeros(M,R,R);
135ddelta = zeros(M,R,R,M);
136d2delta = zeros(M,R,R,M);
137
138totiter = 0;
139Xf = zeros(1,R); Qf = zeros(M,R); Wf = zeros(M,R);
140dmf = zeros(M,M); d2mf = zeros(M,1);
141
142for outer = 1:3
143 % ---- Step 1: CORE at the full population --------------------------
144 [mE{1}, dmE{1}, d2mE{1}, Xf, Wf, it] = core2(L,Z,N,delta,ddelta,d2delta, ...
145 mE{1}, dmE{1}, d2mE{1}, tol, maxiter);
146 totiter = totiter + it;
147
148 if outer < 3
149 % ---- Step 2: CORE at each of the N - e_l populations ------------
150 for l = 1:R
151 if N(l) == 0
152 continue;
153 end
154 [mE{1+l}, dmE{1+l}, d2mE{1+l}, ~, ~, it] = core2(L,Z,pv(1+l,:), ...
155 delta,ddelta,d2delta, mE{1+l}, dmE{1+l}, d2mE{1+l}, tol, maxiter);
156 totiter = totiter + it;
157 end
158
159 % ---- Step 3: refresh delta from (5.1) and (5.3) ----------------
160 [vN, dvN, d2vN] = fractions(mE{1}, dmE{1}, d2mE{1}, N);
161 for lp = 1:R
162 if N(lp) == 0
163 continue;
164 end
165 [vL, dvL, d2vL] = fractions(mE{1+lp}, dmE{1+lp}, d2mE{1+lp}, pv(1+lp,:));
166 for i = 1:M
167 for l = 1:R
168 delta(i,lp,l) = vL(i,l) - vN(i,l);
169 for h = 1:M
170 ddelta(i,lp,l,h) = dvL(i,l,h) - dvN(i,l,h);
171 d2delta(i,lp,l,h) = d2vL(i,l,h) - d2vN(i,l,h);
172 end
173 end
174 end
175 end
176 end
177end
178
179% ---- final measures ------------------------------------------------------
180Qf = mE{1};
181m = sum(Qf,2);
182for i = 1:M
183 for h = 1:M
184 dmf(i,h) = sum(dmE{1}(i,:,h));
185 end
186 d2mf(i) = sum(d2mE{1}(i,:,i));
187end
188U = zeros(M,R);
189for i = 1:M
190 for r = 1:R
191 U(i,r) = Xf(r) * L(i,r);
192 end
193end
194
195res = pack(Xf,Qf,U,Wf,m,dmf,d2mf,totiter);
196end
197
198% =========================================================================
199function [v, dv, d2v] = fractions(m, dm, d2m, n)
200% (5.1) and (5.5): v_i(l) = m_i(l)/n(l), and likewise for the derivatives.
201[M,R] = size(m);
202v = zeros(M,R); dv = zeros(M,R,M); d2v = zeros(M,R,M);
203for l = 1:R
204 if n(l) <= 0
205 continue;
206 end
207 v(:,l) = m(:,l) / n(l);
208 dv(:,l,:) = dm(:,l,:) / n(l);
209 d2v(:,l,:) = d2m(:,l,:) / n(l);
210end
211end
212
213% =========================================================================
214function [m, dm, d2m, lam, w, it] = core2(L,Z,n,delta,ddelta,d2delta,m,dm,d2m,tol,maxiter)
215% CORE-2 of the reference, extended to second derivatives. Iterates (5.1),
216% (5.2) and the MVA equations (1.4)-(1.5) together with their first and second
217% derivatives (5.5)-(5.6) and (3.4), until the mean queue lengths and the
218% variances both stop moving.
219[M,R] = size(L);
220nc = sum(n);
221if isempty(tol)
222 tolm = 1/(4000 + 16*nc); % termination test of the reference
223else
224 tolm = tol;
225end
226tolv = 1e-3;
227
228lam = zeros(1,R); w = zeros(M,R);
229varprev = zeros(M,1);
230it = 0;
231for iter = 1:maxiter
232 it = iter;
233 mprev = m;
234
235 % ---- (5.1)-(5.2) and (5.5)-(5.6): queue lengths one job down --------
236 % maux(i,l,l2) estimates m_i^{(n - e_l)}(l2)
237 [v, dv, d2v] = fractions(m, dm, d2m, n);
238 mtot = zeros(M,R); % mtot(i,l) = sum_l2 m_i^{(n-e_l)}(l2)
239 dmtot = zeros(M,R,M);
240 d2mtot = zeros(M,R,M);
241 for l = 1:R
242 if n(l) <= 0
243 continue;
244 end
245 for i = 1:M
246 acc = 0; dacc = zeros(1,M); d2acc = zeros(1,M);
247 for l2 = 1:R
248 cnt = n(l2) - (l2 == l); % (n - 1_l)_{l2}
249 if cnt <= 0
250 continue;
251 end
252 acc = acc + cnt * (v(i,l2) + delta(i,l,l2));
253 for h = 1:M
254 dacc(h) = dacc(h) + cnt * (dv(i,l2,h) + ddelta(i,l,l2,h));
255 d2acc(h) = d2acc(h) + cnt * (d2v(i,l2,h) + d2delta(i,l,l2,h));
256 end
257 end
258 mtot(i,l) = acc;
259 for h = 1:M
260 dmtot(i,l,h) = dacc(h);
261 d2mtot(i,l,h) = d2acc(h);
262 end
263 end
264 end
265
266 % ---- MVA (1.4)-(1.5) and its derivatives (3.4) ----------------------
267 % w_i(l) = y_i * L(i,l) * (1 + mtot(i,l))
268 w = zeros(M,R); dw = zeros(M,R,M); d2w = zeros(M,R,M);
269 for l = 1:R
270 if n(l) <= 0
271 continue;
272 end
273 for i = 1:M
274 A = 1 + mtot(i,l);
275 w(i,l) = L(i,l) * A;
276 for h = 1:M
277 dA = dmtot(i,l,h);
278 d2A = d2mtot(i,l,h);
279 if i == h
280 dw(i,l,h) = L(i,l) * (A + dA);
281 d2w(i,l,h) = L(i,l) * (2*dA + d2A);
282 else
283 dw(i,l,h) = L(i,l) * dA;
284 d2w(i,l,h) = L(i,l) * d2A;
285 end
286 end
287 end
288 end
289 lam = zeros(1,R); dlam = zeros(R,M); d2lam = zeros(R,M);
290 for l = 1:R
291 if n(l) <= 0
292 continue;
293 end
294 den = Z(l) + sum(w(:,l));
295 lam(l) = n(l) / den;
296 for h = 1:M
297 dden = sum(dw(:,l,h));
298 d2den = sum(d2w(:,l,h));
299 dlam(l,h) = -n(l) * dden / den^2;
300 d2lam(l,h) = -n(l) * d2den / den^2 + 2*n(l) * dden^2 / den^3;
301 end
302 end
303 m = zeros(M,R); dm = zeros(M,R,M); d2m = zeros(M,R,M);
304 for l = 1:R
305 if n(l) <= 0
306 continue;
307 end
308 for i = 1:M
309 m(i,l) = lam(l) * w(i,l);
310 for h = 1:M
311 dm(i,l,h) = dlam(l,h)*w(i,l) + lam(l)*dw(i,l,h);
312 d2m(i,l,h) = d2lam(l,h)*w(i,l) + 2*dlam(l,h)*dw(i,l,h) ...
313 + lam(l)*d2w(i,l,h);
314 end
315 end
316 end
317
318 % ---- termination test of the reference ------------------------------
319 dev = 0;
320 for l = 1:R
321 if n(l) <= 0
322 continue;
323 end
324 dev = max(dev, max(abs(m(:,l) - mprev(:,l))) / n(l));
325 end
326 varnow = zeros(M,1);
327 for i = 1:M
328 varnow(i) = sum(dm(i,:,i));
329 end
330 sv = sum(varnow);
331 if sv > 0
332 vdev = max(abs(varnow - varprev)) / sv;
333 else
334 vdev = 0;
335 end
336 varprev = varnow;
337 if dev <= tolm && vdev <= tolv
338 break;
339 end
340end
341end
342
343% =========================================================================
344function res = pack(X,Q,U,W,m,dm,d2m,it)
345M = size(Q,1);
346res.X = X; res.Q = Q; res.U = U; res.W = W;
347res.m = m; res.dm = dm; res.d2m = d2m; res.iter = it;
348
349% Cov(i,j) = x_j dm_i/dx_j. The product form makes this symmetric, but the
350% Linearizer fixed point does not enforce that, so the raw asymmetry is a
351% genuine error indicator here rather than a roundoff residual.
352Cov = dm;
353res.CovAsym = max(max(abs(Cov - Cov.')));
354if isempty(res.CovAsym)
355 res.CovAsym = 0;
356end
357Cov = (Cov + Cov.') / 2;
358res.Cov = Cov;
359
360Var = zeros(M,1); M2 = zeros(M,1); M3 = zeros(M,1); Skew = zeros(M,1);
361for i = 1:M
362 Var(i) = dm(i,i);
363 M2(i) = dm(i,i) + m(i)^2;
364 M3(i) = d2m(i) + (1 + 3*m(i))*dm(i,i) + m(i)^3;
365 mu3 = M3(i) - 3*m(i)*M2(i) + 2*m(i)^3;
366 if Var(i) > 0
367 Skew(i) = mu3 / Var(i)^1.5;
368 else
369 Skew(i) = NaN;
370 end
371end
372res.Var = Var; res.M2 = M2; res.M3 = M3; res.Skew = Skew;
373end
Definition Station.m:245