LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
qsys_mmck.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_MMCK_H
6
#define LINE_API_QSYS_QSYS_MMCK_H
7
8
/**
9
* @file
10
* @ingroup api_qsys
11
* Exact analysis of the M/M/c/K queue (truncated Erlang form).
12
*
13
* Templated port of matlab/src/api/qsys/qsys_mmck.m, cross-checked against
14
* jar/src/main/java/jline/api/qsys/Qsys_mmck.java.
15
*
16
* a = lambda/mu, rho = a/c
17
* p_n = a^n/n! p_0 0 <= n <= c
18
* p_n = a^c/c! rho^(n-c) p_0 c <= n <= K
19
* p_0 = 1 / [ sum_{n<c} a^n/n! + (a^c/c!) sum_{n=0}^{K-c} rho^n ]
20
*
21
* All exponents are integers and the normalization is a finite sum, so the
22
* whole computation stays in the field of the inputs and is exact for
23
* T = Rational. The exact instantiation is not academic here: MATLAB builds
24
* the unnormalized vector as a^n/n! and warns about overflow, which is the
25
* failure mode for large a and K; in rational arithmetic the intermediate
26
* magnitudes are irrelevant.
27
*
28
* Unlike the unbounded M/M/c, no stability condition is needed: a finite
29
* capacity makes every load admissible, rho >= 1 included.
30
*/
31
32
#include <cstddef>
33
#include <vector>
34
35
#include "
line/api/qsys/qsys_types.h
"
36
#include "
line/num/number.h
"
37
#include "
line/util/error.h
"
38
39
namespace
line
{
40
namespace
qsys
{
41
42
template
<
class
T>
43
struct
MmckResult
{
44
T
meanQueueLength
;
///< L, mean number in system
45
T
meanQueueLengthQ
;
///< Lq, mean number waiting
46
T
meanWaitingTime
;
///< Wq = Lq/lambda_eff
47
T
meanSojournTime
;
///< W = L /lambda_eff
48
T
utilization
;
///< per-server utilization lambda_eff/(c mu)
49
T
throughput
;
///< lambda_eff = lambda (1 - p_K)
50
T
lossProbability
;
///< p_K
51
std::vector<T>
queueLengthDist
;
///< p_0 ... p_K
52
};
53
54
/**
55
* @brief Exact analysis of the M/M/c/K queue (truncated Erlang form).
56
*
57
* @param lambda Poisson arrival rate
58
* @param mu exponential service rate of one server
59
* @param c number of servers, c >= 1
60
* @param K system capacity, K >= c
61
*/
62
template
<
class
T>
63
MmckResult<T>
qsys_mmck
(
const
T& lambda,
const
T& mu,
unsigned
c,
unsigned
K) {
64
const
T zero =
num_traits<T>::from_int
(0), one =
num_traits<T>::from_int
(1);
65
if
(lambda <= zero)
throw
InputError
(
"qsys_mmck: lambda must be a positive real scalar"
);
66
if
(mu <= zero)
throw
InputError
(
"qsys_mmck: mu must be a positive real scalar"
);
67
if
(c < 1)
throw
InputError
(
"qsys_mmck: c must be a positive integer"
);
68
if
(K < c)
throw
InputError
(
"qsys_mmck: K must be an integer >= c"
);
69
70
const
T a = lambda / mu;
71
const
T rho = a /
num_traits<T>::from_int
(
static_cast<
long
>
(c));
72
73
std::vector<T> p(K + 1, zero);
74
for
(
unsigned
n = 0; n < c; ++n) p[n] =
num_pow_int
(a, n) /
num_factorial<T>
(n);
75
const
T ac_over_cfact =
num_pow_int
(a, c) /
num_factorial<T>
(c);
76
for
(
unsigned
n = c; n <= K; ++n) p[n] = ac_over_cfact *
num_pow_int
(rho, n - c);
77
78
T S = zero;
79
for
(
const
T& v : p) S += v;
80
if
(S <= zero)
throw
NumericError
(
"qsys_mmck: stationary distribution failed to normalize"
);
81
for
(T& v : p) v /= S;
82
83
MmckResult<T>
r;
84
r.
queueLengthDist
= p;
85
T L = zero, Lq = zero;
86
for
(
unsigned
n = 0; n <= K; ++n) {
87
L +=
num_traits<T>::from_int
(
static_cast<
long
>
(n)) * p[n];
88
if
(n > c) Lq +=
num_traits<T>::from_int
(
static_cast<
long
>
(n - c)) * p[n];
89
}
90
r.
meanQueueLength
= L;
91
r.
meanQueueLengthQ
= Lq;
92
r.
lossProbability
= p[K];
93
const
T lambdaEff = lambda * (one - p[K]);
94
r.
throughput
= lambdaEff;
95
r.
utilization
= lambdaEff / (
num_traits<T>::from_int
(
static_cast<
long
>
(c)) * mu);
96
if
(lambdaEff > zero) {
97
r.
meanWaitingTime
= Lq / lambdaEff;
98
r.
meanSojournTime
= L / lambdaEff;
99
}
else
{
100
r.
meanWaitingTime
= zero;
101
r.
meanSojournTime
= zero;
102
}
103
return
r;
104
}
105
106
}
// namespace qsys
107
}
// namespace line
108
109
#endif
// LINE_API_QSYS_QSYS_MMCK_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
line::NumericError::NumericError
NumericError(const std::string &what)
Definition
error.h:45
error.h
The exception types the port throws.
line::qsys
Definition
qsys_bmapm1.h:58
line::qsys::qsys_mmck
MmckResult< T > qsys_mmck(const T &lambda, const T &mu, unsigned c, unsigned K)
Exact analysis of the M/M/c/K queue (truncated Erlang form).
Definition
qsys_mmck.h:63
line
Definition
aoi_dist2ph.h:52
line::num_factorial
T num_factorial(unsigned n)
Factorial as a value of T.
Definition
number.h:184
line::num_pow_int
T num_pow_int(const T &base, unsigned e)
Integer power, valid in any field (no transcendental requirement).
Definition
number.h:192
number.h
Number-type abstraction for the templated API port.
qsys_types.h
Shared return type and arithmetic helpers for the templated qsys port.
line::num_traits
Definition
number.h:111
line::qsys::MmckResult
Definition
qsys_mmck.h:43
line::qsys::MmckResult::queueLengthDist
std::vector< T > queueLengthDist
p_0 ... p_K
Definition
qsys_mmck.h:51
line::qsys::MmckResult::meanWaitingTime
T meanWaitingTime
Wq = Lq/lambda_eff.
Definition
qsys_mmck.h:46
line::qsys::MmckResult::meanQueueLengthQ
T meanQueueLengthQ
Lq, mean number waiting.
Definition
qsys_mmck.h:45
line::qsys::MmckResult::meanQueueLength
T meanQueueLength
L, mean number in system.
Definition
qsys_mmck.h:44
line::qsys::MmckResult::utilization
T utilization
per-server utilization lambda_eff/(c mu)
Definition
qsys_mmck.h:48
line::qsys::MmckResult::meanSojournTime
T meanSojournTime
W = L /lambda_eff.
Definition
qsys_mmck.h:47
line::qsys::MmckResult::lossProbability
T lossProbability
p_K
Definition
qsys_mmck.h:50
line::qsys::MmckResult::throughput
T throughput
lambda_eff = lambda (1 - p_K)
Definition
qsys_mmck.h:49
include
line
api
qsys
qsys_mmck.h
Generated by
1.18.0