LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
me_oqn_blk.m
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
4%
5% Extends ME_OQN to open networks in which a station has a finite buffer.
6% Two per-station policies are supported:
7%
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).
16%
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.
31%
32% INPUTS:
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
49%
50% OUTPUTS:
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
62% included
63% iter - Number of iterations performed
64%
65% References:
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,
70% 164-171.
71%
72% Copyright (c) 2012-2026, Imperial College London
73% All rights reserved.
74
75if nargin < 9 || isempty(blockrule)
76 blockrule = zeros(M, 1);
77end
78if nargin < 10
79 options = struct();
80end
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
85
86lambda0 = lambda0(:);
87Ca0 = Ca0(:);
88mu = mu(:);
89Cs = Cs(:);
90c = c(:);
91N = N(:);
92blockrule = blockrule(:);
93
94finiteBuf = isfinite(N) & isfinite(c);
95bas = finiteBuf & (blockrule == 1);
96
97for i = 1:M
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);
100 end
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);
103 end
104end
105
106% see _kb/03-api-layer.md (me_oqn_blk -- GE-type OQN with blocking) for rationale
107Pf = P;
108muf = mu;
109Csf = Cs;
110for i = 1:M
111 pii = P(i, i);
112 if pii > 0
113 muf(i) = mu(i) * (1 - pii);
114 Csf(i) = pii + (1 - pii) * Cs(i);
115 Pf(i, :) = P(i, :) / (1 - pii);
116 Pf(i, i) = 0;
117 end
118end
119
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;
123
124% Fixed-point state
125Ca = ones(M, 1);
126Cd = Csf;
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
131Q = zeros(M, 1);
132U = zeros(M, 1);
133T = zeros(M, 1);
134lambda = zeros(M, 1);
135Lhold = zeros(M, M); % mean occupancy of each holding node
136iter = 0;
137
138for iter = 1:options.maxiter
139 Ca_old = Ca;
140 PBs_old = PBs;
141 PBe_old = PBe;
142
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.
146 PBf = zeros(M, 1);
147 for i = 1:M
148 for j = 1:M
149 if Pf(i, j) > 0 && bas(j)
150 PBf(i) = PBf(i) + Pf(i, j) * PBs(i, j);
151 end
152 end
153 end
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.');
156 end
157 muEff = muf .* (1 - PBf);
158 CsEff = PBf + Csf .* (1 - PBf);
159
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.
163 A = zeros(M, M);
164 b = zeros(M, 1);
165 for j = 1:M
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));
168 for i = 1:M
169 if Pf(i, j) > 0
170 if finiteBuf(j) && ~bas(j)
171 A(i, j) = Pf(i, j) * (1 - PBs(i, j));
172 else
173 A(i, j) = Pf(i, j);
174 end
175 end
176 end
177 end
178 T = (eye(M) - A') \ b;
179 T(T < 0) = 0;
180
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);
186 for j = 1:M
187 attExt(j) = lambda0(j);
188 for i = 1:M
189 if Pf(i, j) > 0
190 if finiteBuf(j) && bas(j)
191 attInt(i, j) = T(i) * Pf(i, j) / max(1 - PBs(i, j), 1e-12);
192 else
193 attInt(i, j) = T(i) * Pf(i, j);
194 end
195 end
196 end
197 end
198 lambda = attExt + sum(attInt, 1)';
199 for j = 1:M
200 if lambda(j) > 0
201 PBa(j) = (attExt(j) * PBe(j) + sum(attInt(:, j) .* PBs(:, j))) / lambda(j);
202 else
203 PBa(j) = 0;
204 end
205 end
206
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);
211 for j = 1:M
212 if lambda(j) <= 0
213 continue
214 end
215 sum_inv = 0;
216 if attExt(j) > 0
217 sum_inv = sum_inv + (attExt(j) / lambda(j)) / (Ca0(j) + 1);
218 end
219 for i = 1:M
220 if attInt(i, j) > 0
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);
223 end
224 end
225 if sum_inv > 0
226 Ca(j) = -1 + 1 / sum_inv;
227 end
228 end
229
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);
236 for j = 1:M
237 if isinf(c(j))
238 % Infinite server: no queueing and no blocking
239 Q(j) = 0;
240 if muEff(j) > 0
241 Q(j) = lambda(j) / muEff(j);
242 end
243 U(j) = Q(j);
244 Cd(j) = Ca(j);
245 continue
246 end
247 if ~finiteBuf(j)
248 % Unbounded buffer: the infinite-capacity GE building blocks
249 rho = 0;
250 if muEff(j) > 0
251 rho = lambda(j) / (c(j) * muEff(j));
252 end
253 if rho >= 1
254 Q(j) = Inf;
255 U(j) = 1;
256 Cd(j) = CsEff(j);
257 elseif c(j) == 1
258 Q(j) = rho * (Ca(j) + 1) / 2 + rho^2 * (CsEff(j) + Ca(j)) / (2 * (1 - rho));
259 U(j) = rho;
260 Cd(j) = rho^2 * CsEff(j) + (1 - rho) * Ca(j) + rho * (1 - rho);
261 else
262 Q(j) = me_gegec_mql(lambda(j), Ca(j), muEff(j), CsEff(j), c(j));
263 U(j) = rho;
264 Cd(j) = rho^2 * CsEff(j) + (1 - rho) * Ca(j) + rho * (1 - rho);
265 end
266 continue
267 end
268 [pj, Lj, Uj] = me_gegecn(lambda(j), Ca(j), muEff(j), CsEff(j), c(j), 0, N(j));
269 Q(j) = Lj;
270 U(j) = Uj;
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);
275 if attExt(j) > 0
276 PBe_new(j) = me_gegecn_pb(pj, 0, N(j), c(j), CsEff(j), Ca0(j));
277 end
278 for i = 1:M
279 if attInt(i, j) > 0
280 PBs_new(i, j) = me_gegecn_pb(pj, 0, N(j), c(j), CsEff(j), CaStreamInt(i, j));
281 if bas(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);
286 end
287 end
288 end
289 end
290
291 % Relaxation on the blocking probabilities
292 w = options.damping;
293 PBe = (1 - w) * PBe + w * PBe_new;
294 PBs = (1 - w) * PBs + w * PBs_new;
295 PBh = (1 - w) * PBh + w * PBh_new;
296
297 delta = max([max(abs(Ca - Ca_old)), max(max(abs(PBs - PBs_old))), max(abs(PBe - PBe_old))]);
298 if options.verbose
299 fprintf('Iteration %d: max delta = %e\n', int32(iter), delta);
300 end
301 if delta < options.tol
302 break
303 end
304end
305
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);
308end
309
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.
313Lhold(:) = 0;
314for i = 1:M
315 for j = 1:M
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));
319 if muH > 0
320 Lhold(i, j) = rateH / muH;
321 end
322 end
323 end
324end
325Q = Q + sum(Lhold, 2);
326
327% see _kb/03-api-layer.md (me_oqn_blk -- GE-type OQN with blocking) for rationale
328for i = 1:M
329 if muf(i) > 0
330 if isinf(c(i))
331 U(i) = T(i) / muf(i);
332 else
333 U(i) = T(i) / (c(i) * muf(i));
334 end
335 else
336 U(i) = 0;
337 end
338end
339W = zeros(M, 1);
340for i = 1:M
341 if T(i) > 0
342 W(i) = Q(i) / T(i);
343 end
344end
345end