LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
pfqn_ssd.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_SSD_H
6#define LINE_API_PFQN_PFQN_SSD_H
7
8/**
9 * @file
10 * @ingroup api_pfqn
11 * Server-Station Disaggregation bounds for a multiserver closed network
12 * (Dallery and Suri, SIGMETRICS 1986).
13 *
14 * Templated port of matlab/src/api/pfqn/pfqn_ssd.m. Single-class model: L is the
15 * per-station demand vector, N the population, Z the think time.
16 *
17 * Theorem 5 eq. (6) carries no think time of its own. The objection this file
18 * used to raise still stands as far as it went: inserting a bare +Z into the
19 * Theorem 5 form is NOT a bound, because the BJB optimistic step needs
20 * sum_k Q_k(N-1) = N-1, which fails once Z X(N-1) jobs sit at the terminal.
21 * What that argument missed is that the queueing term can be corrected instead
22 * of the delay being disaggregated separately. The reference now scales it by
23 * the terminal-workload factor of Lazowska et al. 1984, Table 5.2:
24 * (N-1) Y_l / (1 + Z/(N R_l)) on the lower bound and (N-1) Y_u / (1 + Z/R_u) on
25 * the upper. Both reduce to the Z=0 forms exactly, so this generalises rather
26 * than replaces eq. (6), and the Z>0 case is computed instead of refused.
27 *
28 * All operations stay in the field, so the bound is exact in rational
29 * arithmetic: a bound computed exactly is worth having, since a bound violated
30 * only by rounding is indistinguishable from a real violation.
31 */
32
33#include <algorithm>
34#include <vector>
35
36#include "line/num/number.h"
37#include "line/util/error.h"
38#include "line/util/matrix.h"
39
40namespace line {
41namespace pfqn {
42
43template <class T>
44struct SsdBounds {
45 T Xlo;
46 T Xhi;
47};
48
49/**
50 * @brief Server-Station Disaggregation bounds for a multiserver closed
51 * network (Dallery and Suri, SIGMETRICS 1986).
52 *
53 * @param L demands, @param N population, @param Z think time,
54 * @param nservers per-station server counts (empty for all ones)
55 */
56template <class T>
57SsdBounds<T> pfqn_ssd(const std::vector<T>& L, const T& N, const T& Z,
58 const std::vector<T>& nservers) {
59 const std::size_t K = L.size();
60 if (K == 0) throw InputError("pfqn_ssd: empty demand vector");
61 if (!nservers.empty() && nservers.size() != K)
62 throw InputError("pfqn_ssd: server-count vector has the wrong length");
63 const T one = num_traits<T>::from_int(1);
64
67 std::size_t b = 0;
68 for (std::size_t i = 0; i < K; ++i) {
69 const T c = nservers.empty() ? one : nservers[i];
70 if (c == num_traits<T>::from_int(0)) throw InputError("pfqn_ssd: zero server count");
71 Rl += L[i];
72 const T lc = L[i] / c;
73 Ru += lc;
74 if (lc > Yl) {
75 Yl = lc;
76 b = i;
77 }
78 }
79 const T Kt = num_traits<T>::from_int(static_cast<long>(K));
80 const T Yu = Ru / Kt;
81 const T cb = nservers.empty() ? one : nservers[b];
82
83 const T zero = num_traits<T>::from_int(0);
84 // Lazowska Table 5.2 terminal-workload scaling; at Z=0 both factors are 1.
85 // A zero total demand forces Yl = Yu = 0, so the term vanishes and the
86 // division that would be undefined is never reached.
87 const T ql = (Rl == zero) ? zero : (N - one) * Yl / (one + Z / (N * Rl));
88 const T qu = (Ru == zero) ? zero : (N - one) * Yu / (one + Z / Ru);
89
91 r.Xlo = N / (Rl + Z + ql); // Theorem 5 lower, think-time corrected
92 T hi = N / (Ru + Z + qu); // Theorem 5 upper, eq. (6), think-time corrected
93 const T cap = cb / L[b];
94 if (cap < hi) hi = cap;
95 const T pop = N / (Rl + Z);
96 if (pop < hi) hi = pop;
97 r.Xhi = hi;
98 return r;
99}
100
101template <class T>
102SsdBounds<T> pfqn_ssd(const std::vector<T>& L, const T& N, const T& Z) {
103 return pfqn_ssd(L, N, Z, std::vector<T>());
104}
105
106} // namespace pfqn
107} // namespace line
108
109#endif
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
Dense matrix and non-owning view.
SsdBounds< T > pfqn_ssd(const std::vector< T > &L, const T &N, const T &Z, const std::vector< T > &nservers)
Server-Station Disaggregation bounds for a multiserver closed network (Dallery and Suri,...
Definition pfqn_ssd.h:57
Number-type abstraction for the templated API port.