LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
pfqn_mushift.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_MUSHIFT_H
6#define LINE_API_PFQN_MUSHIFT_H
7
8/**
9 * @file
10 * @ingroup api_pfqn
11 * Shift the load-dependent service-rate lattice of selected stations.
12 *
13 * Templated port of matlab/src/api/pfqn/pfqn_mushift.m, cross-checked against
14 * jar/src/main/java/jline/api/pfqn/ld/Pfqn_mushift.java.
15 *
16 * The load-dependent convolution and MVA recursions need mu(i, n+1) when a job
17 * is added at station i. This drops the first column of that station's rate
18 * row and the last column of every other row, giving an (M x N-1) lattice in
19 * which station i is "one job ahead":
20 *
21 * mushifted(i, j) = mu(i, j+1) for the shifted stations
22 * mushifted(m, j) = mu(m, j) otherwise, j = 1 .. N-1
23 *
24 * Arithmetic: EXACT-CAPABLE. The routine only copies entries, so it is exact
25 * in every arithmetic and carries no transcendental gate.
26 *
27 * Note on the MATLAB loop. The reference recomputes the whole matrix inside a
28 * loop over iset, so with more than one index only the LAST one is actually
29 * shifted; every earlier one is overwritten. That is a defect, not a
30 * convention -- the routine's own name and its single caller (one station at a
31 * time) say each listed station should be shifted -- so this port shifts every
32 * station in iset. With the single-element iset that the reference is called
33 * with, the two agree exactly.
34 */
35
36#include <cstddef>
37#include <vector>
38
39#include "line/num/number.h"
40#include "line/util/error.h"
41#include "line/util/matrix.h"
42
43namespace line {
44namespace pfqn {
45
46/**
47 * @brief Shift the load-dependent service-rate lattice of selected stations.
48 *
49 * @param mu (M x N) rate lattice, N >= 1
50 * @param iset 0-based station indices to shift
51 * @return (M x N-1) shifted lattice
52 */
53template <class T>
54Matrix<T> pfqn_mushift(const Matrix<T>& mu, const std::vector<std::size_t>& iset) {
55 const std::size_t M = mu.rows();
56 const std::size_t N = mu.cols();
57 if (N < 1) throw InputError("pfqn_mushift: the rate lattice is empty");
58 for (std::size_t i : iset)
59 if (i >= M) throw InputError("pfqn_mushift: station index out of range");
60
61 std::vector<bool> shift(M, false);
62 for (std::size_t i : iset) shift[i] = true;
63
64 Matrix<T> out(M, N - 1);
65 for (std::size_t m = 0; m < M; ++m)
66 for (std::size_t j = 0; j + 1 < N; ++j) out(m, j) = shift[m] ? mu(m, j + 1) : mu(m, j);
67 return out;
68}
69
70/** Single-station overload, the form the reference is actually called with. */
71template <class T>
72Matrix<T> pfqn_mushift(const Matrix<T>& mu, std::size_t i) {
73 return pfqn_mushift(mu, std::vector<std::size_t>{i});
74}
75
76} // namespace pfqn
77} // namespace line
78
79#endif // LINE_API_PFQN_MUSHIFT_H
InputError(const std::string &what)
Definition error.h:39
std::size_t cols() const
Definition matrix.h:90
std::size_t rows() const
Definition matrix.h:89
The exception types the port throws.
Dense matrix and non-owning view.
Matrix< T > pfqn_mushift(const Matrix< T > &mu, const std::vector< std::size_t > &iset)
Shift the load-dependent service-rate lattice of selected stations.
Number-type abstraction for the templated API port.