LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
pfqn_cntol.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_CNTOL_H
6#define LINE_API_PFQN_CNTOL_H
7
8/**
9 * @file
10 * @ingroup api_pfqn
11 * Chandy-Neuse population-scaled termination cutoff for approximate MVA.
12 *
13 * Templated port of matlab/src/api/pfqn/pfqn_cntol.m. The cutoff
14 * 1/(4000 + 16*sum(N)) is published in K. M. Chandy, D. Neuse, "Linearizer: A
15 * Heuristic Algorithm for Queuing Network Models of Computing Systems",
16 * Commun. ACM 25(2):126-134, 1982, p.129 and appendix. The iteration continues
17 * while
18 *
19 * max_{i,r} |Q^I(i,r) - Q^{I-1}(i,r)| / N_r > 1/(4000 + 16*|N|),
20 *
21 * |N| = sum(N). The paper motivates the scaling with |N|: at large populations
22 * removing one job changes the queue lengths very little, so a fixed cutoff
23 * would terminate the iteration prematurely. It also notes that the expression
24 * stays below 0.00025 even at very small populations.
25 *
26 * The same expression is what LQNS uses as its termination test, set in the
27 * SchweitzerCommon constructor of libmva/src/mva.cc; that code carries no
28 * citation, and the paper above is its source.
29 *
30 * The cutoff is a stopping rule, not an algebraic quantity, so it is a double
31 * in every arithmetic backend: it is compared against a double residual, and
32 * making it exact would not make the fixed point it selects any more exact.
33 *
34 * Passing NaN as the tol argument of pfqn_bs / pfqn_egflinearizer selects BOTH
35 * this cutoff and the normalized-maximum metric of the paper, which is the
36 * published test; passing pfqn_cntol(N) as a plain number selects only the
37 * cutoff, with those functions' own convergence metric. NaN is the sentinel
38 * because it cannot collide with any legitimate tolerance and it is the one
39 * form the MATLAB, Java and Python twins share (MATLAB and Python additionally
40 * accept the string "cn").
41 */
42
43#include <cmath>
44#include <vector>
45
46#include "line/num/number.h"
47
48namespace line {
49namespace pfqn {
50
51/** Termination cutoff at the given total population. */
52inline double pfqn_cntol_total(double total_population) {
53 return 1.0 / (4000.0 + 16.0 * total_population);
54}
55
56/** Termination cutoff at the given population vector. */
57template <class T>
58double pfqn_cntol(const std::vector<T>& N) {
59 double total = 0.0;
60 for (const T& n : N) total += num_traits<T>::to_double(n);
61 return pfqn_cntol_total(total);
62}
63
64/** Termination cutoff at the given integer population vector. */
65inline double pfqn_cntol(const std::vector<int>& N) {
66 double total = 0.0;
67 for (int n : N) total += static_cast<double>(n);
68 return pfqn_cntol_total(total);
69}
70
71/** True when tol is the sentinel requesting the Chandy-Neuse test. */
72inline bool is_cntol(double tol) { return std::isnan(tol); }
73
74} // namespace pfqn
75} // namespace line
76
77#endif // LINE_API_PFQN_CNTOL_H
double pfqn_cntol_total(double total_population)
Termination cutoff at the given total population.
Definition pfqn_cntol.h:52
bool is_cntol(double tol)
True when tol is the sentinel requesting the Chandy-Neuse test.
Definition pfqn_cntol.h:72
double pfqn_cntol(const std::vector< T > &N)
Termination cutoff at the given population vector.
Definition pfqn_cntol.h:58
Number-type abstraction for the templated API port.