LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
pfqn_bkt.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_BKT_H
6
#define LINE_API_PFQN_PFQN_BKT_H
7
8
/**
9
* @file
10
* @ingroup api_pfqn
11
* Knessl-Tier expansion with the Stirling-remainder correction (BKT).
12
*
13
* Templated port of matlab/src/api/pfqn/pfqn_bkt.m. pfqn_kt extracts N from the
14
* generating function of G by steepest descent on
15
*
16
* F(xi) = sum_r Z_r xi_r - sum_k log(1 - U_k) - sum_r N_r log xi_r, U = L xi.
17
*
18
* On the demand-free integral the exact coefficient is [xi^N] exp(Z xi) = Z^N/N!,
19
* whereas the expansion returns N log Z - (N log N - N + log(2 pi N)/2), which is
20
* Stirling's approximation of log(N!) in place of log(N!). So KT lies ABOVE the
21
* exact value by the remainder
22
*
23
* s(N) = log(N!) - (N log N - N + log(2 pi N)/2)
24
* = lgamma(N+1) - (N + 1/2) log N + N - log(2 pi)/2
25
*
26
* per Laplaced class direction, and BKT subtracts sum_r s(N_r). s(1) is the
27
* constant pfqn_ble adds per STATION direction, and s(N) = 1/(12 N) + O(N^-2);
28
* the remainder is evaluated exactly, since truncating it at 1/(12 N) loses an
29
* order of magnitude (median |error| on the 1562 models of Cas17 sec5.3.1: 0.083
30
* nats for KT, 1.9e-4 for the truncation, 1.4e-5 for the exact remainder). With
31
* a think time BKT is the SAME estimator as pfqn_ble, to the accuracy of the
32
* two saddle-point solvers; without one they differ by the constant
33
* kappa - r(N+M). See _kb/03-api-layer.md.
34
*
35
* WHICH CLASSES. Only the classes pfqn_kt actually Laplaces are corrected: a class
36
* with no jobs is dropped by its recursion, and a self-looping class (one nonzero
37
* demand and no think time, folded only when more than one class remains) has its
38
* coefficient extracted exactly, so neither carries a remainder. The predicate
39
* below is pfqn_kt's own, re-derived here rather than trusting R.
40
*
41
* ARITHMETIC. Inherited from pfqn_kt: gated on num_traits<T>::has_transcendental.
42
*/
43
44
#include <cmath>
45
#include <cstddef>
46
#include <vector>
47
48
#include "
line/api/pfqn/pfqn_asympt_common.h
"
49
#include "
line/api/pfqn/pfqn_kt.h
"
50
#include "
line/num/number.h
"
51
#include "
line/util/matrix.h
"
52
53
namespace
line
{
54
namespace
pfqn
{
55
56
/** Return value of pfqn_bkt, mirroring [Gn, lGn] (X and Q are pfqn_kt's seeds). */
57
template
<
class
T>
58
using
BktResult
=
KtResult<T>
;
59
60
/** s(N) = log(N!) - (N log N - N + log(2 pi N)/2), exactly, for N >= 1. */
61
template
<
class
T>
62
T
pfqn_stirling_remainder
(
const
T& n) {
63
static_assert
(
num_traits<T>::has_transcendental
,
64
"pfqn_stirling_remainder requires transcendental arithmetic"
);
65
using
std::log;
66
const
T half =
num_traits<T>::from_double
(0.5);
67
const
T twopi =
num_traits<T>::from_double
(6.283185307179586476925286766559);
68
return
T(detail::num_factln<T>(n) - (n + half) * log(n) + n - log(twopi) /
num_traits<T>::from_int
(2));
69
}
70
71
/**
72
* @brief Knessl-Tier expansion with the Stirling-remainder correction (BKT).
73
*
74
* @param L (M x R) demands, @param N (R) population, @param Z (R) think times
75
* (pass an empty vector or all zeros for the Z = 0 branch)
76
*/
77
template
<
class
T>
78
BktResult<T>
pfqn_bkt
(
const
Matrix<T>
& L,
const
std::vector<T>& N,
const
std::vector<T>& Z) {
79
static_assert
(
num_traits<T>::has_transcendental
,
80
"pfqn_bkt requires transcendental arithmetic (steepest-descent expansion of log G)"
);
81
using
std::exp;
82
const
T zero =
num_traits<T>::from_int
(0);
83
const
std::size_t M = L.
rows
(), R = L.
cols
();
84
std::vector<T> Zc = Z;
85
if
(Zc.empty()) Zc.assign(R, zero);
86
87
BktResult<T>
res =
pfqn_kt
(L, N, Zc);
88
89
std::size_t nkeep = 0;
90
for
(std::size_t r = 0; r < R; ++r)
91
if
(N[r] > zero) ++nkeep;
92
T corr = zero;
93
for
(std::size_t r = 0; r < R; ++r) {
94
if
(!(N[r] > zero))
continue
;
// dropped by pfqn_kt's recursion
95
if
(nkeep > 1) {
// pfqn_kt folds self-loops only with Rorig > 1
96
std::size_t nnz = 0;
97
for
(std::size_t i = 0; i < M; ++i)
98
if
(L(i, r) != zero) ++nnz;
99
if
(nnz == 1 && Zc[r] == zero)
continue
;
// extracted exactly, no remainder
100
}
101
corr +=
pfqn_stirling_remainder<T>
(N[r]);
102
}
103
res.
lG
-= corr;
104
res.
G
= exp(res.
lG
);
105
return
res;
106
}
107
108
template
<
class
T>
109
BktResult<T>
pfqn_bkt
(
const
Matrix<T>
& L,
const
std::vector<T>& N) {
110
return
pfqn_bkt
(L, N, std::vector<T>());
111
}
112
113
}
// namespace pfqn
114
}
// namespace line
115
116
#endif
// LINE_API_PFQN_PFQN_BKT_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
matrix.h
Dense matrix and non-owning view.
line::pfqn
Definition
cd_peak_scaling.h:43
line::pfqn::pfqn_bkt
BktResult< T > pfqn_bkt(const Matrix< T > &L, const std::vector< T > &N, const std::vector< T > &Z)
Knessl-Tier expansion with the Stirling-remainder correction (BKT).
Definition
pfqn_bkt.h:78
line::pfqn::pfqn_stirling_remainder
T pfqn_stirling_remainder(const T &n)
s(N) = log(N!) - (N log N - N + log(2 pi N)/2), exactly, for N >= 1.
Definition
pfqn_bkt.h:62
line::pfqn::pfqn_kt
KtResult< T > pfqn_kt(const Matrix< T > &L0, const std::vector< T > &N0, const std::vector< T > &Z0)
Knessl-Tier asymptotic expansion of the normalizing constant.
Definition
pfqn_kt.h:71
line::pfqn::BktResult
KtResult< T > BktResult
Return value of pfqn_bkt, mirroring [Gn, lGn] (X and Q are pfqn_kt's seeds).
Definition
pfqn_bkt.h:58
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
pfqn_asympt_common.h
Shared scalar machinery for the integration / asymptotic members of the pfqn family (pfqn_le,...
pfqn_kt.h
Knessl-Tier asymptotic expansion of the normalizing constant.
line::num_traits
Definition
number.h:111
line::pfqn::KtResult
Return value of pfqn_kt, mirroring [G, lG, X, Q].
Definition
pfqn_kt.h:56
line::pfqn::KtResult::G
T G
Definition
pfqn_kt.h:57
line::pfqn::KtResult::lG
T lG
Definition
pfqn_kt.h:58
include
line
api
pfqn
pfqn_bkt.h
Generated by
1.18.0