3 % @file pfqn_sens_respt.m
4 % @brief Exact moments of
the sojourn time of a job at FCFS multiserver
5 % centers of a closed product-form queueing network.
9function res = pfqn_sens_respt(S,V,N,Z,b,tmax)
12 % @brief Exact raw moments E[W_(i,l)^t], t = 1..tmax, of
the sojourn time of a
13 %
class-l job at an FCFS b-server center i of a closed product-form
14 % queueing network, together with
the variance of that sojourn time.
16 % This
is Theorem 4.1 of
the reference. Its mechanism
is the arrival
17 % theorem of Lavenberg-Reiser and Sevcik-Mitrani: a
class-l job arriving
18 % at center i finds j jobs already there with probability
19 % p_i(j, N - 1_l). Conditioning
the sojourn time on j and inverting
the
20 % Laplace transform of
the conditional density gives
22 % E[W_(i,l)^t] = t!/mu^t + sum_{tau=0..t} a_(t,tau)(0) E[Qt_i^tau]
23 % - sum_{j=0..b-1} p_i(j,N-1_l) sum_{tau=0..t} a_(t,tau)(0) j^tau
25 % where mu = 1/S(i)
is the rate of each of
the b servers, Qt_i
is the
26 % total queue length at center i at population N - 1_l (so its moments
27 % are those of pfqn_sens_mom evaluated one job down in
class l), and
the
28 % coefficients a_(t,tau)(0) depend only on b and mu, not on
the network
29 % (Remark 4.3 of
the reference). The moments E[Qt_i^tau] up to tau = 3
30 % need
the second derivative of
the MVA recursion, so
this routine
31 % carries a second-order forward-mode pass exactly as pfqn_sens_mom
32 % does, but over
the b-server recursion (4.1)-(4.2) rather than
the
35 % For b = 1
the coefficients a_(t,0)(0) vanish identically and
the
36 %
double-sum correction disappears, so no marginal probabilities are
37 % needed (Remark 4.2 of
the reference);
the routine still evaluates
the
38 % general expression, which reduces to that
case on its own.
40 % Only FCFS centers are covered. The reference
is explicit that
the
41 % sojourn-time distribution at PS and LCFS centers
is in general not
42 % known, so no analogue exists there. FCFS in a BCMP network further
43 %
requires the service time to be exponential and
class-independent,
44 % which
is why
this routine takes a per-station service time S(i) and a
45 % separate visit-ratio matrix V rather than a demand matrix:
the sojourn
46 % time
is per visit, so
the per-visit rate mu = 1/S(i) must be known and
47 % cannot be recovered from
the demand L(i,l) = S(i)*V(i,l) alone.
49 % Reference: J. C. Strelen,
"Moment Analysis for Closed Queuing Networks
50 % and its Linearizer", Performance Evaluation 11:127-142, 1990,
51 % Theorem 4.1 with equations (4.1)-(4.5) and Remarks 4.2-4.3.
53 % @fn pfqn_sens_respt(S, V, N, Z, b, tmax)
54 % @param S Service time at each station (M x 1), common to all classes.
55 % @param V Visit ratio matrix (M x R). The demand
is L(i,r) = S(i)*V(i,r).
56 % @param N Population vector (1 x R).
57 % @param Z Think time vector (1 x R). Default: zeros.
58 % @param b Number of servers at each station (M x 1). Default: ones.
59 % @param tmax Highest sojourn-time moment to
return, 1..3. Default: 3. The
60 % coefficients a_(t,tau)(0) are tabulated in
the reference up to t = 3.
61 % @
return res A
struct with:
62 % .X (1 x R), .Q (M x R), .U (M x R) base measures at population N.
63 % .W (M x R) W(i,l) = E[W_(i,l)],
the mean sojourn time per visit of
64 % a class-l job at station i. Zero where class l does not visit i.
65 % .WM (M x R x tmax) WM(i,l,t) = E[W_(i,l)^t].
66 % .WVar (M x R) Var[W_(i,l)] = E[W^2] - E[W]^2. Requires tmax >= 2.
67 % .WSkew (M x R) skewness of W_(i,l). Requires tmax >= 3; NaN
if the
69 % .m (M x 1) E[Q_i] at population N,
the total queue length.
70 % .Var (M x 1) Var[Q_i] at population N.
71 % .p (M x max(b)) p(i,1+j) =
P[Q_i = j] at population N,
for j = 0..b_i-1.
72 % These are
the only marginal probabilities
the b-server recursion needs,
73 % so
the matrix
is RAGGED: row i
is meaningful only up to
column b_i and
74 %
is zero-padded out to max(b). A padded entry
is not
P[Q_i = j]; it
is
75 % simply not computed. Read row i as p(i,1:b(i)).
76 % .Wresid (M x R)
the residence time w_i(l) of
the MVA recursion. The
77 % identity W(i,l) = w_i(l)/V(i,l)
is an independent check of
the t = 1
78 % case of (4.5) and
is asserted by pfqn_sens_respt_validate.
81 % - Restricted to closed populations.
82 % - Load-dependent rates are not covered here;
the b-server dependence
is the
83 % only state dependence, and it
is carried exactly by (4.1)-(4.2).
89if nargin < 4 || isempty(Z)
93if nargin < 5 || isempty(b)
97if nargin < 6 || isempty(tmax)
100if tmax < 1 || tmax > 3
101 line_error(mfilename,
'tmax must be 1, 2 or 3: the coefficients a_{t,tau}(0) are tabulated in the reference up to order three.');
104 line_error(mfilename,
'visit matrix and population vector have different number of classes');
107 line_error(mfilename,
'pfqn_sens_respt requires a closed population');
110 line_error(mfilename,'
the number of servers must be at least one at every station');
113 line_error(mfilename,'every FCFS station must have a strictly positive service time');
119 rho(i,l) = S(i) * V(i,l);
125X = zeros(1,R); Q = zeros(M,R); U = zeros(M,R);
127W = zeros(M,R); WM = zeros(M,R,tmax); Wresid = zeros(M,R);
131 res = pack(X,Q,U,m,zeros(M,1),pN,W,WM,Wresid,tmax);
135% ---- population lattice --------------------------------------------------
138 prods(w) = prod(ones(1,R-(w+1)+1) + N(w+1:R));
141while N(firstnonempty) == 0
142 firstnonempty = firstnonempty - 1;
147% state carried along
the lattice:
the mean total queue length at each station,
148%
the marginal probabilities p_i(j) for j = 0..bmax-1, and
the first and second
149% derivatives of both with respect to y_h, a scaling of station h's service
150% time. At y = 1
the y-derivatives are
the scaled x-derivatives of (3.2).
151Mrow = zeros(totpop,M);
152D1m = zeros(totpop,M,M);
153D2m = zeros(totpop,M,M);
154Prow = zeros(totpop,M,bmax);
155D1p = zeros(totpop,M,bmax,M);
156D2p = zeros(totpop,M,bmax,M);
157Prow(1,:,1) = 1; % empty population: every station holds zero jobs
166 % ---- residence times, eq. (4.1), and their first two derivatives ----
167 wv = zeros(M,R); d1w = zeros(M,R,M); d2w = zeros(M,R,M);
175 pos = pos + n(w)*prods(w);
183 continue; % w and every derivative stay zero, as does X(s)
186 % bracket = 1 + m_i(n-e_s) + sum_{j=0}^{b_i-2} (b_i-1-j) p_i(j,n-e_s)
187 brk = 1 + Mrow(row,i);
189 brk = brk + (b(i)-1-j) * Prow(row,i,1+j);
191 wv(i,s) = (rho(i,s)/b(i)) * brk;
194 d2brk = D2m(row,i,h);
196 dbrk = dbrk + (b(i)-1-j) * D1p(row,i,1+j,h);
197 d2brk = d2brk + (b(i)-1-j) * D2p(row,i,1+j,h);
199 % w = y_i * (rho/b) * brk
201 d1w(i,s,h) = (rho(i,s)/b(i)) * (brk + dbrk);
202 d2w(i,s,h) = (rho(i,s)/b(i)) * (2*dbrk + d2brk);
204 d1w(i,s,h) = (rho(i,s)/b(i)) * dbrk;
205 d2w(i,s,h) = (rho(i,s)/b(i)) * d2brk;
211 % ---- throughputs and their derivatives ------------------------------
212 lam = zeros(1,R); d1lam = zeros(R,M); d2lam = zeros(R,M);
217 den = Z(s) + sum(wv(:,s));
220 dden = sum(d1w(:,s,h));
221 d2den = sum(d2w(:,s,h));
222 d1lam(s,h) = -n(s) * dden / den^2;
223 d2lam(s,h) = -n(s) * d2den / den^2 + 2*n(s) * dden^2 / den^3;
227 % ---- mean queue lengths ---------------------------------------------
231 if n(s) == 0,
continue; end
232 acc = acc + lam(s) * wv(i,s);
236 d1acc = 0; d2acc = 0;
238 if n(s) == 0,
continue; end
239 d1acc = d1acc + d1lam(s,h)*wv(i,s) + lam(s)*d1w(i,s,h);
240 d2acc = d2acc + d2lam(s,h)*wv(i,s) + 2*d1lam(s,h)*d1w(i,s,h) ...
243 D1m(hnvec,i,h) = d1acc;
244 D2m(hnvec,i,h) = d2acc;
248 % ---- marginal probabilities, eq. (4.2), and their derivatives --------
251 % p_i(j,n) = (1/j) sum_l lam(l) * rho_i(l)*y_i * p_i(j-1, n-e_l)
254 Prow(hnvec,i,1+j) = 0;
259 if n(l) == 0,
continue; end
260 acc = acc + lam(l) * rho(i,l) * Prow(rows(l),i,1+(j-1));
262 Prow(hnvec,i,1+j) = acc / j;
264 d1acc = 0; d2acc = 0;
266 if n(l) == 0,
continue; end
267 pprev = Prow(rows(l),i,1+(j-1));
268 d1prev = D1p(rows(l),i,1+(j-1),h);
269 d2prev = D2p(rows(l),i,1+(j-1),h);
270 % g = rho * u * v with u = lam, v = y_i * pprev
273 v2 = 2*d1prev + d2prev;
278 d1acc = d1acc + rho(i,l) * (d1lam(l,h)*pprev + lam(l)*v1);
279 d2acc = d2acc + rho(i,l) * (d2lam(l,h)*pprev + 2*d1lam(l,h)*v1 ...
282 D1p(hnvec,i,1+j,h) = d1acc / j;
283 D2p(hnvec,i,1+j,h) = d2acc / j;
286 % u_i = sum_l lam(l) * rho_i(l)*y_i (mean number of busy servers)
287 ui = 0; d1ui = zeros(1,M); d2ui = zeros(1,M);
289 if n(l) == 0,
continue; end
290 ui = ui + lam(l) * rho(i,l);
293 d1ui(h) = d1ui(h) + rho(i,l) * (d1lam(l,h) + lam(l));
294 d2ui(h) = d2ui(h) + rho(i,l) * (d2lam(l,h) + 2*d1lam(l,h));
296 d1ui(h) = d1ui(h) + rho(i,l) * d1lam(l,h);
297 d2ui(h) = d2ui(h) + rho(i,l) * d2lam(l,h);
301 % p_i(0,n) = 1 - (1/b)(u_i + sum_{j=1}^{b-1} (b-j) p_i(j,n))
304 acc0 = acc0 + (b(i)-j) * Prow(hnvec,i,1+j);
306 Prow(hnvec,i,1) = 1 - acc0/b(i);
308 d1acc0 = d1ui(h); d2acc0 = d2ui(h);
310 d1acc0 = d1acc0 + (b(i)-j) * D1p(hnvec,i,1+j,h);
311 d2acc0 = d2acc0 + (b(i)-j) * D2p(hnvec,i,1+j,h);
313 D1p(hnvec,i,1,h) = -d1acc0/b(i);
314 D2p(hnvec,i,1,h) = -d2acc0/b(i);
318 % keep
the measures of
the last (full) population
322 Wresid(i,s) = wv(i,s);
323 Q(i,s) = lam(s) * wv(i,s);
324 U(i,s) = lam(s) * rho(i,s);
328 % ---- odometer advance ------------------------------------------------
330 while (s>0 && n(s)==N(s)) || s>firstnonempty
343 currentpop = currentpop + 1;
348 m(i) = Mrow(lastrow,i);
350 pN(i,1+j) = Prow(lastrow,i,1+j);
355 Var(i) = D1m(lastrow,i,i);
358% ---- sojourn-time moments, eq. (4.5) -------------------------------------
359% index of N - e_l on
the lattice
363 nn = N; nn(l) = nn(l) - 1;
366 pos = pos + nn(w)*prods(w);
374 if N(l) == 0 || V(i,l) <= 0
378 % moments of
the queue length seen by an arriving
class-l job, i.e. of
379 %
the total queue at station i at population N - e_l, from (3.2)
383 EQ = zeros(1,4); % EQ(1+tau) = E[Qt_i^tau]
387 EQ(4) = d2t + (1 + 3*mt)*d1t + mt^3;
388 acoef = strelen_a(b(i), mu(i), tmax);
390 val = factorial(t) / mu(i)^t;
392 val = val + acoef(t,1+tau) * EQ(1+tau);
394 % correction over
the states in which a server
is idle
398 inner = inner + acoef(t,1+tau) * jpow(j,tau);
400 val = val - Prow(rl,i,1+j) * inner;
408res = pack(X,Q,U,m,Var,pN,W,WM,Wresid,tmax);
411% =========================================================================
412function v = jpow(j,tau)
413% j^tau with
the convention j^0 = 1, so that 0^0 = 1 as
the reference states.
421% =========================================================================
422function a = strelen_a(b,mu,tmax)
423% Coefficients a_{t,tau}(0) of Remark 4.3 of
the reference. They depend only on
424%
the number of servers b and on
the per-server rate mu, not on
the network.
426a(1,1) = (1-b)/(b*mu);
429 a(2,1) = (2 - b - b^2)/(b^2*mu^2);
430 a(2,2) = 3/(b^2*mu^2);
431 a(2,3) = 1/(b^2*mu^2);
434 a(3,1) = (6 - 5*b + 3*b^2 - 4*b^3)/(b^3*mu^3);
435 a(3,2) = (11 - 3*b + 3*b^2)/(b^3*mu^3);
436 a(3,3) = 6/(b^3*mu^3);
437 a(3,4) = 1/(b^3*mu^3);
441% =========================================================================
442function res = pack(X,Q,U,m,Var,p,W,WM,Wresid,tmax)
444res.X = X; res.Q = Q; res.U = U;
445res.m = m; res.Var = Var; res.p = p;
446res.W = W; res.WM = WM; res.Wresid = Wresid;
447WVar = zeros(M,R); WSkew = zeros(M,R);
451 WVar(i,l) = WM(i,l,2) - WM(i,l,1)^2;
458 mu3 = WM(i,l,3) - 3*WM(i,l,1)*WM(i,l,2) + 2*WM(i,l,1)^3;
460 WSkew(i,l) = mu3 / WVar(i,l)^1.5;
467res.WVar = WVar; res.WSkew = WSkew;