LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
qsys_mm1k_loss.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_MM1K_LOSS_H
6#define LINE_API_QSYS_QSYS_MM1K_LOSS_H
7
8/**
9 * @file
10 * @ingroup api_qsys
11 * Blocking probability of the M/M/1/K queue.
12 *
13 * Templated port of matlab/src/api/qsys/qsys_mm1k_loss.m, cross-checked
14 * against jar/src/main/java/jline/api/qsys/Qsys_mm1k_loss.java (identical).
15 *
16 * rho = lambda/mu
17 * Ploss = (1-rho)/(1-rho^(K+1)) * rho^K
18 *
19 * Only integer powers appear, so this is exact for T = Rational. It is the
20 * closed form the Niu-Cooper transform-free M/G/1/K analysis collapses onto
21 * when the service is exponential, and qsys_mg1k_loss must reproduce it.
22 *
23 * The formula has a removable singularity at rho = 1, where the true value is
24 * 1/(K+1): the stationary law is uniform over 0..K, so the full state carries
25 * 1/(K+1) like every other. Return the limit there, as MATLAB, the JAR and
26 * python do; do not raise. It is a rational, so exact for T = Rational too.
27 */
28
29#include <cmath>
30
33#include "line/num/number.h"
34#include "line/util/error.h"
35
36namespace line {
37namespace qsys {
38
39template <class T>
42 T utilization; ///< rho = lambda/mu, the offered load (not the carried one)
43};
44
45/**
46 * @brief Blocking probability of the M/M/1/K queue.
47 *
48 * @param lambda arrival rate
49 * @param mu service rate
50 * @param K system capacity, jobs in service included, K >= 1
51 */
52template <class T>
53Mm1kLossResult<T> qsys_mm1k_loss(const T& lambda, const T& mu, unsigned K) {
54 if (K == 0) throw InputError("qsys_mm1k_loss: K must be at least 1");
55 const T one = num_traits<T>::from_int(1);
56 const T rho = lambda / mu;
58 r.utilization = rho;
59 // The removable singularity, taken as the reference takes it. The tolerance
60 // matches qsys_mm1k_loss.m; on an exact T the subtraction is exact and the
61 // test fires only at rho = 1 itself.
62 if (std::fabs(num_traits<T>::to_double(rho) - 1.0) < lang::GlobalConstants::FineTol) {
63 r.lossProbability = one / num_traits<T>::from_int(static_cast<int>(K) + 1);
64 return r;
65 }
66 r.lossProbability = (one - rho) / (one - num_pow_int(rho, K + 1)) * num_pow_int(rho, K);
67 return r;
68}
69
70} // namespace qsys
71} // namespace line
72
73#endif // LINE_API_QSYS_QSYS_MM1K_LOSS_H
InputError(const std::string &what)
Definition error.h:105
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
Mm1kLossResult< T > qsys_mm1k_loss(const T &lambda, const T &mu, unsigned K)
Blocking probability of the M/M/1/K queue.
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52
T num_pow_int(const T &base, unsigned e)
Integer power, valid in any field (no transcendental requirement).
Definition number.h:204
Number-type abstraction for the templated API port.
Shared return type and arithmetic helpers for the templated qsys port.
static constexpr double FineTol
Definition lang_types.h:765
T utilization
rho = lambda/mu, the offered load (not the carried one)