LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
solver_mam_qsys.m
1function [QN, UN, RN, TN, piAgg, GM] = solver_mam_qsys(arrival, service, options)
2% SOLVER_MAM_QSYS Unified solver for MAP/BMAP queueing systems with single server
3%
4% [QN, UN, RN, TN, PI, GM] = SOLVER_MAM_QSYS(ARRIVAL, SERVICE) solves a queueing
5% system with Markovian arrival and service processes. Automatically detects
6% whether arrivals or service are batched and applies the appropriate
7% matrix-analytic method:
8% - BMAP/MAP/1: M/G/1 type analysis (batch arrivals, single service)
9% - MAP/BMAP/1: GI/M/1 type analysis (single arrivals, batch service)
10%
11% Input:
12% arrival - Arrival process: MAP object, BMAP object, or cell array
13% MAP: {D0, D1} or MAP object
14% BMAP: {D0, D1, D2, ..., DK} or BMAP object
15% service - Service process: MAP object, BMAP object, or cell array
16% MAP: {S0, S1} or MAP object
17% BMAP: {S0, S1, S2, ..., SK} or BMAP object
18% options - (optional) Options structure with fields:
19% .nMoments: number of queue length moments to compute (default: 3)
20%
21% Output:
22% QN - Mean queue length E[N]
23% UN - Server utilization rho
24% RN - Mean response time E[R]
25% TN - Throughput (arrival rate)
26% piAgg - Aggregated stationary probabilities
27% GM - G matrix (M/G/1 type) or R matrix (GI/M/1 type)
28%
29% Queue Types:
30% BMAP/MAP/1 - Batch arrivals, single service (M/G/1 type)
31% Level increases by batch size (1, 2, 3, ...), decreases by 1
32% MAP/BMAP/1 - Single arrivals, batch service (GI/M/1 type)
33% Level increases by 1, decreases by batch size (1, 2, 3, ...)
34%
35% References:
36% Stathopoulos, Riska, Hua, Smirni: ETAQA algorithm
37% MAMSolver: www.cs.wm.edu/MAMSolver
38%
39% See also: MAP, BMAP
40%
41% Copyright (c) 2012-2026, Imperial College London
42% All rights reserved.
43
44%% Input validation and setup
45if nargin < 3
46 options = struct();
47end
48if ~isfield(options, 'nMoments')
49 options.nMoments = 3;
50end
51
52%% Determine arrival type (MAP or BMAP)
53[arrivalMatrices, arrivalIsBatch, ma] = parseProcess(arrival, 'arrival');
54
55%% Determine service type (MAP or BMAP)
56[serviceMatrices, serviceIsBatch, ms] = parseProcess(service, 'service');
57
58%% Route to appropriate solver based on queue type
59if arrivalIsBatch && ~serviceIsBatch
60 % BMAP/MAP/1 queue - M/G/1 type analysis
61 [QN, UN, RN, TN, piAgg, GM] = solveBMAPMAP1(arrivalMatrices, serviceMatrices, ma, ms, options);
62elseif ~arrivalIsBatch && serviceIsBatch
63 % MAP/BMAP/1 queue - GI/M/1 type analysis
64 [QN, UN, RN, TN, piAgg, GM] = solveMAPBMAP1(arrivalMatrices, serviceMatrices, ma, ms, options);
65elseif ~arrivalIsBatch && ~serviceIsBatch
66 % MAP/MAP/1 queue - treat as BMAP/MAP/1 with batch size 1
67 [QN, UN, RN, TN, piAgg, GM] = solveBMAPMAP1(arrivalMatrices, serviceMatrices, ma, ms, options);
68else
69 % BMAP/BMAP/1 - both batched (not yet supported)
70 error('BMAP/BMAP/1 queues with both batch arrivals and batch service are not yet supported');
71end
72
73end
74
75%% Helper function to parse arrival/service process
76function [matrices, isBatch, nPhases] = parseProcess(proc, procType)
77 if isa(proc, 'BMAP')
78 K = proc.getMaxBatchSize();
79 matrices = cell(1, K + 1);
80 matrices{1} = proc.D(0); % D0
81 for k = 1:K
82 matrices{k+1} = proc.D(1, k); % Dk (batch size k)
83 end
84 isBatch = K > 1;
85 nPhases = size(matrices{1}, 1);
86 elseif isa(proc, 'MAP')
87 matrices = {proc.D(0), proc.D(1)};
88 isBatch = false;
89 nPhases = size(matrices{1}, 1);
90 elseif iscell(proc)
91 matrices = proc;
92 isBatch = length(proc) > 2; % More than {D0, D1} means batch process
93 nPhases = size(proc{1}, 1);
94 else
95 error('%s must be a MAP object, BMAP object, or cell array', procType);
96 end
97
98 % Validate dimensions
99 for k = 1:length(matrices)
100 if size(matrices{k}, 1) ~= nPhases || size(matrices{k}, 2) ~= nPhases
101 error('All %s matrices must be %dx%d', procType, nPhases, nPhases);
102 end
103 end
104end
105
106%% BMAP/MAP/1 solver using M/G/1 type analysis
107function [QN, UN, RN, TN, pi, G] = solveBMAPMAP1(D, S, ma, ms, options)
108% Solves BMAP/MAP/1 using M/G/1 type matrix-analytic methods
109%
110% M/G/1 type structure (level can jump UP by any amount, DOWN by exactly 1):
111% A0 = I_ma \otimes S1 (service completion, level -1)
112% A1 = D0 \otimes I_ms + I_ma \otimes S0 (phase changes, level 0)
113% A_{k+1} = D_k \otimes I_ms (batch arrival size k, level +k)
114
115K = length(D) - 1; % max batch size for arrivals
116m = ma * ms; % Combined phases per level
117
118% Extract MAP service matrices
119S0 = S{1};
120S1 = S{2};
121
122%% Construct M/G/1 type matrices using Kronecker products
123I_ma = eye(ma);
124I_ms = eye(ms);
125
126A = zeros(m, m * (K + 2));
127
128% A0 = I_ma \otimes S1 (service completion)
129A0 = kron(I_ma, S1);
130A(:, 1:m) = A0;
131
132% A1 = D0 \otimes I_ms + I_ma \otimes S0 (phase changes only)
133A1 = kron(D{1}, I_ms) + kron(I_ma, S0);
134A(:, m+1:2*m) = A1;
135
136% A_{k+1} = D_k \otimes I_ms for k >= 1 (batch arrivals)
137for k = 1:K
138 Ak = kron(D{k+1}, I_ms);
139 A(:, (k+1)*m + 1 : (k+2)*m) = Ak;
140end
141
142% B = [B0, B1, B2, ..., BK] for level 0 (empty queue)
143B = zeros(m, m * (K + 1));
144
145% B0: At level 0, no service (add S1 back as self-loop)
146B0 = kron(D{1}, I_ms) + kron(I_ma, S0 + S1);
147B(:, 1:m) = B0;
148
149% B_k = D_k \otimes I_ms for k >= 1 (batch arrivals from empty queue)
150for k = 1:K
151 Bk = kron(D{k+1}, I_ms);
152 B(:, k*m + 1 : (k+1)*m) = Bk;
153end
154
155%% Verify stability condition
156D0 = D{1};
157D1_total = zeros(ma, ma);
158for k = 1:K
159 D1_total = D1_total + D{k+1};
160end
161
162% Stationary distribution of BMAP
163pi_bmap = map_prob({D0, D1_total});
164e_ma = ones(ma, 1);
165
166% Total customer arrival rate: sum_k (k * π * Dk * e)
167lambda_total = 0;
168for k = 1:K
169 rate_k = pi_bmap * D{k+1} * e_ma;
170 lambda_total = lambda_total + k * rate_k;
171end
172
173% Compute service rate from MAP
174pi_map = map_prob({S0, S1});
175e_ms = ones(ms, 1);
176mu = pi_map * S1 * e_ms; % Service rate
177
178% Utilization
179rho = lambda_total / mu;
180
181if rho >= 1
182 warning('solver_mam_qsys:Unstable', ...
183 'System is unstable (rho = %.4f >= 1). Results may be invalid.', rho);
184end
185
186%% Compute G matrix using MG1_G_ETAQA
187G = MG1_G_ETAQA(A);
188
189%% Compute stationary probabilities using MG1_pi_ETAQA
190pi = MG1_pi_ETAQA(B, A, G);
191
192%% Compute queue length moments using MG1_qlen_ETAQA
193qlen_moments = zeros(1, options.nMoments);
194for n = 1:options.nMoments
195 qlen_moments(n) = MG1_qlen_ETAQA(B, A, pi, n);
196end
197
198%% Compute performance metrics
199QN = qlen_moments(1); % Mean queue length (E[N])
200UN = rho; % Utilization
201TN = lambda_total; % Throughput (total arrival rate)
202RN = QN / TN; % Mean response time (Little's law: E[R] = E[N] / λ)
203
204end
205
206%% MAP/BMAP/1 solver using GI/M/1 type analysis
207function [QN, UN, RN, TN, piAgg, R] = solveMAPBMAP1(C, D, ma, ms, options)
208% Solves MAP/BMAP/1 using GI/M/1 type matrix-analytic methods
209%
210% GI/M/1 type structure (level jumps UP by 1, DOWN by any amount):
211% A0 = C1 \otimes I_ms (MAP arrival, level +1)
212% A1 = C0 \otimes I_ms + I_ma \otimes D0 (phase changes, level 0)
213% A_{k+1} = I_ma \otimes D_k (batch size k service, level -k)
214
215C0 = C{1};
216C1 = C{2};
217K = length(D) - 1; % max batch size for service
218m = ma * ms; % Combined phases per level
219
220%% Validate inputs
221% Check MAP is valid generator
222rowSumsC = sum(C0 + C1, 2);
223if max(abs(rowSumsC)) > 1e-10
224 error('MAP matrices C0 + C1 must have zero row sums');
225end
226
227% Check BMAP is valid generator
228DTotal = D{1};
229for k = 1:K
230 DTotal = DTotal + D{k+1};
231end
232rowSumsD = sum(DTotal, 2);
233if max(abs(rowSumsD)) > 1e-10
234 error('BMAP matrices D0 + D1 + ... + DK must have zero row sums');
235end
236
237%% Compute arrival and service rates
238% Arrival rate from MAP
239piC = map_prob({C0, C1});
240lambdaArr = piC * C1 * ones(ma, 1);
241
242% Service rate from BMAP (total customers served per unit time)
243piD = map_prob({D{1}, DTotal - D{1}}); % D0, sum of D1...DK
244muTotal = 0;
245for k = 1:K
246 muTotal = muTotal + k * (piD * D{k+1} * ones(ms, 1));
247end
248
249% Utilization
250rho = lambdaArr / muTotal;
251
252if rho >= 1.0
253 warning('solver_mam_qsys:Unstable', ...
254 'System is unstable (rho = %.4f >= 1). Results may be invalid.', rho);
255end
256
257%% Construct A matrix for GI/M/1-type (repeating part)
258A = zeros(m * (K + 2), m);
259
260% A0: MAP arrival (level +1)
261A0 = kron(C1, eye(ms));
262A(1:m, :) = A0;
263
264% A1: Phase changes only (level 0)
265A1 = kron(C0, eye(ms)) + kron(eye(ma), D{1});
266A(m+1:2*m, :) = A1;
267
268% A_{k+1}: Batch service of size k (level -k)
269for k = 1:K
270 Ak = kron(eye(ma), D{k+1});
271 A((k+1)*m+1:(k+2)*m, :) = Ak;
272end
273
274%% Construct B matrix for boundary levels
275B = zeros(m * (K + 1) + m, m);
276
277% B1 (level 0 -> level 0): Phase changes only, no service from empty
278B1 = kron(C0, eye(ms)) + kron(eye(ma), D{1});
279% Add service transitions that would go to negative levels back to level 0
280for k = 1:K
281 B1 = B1 + kron(eye(ma), D{k+1});
282end
283B(1:m, :) = B1;
284
285% B2, B3, ..., B_{K+1}: Transitions to level 0 from levels 1, 2, ..., K
286for j = 1:K
287 Bj = zeros(m, m);
288 for k = j:K
289 Bj = Bj + kron(eye(ma), D{k+1});
290 end
291 B(m + (j-1)*m + 1 : m + j*m, :) = Bj;
292end
293
294%% Compute R matrix using GI/M/1 ETAQA
295R = GIM1_R_ETAQA(A);
296
297%% Compute stationary probabilities using GI/M/1 ETAQA
298piAgg = GIM1_pi_ETAQA(B, A, R, 'Boundary', A0);
299
300%% Compute performance metrics
301% Mean queue length using ETAQA moments
302QN = GIM1_qlen_ETAQA(B, A, R, piAgg, 1, 'Boundary', A0);
303
304% Throughput equals arrival rate (in steady state)
305TN = lambdaArr;
306
307% Utilization
308UN = rho;
309
310% Mean response time via Little's Law
311RN = QN / TN;
312
313end