LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
pfqn_ble.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_PFQN_PFQN_BLE_H
6
#define LINE_API_PFQN_PFQN_BLE_H
7
8
/**
9
* @file
10
* @ingroup api_pfqn
11
* Logistic expansion with the eps->0 bias correction (BLE).
12
*
13
* Templated port of matlab/src/api/pfqn/pfqn_ble.m. Cas17 Theorem 4.1 holds for
14
* eps >= eps_N > 0; the K(1+eps*N) self-looping populations are what make the
15
* integrand concentrate. Evaluated at eps->0, as pfqn_le does, the curvature at
16
* the saddle tends to 1 rather than growing with N, so Laplace's method has no
17
* asymptotic regime there and carries an O(1) relative bias of e/sqrt(2 pi) PER
18
* LAPLACED DIRECTION. The count is the exponent on sqrt(2 pi) in the branch
19
* taken: M-1 with Z = 0, where the radial integral is exact as Gamma(N+M), and M
20
* with Z > 0, where the radius is Laplaced too. Measured over the 1562 models of
21
* the Cas17 dataset (Zenodo 546873, sec5.3.1, sigma = 100) the Z > 0 deficit is M
22
* to within 0.01 units. The published expansion is NOT in error and the
23
* correction is EMPIRICAL, not part of Cas17; see _kb/03-api-layer.md.
24
*
25
* ARITHMETIC. Inherited from pfqn_le: the correction is a logarithm, so the
26
* routine is gated on num_traits<T>::has_transcendental for the same reason.
27
*
28
* DEGENERATE BRANCH. When there is no queueing station to expand around, pfqn_le
29
* returns the exact delay term and there is no Laplace step to correct, so
30
* pfqn_ble returns it unchanged; this is the MATLAB branching.
31
*/
32
33
#include <cmath>
34
#include <cstddef>
35
#include <vector>
36
37
#include "
line/api/pfqn/pfqn_le.h
"
38
#include "
line/lang/lang_types.h
"
39
#include "
line/num/number.h
"
40
#include "
line/util/matrix.h
"
41
42
namespace
line
{
43
namespace
pfqn
{
44
45
/** Return value of pfqn_ble, mirroring [Gn, lGn]. */
46
template
<
class
T>
47
using
BleResult
=
LeResult<T>
;
48
49
/**
50
* Logistic expansion estimate of the normalizing constant, bias-corrected.
51
*
52
* @param L (M x R) demands, @param N (R) population, @param Z (R) think times
53
* (pass an empty vector or all zeros for the Z = 0 branch)
54
*/
55
template
<
class
T>
56
BleResult<T>
pfqn_ble
(
const
Matrix<T>
& L,
const
std::vector<T>& N,
const
std::vector<T>& Z) {
57
static_assert
(
num_traits<T>::has_transcendental
,
58
"pfqn_ble requires transcendental arithmetic (Laplace approximation of an integral)"
);
59
using
std::exp;
60
using
std::log;
61
const
std::size_t M = L.
rows
(), R = L.
cols
();
62
const
T zero =
num_traits<T>::from_int
(0);
63
64
BleResult<T>
res =
pfqn_le
(L, N, Z);
65
66
T Ntot = zero, Lsum = zero, Zsum = zero;
67
for
(
const
T& x : N) Ntot += x;
68
for
(
const
T& x : Z) Zsum += x;
69
for
(std::size_t i = 0; i < M; ++i)
70
for
(std::size_t r = 0; r < R; ++r) Lsum += L(i, r);
71
if
(M == 0 || N.empty() || Ntot == zero ||
num_traits<T>::to_double
(Lsum) < 1e-4) {
72
return
res;
73
}
74
75
// Same predicate pfqn_le branches on, so the count always matches the branch.
76
const
bool
no_delay =
77
Z.empty() ||
num_traits<T>::to_double
(Zsum) <
lang::GlobalConstants::Zero
;
78
const
long
n_gauss =
static_cast<
long
>
(M) - (no_delay ? 1 : 0);
79
const
T twopi =
num_traits<T>::from_double
(6.283185307179586476925286766559);
80
res.
lG
+=
num_traits<T>::from_int
(n_gauss) *
81
T(
num_traits<T>::from_int
(1) - log(twopi) /
num_traits<T>::from_int
(2));
82
res.
G
= exp(res.
lG
);
83
return
res;
84
}
85
86
template
<
class
T>
87
BleResult<T>
pfqn_ble
(
const
Matrix<T>
& L,
const
std::vector<T>& N) {
88
return
pfqn_ble
(L, N, std::vector<T>());
89
}
90
91
}
// namespace pfqn
92
}
// namespace line
93
94
#endif
// LINE_API_PFQN_PFQN_BLE_H
line::Matrix
Definition
matrix.h:56
line::Matrix::cols
std::size_t cols() const
Definition
matrix.h:90
line::Matrix::rows
std::size_t rows() const
Definition
matrix.h:89
lang_types.h
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
matrix.h
Dense matrix and non-owning view.
line::pfqn
Definition
cd_peak_scaling.h:43
line::pfqn::pfqn_ble
BleResult< T > pfqn_ble(const Matrix< T > &L, const std::vector< T > &N, const std::vector< T > &Z)
Logistic expansion estimate of the normalizing constant, bias-corrected.
Definition
pfqn_ble.h:56
line::pfqn::BleResult
LeResult< T > BleResult
Return value of pfqn_ble, mirroring [Gn, lGn].
Definition
pfqn_ble.h:47
line::pfqn::pfqn_le
LeResult< T > pfqn_le(const Matrix< T > &L, const std::vector< T > &N, const std::vector< T > &Z)
Logistic expansion estimate of the normalizing constant.
Definition
pfqn_le.h:245
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
pfqn_le.h
Logistic expansion (LE) asymptotic approximation of the normalizing constant of a closed product-form...
line::lang::GlobalConstants::Zero
static constexpr double Zero
Definition
lang_types.h:670
line::num_traits
Definition
number.h:111
line::pfqn::LeResult
Return value of pfqn_le, mirroring [Gn, lGn].
Definition
pfqn_le.h:233
line::pfqn::LeResult::lG
T lG
Definition
pfqn_le.h:235
line::pfqn::LeResult::G
T G
Definition
pfqn_le.h:234
include
line
api
pfqn
pfqn_ble.h
Generated by
1.18.0