LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
pfqn_nintmva.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_NINTMVA_H
6
#define LINE_API_PFQN_NINTMVA_H
7
8
/**
9
* @file
10
* @ingroup api_pfqn
11
* Mean value analysis at a nonintegral population (fractional-base aMVA).
12
*
13
* Templated port of matlab/src/api/pfqn/pfqn_nintmva.m.
14
*
15
* The exact MVA recursion started from the FRACTIONAL base n_0 = N - floor(N)
16
* instead of from the empty network, giving mean performance measures of a
17
* single-class closed product-form network at a real-valued population (Dowdy
18
* and Gordon 1984, "aMVA"). The recursion is the standard Reiser-Lavenberg one,
19
*
20
* R_i(n) = D_i (1 + Q_i(n-1)), X(n) = n / (Z + sum_i R_i(n)), Q_i(n) = X R_i,
21
*
22
* stepped in unit increments from n = n_0 (where the arrival-theorem term
23
* Q_i(n_0 - 1) is taken as 0, the network below the base being empty) up to
24
* n = N. At integer N the base is 0 and the recursion is bit-identical to exact
25
* MVA; at fractional N it interpolates smoothly through the integral points,
26
* which is what a nonintegral degree of multiprogramming (a time-average over a
27
* measurement window) calls for.
28
*
29
* Unlike pfqn_dnc this accepts a think time, since the delay enters the
30
* recursion and not a partial-fraction continuation. It is single-class: the
31
* multiclass recursion has no one-dimensional step. For fractional multiclass
32
* populations use pfqn_bs, which accepts them directly.
33
*
34
* Reference: L. W. Dowdy, K. D. Gordon, "Algorithms for Nonintegral Degrees of
35
* Multiprogramming in Closed Queuing Networks", Performance Evaluation
36
* 4(1):19-28, 1984.
37
*
38
* Arithmetic: EXACT-CAPABLE. Only field operations on T; the integer part of N
39
* is read through a double, which is lossless for any population a closed model
40
* can carry.
41
*/
42
43
#include <cmath>
44
#include <cstddef>
45
#include <vector>
46
47
#include "
line/num/number.h
"
48
#include "
line/util/error.h
"
49
50
namespace
line
{
51
namespace
pfqn
{
52
53
/** Mean performance measures of pfqn_nintmva at the requested population. */
54
template
<
class
T>
55
struct
NintMvaResult
{
56
T
X
;
///< throughput at population N
57
std::vector<T>
Q
;
///< (M) mean queue lengths
58
std::vector<T>
U
;
///< (M) utilizations
59
std::vector<T>
R
;
///< (M) residence times
60
};
61
62
/**
63
* @brief Mean value analysis at a nonintegral population (fractional-base
64
* aMVA).
65
*
66
* @param L (M) service demands of the queueing stations
67
* @param N population, real and nonnegative (may be fractional)
68
* @param Z think time
69
*/
70
template
<
class
T>
71
NintMvaResult<T>
pfqn_nintmva
(
const
std::vector<T>& L,
const
T& N,
const
T& Z) {
72
const
std::size_t M = L.size();
73
const
T zero =
num_traits<T>::from_int
(0);
74
const
T one =
num_traits<T>::from_int
(1);
75
if
(N < zero)
throw
InputError
(
"pfqn_nintmva requires a nonnegative population"
);
76
77
NintMvaResult<T>
res;
78
res.
Q
.assign(M, zero);
79
res.
U
.assign(M, zero);
80
res.
R
.assign(M, zero);
81
res.
X
= zero;
82
if
(N == zero)
return
res;
83
84
// n_0 = N - floor(N), with the integral case starting the recursion at 1
85
const
double
Nd =
num_traits<T>::to_double
(N);
86
T n = T(N -
num_traits<T>::from_int
(
static_cast<
long
>
(std::floor(Nd))));
87
if
(n == zero) n = one;
88
89
// The reference guards the real-valued loop bound with an absolute 1e-12
90
const
T stop = T(N +
num_traits<T>::from_double
(1e-12));
91
while
(n <= stop) {
92
T sumR = zero;
93
for
(std::size_t i = 0; i < M; ++i) {
94
res.
R
[i] = T(L[i] * T(one + res.
Q
[i]));
95
sumR += res.
R
[i];
96
}
97
const
T den = T(Z + sumR);
98
if
(den == zero)
throw
NumericError
(
"pfqn_nintmva: the network has zero total demand"
);
99
res.
X
= T(n / den);
100
for
(std::size_t i = 0; i < M; ++i) res.
Q
[i] = T(res.
X
* res.
R
[i]);
101
n += one;
102
}
103
for
(std::size_t i = 0; i < M; ++i) res.
U
[i] = T(res.
X
* L[i]);
104
return
res;
105
}
106
107
/** MATLAB default: no think time. */
108
template
<
class
T>
109
NintMvaResult<T>
pfqn_nintmva
(
const
std::vector<T>& L,
const
T& N) {
110
return
pfqn_nintmva
(L, N,
num_traits<T>::from_int
(0));
111
}
112
113
}
// namespace pfqn
114
}
// namespace line
115
116
#endif
// LINE_API_PFQN_NINTMVA_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
line::NumericError::NumericError
NumericError(const std::string &what)
Definition
error.h:45
error.h
The exception types the port throws.
line::pfqn
Definition
cd_peak_scaling.h:43
line::pfqn::pfqn_nintmva
NintMvaResult< T > pfqn_nintmva(const std::vector< T > &L, const T &N, const T &Z)
Mean value analysis at a nonintegral population (fractional-base aMVA).
Definition
pfqn_nintmva.h:71
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
line::num_traits
Definition
number.h:111
line::pfqn::NintMvaResult
Mean performance measures of pfqn_nintmva at the requested population.
Definition
pfqn_nintmva.h:55
line::pfqn::NintMvaResult::R
std::vector< T > R
(M) residence times
Definition
pfqn_nintmva.h:59
line::pfqn::NintMvaResult::U
std::vector< T > U
(M) utilizations
Definition
pfqn_nintmva.h:58
line::pfqn::NintMvaResult::X
T X
throughput at population N
Definition
pfqn_nintmva.h:56
line::pfqn::NintMvaResult::Q
std::vector< T > Q
(M) mean queue lengths
Definition
pfqn_nintmva.h:57
include
line
api
pfqn
pfqn_nintmva.h
Generated by
1.18.0