LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
qsys_mapmap1.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_QSYS_QSYS_MAPMAP1_H
6
#define LINE_API_QSYS_QSYS_MAPMAP1_H
7
8
/**
9
* @file
10
* @ingroup api_qsys
11
* The MAP/MAP/1 FCFS queue: mean number in system, waiting time, sojourn time,
12
* utilization and the queue-length distribution.
13
*
14
* ALGORITHM, AND HOW IT DIFFERS FROM THE MATLAB REFERENCE.
15
* matlab/src/api/qsys/qsys_mapmap1.m obtains these quantities by calling
16
* BUTools' MMAPPH1FCFS, which is not transcribed here; this port computes the
17
* SAME quantities from the port's own
18
* quasi-birth-death machinery (line/api/mam/qbd_mapmap1.h), which solves the
19
* level-independent QBD whose level is the number in system and whose phase is
20
* the pair (arrival phase, service phase). The algorithm is therefore
21
* different, the quantity is the same.
22
*
23
* The reference does one further thing this port deliberately does not. Before
24
* calling BUTools it replaces the service MAP (D0,D1) by the phase-type
25
* distribution
26
*
27
* sigma = theta D1 / (theta D1 e), S = D0, theta (D0+D1) = 0,
28
*
29
* i.e. by the stationary marginal of a service time. That embedded PH keeps the
30
* service-time MARGINAL exactly but DISCARDS the serial correlation between
31
* consecutive service times, so the reference solves a MAP/PH/1 queue in place
32
* of the MAP/MAP/1 queue it names. The two coincide exactly when the service
33
* MAP is a renewal process (D1 = (-D0 e) sigma, which includes every PH-renewal
34
* service), and diverge otherwise. This port solves the genuine MAP/MAP/1 QBD,
35
* so on a correlated service MAP it does not agree with the reference and is
36
* not meant to: see the measured numbers below.
37
*
38
* MEASURED AGREEMENT (MATLAB R2025a, T = double). Metric order is
39
* meanQueueLength / meanWaitingTime / meanSojournTime / utilization. Arrival
40
* MAPs used below:
41
* P(2) = Poisson, D0 = [-2], D1 = [2]
42
* C = correlated MMPP2, D0 = [-2.5 0.2; 0.1 -0.7], D1 = diag(2.3, 0.6),
43
* lambda = 7/6
44
*
45
* 1. M/M/1 collapse, qsys_mapmap1(P(2), service D0 = [-3], D1 = [3]). MATLAB
46
* 1.999999999999999 / 0.6666666666666656 / 0.9999999999999989 /
47
* 0.6666666666666666; port 2 / 0.666666666666668 / 1 / 0.666666666666667,
48
* the textbook values. Relative differences 5e-16, 1.8e-15, 1.1e-15.
49
*
50
* 2. Renewal service, where the reference's PH reduction is exact. Arrival C,
51
* service the Erlang-2 renewal MAP D0 = [-6 6; 0 -6], D1 = [0 0; 6 0].
52
* MATLAB 0.8364637529649164 / 0.3836355977794533 / 0.7169689311127866 /
53
* 0.3888888888888888; port 0.836463752964917 / 0.383635597779453 /
54
* 0.716968931112786 / 0.388888888888889. Relative differences below 1e-15
55
* on every metric: with a renewal service the two model the same system and
56
* the port reproduces the reference to machine precision.
57
*
58
* 3. Correlated service, where the reference's PH reduction is NOT exact.
59
* Arrival C, service MAP D0 = [-5 0.4; 0.2 -1.4], D1 = diag(4.6, 1.2)
60
* (lambda_s = 7/3, so rho = 1/2). MATLAB qsys_mapmap1 reports
61
* 2.0305355320573 / 1.311887598906254 / 1.740459027477683 / 0.5; this port
62
* returns 2.54755753480255 / 1.75504931554505 / 2.18362074411647 / 0.5,
63
* relative differences of 2.03e-1, 2.53e-1 and 2.03e-1. The port's value is
64
* the correct MAP/MAP/1 answer: LINE's own MATLAB qbd_mapmap1 on the
65
* identical pair of MAPs returns QN = 2.547554867631855, UN =
66
* 0.5000000000000002 and RN = 2.183618457970162, i.e. the port to within
67
* 1.05e-6. That residual 1.05e-6 is MATLAB qbd_mapmap1's truncated level
68
* sum, which stops once the accumulated mass reaches 1 - 1e-10 and so
69
* discards the tail times its level index; this port sums the geometric
70
* tail in closed form (see qbd_mapmap1.h). The 20% gap against
71
* qsys_mapmap1.m is a different thing entirely: it is the service
72
* correlation the reference's PH reduction throws away.
73
*
74
* meanWaitingTime is meanSojournTime minus the mean service time 1/lambda_s,
75
* and utilization is lambda_a/lambda_s, both matching the reference's own
76
* definitions.
77
*
78
* ARITHMETIC. The function is gated on num_traits<T>::has_transcendental
79
* because qbd_mapmap1 reaches R by cyclic reduction, a fixed-point iteration
80
* driven to a tolerance that does not terminate in a finite number of field
81
* operations; running it at exact rational arithmetic would produce a rational
82
* with a denominator doubling every step and still not the exact R. See
83
* qbd_r.h. Everything downstream of R here -- the mean, the level
84
* probabilities, the Little's-law conversions -- is finite exact matrix
85
* algebra and carries no additional error.
86
*/
87
88
#include <cstddef>
89
#include <vector>
90
91
#include "
line/api/mam/map_moment.h
"
92
#include "
line/api/mam/qbd_mapmap1.h
"
93
#include "
line/api/mam/qbd_r.h
"
94
#include "
line/num/number.h
"
95
#include "
line/util/error.h
"
96
#include "
line/util/matrix.h
"
97
98
namespace
line
{
99
namespace
qsys
{
100
101
/**
102
* Return value of the MAP/MAP/1 family (qsys_mapmap1, qsys_mapph1, qsys_phph1),
103
* carrying the same quantities as the MATLAB result struct.
104
*/
105
template
<
class
T>
106
struct
MapMap1Result
{
107
T
meanQueueLength
;
///< E[N], number in system
108
T
meanWaitingTime
;
///< E[Wq], time in queue
109
T
meanSojournTime
;
///< E[W] = E[Wq] + E[S]
110
T
utilization
;
///< rho = lambda_a / lambda_s
111
std::vector<T>
queueLengthDist
;
///< P(N = n), n = 0, 1, ...
112
};
113
114
/**
115
* MAP/MAP/1 by the exact QBD solution.
116
*
117
* @param arrival arrival MAP (D0, D1)
118
* @param service service MAP (D0, D1); its correlation IS honoured
119
* @param dist_size how many entries of queueLengthDist to materialize
120
*/
121
template
<
class
T>
122
MapMap1Result<T>
qsys_mapmap1
(
const
mam::Map<T>
& arrival,
const
mam::Map<T>
& service,
123
std::size_t dist_size) {
124
static_assert
(
num_traits<T>::has_transcendental
,
125
"qsys_mapmap1 requires transcendental arithmetic"
);
126
if
(dist_size == 0)
throw
InputError
(
"qsys_mapmap1: dist_size must be positive"
);
127
const
T zero =
num_traits<T>::from_int
(0);
128
const
mam::QbdMapMap1Result<T>
q =
mam::qbd_mapmap1
(arrival, service, T(zero), dist_size);
129
130
const
T lambda_a =
mam::map_lambda
(arrival);
131
const
T lambda_s =
mam::map_lambda
(service);
132
const
T mean_service =
num_traits<T>::from_int
(1) / lambda_s;
133
134
MapMap1Result<T>
r;
135
r.
meanQueueLength
= q.
QN
;
136
r.
meanSojournTime
= q.
QN
/ lambda_a;
137
r.
meanWaitingTime
= r.
meanSojournTime
- mean_service;
138
r.
utilization
= lambda_a / lambda_s;
139
r.
queueLengthDist
.assign(q.
pqueue
.rows(), zero);
140
for
(std::size_t k = 0; k < q.
pqueue
.rows(); ++k) {
141
T s = zero;
142
for
(std::size_t j = 0; j < q.
pqueue
.cols(); ++j) s += q.
pqueue
(k, j);
143
r.
queueLengthDist
[k] = s;
144
}
145
return
r;
146
}
147
148
/** qsys_mapmap1 with 100 materialized levels, the reference's numQLProbs. */
149
template
<
class
T>
150
MapMap1Result<T>
qsys_mapmap1
(
const
mam::Map<T>
& arrival,
const
mam::Map<T>
& service) {
151
return
qsys_mapmap1
(arrival, service,
static_cast<
std::size_t
>
(100));
152
}
153
154
}
// namespace qsys
155
}
// namespace line
156
157
#endif
// LINE_API_QSYS_QSYS_MAPMAP1_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
error.h
The exception types the port throws.
map_moment.h
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
matrix.h
Dense matrix and non-owning view.
line::mam::qbd_mapmap1
QbdMapMap1Result< T > qbd_mapmap1(const Map< T > &arrival, const Map< T > &service_in, const T &util, std::size_t max_levels)
MAP/MAP/1 queue (qbd_mapmap1.m).
Definition
qbd_mapmap1.h:201
line::mam::map_lambda
T map_lambda(const Map< T > &m)
Stationary arrival rate, lambda = pi D1 e.
Definition
map_moment.h:79
line::qsys
Definition
qsys_bmapm1.h:58
line::qsys::qsys_mapmap1
MapMap1Result< T > qsys_mapmap1(const mam::Map< T > &arrival, const mam::Map< T > &service, std::size_t dist_size)
MAP/MAP/1 by the exact QBD solution.
Definition
qsys_mapmap1.h:122
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
qbd_mapmap1.h
The MAP/MAP/1 queue solved as a quasi-birth-death process.
qbd_r.h
Quasi-birth-death processes: the rate matrix R, the fundamental matrix G, the caudal characteristic,...
line::mam::Map
A MAP as the pair of matrices (D0, D1).
Definition
map_moment.h:53
line::mam::QbdMapMap1Result
Result of qbd_mapmap1, mirroring the MATLAB return list.
Definition
qbd_mapmap1.h:170
line::mam::QbdMapMap1Result::QN
T QN
mean number in system, closed form
Definition
qbd_mapmap1.h:172
line::mam::QbdMapMap1Result::pqueue
Matrix< T > pqueue
level distribution, row k = pi_k
Definition
qbd_mapmap1.h:176
line::num_traits
Definition
number.h:111
line::qsys::MapMap1Result
Return value of the MAP/MAP/1 family (qsys_mapmap1, qsys_mapph1, qsys_phph1), carrying the same quant...
Definition
qsys_mapmap1.h:106
line::qsys::MapMap1Result::utilization
T utilization
rho = lambda_a / lambda_s
Definition
qsys_mapmap1.h:110
line::qsys::MapMap1Result::meanQueueLength
T meanQueueLength
E[N], number in system.
Definition
qsys_mapmap1.h:107
line::qsys::MapMap1Result::meanSojournTime
T meanSojournTime
E[W] = E[Wq] + E[S].
Definition
qsys_mapmap1.h:109
line::qsys::MapMap1Result::queueLengthDist
std::vector< T > queueLengthDist
P(N = n), n = 0, 1, ...
Definition
qsys_mapmap1.h:111
line::qsys::MapMap1Result::meanWaitingTime
T meanWaitingTime
E[Wq], time in queue.
Definition
qsys_mapmap1.h:108
include
line
api
qsys
qsys_mapmap1.h
Generated by
1.18.0