4 % @brief MVAC (Mean Value Analysis by Chain)
for load-dependent networks.
10 % @brief MVAC (Mean Value Analysis by Chain)
for load-dependent networks.
11 % @fn pfqn_mvacld(L, N, Z, mu)
12 % @param L Service demand matrix of
the queue-length dependent centers (M x R).
13 % @param N Population vector (1 x R).
14 % @param Z Think time matrix of
the infinite-server centers (1 x R or Mz x R).
15 % @param mu Load-dependent rate matrix (M x Nt), mu(j,n) = rate with n jobs.
16 % @
return XN Per-
class throughput (1 x R).
17 % @
return QN Per-
class mean queue-length at
the centers (M x R).
18 % @
return UN Utilization of each center (M x 1), i.e. 1-P_j(0).
19 % @
return CN Per-
class cycle time exclusive of think time (1 x R).
20 % @
return pij Marginal queue-length probabilities (M x (Nt+1)).
23function [XN,QN,UN,CN,pij] = pfqn_mvacld(L,N,Z,mu)
24% [XN,QN,UN,CN,PIJ] = PFQN_MVACLD(L,N,Z,MU)
26% Exact mean value analysis by chain (MVAC) of a closed multichain product-form
27% queueing network that may contain queue-length dependent (QLD) service
28% centers. This
is the extension of Section V of Conway, de Souza e Silva and
29% Lavenberg,
"Mean Value Analysis by Chain of Product Form Queueing Networks",
30% IEEE Trans. Computers 38(3):432-442, 1989;
PFQN_MVAC implements Sections II-IV,
31% which cover single-server fixed-rate (SSFR) and infinite-server (IS) centers
34% Where
PFQN_MVAC propagates
the MEAN queue-lengths L^k_j(v) through eq. (7) and
35% closes
the recursion with
the arrival-theorem identity (10),
the QLD extension
36% propagates
the MARGINAL queue-length DISTRIBUTIONS
P^k_j(n,v) instead. That
is
37% forced by load dependence --
the rate seen by a job depends on
the whole
38% occupancy, so a mean no longer suffices -- but it also SIMPLIFIES
the
39% recursion: eq. (21)-(25) read level k-1 only at
the shifted vectors v + 1_i,
40% so
the basic step sweeps v in I_k alone, where
PFQN_MVAC must sweep
the larger
41% I_k u ... u I_K. The extra information comes almost
for free, and PIJ
is
42% returned as a first-
class output.
44% Notation follows
PFQN_MVAC: j and i index centers (j = 1,...,J1 are
the QLD
45% centers of L, j = J1+1,...,J
the IS centers of Z), k and l index
the
46% single-customer chains, a_jk = theta_jk T_jk
is the demand of chain k at
47% center j, K = sum(N) and I_k = {v : sum_j v_j = K - k} with v_j
the number of
48% self-looping single-customer (SCSL) chains pinned at center j.
P^k_j(n,v)
is
49%
the probability of n customers at center j -- EXCLUDING
the v_j SCSL customers
50% there -- in
the network with normalizing constant G_k(v). Writing tau_k(v,i)
51%
for the throughput of an SCSL chain that replaces chain k at center i,
the
52% recursion of Section V reads
53% tau_k(v,i) = T_ik^-1 sum_{n=0}^{k-1}
P^{k-1}_i(n,v+1_i) mu_i(n+v_i+1)
55% tau_k(v,i) = T_ik^-1, i IS, (22)
56% L^k_{jk}(v) = theta_jk tau_k(v,j)^-1 / sum_m theta_mk tau_k(v,m)^-1, (23)
57% lambda^k_k(v) = tau_k(v,j(k)) L^k_{j(k)k}(v), (24)
58%
P^k_j(n,v) = L^k_{jk}(v)
P^{k-1}_j(n-1,v+1_j)
59% + sum_{m ~= j} L^k_{mk}(v)
P^{k-1}_j(n,v+1_m), (25)
60% with
P^0_j(0,v) = 1 and
P^{k-1}_j(n,.) = 0
for n < 0 or n > k-1. Eq. (21)
is
61% just
"the mean rate at which an SCSL chain is served": given n other customers
62%
the processor-sharing rate share
is mu_i(n+v_i+1)/(n+v_i+1), averaged over
the
63% distribution of those others. The queueing discipline may be assumed PS with
64% no loss of generality, since product-form measures do not depend on it.
66% This implementation writes (23)-(24) in
the reference-station-free form
67% c_i(k,v) = sum_{n=0}^{k-1}
P^{k-1}_i(n,v+1_i) mu_i(n+v_i+1)/(n+v_i+1),
68% L^k_{jk}(v) = (a_jk/c_j) / sum_m (a_mk/c_m),
69% lambda^k_k(v) = 1 / sum_m (a_mk/c_m),
70% which follows from theta_jk tau_k(v,j)^-1 = a_jk/c_j and theta_{j(k)k} = 1, so
71% only
the demands a_jk are needed and
the visit ratios never appear separately.
72% For an IS center c_i = 1 identically, which
is exactly (22). Eq. (25)
is
73% self-normalizing, sum_n
P^k_j(n,v) = sum_m L^k_{mk}(v) = 1, so no normalizing
74% constant
is formed and
the recursion involves only positive quantities: unlike
75%
the classic load-dependent MVA of PFQN_MVALD it cannot produce negative
76% probabilities and needs no stabilization.
78% Parts 2 and 3 of
the algorithm are unchanged from
PFQN_MVAC, since eq. (6)
79% holds verbatim in
the presence of QLD centers: part 2 resolves
the chains that
80% visit at least one IS center, and
the chains that visit no IS center are
81% resolved by re-executing part 1 with their label interchanged with K.
84% L - (M x R) service demand matrix of
the QLD centers.
85% N - (1 x R) closed population vector, finite and nonnegative.
86% Z - (1 x R) or (Mz x R) demand matrix of
the IS centers, one row per
87% center. Defaults to zeros(1,R).
88% mu - (M x Nt) load-dependent rates, Nt >= sum(N); mu(j,n)
is the total
89% service rate of center j with n jobs present. mu(j,:) = 1
is a
90% single-server fixed-rate queue, mu(j,n) = min(n,c) a c-server queue,
91% mu(j,n) = n an infinite server. Defaults to ones(M,sum(N)), i.e. all
92% centers SSFR, in which case
the results agree with
PFQN_MVAC.
95% XN - (1 x R) per-class throughput at
the reference station.
96% QN - (M x R) per-class mean queue-length at
the QLD centers.
97% UN - (M x 1) utilization of each center, 1 - P_j(0). PER-STATION, not
98% per-class, as in PFQN_MVALD and PFQN_DAC: for a load-dependent center
100% CN - (1 x R) per-class cycle time exclusive of think time, N(r)/XN(r)-Z(r),
101% as in PFQN_MVALD and PFQN_DAC. NOT
the (M x R) per-station residence
102% time of
PFQN_MVAC:
the whole LD family reports a cycle time here.
103% pij - (M x (sum(N)+1)) marginal queue-length probabilities,
104% pij(j,n+1) =
P(n jobs at center j).
106% See also
PFQN_MVAC, PFQN_MVALD, PFQN_DAC, PFQN_GLD.
108% Copyright (c) 2012-2026, Imperial College London
109% All rights reserved.
112if nargin < 3 || isempty(Z)
116 line_error(mfilename,
'the think time matrix and the demand matrix have a different number of classes');
120 line_error(mfilename,'the demand matrix and
the population vector have a different number of classes
');
122if any(N < 0) || any(isinf(N))
123 line_error(mfilename,'the population vector must be finite and nonnegative
');
125K = sum(N); % number of single-customer chains in the original network
126if nargin < 4 || isempty(mu)
127 mu = ones(M,max(K,1));
130 line_error(mfilename,'the rate matrix and
the demand matrix have a different number of centers
');
132if K > 0 && size(mu,2) < K
133 line_error(mfilename,'the rate matrix must supply a rate for every population up to sum(N)
');
141pij(:,1) = 1; % an unvisited center holds no jobs
146% Discard the centers that no chain visits: they carry no customers and would
147% only inflate the multiplicity vector v.
148ldIdx = find(any(L > 0, 2))';
149isIdx = find(any(Z > 0, 2))
';
151J = J1 + length(isIdx);
153 line_error(mfilename,'all service demands are zero,
the throughput
is unbounded
');
155% A(j,r) = a_jr, centers ordered QLD first, then IS, as required by (21)-(22)
156A = [L(ldIdx,:); Z(isIdx,:)];
157MU = mu(ldIdx,1:K); % (J1 x K) rates of the QLD centers
159 line_error(mfilename,'the service rates must be strictly positive
for every population up to sum(N)
');
162%% Partition the chains into subsets of identical single-customer chains.
163% Two chains are identical when they have the same demand at every center, so
164% the subsets are the distinct columns of A restricted to the populated classes.
166[Adist,~,grpOfClass] = unique(A(:,posr)',
'rows',
'stable');
168visitsIS =
false(1,Dall);
170 visitsIS(g) = any(Adist(g,(J1+1):J) > 0);
172% Chains that visit at least one IS center are labelled K-D+1,...,K-S and are
173% resolved by part 2 (their throughput follows from Little
's law at that IS
174% center); the S chains that visit no IS center are labelled K-S+1,...,K and are
175% resolved by re-executions of part 1.
176gorder = [find(visitsIS), find(~visitsIS)];
179Agrp = Adist(gorder,:)'; % (J x D) demands of
the representative of each subset
182 mult(g) = sum(N(posr(grpOfClass == gorder(g))));
185% Chain labels:
the D representatives are labelled K-D+1,...,K,
the remaining
186% K-D identical chains fill
the labels 1,...,K-D in any order.
187chainGroup = zeros(1,K);
188chainGroup((K-D+1):K) = 1:D;
191 for c = 1:(mult(g)-1)
196a = Agrp(:,chainGroup); % (J x K) relative utilizations a_jk
198%% Enumerate
the multiplicity vectors.
199% Unlike
PFQN_MVAC,
the QLD basic step at level k sweeps I_k ALONE, because
200% (21) and (25) read level k-1 only at v + 1_i. Vectors are enumerated by
201% increasing component sum, so I_k occupies
the contiguous block of sum K-k.
206 Vt = multichoose(J,t);
207 off(t+1) = size(Vlist,1);
208 cnt(t+1) = size(Vt,1);
209 Vlist = [Vlist; Vt]; %
#ok<AGROW>
212% succ(vi,i)
is the global index of v + 1_i, or 0 when out of range (sum(v)==K)
216 Vplus(:,j) = Vplus(:,j) + 1;
217 [tf,loc] = ismember(Vplus,Vlist,
'rows');
218 succ(:,j) = loc .* tf;
222Pall = cell(1,K+1); % Pall{k+1}(j,vloc,n+1) =
P^k_j(n,v), v
the vloc-th of I_k
223Ljkall = cell(1,K+1); % Ljkall{k+1}(j,vloc) = L^k_{jk}(v)
224lamall = cell(1,K+1); % lamall{k+1}(vloc) = lambda^k_k(v)
225Pall{1} = ones(J1,cnt(K+1),1); %
P^0_j(0,v) = 1, I_0
is the block of sum K
227lamChain = zeros(1,K); % per-chain throughput, indexed by
the ORIGINAL chain label
228Lchain = zeros(J,K); % per-chain mean queue-length, same indexing
230% First execution of
the basic step, k0 = 1.
231[Pall,Ljkall,lamall] = mvacld_part1(1,K,J,J1,a,MU,Vlist,off,cnt,succ,Pall,Ljkall,lamall);
232lamChain(K) = lamall{K+1}(1);
233Lchain(:,K) = Ljkall{K+1}(:,1);
234% The marginals of
the ORIGINAL network are read at k = K and v = 0;
the label
235% interchanges below overwrite
this level, so capture them now.
236pij(ldIdx,:) = reshape(Pall{K+1}(:,1,:),J1,K+1);
238% Part 2: measures of
the chains that visit at least one IS center. Eq. (6)
is
239% unchanged by load dependence.
241if D >= 2 && lmaxK >= K-D+1
246 for l = (K-D+1):min(k-1,K-S)
247 acc = zeros(J,cnt(t+1));
248 for vloc = 1:cnt(t+1)
249 vi = off(t+1) + vloc;
251 sloc = succ(vi,j) - off(t+2);
253 % base case of (6): L^{k-1}_{i,k-1} comes from (23)
254 prev = Ljkall{k}(:,sloc);
256 prev = L2prev{l}(:,sloc);
258 acc(:,vloc) = acc(:,vloc) + Ljkall{k+1}(j,vloc) * prev;
264 for l = (K-D+1):lmaxK
265 Lchain(:,l) = L2cur{l}(:,1);
266 % Little
's law at an IS center visited by chain l
267 jIS = find(a((J1+1):J,l) > 0,1) + J1;
268 lamChain(l) = Lchain(jIS,l) / a(jIS,l);
275% Re-executions of part 1: measures of the chains that visit no IS center.
276% Interchanging the labels of chains K-l and K leaves chains 1,...,K-l-1 in
277% place, so the levels up to K-l-1 computed by the first execution stay valid
278% and the basic step can restart at k0 = K-l.
279perm = 1:K; % perm(k) is the original label of the chain now labelled k
281 perm([K-l,K]) = perm([K,K-l]);
282 a(:,[K-l,K]) = a(:,[K,K-l]);
283 [Pall,Ljkall,lamall] = mvacld_part1(K-l,K,J,J1,a,MU,Vlist,off,cnt,succ,Pall,Ljkall,lamall);
284 lamChain(perm(K)) = lamall{K+1}(1);
285 Lchain(:,perm(K)) = Ljkall{K+1}(:,1);
288%% Expand the per-chain measures back to the per-class measures.
289% Every chain of a subset has the same measures, hence a class with N_r chains
290% in that subset carries N_r times the measures of the subset representative.
292 kg = K-D+g; % original label of the representative of subset g
293 for r = posr(grpOfClass == gorder(g))
294 XN(r) = N(r) * lamChain(kg);
295 QN(ldIdx,r) = N(r) * Lchain(1:J1,kg);
298% Utilization of a load-dependent center is 1-P_j(0), NOT XN(r)*L(j,r).
300% Cycle time exclusive of think time, as in PFQN_MVALD and PFQN_DAC. An empty
301% class has zero throughput, hence no cycle time.
303CN(posr) = N(posr) ./ XN(posr) - sum(Z(:,posr),1);
306function [Pall,Ljkall,lamall] = mvacld_part1(k0,K,J,J1,a,MU,Vlist,off,cnt,succ,Pall,Ljkall,lamall)
307% Part 1 of the basic step for networks with QLD centers: evaluate (21)-(25) for
308% k = k0,...,K over v in I_k, the block of multiplicity vectors of sum K-k.
312 Pp = Pall{k}; % P^{k-1}, over I_{k-1}, third dimension n = 0,...,k-1
315 Pk = zeros(J1,nvk,k+1);
317 vi = off(t+1) + vloc;
319 sloc = succ(vi,:) - off(t+2); % local index of v + 1_i within I_{k-1}
320 % (21): c(i) is the mean rate at which an SCSL chain pinned at center i
321 % is served, i.e. tau_k(v,i)*T_ik. For an IS center (22) gives c(i) = 1,
322 % which the general formula would also return since mu_i(n) = n.
327 ci = ci + Pp(i,sloc(i),n+1) * MU(i,n+v(i)+1) / (n+v(i)+1);
331 % (23)-(24) in reference-station-free form: theta_jk/tau_k(v,j) = a_jk/c_j
335 w(j) = a(j,k) / c(j);
341 % (25): condition on the center holding the single chain-k customer
346 % chain k is at j, so n-1 of the k-1 others are there too
347 s = Lk(j,vloc) * Pp(j,sloc(j),n);
350 % chain k is elsewhere, so all n are from the k-1 others
353 s = s + Lk(m,vloc) * Pp(j,sloc(m),n+1);