LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
npfqn_rqna_weight.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_NPFQN_RQNA_WEIGHT_H
6#define LINE_API_NPFQN_RQNA_WEIGHT_H
7
8/**
9 * @file
10 * @ingroup api_npfqn
11 * Canonical reflected-Brownian-motion correlation weight w*(t) used by the
12 * Robust Queueing Network Analyzer (RQNA).
13 *
14 * Templated port of matlab/src/api/npfqn/npfqn_rqna_weight.m, cross-checked
15 * against jar/src/main/java/jline/api/npfqn/Npfqn_rqna_weight.java (identical
16 * term for term, including both numerical guards).
17 *
18 * w*(t) = 1 - (1 - c*(t)) / (2 t)
19 * c*(t) = 2 (1 - 2t - t^2) Phi^c(sqrt(t)) + 2 sqrt(t) phi(sqrt(t)) (1 + t)
20 *
21 * with Phi^c the standard-normal complementary cdf and phi its density. The
22 * weight increases monotonically from w*(0) = 0 to w*(Inf) = 1.
23 * Reference: W. Whitt and W. You (2018), "A Robust Queueing Network Analyzer
24 * Based on Indices of Dispersion", eqs. (24)-(25).
25 *
26 * Arithmetic. Phi^c is an erfc and phi is an exp, neither of which exists in
27 * the field of the inputs, so this requires transcendental arithmetic and
28 * cannot be instantiated at T = Rational.
29 */
30
31#include <vector>
32
34#include "line/num/number.h"
35
36namespace line {
37namespace npfqn {
38
39/**
40 * @brief Canonical reflected-Brownian-motion correlation weight w*(t) used by
41 * the Robust Queueing Network Analyzer (RQNA).
42 *
43 * @param t nonnegative time argument; t <= 0 gives 0 and t = Inf gives 1
44 * @return the weight w*(t), clamped to [0,1] as in MATLAB and the JAR
45 */
46template <class T>
47T npfqn_rqna_weight(const T& t) {
49 "npfqn_rqna_weight requires transcendental arithmetic");
50 const T zero = num_traits<T>::from_int(0);
51 const T one = num_traits<T>::from_int(1);
52 const T two = num_traits<T>::from_int(2);
53
54 if (t <= zero) return zero;
55 if (!detail::num_isfinite(t)) return one;
56
57 const T st = detail::num_sqrt(t);
58 // Phi^c(sqrt(t)) = 0.5 erfc(sqrt(t)/sqrt(2))
59 const T phic = num_traits<T>::from_rational(1, 2) * detail::num_erfc(T(st / detail::num_sqrt(two)));
60 // phi(sqrt(t)) = exp(-t/2)/sqrt(2 pi)
61 const T twopi = two * boost::math::constants::pi<T>();
62 const T phi = detail::num_exp(T(-t / two)) / detail::num_sqrt(twopi);
63 const T cstar = two * (one - two * t - t * t) * phic + two * st * phi * (one + t);
64
65 T w;
66 if (t < num_traits<T>::from_double(1e-6)) {
67 // limit w*(t) -> 0 as t -> 0; taking the difference below would be
68 // catastrophic cancellation there
69 w = zero;
70 } else {
71 w = one - (one - cstar) / (two * t);
72 }
73 // numerical guard: w* is a weight in [0,1]
74 if (w < zero) w = zero;
75 if (w > one) w = one;
76 return w;
77}
78
79/** Elementwise form, mirroring the MATLAB array argument. */
80template <class T>
81std::vector<T> npfqn_rqna_weight(const std::vector<T>& t) {
82 std::vector<T> w(t.size());
83 for (std::size_t i = 0; i < t.size(); ++i) w[i] = npfqn_rqna_weight(t[i]);
84 return w;
85}
86
87} // namespace npfqn
88} // namespace line
89
90#endif // LINE_API_NPFQN_RQNA_WEIGHT_H
T npfqn_rqna_weight(const T &t)
Canonical reflected-Brownian-motion correlation weight w*(t) used by the Robust Queueing Network Anal...
Shared arithmetic helpers for the templated npfqn port.
Number-type abstraction for the templated API port.