LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
sn_patience_handles.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_SN_SN_PATIENCE_HANDLES_H
6#define LINE_API_SN_SN_PATIENCE_HANDLES_H
7
8/**
9 * @file
10 * @ingroup api_sn
11 * Port of matlab/src/api/sn/sn_patience_handles.m.
12 *
13 * The abandonment solvers need the patience law as FUNCTIONS -- a complementary
14 * cdf and a hazard rate -- not as moments, because that is what the underlying
15 * theory consumes: Whitt's engineering solution reads the hazard near the
16 * origin, and the fluid models integrate the ccdf. This port reads the law from
17 * `Station::patience`, which holds the distribution itself rather than the
18 * (D0,D1) pair the MATLAB and Java structs carry.
19 *
20 * ARITHMETIC: transcendental. The ccdf of a phase-type law is a matrix
21 * exponential.
22 */
23
24#include <cmath>
25#include <cstddef>
26#include <functional>
27#include <limits>
28
36#include "line/num/number.h"
37
38namespace line {
39namespace api {
40
41/** The patience law of one station-class pair, in the forms the solvers consume. */
42template <class T>
44 /** Whether the pair declares reneging at all; everything below is unset when false. */
45 bool present = false;
46 /** F^c(t) = P(patience > t). */
47 std::function<T(const T&)> ccdf;
48 /** The patience density. */
49 std::function<T(const T&)> pdf;
50 /** The hazard rate h = f/(1-F). */
51 std::function<T(const T&)> hazard;
52 /** Mean patience. */
54 /** Whether the law is exponential, in which case the analysis is exact. */
55 bool isExponential = false;
56 /** The abandonment rate 1/mean. */
58
59 /** This law as the `Patience` argument of the abandonment solvers. */
64};
65
66/**
67 * Build the patience handles of station `ist` (0-based), class `r`.
68 *
69 * Returns a handle set with `present == false` when the pair declares no
70 * reneging patience.
71 */
72template <class T>
74 std::size_t r) {
76 if (ist >= sn.nstations || r >= sn.nclasses) return h;
77 const qn::Station<T>& st = sn.stations[ist];
78 if (r >= st.impatience.size() || st.impatience[r] != lang::ImpatienceType::RENEGING) return h;
79 if (r >= st.patience.size() || st.patience[r].disabled) return h;
80
81 const lang::Distrib<T>& d = st.patience[r];
82 const T zero = num_traits<T>::from_int(0);
83 const T one = num_traits<T>::from_int(1);
84 (void)one;
85 h.present = true;
86 h.mean = d.mean;
87 h.rate = d.mean > zero ? T(one / d.mean) : zero;
89
90 // WHAT IS AVAILABLE UNDER EXACT ARITHMETIC, and what is not. Whether the
91 // pair reneges, at what rate and under which family are all read off the
92 // struct, so `present`, `mean`, `rate` and `isExponential` are answered for
93 // every T -- which is what lets the method list and the method resolution
94 // run under Rational. The ccdf and the hazard are a matrix exponential, so
95 // they exist only where the arithmetic has one; the abandonment methods
96 // themselves are refused by name before they are ever called.
98 if (h.isExponential) {
99 const T theta = h.rate;
100 h.ccdf = [theta](const T& t) { return qsys::detail::num_exp(T(-theta * t)); };
101 h.pdf = [theta](const T& t) { return T(theta * qsys::detail::num_exp(T(-theta * t))); };
102 h.hazard = [theta](const T&) { return theta; };
103 return h;
104 }
105
106 const mam::Map<T> m = lang::dist_to_map(d);
107 h.ccdf = [m, one](const T& t) {
108 std::vector<T> pts(1, t);
109 return T(one - mam::map_cdf(m, pts)[0]);
110 };
111 h.pdf = [m](const T& t) {
112 std::vector<T> pts(1, t);
113 return mam::map_pdf(m, pts)[0];
114 };
115 const T asymptotic = h.rate;
116 std::function<T(const T&)> ccdf = h.ccdf;
117 std::function<T(const T&)> pdf = h.pdf;
118 h.hazard = [ccdf, pdf, asymptotic](const T& t) {
119 // h = f/(1-F). Past the point where the ccdf underflows the hazard
120 // is the asymptotic decay rate, and returning that is better
121 // conditioned than dividing two zeros.
122 const T c = ccdf(t);
123 if (num_traits<T>::to_double(c) <= 1e-300) return asymptotic;
124 return T(pdf(t) / c);
125 };
126 }
127 return h;
128}
129
130} // namespace api
131} // namespace line
132
133#endif // LINE_API_SN_SN_PATIENCE_HANDLES_H
A network plus its refreshed NetworkStruct.
What refreshProcessRepresentations and refreshLST compute FROM a distribution: the (D0,...
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
Cumulative distribution of the inter-arrival time of a MAP.
Probability density of the inter-arrival time of a MAP.
PatienceHandles< T > sn_patience_handles(const qn::NetworkStruct< T > &sn, std::size_t ist, std::size_t r)
Build the patience handles of station ist (0-based), class r.
mam::Map< T > dist_to_map(const Distrib< T > &d)
std::vector< T > map_cdf(const Map< T > &m, const std::vector< T > &points)
Cumulative distribution of the inter-arrival time at the given points.
Definition map_cdf.h:63
std::vector< T > map_pdf(const Map< T > &m, const std::vector< T > &tset)
Probability density of the inter-arrival time at the given points.
Definition map_pdf.h:43
A queueing network and its refreshed NetworkStruct.
Number-type abstraction for the templated API port.
Engineering solution of the call-center model M/GI/s/r+GI.
Shared return type and arithmetic helpers for the templated qsys port.
The patience law of one station-class pair, in the forms the solvers consume.
std::function< T(const T &)> pdf
The patience density.
qsys::Patience< T > as_patience() const
This law as the Patience argument of the abandonment solvers.
std::function< T(const T &)> ccdf
F^c(t) = P(patience > t).
bool present
Whether the pair declares reneging at all; everything below is unset when false.
std::function< T(const T &)> hazard
The hazard rate h = f/(1-F).
bool isExponential
Whether the law is exponential, in which case the analysis is exact.
T rate
The abandonment rate 1/mean.
A MAP as the pair of matrices (D0, D1).
Definition map_moment.h:53
One station of the network.
std::vector< Distrib< T > > patience
Queue.setPatience(class, dist): the abandonment timer of a WAITING job, with impatience[r] naming whi...
std::vector< lang::ImpatienceType > impatience
The patience (time-to-abandon) law, in the three forms the algorithm accepts.
static Patience hazard(std::function< T(const T &)> h)
Patience given by its hazard rate h = f/(1-F).
static Patience exponential(const T &theta)
Exponential patience of rate theta, h(t) = theta, the Erlang A case.