LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
solver_mam_bmap_map_1.m
1function [QN, UN, RN, TN, pi, G] = solver_mam_bmap_map_1(bmap, service_map, options)
2% SOLVER_MAM_BMAP_MAP_1 Solves a BMAP/MAP/1 queue using M/G/1 type analysis
3%
4% [QN, UN, RN, TN, PI, G] = SOLVER_MAM_BMAP_MAP_1(BMAP, SERVICE_MAP) solves a
5% BMAP/MAP/1 queue with batch Markovian arrival process BMAP and Markovian
6% service process SERVICE_MAP. Uses M/G/1 type matrix-analytic methods via
7% the ETAQA algorithm.
8%
9% Input:
10% bmap - BMAP object or cell array {D0, D1, D2, ..., DK} where
11% D0: transitions without arrivals
12% Dk: transitions triggering batch size k arrivals (k >= 1)
13% service_map - MAP object or cell array {S0, S1} where
14% S0: transitions without service completions
15% S1: transitions triggering service completions
16% options - (optional) Options structure with fields:
17% .nMoments: number of queue length moments to compute (default: 3)
18%
19% Output:
20% QN - Mean queue length (1st moment)
21% UN - Server utilization
22% RN - Mean response time
23% TN - Throughput (arrival rate)
24% pi - Aggregated stationary probability [pi0, pi1, pi2+pi3+...]
25% G - G matrix (minimal nonnegative solution)
26%
27% The BMAP/MAP/1 queue is modeled as an M/G/1 type Markov chain where:
28% - Level corresponds to queue length
29% - Phases correspond to combined (BMAP phase, MAP phase) states
30%
31% M/G/1 type structure (level can jump UP by any amount, DOWN by exactly 1):
32% A0 = I_ma ⊗ S1 (service completion, level -1)
33% A1 = D0 ⊗ I_ms + I_ma ⊗ S0 (phase changes, level 0)
34% A_{k+1} = D_k ⊗ I_ms (batch arrival size k, level +k)
35%
36% References:
37% - Stathopoulos, Riska, Hua, Smirni: ETAQA algorithm
38% - MAMSolver: www.cs.wm.edu/MAMSolver
39%
40% Copyright (c) 2012-2026, Imperial College London
41% All rights reserved.
42
43%% Input validation and setup
44if nargin < 3
45 options = struct();
46end
47if ~isfield(options, 'nMoments')
48 options.nMoments = 3;
49end
50
51% Extract BMAP matrices
52if isa(bmap, 'BMAP')
53 K = bmap.getMaxBatchSize();
54 D = cell(1, K+1);
55 D{1} = bmap.D(0); % D0
56 for k = 1:K
57 D{k+1} = bmap.D(1, k); % Dk (batch size k)
58 end
59elseif iscell(bmap)
60 D = bmap;
61 K = length(D) - 1; % max batch size
62else
63 error('BMAP must be a BMAP object or cell array {D0, D1, ..., DK}');
64end
65
66% Extract MAP service matrices
67if isa(service_map, 'MAP')
68 S0 = service_map.D(0);
69 S1 = service_map.D(1);
70elseif iscell(service_map) && length(service_map) == 2
71 S0 = service_map{1};
72 S1 = service_map{2};
73else
74 error('service_map must be a MAP object or cell array {S0, S1}');
75end
76
77% Number of phases
78ma = size(D{1}, 1); % BMAP phases
79ms = size(S0, 1); % MAP service phases
80m = ma * ms; % Combined phases per level
81
82% Validate dimensions
83for k = 1:length(D)
84 if size(D{k}, 1) ~= ma || size(D{k}, 2) ~= ma
85 error('All BMAP matrices must be %dx%d', ma, ma);
86 end
87end
88if size(S0, 1) ~= ms || size(S0, 2) ~= ms || size(S1, 1) ~= ms || size(S1, 2) ~= ms
89 error('MAP service matrices must be %dx%d', ms, ms);
90end
91
92%% Construct M/G/1 type matrices using Kronecker products
93% A = [A0, A1, A2, ..., A_{K+1}] for levels >= 1
94% A0 = I_ma ⊗ S1 (service completion, level -1)
95% A1 = D0 ⊗ I_ms + I_ma ⊗ S0 (phase changes, level 0)
96% A_{k+1} = D_k ⊗ I_ms for k >= 1 (batch arrivals size k, level +k)
97
98I_ma = eye(ma);
99I_ms = eye(ms);
100
101A = zeros(m, m * (K + 2));
102
103% A0 = I_ma ⊗ S1 (service completion)
104A0 = kron(I_ma, S1);
105A(:, 1:m) = A0;
106
107% A1 = D0 ⊗ I_ms + I_ma ⊗ S0 (phase changes only)
108A1 = kron(D{1}, I_ms) + kron(I_ma, S0);
109A(:, m+1:2*m) = A1;
110
111% A_{k+1} = D_k ⊗ I_ms for k >= 1 (batch arrivals)
112for k = 1:K
113 Ak = kron(D{k+1}, I_ms);
114 A(:, (k+1)*m + 1 : (k+2)*m) = Ak;
115end
116
117% B = [B0, B1, B2, ..., BK] for level 0 (empty queue)
118% At level 0, no service can occur, so we add S1 back to the diagonal block
119% B0 = D0 ⊗ I_ms + I_ma ⊗ (S0 + S1)
120% B_k = D_k ⊗ I_ms for k >= 1
121
122B = zeros(m, m * (K + 1));
123
124% B0: At level 0, no service (add S1 back as self-loop)
125B0 = kron(D{1}, I_ms) + kron(I_ma, S0 + S1);
126B(:, 1:m) = B0;
127
128% B_k = D_k ⊗ I_ms for k >= 1 (batch arrivals from empty queue)
129for k = 1:K
130 Bk = kron(D{k+1}, I_ms);
131 B(:, k*m + 1 : (k+1)*m) = Bk;
132end
133
134%% Verify stability condition
135% Compute arrival rate from BMAP
136D0 = D{1};
137D1_total = zeros(ma, ma);
138for k = 1:K
139 D1_total = D1_total + D{k+1};
140end
141
142% Stationary distribution of BMAP
143pi_bmap = map_prob({D0, D1_total});
144e_ma = ones(ma, 1);
145
146% Total customer arrival rate: sum_k (k * π * Dk * e)
147lambda_total = 0;
148for k = 1:K
149 rate_k = pi_bmap * D{k+1} * e_ma;
150 lambda_total = lambda_total + k * rate_k;
151end
152
153% Compute service rate from MAP
154pi_map = map_prob({S0, S1});
155e_ms = ones(ms, 1);
156mu = pi_map * S1 * e_ms; % Service rate
157
158% Utilization
159rho = lambda_total / mu;
160
161if rho >= 1
162 warning('solver_mam_bmap_map_1:Unstable', ...
163 'System is unstable (rho = %.4f >= 1). Results may be invalid.', rho);
164end
165
166%% Compute G matrix using MG1_G_ETAQA
167G = MG1_G_ETAQA(A);
168
169%% Compute stationary probabilities using MG1_pi_ETAQA
170pi = MG1_pi_ETAQA(B, A, G);
171
172%% Compute queue length moments using MG1_qlen_ETAQA
173qlen_moments = zeros(1, options.nMoments);
174for n = 1:options.nMoments
175 qlen_moments(n) = MG1_qlen_ETAQA(B, A, pi, n);
176end
177
178%% Compute performance metrics
179QN = qlen_moments(1); % Mean queue length (E[N])
180UN = rho; % Utilization
181TN = lambda_total; % Throughput (total arrival rate)
182RN = QN / TN; % Mean response time (Little's law: E[R] = E[N] / λ)
183
184end