LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
qbd_bmapbmap1.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_MAM_QBD_BMAPBMAP1_H
6#define LINE_API_MAM_QBD_BMAPBMAP1_H
7
8/**
9 * @file
10 * @ingroup api_mam
11 * Level blocks of a BMAP/MAP/1 queue: batch Markovian arrivals against a
12 * single-departure MAP service process.
13 *
14 * Templated port of matlab/src/api/mam/qbd_bmapbmap1.m. The level is the
15 * number in system and the phase is the pair (arrival phase, service phase)
16 * with the arrival phase major, the same layout as qbd_mapmap1. A batch of
17 * size b raises the level by b, so the process is an M/G/1-type chain rather
18 * than a QBD, with one up-block per batch size:
19 *
20 * A1[b] = (D1^a p_b) (x) I_ns an arrival batch of size b, level up by b
21 * A0 = D0^a (+) D0^s no event
22 * A_1 = I_na (x) D1^s a service completion, level down by one
23 * A0bar = D0^a (x) I_ns level zero, no server busy
24 * B0 = D0^a (+) I_ns level-zero local block
25 * B1[b] = A1[b] level-zero up-blocks
26 *
27 * REFERENCE DEFECT. The MATLAB function declares NO output argument and
28 * assembles the blocks into local variables that are discarded on return; the
29 * commented-out tail of the file shows the intended Q matrix. Calling it
30 * therefore computes the blocks and throws them away, and in a context that
31 * expects a value MATLAB raises "Output argument not assigned". The port
32 * returns the blocks in a struct, which is the only content the function
33 * actually has; nothing else can be inferred from it, in particular no
34 * solution of the chain, because none is written.
35 *
36 * Two further observations on the reference, reproduced rather than repaired:
37 * - despite the name, the SERVICE process is an ordinary MAP: A_1 uses
38 * D1^s with no batch-size distribution, so only the arrivals are batched.
39 * - B0 = krons(D0^a, I_ns) is the Kronecker SUM of D0^a with the identity,
40 * i.e. D0^a (x) I + I (x) I, which adds an unconditional unit rate on the
41 * diagonal of every phase; the analogous boundary block in qbd_mapmap1 is
42 * the Kronecker PRODUCT kron(D0^a, I_ns), which is what A0bar holds here.
43 * Both are returned under their own names so the discrepancy is visible.
44 *
45 * ARITHMETIC. Kronecker products and sums only, so exact at Rational.
46 */
47
48#include <cstddef>
49#include <vector>
50
53#include "line/num/number.h"
54#include "line/util/error.h"
55#include "line/util/linalg.h"
56#include "line/util/matrix.h"
57
58namespace line {
59namespace mam {
60
61/** The level blocks assembled by qbd_bmapbmap1. */
62template <class T>
64 std::vector<Matrix<T>> A1; ///< A1[b-1] is the up-block for a batch of size b
65 Matrix<T> A0; ///< local block
66 Matrix<T> Am1; ///< down-block (A_1 in the reference)
67 Matrix<T> A0bar; ///< kron(D0^a, I_ns)
68 Matrix<T> B0; ///< boundary local block, krons(D0^a, I_ns)
69 std::vector<Matrix<T>> B1; ///< boundary up-blocks, equal to A1
70};
71
72/**
73 * Level blocks of a BMAP/MAP/1 queue.
74 *
75 * @param arrival arrival MAP, whose D1 is split by the batch-size law
76 * @param pbatch batch-size probabilities, pbatch[b-1] = P(batch = b)
77 * @param service service MAP
78 */
79template <class T>
80QbdBmapBmap1Blocks<T> qbd_bmapbmap1(const Map<T>& arrival, const std::vector<T>& pbatch,
81 const Map<T>& service) {
82 const std::size_t na = arrival.order();
83 const std::size_t ns = service.order();
84 if (na == 0 || ns == 0) throw InputError("qbd_bmapbmap1: empty MAP");
85 if (pbatch.empty()) throw InputError("qbd_bmapbmap1: empty batch-size distribution");
86
88 const Matrix<T> Ins = eye<T>(ns);
89 for (std::size_t b = 0; b < pbatch.size(); ++b) {
90 Matrix<T> scaled(na, na);
91 for (std::size_t i = 0; i < na; ++i)
92 for (std::size_t j = 0; j < na; ++j) scaled(i, j) = arrival.D1(i, j) * pbatch[b];
93 out.A1.push_back(kron(scaled, Ins));
94 }
95 out.A0 = krons(arrival.D0, service.D0);
96 out.Am1 = kron(eye<T>(na), service.D1);
97 out.A0bar = kron(arrival.D0, Ins);
98 out.B0 = krons(arrival.D0, Ins);
99 out.B1 = out.A1;
100 return out;
101}
102
103} // namespace mam
104} // namespace line
105
106#endif // LINE_API_MAM_QBD_BMAPBMAP1_H
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
Dense matrix and non-owning view.
Marked MAP (MMAP) algebra: per-class rates, class probabilities, superposition, normalization and sca...
Matrix< T > krons(const Matrix< T > &A, const Matrix< T > &B)
Kronecker sum, MATLAB's krons: kron(A, I_nb) + kron(I_na, B).
Definition mmap_lambda.h:71
Matrix< T > kron(const Matrix< T > &A, const Matrix< T > &B)
Kronecker product.
Definition mmap_lambda.h:57
QbdBmapBmap1Blocks< T > qbd_bmapbmap1(const Map< T > &arrival, const std::vector< T > &pbatch, const Map< T > &service)
Level blocks of a BMAP/MAP/1 queue.
Matrix< T > eye(std::size_t n)
Identity of order n.
Definition linalg.h:28
Number-type abstraction for the templated API port.
A MAP as the pair of matrices (D0, D1).
Definition map_moment.h:53
Matrix< T > D1
Definition map_moment.h:55
Matrix< T > D0
Definition map_moment.h:54
std::size_t order() const
Definition map_moment.h:57
The level blocks assembled by qbd_bmapbmap1.
std::vector< Matrix< T > > A1
A1[b-1] is the up-block for a batch of size b.
Matrix< T > Am1
down-block (A_1 in the reference)
Matrix< T > A0bar
kron(D0^a, I_ns)
Matrix< T > A0
local block
std::vector< Matrix< T > > B1
boundary up-blocks, equal to A1
Matrix< T > B0
boundary local block, krons(D0^a, I_ns)