LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
pfqn_lcfsqn_ca.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_LCFSQN_CA_H
6#define LINE_API_PFQN_LCFSQN_CA_H
7
8/**
9 * @file
10 * @ingroup api_pfqn
11 * Convolution algorithm for the two-station multiclass LCFS queueing network
12 * of Casale, "A family of multiclass LCFS queueing networks with
13 * order-dependent product-form solutions", QUESTA 2026.
14 *
15 * Templated port of matlab/src/api/pfqn/pfqn_lcfsqn_ca.m.
16 *
17 * Station 1 is LCFS (non-preemptive) and station 2 is LCFS-PR
18 * (preemptive-resume); alpha_r and beta_r are the class-r mean service times
19 * at the two stations. The network is NOT product form in the classical sense
20 * -- the balance function depends on the ORDER of the jobs in the LCFS queue,
21 * not only on their counts -- so the constant obeys a coupled pair of
22 * recursions over the population lattice rather than a single Buzen update:
23 *
24 * V(0) = 1, V(n) = prod_r alpha_r^{n_r} * sum_{r: n_r > 0} V(n - e_r)
25 * G(0) = 1, G(n) = sum_{r: n_r > 0} alpha_r^{|n|-1} beta_r G(n - e_r) + V(n)
26 *
27 * V is the order-dependent auxiliary term contributed by the non-preemptive
28 * station; it is returned alongside G because the mean-value routine
29 * pfqn_lcfsqn_mva needs it.
30 *
31 * Arithmetic: EXACT-CAPABLE. Only integer powers, additions and
32 * multiplications in the field of the inputs.
33 */
34
35#include <cstddef>
36#include <vector>
37
38#include "line/num/number.h"
39#include "line/util/error.h"
40#include "line/util/matrix.h"
42
43namespace line {
44namespace pfqn {
45
46template <class T>
48 T G; ///< normalizing constant
49 T V; ///< order-dependent auxiliary term
50};
51
52/**
53 * @brief Convolution algorithm for the two-station multiclass LCFS queueing
54 * network of Casale, "A family of multiclass LCFS queueing networks
55 * with order-dependent product-form solutions", QUESTA 2026.
56 *
57 * @param alpha (R) mean service times at the LCFS station
58 * @param beta (R) mean service times at the LCFS-PR station
59 * @param N (R) population per class
60 */
61template <class T>
62LcfsQnResult<T> pfqn_lcfsqn_ca(const std::vector<T>& alpha, const std::vector<T>& beta,
63 const std::vector<int>& N) {
64 const std::size_t R = alpha.size();
65 if (beta.size() != R) throw InputError("pfqn_lcfsqn_ca: alpha and beta have different lengths");
66 if (N.size() != R) throw InputError("pfqn_lcfsqn_ca: alpha and N have different lengths");
67
68 const T one = num_traits<T>::from_int(1);
69 const T zero = num_traits<T>::from_int(0);
70 long K = 0;
71 for (int v : N) {
72 if (v < 0) throw InputError("pfqn_lcfsqn_ca: negative population");
73 K += v;
74 }
75 if (K == 0) return {one, one};
76
77 const std::vector<std::size_t> prods = plane_sizes(N);
78 const std::size_t total = population_count(N);
79 std::vector<T> G(total, zero), V(total, zero);
80
81 std::vector<int> n(R, 0);
82 bool more = true;
83 while (more) {
84 const std::size_t idx = pop_index(n, prods);
85 int tot = 0;
86 for (int v : n) tot += v;
87 if (tot == 0) {
88 G[idx] = one;
89 V[idx] = one;
90 } else {
91 T gv = zero, vv = zero;
92 for (std::size_t r = 0; r < R; ++r) {
93 if (n[r] == 0) continue;
94 const std::size_t idxr = idx - prods[r];
95 vv += V[idxr];
96 gv += num_pow_int(alpha[r], static_cast<unsigned>(tot - 1)) * beta[r] * G[idxr];
97 }
98 // V picks up the full prod_r alpha_r^{n_r} factor once per state.
99 T apow = one;
100 for (std::size_t r = 0; r < R; ++r)
101 apow *= num_pow_int(alpha[r], static_cast<unsigned>(n[r]));
102 V[idx] = apow * vv;
103 G[idx] = gv + V[idx];
104 }
105 more = next_pop(n, N);
106 }
107 return {G[total - 1], V[total - 1]};
108}
109
110} // namespace pfqn
111} // namespace line
112
113#endif // LINE_API_PFQN_LCFSQN_CA_H
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
Dense matrix and non-owning view.
LcfsQnResult< T > pfqn_lcfsqn_ca(const std::vector< T > &alpha, const std::vector< T > &beta, const std::vector< int > &N)
Convolution algorithm for the two-station multiclass LCFS queueing network of Casale,...
std::size_t population_count(const std::vector< int > &N)
Number of population vectors n with 0 <= n <= N.
Definition population.h:38
std::vector< std::size_t > plane_sizes(const std::vector< int > &N)
Mixed-radix plane sizes: prods[r] = prod_{s<r} (N[s]+1).
Definition population.h:27
bool next_pop(std::vector< int > &n, const std::vector< int > &N)
Advance n to the next population vector in the lattice 0 <= n <= N, odometer order with the last clas...
Definition population.h:56
T num_pow_int(const T &base, unsigned e)
Integer power, valid in any field (no transcendental requirement).
Definition number.h:192
std::size_t pop_index(const std::vector< int > &n, const std::vector< std::size_t > &prods)
Index of n in the lattice, 0-based (MATLAB hashpop is 1-based).
Definition population.h:45
Number-type abstraction for the templated API port.
Population-vector enumeration and combinatorics.
T V
order-dependent auxiliary term
T G
normalizing constant