1function [Q, W, T, U, Ca, Cd, PBa, lambda, iter] = me_oqn_blk(M, lambda0, Ca0, mu, Cs,
P, c, N, blockrule, options)
2%ME_OQN_BLK Maximum Entropy algorithm
for single-
class open queueing
3%networks with finite buffers, loss and transfer blocking
5% Extends ME_OQN to open networks in which a station has a finite buffer.
6% Two per-station policies are supported:
8% loss (blockrule = 0) - a job that finds the destination full
is
9% discarded. Each station
is then a censored
10% GE/GE/c/0;N queue, and the network
is the ME
11% decomposition of Kouvatsos (1994), Section 4.
12% transfer blocking - a job that completes service at station i and
13% (blockrule = 1) finds the destination j full
is held in i
's
14% server, which cannot serve anyone else until
15% j has room (blocking after service, BAS).
17% Transfer blocking is not work conserving, so a product-form
18% approximation cannot be applied to the network as it stands. Following
19% Tahilramani, Manjunath and Bose (1999) the network is first made work
20% conserving by inserting a GE/GE/inf HOLDING NODE h_ij on every routing
21% pair with p_ij > 0 and a finite-buffer destination j. The holding node
22% absorbs the blocked job, so station i's server
is released; the delay it
23% introduces
is the residual life of the minimum of the c_j service times
24% in progress at j, inflated geometrically because the released job may
25% find j full again.
Station i
's own service time is inflated by the same
26% blocking probability so that the jobs queued behind the blocked one
27% still see the server as busy. The expanded network is work conserving
28% and is solved node by node with the censored ME queue of ME_GEGECN,
29% iterating over the blocking probabilities and the first two moments of
30% the flows until they converge.
33% M - Number of stations
34% lambda0 - External arrival rates [M x 1]
35% Ca0 - External interarrival scv [M x 1] (>= 1 where lambda0 > 0)
36% mu - Service rates [M x 1]
37% Cs - Service scv [M x 1] (>= 1 at every finite-buffer station)
38% P - Routing probabilities [M x M], P(i,j) = p_ij. Row sums
39% below one send the residual flow out of the network
40% c - Servers per station [M x 1]; Inf marks an infinite server
41% N - Buffer capacity per station [M x 1] in jobs, in service
42% included; Inf marks an unbounded buffer
43% blockrule - Policy at each finite-buffer station [M x 1]: 0 = loss,
44% 1 = transfer blocking (BAS)
45% options - (optional) struct with fields .tol (default 1e-6),
46% .maxiter (default 1000), .verbose (default false),
47% .damping (default 0.5), applied to the blocking
48% probabilities as in the relaxation scheme of the source
51% Q - Mean number of jobs at each station [M x 1], including the
52% jobs held blocked in that station's servers
53% W - Mean response time [M x 1], Q ./ T
54% T - Throughput (carried flow) [M x 1]
55% U - Utilization [M x 1], mean fraction of busy servers, the jobs
56% held blocked counted as occupying their server
57% Ca - Interarrival scv of the offered flow at each station [M x 1]
58% Cd - Interdeparture scv at each station [M x 1]
59% PBa - Probability that an arrival at each station finds it full,
60% averaged over the incoming streams [M x 1]
61% lambda - Offered arrival rate at each station [M x 1], attempts
63% iter - Number of iterations performed
66% D.D. Kouvatsos,
"Entropy Maximisation and Queueing Network Models",
67% Annals of Operations Research, 48:63-126, 1994, Section 4.
68% H. Tahilramani, D. Manjunath, S.K. Bose,
"Approximate analysis of open
69% network of GE/GE/m/N queues with transfer blocking", MASCOTS 1999,
72% Copyright (c) 2012-2026, Imperial College London
75if nargin < 9 || isempty(blockrule)
76 blockrule = zeros(M, 1);
81if ~isfield(options,
'tol'), options.tol = 1e-6; end
82if ~isfield(options,
'maxiter'), options.maxiter = 1000; end
83if ~isfield(options,
'verbose'), options.verbose =
false; end
84if ~isfield(options,
'damping'), options.damping = 0.5; end
92blockrule = blockrule(:);
94finiteBuf = isfinite(N) & isfinite(c);
95bas = finiteBuf & (blockrule == 1);
98 if finiteBuf(i) && Cs(i) < 1 - 1e-12
99 line_error(mfilename,
'MEM with finite buffers requires a service scv of at least 1 at station %d: the GE distribution is not defined for scv < 1.', i);
101 if lambda0(i) > 0 && Ca0(i) < 1 - 1e-12
102 line_error(mfilename,
'MEM with finite buffers requires an external interarrival scv of at least 1 at station %d.', i);
106% see _kb/03-api-layer.md (me_oqn_blk -- GE-type OQN with blocking)
for rationale
113 muf(i) = mu(i) * (1 - pii);
114 Csf(i) = pii + (1 - pii) * Cs(i);
115 Pf(i, :) =
P(i, :) / (1 - pii);
120% see _kb/03-api-layer.md (me_oqn_blk -- GE-type OQN with blocking)
for rationale
121sigmaS = 2 ./ (Csf + 1);
122muRes = c .* muf .* sigmaS;
127PBs = zeros(M, M); % PB^i_j, blocking of the flow from i into j
128PBe = zeros(M, 1); % PBe_j, blocking of the external flow into j
129PBh = zeros(M, M); % PB^{h_ij}_j, blocking of the flow released by h_ij
130PBa = zeros(M, 1); % aggregate blocking probability at j
135Lhold = zeros(M, M); % mean occupancy of each holding node
138for iter = 1:options.maxiter
143 % Service inflation at the blocking stations, eqs. (15)-(16): the
144 % fraction PBf(i) of the service completions at i
is followed by a
145 % blocking period during which the server stays unavailable.
149 if Pf(i, j) > 0 && bas(j)
150 PBf(i) = PBf(i) + Pf(i, j) * PBs(i, j);
154 if any(PBf >= 1 - 1e-9)
155 line_error(mfilename, 'MEM transfer-blocking fixed point saturates: a station
is blocked with probability one. The network has no stable operating point under BAS.');
157 muEff = muf .* (1 - PBf);
158 CsEff = PBf + Csf .* (1 - PBf);
160 % Flow balance on the carried flow, eq. (11). Under loss the fraction
161 % PB of a stream
is discarded; under transfer blocking every job
162 % eventually enters, the delay being charged to the holding node.
166 % see _kb/03-api-layer.md (me_oqn_blk -- GE-type OQN with blocking) for rationale
167 b(j) = lambda0(j) * (1 - PBe(j));
170 if finiteBuf(j) && ~bas(j)
171 A(i, j) = Pf(i, j) * (1 - PBs(i, j));
178 T = (eye(M) - A') \ b;
181 % Offered (attempt) rates and the aggregate blocking probability,
182 % eq. (13). A blocked job under transfer blocking re-attempts from the
183 % holding node, so its stream contributes carried/(1-PB) attempts.
184 attExt = zeros(M, 1);
185 attInt = zeros(M, M);
187 attExt(j) = lambda0(j);
190 if finiteBuf(j) && bas(j)
191 attInt(i, j) = T(i) * Pf(i, j) / max(1 - PBs(i, j), 1e-12);
193 attInt(i, j) = T(i) * Pf(i, j);
198 lambda = attExt + sum(attInt, 1)';
201 PBa(j) = (attExt(j) * PBe(j) + sum(attInt(:, j) .* PBs(:, j))) / lambda(j);
207 % Interarrival scv of the offered flow, by GE splitting and merging.
208 % A stream thinned with probability p has scv 1-p+p*Cd; the merge of
209 % GE streams satisfies 1/(Cm+1) = sum_s (lam_s/lam)/(Cs+1).
210 CaStreamInt = ones(M, M);
217 sum_inv = sum_inv + (attExt(j) / lambda(j)) / (Ca0(j) + 1);
221 CaStreamInt(i, j) = 1 - Pf(i, j) + Pf(i, j) * Cd(i);
222 sum_inv = sum_inv + (attInt(i, j) / lambda(j)) / (CaStreamInt(i, j) + 1);
226 Ca(j) = -1 + 1 / sum_inv;
230 %
Station solution in isolation and the per-stream blocking
231 % probabilities, eqs. (12) and (14), i.e. eq. (4.3) of the source
232 % evaluated with each stream's own scv.
233 PBe_new = zeros(M, 1);
234 PBs_new = zeros(M, M);
235 PBh_new = zeros(M, M);
238 % Infinite server: no queueing and no blocking
241 Q(j) = lambda(j) / muEff(j);
248 % Unbounded buffer: the infinite-capacity GE building blocks
251 rho = lambda(j) / (c(j) * muEff(j));
258 Q(j) = rho * (Ca(j) + 1) / 2 + rho^2 * (CsEff(j) + Ca(j)) / (2 * (1 - rho));
260 Cd(j) = rho^2 * CsEff(j) + (1 - rho) * Ca(j) + rho * (1 - rho);
262 Q(j) = me_gegec_mql(lambda(j), Ca(j), muEff(j), CsEff(j), c(j));
264 Cd(j) = rho^2 * CsEff(j) + (1 - rho) * Ca(j) + rho * (1 - rho);
268 [pj, Lj, Uj] = me_gegecn(lambda(j), Ca(j), muEff(j), CsEff(j), c(j), 0, N(j));
271 % Interdeparture scv, eq. (4), evaluated at the utilization of the
272 % censored queue: with losses the offered load can exceed one
273 % while the fraction of busy servers cannot.
274 Cd(j) = Uj^2 * CsEff(j) + (1 - Uj) * Ca(j) + Uj * (1 - Uj);
276 PBe_new(j) = me_gegecn_pb(pj, 0, N(j), c(j), CsEff(j), Ca0(j));
280 PBs_new(i, j) = me_gegecn_pb(pj, 0, N(j), c(j), CsEff(j), CaStreamInt(i, j));
282 % see _kb/03-api-layer.md (me_oqn_blk -- GE-type OQN with blocking) for rationale
283 q = Pf(i, j) * PBs(i, j);
284 CaH = 1 - q + q * Cd(i);
285 PBh_new(i, j) = me_gegecn_pb(pj, 0, N(j), c(j), CsEff(j), CaH);
291 % Relaxation on the blocking probabilities
293 PBe = (1 - w) * PBe + w * PBe_new;
294 PBs = (1 - w) * PBs + w * PBs_new;
295 PBh = (1 - w) * PBh + w * PBh_new;
297 delta = max([max(abs(Ca - Ca_old)), max(max(abs(PBs - PBs_old))), max(abs(PBe - PBe_old))]);
299 fprintf('Iteration %d: max delta = %e\n', int32(iter), delta);
301 if delta < options.tol
306if iter == options.maxiter && delta >= options.tol
307 warning('me_oqn_blk:noconverge', 'Did not converge within %d iterations (delta=%e)', int32(options.maxiter), delta);
310% Holding node occupancy, eq. (7) and the correction of eq. (17). The jobs
311% held in h_ij are physically blocked in the servers of station i, so they
312% are added back to station i.
316 if bas(j) && Pf(i, j) > 0 && PBs(i, j) > 0
317 rateH = T(i) * Pf(i, j) * PBs(i, j);
318 muH = muRes(j) * (1 - PBh(i, j));
320 Lhold(i, j) = rateH / muH;
325Q = Q + sum(Lhold, 2);
327% see _kb/03-api-layer.md (me_oqn_blk -- GE-type OQN with blocking) for rationale
331 U(i) = T(i) / muf(i);
333 U(i) = T(i) / (c(i) * muf(i));