LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
pfqn_amva_common.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_AMVA_COMMON_H
6
#define LINE_API_PFQN_AMVA_COMMON_H
7
8
/**
9
* @file
10
* @ingroup api_pfqn
11
* Scaffolding shared by the approximate-MVA family. This header is NOT a port
12
* of a MATLAB function: it collects the small utilities that
13
* matlab/src/util/ provides to every AMVA routine (oner, pprod, sprod,
14
* multichoose, enorm) plus the scheduling-discipline tag those routines branch
15
* on, so that each pfqn_*.h below stays a 1:1 port of its own MATLAB file.
16
*
17
* Scheduling disciplines. The MATLAB routines take sn.sched-valued vectors but
18
* only ever compare them against SchedStrategy.PS, SchedStrategy.FCFS and
19
* SchedStrategy.INF, so the full enum is not part of the porting surface: the
20
* three tags below are what the algorithms actually distinguish. Anything else
21
* in a model is handled upstream, in the NetworkStruct layer, which is out of
22
* scope here.
23
*/
24
25
#include <cstddef>
26
#include <vector>
27
28
#include "
line/num/number.h
"
29
#include "
line/util/error.h
"
30
#include "
line/util/matrix.h
"
31
#include "
line/util/population.h
"
32
33
namespace
line
{
34
namespace
pfqn
{
35
36
/** The three scheduling disciplines the AMVA and Schmidt recursions branch on. */
37
enum class
SchedStrategy
{
PS
,
FCFS
, INF };
38
39
/**
40
* matlab/src/util/oner.m: decrement position r of N, with r given 1-based and
41
* r == 0 meaning "leave N alone" (the s == 0 arm of every `for s=0:R` loop).
42
* The result may go negative, exactly as in MATLAB; callers that cannot cope
43
* with a negative population guard it themselves, as the MATLAB ones do.
44
*/
45
inline
std::vector<int>
oner
(
const
std::vector<int>& N, std::size_t r) {
46
std::vector<int> n(N);
47
if
(r >= 1) {
48
if
(r > n.size())
throw
InputError
(
"oner: class index out of range"
);
49
n[r - 1] -= 1;
50
}
51
return
n;
52
}
53
54
/** matlab/src/util/enorm.m: Frobenius norm of a matrix. */
55
template
<
class
T>
56
T
enorm
(
const
Matrix<T>
& A) {
57
T s =
num_traits<T>::from_int
(0);
58
for
(std::size_t i = 0; i < A.
rows
(); ++i)
59
for
(std::size_t j = 0; j < A.
cols
(); ++j) s += A(i, j) * A(i, j);
60
using
std::sqrt;
61
return
sqrt(s);
62
}
63
64
/**
65
* Frobenius norm of the difference of two equally shaped matrices, AS A DOUBLE.
66
*
67
* The only use of this quantity anywhere in the AMVA family is the stopping
68
* test `enorm_diff(Q, Qlast) < tol`, and tol is a double. Returning a double
69
* therefore loses nothing and buys the exact backend the whole family: sqrt is
70
* not an operation of the rational field, so a T-valued version cannot be
71
* instantiated there at all. The sum of squares is accumulated in T, exactly,
72
* and only the final square root drops to double, so for T == double the
73
* result is bit-identical to sqrt of the T-valued sum.
74
*/
75
template
<
class
T>
76
double
enorm_diff
(
const
Matrix<T>
& A,
const
Matrix<T>
& B) {
77
T s =
num_traits<T>::from_int
(0);
78
for
(std::size_t i = 0; i < A.
rows
(); ++i)
79
for
(std::size_t j = 0; j < A.
cols
(); ++j) {
80
const
T d = A(i, j) - B(i, j);
81
s += d * d;
82
}
83
return
std::sqrt(
num_traits<T>::to_double
(s));
84
}
85
86
/**
87
* Sum the rows of a think-time matrix into a length-R vector, the `sum(Z,1)`
88
* that every AMVA entry point performs on its Z argument. An empty Z gives
89
* the all-zero vector.
90
*/
91
template
<
class
T>
92
std::vector<T>
sum_rows
(
const
Matrix<T>
& Z, std::size_t R) {
93
std::vector<T> z(R,
num_traits<T>::from_int
(0));
94
if
(Z.
empty
())
return
z;
95
if
(Z.
cols
() != R)
throw
InputError
(
"think-time matrix has the wrong class count"
);
96
for
(std::size_t k = 0; k < Z.
rows
(); ++k)
97
for
(std::size_t r = 0; r < R; ++r) z[r] += Z(k, r);
98
return
z;
99
}
100
101
/**
102
* matlab/src/util/multichoose.m and sprod.m, as an in-place odometer: the
103
* compositions of `c` into R non-negative parts, i.e. the vectors n with
104
* sum(n) == c. Start from first_composition and iterate until this returns
105
* false. The enumeration order differs from MATLAB's recursive one; every use
106
* site sums over the whole set, so only completeness matters.
107
*/
108
inline
void
first_composition
(std::vector<int>& n,
int
c) {
109
n.assign(n.size(), 0);
110
if
(!n.empty()) n[0] = c;
111
}
112
113
inline
bool
next_composition
(std::vector<int>& n) {
114
const
long
R =
static_cast<
long
>
(n.size());
115
if
(R < 2)
return
false
;
116
long
i = R - 2;
117
while
(i >= 0 && n[i] == 0) --i;
118
if
(i < 0)
return
false
;
119
// Every entry strictly between i and the last is zero by the choice of i,
120
// so the whole remainder is carried in the last slot.
121
const
int
tail = n[R - 1];
122
n[R - 1] = 0;
123
n[i] -= 1;
124
n[i + 1] = tail + 1;
125
return
true
;
126
}
127
128
/** Multinomial coefficient sum(m)!/prod_i m_i!, exact in any arithmetic. */
129
template
<
class
T>
130
T
num_multinomial
(
const
std::vector<int>& m) {
131
int
tot = 0;
132
for
(
int
v : m) tot += v;
133
T r =
num_factorial<T>
(
static_cast<
unsigned
>
(tot));
134
for
(
int
v : m) r /=
num_factorial<T>
(
static_cast<
unsigned
>
(v));
135
return
r;
136
}
137
138
}
// namespace pfqn
139
}
// namespace line
140
141
#endif
// LINE_API_PFQN_AMVA_COMMON_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
line::Matrix
Definition
matrix.h:56
line::Matrix::cols
std::size_t cols() const
Definition
matrix.h:90
line::Matrix::rows
std::size_t rows() const
Definition
matrix.h:89
line::Matrix::empty
bool empty() const
Definition
matrix.h:92
error.h
The exception types the port throws.
matrix.h
Dense matrix and non-owning view.
line::pfqn
Definition
cd_peak_scaling.h:43
line::pfqn::num_multinomial
T num_multinomial(const std::vector< int > &m)
Multinomial coefficient sum(m)!
Definition
pfqn_amva_common.h:130
line::pfqn::enorm
T enorm(const Matrix< T > &A)
matlab/src/util/enorm.m: Frobenius norm of a matrix.
Definition
pfqn_amva_common.h:56
line::pfqn::sum_rows
std::vector< T > sum_rows(const Matrix< T > &Z, std::size_t R)
Sum the rows of a think-time matrix into a length-R vector, the sum(Z,1) that every AMVA entry point ...
Definition
pfqn_amva_common.h:92
line::pfqn::oner
std::vector< int > oner(const std::vector< int > &N, std::size_t r)
matlab/src/util/oner.m: decrement position r of N, with r given 1-based and r == 0 meaning "leave N a...
Definition
pfqn_amva_common.h:45
line::pfqn::SchedStrategy
SchedStrategy
The three scheduling disciplines the AMVA and Schmidt recursions branch on.
Definition
pfqn_amva_common.h:37
line::pfqn::SchedStrategy::FCFS
@ FCFS
Definition
pfqn_amva_common.h:37
line::pfqn::SchedStrategy::PS
@ PS
Definition
pfqn_amva_common.h:37
line::pfqn::next_composition
bool next_composition(std::vector< int > &n)
Definition
pfqn_amva_common.h:113
line::pfqn::first_composition
void first_composition(std::vector< int > &n, int c)
matlab/src/util/multichoose.m and sprod.m, as an in-place odometer: the compositions of c into R non-...
Definition
pfqn_amva_common.h:108
line::pfqn::enorm_diff
double enorm_diff(const Matrix< T > &A, const Matrix< T > &B)
Frobenius norm of the difference of two equally shaped matrices, AS A DOUBLE.
Definition
pfqn_amva_common.h:76
line
Definition
aoi_dist2ph.h:52
line::num_factorial
T num_factorial(unsigned n)
Factorial as a value of T.
Definition
number.h:184
number.h
Number-type abstraction for the templated API port.
population.h
Population-vector enumeration and combinatorics.
line::num_traits
Definition
number.h:111
include
line
api
pfqn
pfqn_amva_common.h
Generated by
1.18.0