1classdef BMAP < MarkedMAP
2 % Batch Markovian Arrival Process (BMAP)
4 % BMAP
is a point process where arrivals occur in batches.
5 % Uses the standard BMAP representation:
6 % - D0: infinitesimal generator
for transitions without arrivals
7 % - D1: rate matrix
for transitions generating 1 arrival
8 % - D2: rate matrix
for transitions generating 2 arrivals
10 % - Dk: rate matrix
for transitions generating k arrivals
12 % BMAP extends MarkedMAP where each
"mark" k represents a batch size k.
14 % Copyright (c) 2012-2026, Imperial College London
15 % All rights reserved.
19 function self = BMAP(D)
22 % D
is a cell array {D0, D1, D2, ..., Dk} where:
23 % - D0: transitions without arrivals
24 % - Dk: transitions generating k arrivals (
for k >= 1)
26 % The number of marking types K equals the maximum batch size
27 % (i.e., K = length(D) - 2 when D also includes D1_total,
28 % or K = length(D) - 1 otherwise)
34 % Determine K (number of marking types = max batch size)
35 % If D = {D0, D1, D2, ..., Dk}, then K = k (max batch size)
36 % MarkedMAP expects either:
37 % - {D0, D1_total, D11, D12, ..., D1K} with K marking types
38 % - {D0, D11, D12, ..., D1K} with K marking types
43 % Assume format {D0, D1, D2, ..., Dk} where Dk generates k arrivals
44 % Need to convert to MarkedMAP format {D0, D1_total, D1, D2, ..., Dk}
45 % where D1_total = sum(D1, D2, ..., Dk)
46 K = length(D) - 1; % max batch size
48 % Compute total arrival matrix
51 D1_total = D1_total + D{k};
54 % Create MarkedMAP cell array
55 D_mmap = cell(1, K+2);
56 D_mmap{1} = D{1}; % D0
57 D_mmap{2} = D1_total; % D1_total
59 D_mmap{2+k} = D{1+k}; % Dk (batch size k)
65 % Call parent MarkedMAP constructor
68 % Fix self.process which
is incorrectly set by MarkedMAP constructor
69 % MarkedMAP constructor has a bug on line 33-37 where it creates
70 % a cell array of size K-1 instead of K+2
74 self.validateGenerator();
77 % Validate that D0 + sum(Dk) forms a proper infinitesimal generator
78 function validateGenerator(self)
82 % Compute D0 + sum(Dk)
84 for k = 1:self.getMaxBatchSize()
85 generator = generator + self.D(1, k-1);
88 % Check row sums (should be close to zero)
89 rowSums = sum(generator, 2);
90 maxRowSum = max(abs(rowSums));
93 warning(
'BMAP:InvalidGenerator', ...
94 'BMAP generator row sums are not zero (max: %.2e). Consider calling normalize().', maxRowSum);
98 % Get maximum batch size
99 function k = getMaxBatchSize(self)
100 % K = GETMAXBATCHSIZE()
102 % Returns the maximum batch size k where Dk
is defined
103 k = self.getNumberOfTypes();
106 % Get mean batch size
107 function mean_bs = getMeanBatchSize(self)
108 % MEAN_BS = GETMEANBATCHSIZE()
110 % Computes the mean batch size as a weighted average:
111 % E[batch size] = sum(k * rate_k) / sum(rate_k)
113 % Get stationary distribution
using D0 and D1_total
115 D1_total = self.D(1);
116 pi = map_pie({D0, D1_total});
118 % Compute weighted average
121 maxBatch = self.getMaxBatchSize();
125 rate_k = sum(pi * Dk * ones(size(Dk, 1), 1));
126 totalRate = totalRate + rate_k;
127 weightedSum = weightedSum + k * rate_k;
131 mean_bs = weightedSum / totalRate;
138 function rates = getBatchRates(self)
139 % RATES = GETBATCHRATES()
141 % Returns array where rates(k)
is the rate of batch size k arrivals
144 D1_total = self.D(1);
145 maxBatch = self.getMaxBatchSize();
147 % Get stationary distribution
148 pi = map_pie({D0, D1_total});
150 % Compute rate
for each batch size
151 rates = zeros(1, maxBatch);
154 rates(k) = sum(pi * Dk * ones(size(Dk, 1), 1));
158 % Override toString-like display
159 function display(self)
161 fprintf(
'BMAP(phases=%d, maxBatchSize=%d)\n', ...
162 self.getNumberOfPhases(), self.getMaxBatchSize());
165 % Get distribution name
166 function name = getName(self)
169 % Returns the name of
this distribution type
173 % Sample from BMAP (returns inter-arrival times and batch sizes)
174 function [X, B] = sample(self, n)
177 % Sample n batches from the BMAP
179 % X: inter-arrival times (between batches)
180 % B: batch sizes
for each arrival
186 % Use parent MarkedMAP sampling
187 % This returns inter-arrival times and
class labels
188 [X, C] = sample@MarkedMAP(self, n);
190 % Convert
class labels to batch sizes
191 % Class k corresponds to batch size k
195 % Sample only inter-batch times
196 function X = sampleInterBatch(self, n)
197 % X = SAMPLEINTERBATCH(N)
199 % Sample n inter-batch arrival times
200 % (ignoring batch sizes)
206 % Sample from aggregate MAP
211 % Get inter-batch MAP
212 function
map = getInterBatchMAP(self)
213 % MAP = GETINTERBATCHMAP()
215 % Returns the underlying MAP
for inter-batch arrivals
221 % Factory method: create BMAP from MAP + batch size distribution
222 function bmap = fromMAPWithBatchPMF(D0, D1, batchSizes, pmf)
223 % BMAP = FROMMAPWITHBATCHPMF(D0, D1, BATCHSIZES, PMF)
225 % Create BMAP from a base MAP and batch size distribution
228 % D0: base MAP
's D0 matrix (transitions without batch arrivals)
229 % D1: base MAP's D1 matrix (inter-batch arrival transitions)
230 % batchSizes: array of batch sizes (e.g., [1, 2, 4, 8])
231 % pmf: probability mass function
for batch sizes (must sum to 1)
234 % bmap: BMAP constructed from the base MAP and batch distribution
236 if length(batchSizes) ~= length(pmf)
237 line_error(mfilename,
'Batch sizes and PMF must have the same length');
241 pmf = pmf / sum(pmf);
243 % Find maximum batch size
244 maxBatch = max(batchSizes);
246 % Create D matrices: Dk = D1 * pmf(batchSize==k)
247 D = cell(1, maxBatch + 1);
250 % Initialize Dk matrices to zero
252 D{1+k} = zeros(size(D0));
255 % Set Dk based on batch sizes and PMF
256 for i = 1:length(batchSizes)
258 if k < 1 || k > maxBatch
259 line_error(mfilename, sprintf(
'Invalid batch size: %d', k));
261 D{1+k} = D{1+k} + D1 * pmf(i);
268 % Generate random BMAP
269 function bmap = rand(order, maxBatchSize)
270 % BMAP = RAND(ORDER, MAXBATCHSIZE)
272 % Generate random BMAP
using uniform random numbers
275 % order: number of phases (
default: 2)
276 % maxBatchSize: maximum batch size (default: 3)
285 % Generate random MarkedMAP and interpret as BMAP
286 mmap = MarkedMAP.rand(order, maxBatchSize);
288 % Convert to BMAP format
289 D = cell(1, maxBatchSize + 1);
290 D{1} = mmap.D(0); % D0
291 for k = 1:maxBatchSize
292 D{1+k} = mmap.D(1, k-1); % Dk