LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
fj_tsm_capacity.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_FJ_TSM_CAPACITY_H
6
#define LINE_API_FJ_TSM_CAPACITY_H
7
8
/**
9
* @file
10
* @ingroup api_fj
11
* Saturation throughput of the team service model.
12
*
13
* Templated port of matlab/src/api/fj/fj_tsm_capacity.m.
14
*
15
* A class-k job seizes r(k) of the s servers at once, holds them for a mean
16
* x(k), and releases them all together. The apparent saturation rate is
17
*
18
* Lambda_max = s / sum_k f(k) r(k) x(k),
19
*
20
* attainable only when the scheduler can pack jobs into execution states that
21
* leave no server idle. The attainable capacity is the largest arrival rate for
22
* which some mixture p over the feasible execution states balances every class,
23
*
24
* maximise Lambda s.t. sum_j p_j n(j,k)/x(k) = Lambda f(k),
25
* sum_j p_j = 1, p >= 0,
26
*
27
* over the multisets of jobs whose total server demand is at most s. The
28
* optimum equals Lambda_max exactly when every state carrying positive
29
* probability is full capacity.
30
*
31
* For the two-server two-class case with r = (1,2), strict first come first
32
* served cannot pack at all and reaches only
33
*
34
* lambda_FCFS = 2 mu1 mu2 / (f1^2 mu2 + 2 f2^2 mu1 + 2 f1 f2 (mu1+mu2)).
35
*/
36
37
#include <cstddef>
38
#include <vector>
39
40
#include "
line/api/fj/fj_types.h
"
41
#include "
line/num/number.h
"
42
#include "
line/util/error.h
"
43
#include "
line/util/simplex.h
"
44
45
namespace
line
{
46
namespace
fj
{
47
48
/** [Lmax, Llp, Lfcfs, states, prob] of fj_tsm_capacity. */
49
template
<
class
T>
50
struct
FJTsmCapacityResult
{
51
T
Lmax
;
52
T
Llp
;
53
T
Lfcfs
;
54
bool
fcfs_available
;
55
std::vector<std::vector<unsigned> >
states
;
56
std::vector<T>
prob
;
57
};
58
59
namespace
detail {
60
61
/** Every multiset of jobs whose total server demand is at most s, minus the empty one. */
62
inline
void
tsm_states(
const
std::vector<unsigned>& r,
unsigned
left, std::size_t k,
63
std::vector<unsigned>& stack,
64
std::vector<std::vector<unsigned> >& out) {
65
if
(k == r.size()) {
66
for
(std::size_t i = 0; i < stack.size(); ++i)
67
if
(stack[i] > 0) { out.push_back(stack);
return
; }
68
return
;
69
}
70
const
unsigned
nmax = left / r[k];
71
for
(
unsigned
n = 0; n <= nmax; ++n) {
72
stack[k] = n;
73
tsm_states(r, left - n * r[k], k + 1, stack, out);
74
}
75
stack[k] = 0;
76
}
77
78
}
// namespace detail
79
80
/**
81
* @brief Saturation throughput of the team service model.
82
*
83
* @param s number of servers
84
* @param f class frequencies in the arrival stream, summing to one
85
* @param r per-class server requirements, integers in 1..s
86
* @param x per-class mean service times, all positive
87
* @return the apparent and attainable capacities with the optimal state mixture
88
*/
89
template
<
class
T>
90
FJTsmCapacityResult<T>
fj_tsm_capacity
(
unsigned
s,
const
std::vector<T>& f,
91
const
std::vector<unsigned>& r,
const
std::vector<T>& x) {
92
const
std::size_t K = f.size();
93
if
(s < 1)
throw
InputError
(
"fj_tsm_capacity: s must be a positive integer"
);
94
if
(r.size() != K || x.size() != K)
95
throw
InputError
(
"fj_tsm_capacity: f, r and x must have the same length"
);
96
const
T zero =
num_traits<T>::from_int
(0), one =
num_traits<T>::from_int
(1);
97
T tot = zero;
98
for
(std::size_t k = 0; k < K; ++k) {
99
if
(f[k] < zero)
throw
InputError
(
"fj_tsm_capacity: the class frequencies must be non-negative"
);
100
if
(r[k] < 1 || r[k] > s)
101
throw
InputError
(
"fj_tsm_capacity: the server requirements must lie in 1..s"
);
102
if
(!(x[k] > zero))
throw
InputError
(
"fj_tsm_capacity: the mean service times must be positive"
);
103
tot += f[k];
104
}
105
if
(!(tot - one <
num_traits<T>::from_double
(1e-9)) ||
106
!(one - tot <
num_traits<T>::from_double
(1e-9)))
107
throw
InputError
(
"fj_tsm_capacity: the class frequencies must sum to one"
);
108
109
FJTsmCapacityResult<T>
out;
110
T den = zero;
111
for
(std::size_t k = 0; k < K; ++k)
112
den += f[k] *
num_traits<T>::from_int
(
static_cast<
long
>
(r[k])) * x[k];
113
out.
Lmax
=
num_traits<T>::from_int
(
static_cast<
long
>
(s)) / den;
114
115
std::vector<unsigned> stack(K, 0);
116
detail::tsm_states(r, s, 0, stack, out.
states
);
117
const
std::size_t ns = out.
states
.size();
118
if
(ns == 0)
throw
NumericError
(
ErrorKind
{
"Infeasible"
},
"fj_tsm_capacity: no feasible execution state"
);
119
120
// Variables [p_1..p_ns, Lambda], maximise Lambda
121
lp::LpModel<T>
lpm(ns + 1);
122
lpm.set_maximize(
true
);
123
lpm.set_cost(ns, one);
124
for
(std::size_t k = 0; k < K; ++k) {
125
if
(!(f[k] > zero))
continue
;
126
lpm.row_clear();
127
for
(std::size_t j = 0; j < ns; ++j)
128
lpm.row_add(j,
num_traits<T>::from_int
(
static_cast<
long
>
(out.
states
[j][k])) / x[k]);
129
lpm.row_add(ns, -f[k]);
130
lpm.emit(
lp::LpSense::EQ
, zero);
131
}
132
lpm.row_clear();
133
for
(std::size_t j = 0; j < ns; ++j) lpm.row_add(j, one);
134
lpm.emit(
lp::LpSense::EQ
, one);
135
136
const
lp::LpSolution<T>
sol =
lp::simplex_solve
(lpm);
137
if
(!sol.
ok
())
138
throw
NumericError
(
ErrorKind
{
"NonConvergence"
}, std::string(
"fj_tsm_capacity: the capacity linear program returned "
) +
139
lp::lp_status_name
(sol.
status
));
140
out.
Llp
= sol.
x
[ns];
141
out.
prob
.assign(sol.
x
.begin(), sol.
x
.begin() +
static_cast<
long
>
(ns));
142
143
// Strict first come first served capacity of the two-server two-class case
144
out.
fcfs_available
=
false
;
145
out.
Lfcfs
= zero;
146
if
(s == 2 && K == 2 && ((r[0] == 1 && r[1] == 2) || (r[0] == 2 && r[1] == 1))) {
147
const
std::size_t a = (r[0] == 1) ? 0 : 1, b = 1 - a;
148
const
T f1 = f[a], f2 = f[b], mu1 = one / x[a], mu2 = one / x[b];
149
const
T two =
num_traits<T>::from_int
(2);
150
out.
Lfcfs
= two * mu1 * mu2 /
151
(f1 * f1 * mu2 + two * f2 * f2 * mu1 + two * f1 * f2 * (mu1 + mu2));
152
out.
fcfs_available
=
true
;
153
}
154
return
out;
155
}
156
157
}
// namespace fj
158
}
// namespace line
159
160
#endif
// LINE_API_FJ_TSM_CAPACITY_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:105
line::NumericError::NumericError
NumericError(const std::string &what)
Definition
error.h:112
line::lp::LpModel
Sparse LP in the natural form, with per-variable bounds.
Definition
simplex.h:112
error.h
The exception types the port throws.
fj_types.h
Shared return types and arithmetic helpers for the templated fork-join port.
line::fj
Definition
fj_amva.h:34
line::fj::fj_tsm_capacity
FJTsmCapacityResult< T > fj_tsm_capacity(unsigned s, const std::vector< T > &f, const std::vector< unsigned > &r, const std::vector< T > &x)
Saturation throughput of the team service model.
Definition
fj_tsm_capacity.h:90
line::lp::LpSense::EQ
@ EQ
Definition
simplex.h:103
line::lp::lp_status_name
const char * lp_status_name(LpStatus s)
Definition
simplex.h:84
line::lp::simplex_solve
LpSolution< T > simplex_solve(const LpModel< T > &model, std::size_t max_iterations=0)
Solve the model.
Definition
simplex.h:286
line
Conservation laws of a layered queueing network, enumerated from its structure.
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
simplex.h
Templated primal simplex with Bland's rule.
line::ErrorKind
The <kind> part of a LINE:<category>:<kind> identifier (see _kb/17-error-vocabulary....
Definition
error.h:37
line::fj::FJTsmCapacityResult
[Lmax, Llp, Lfcfs, states, prob] of fj_tsm_capacity.
Definition
fj_tsm_capacity.h:50
line::fj::FJTsmCapacityResult::Lmax
T Lmax
Definition
fj_tsm_capacity.h:51
line::fj::FJTsmCapacityResult::prob
std::vector< T > prob
Definition
fj_tsm_capacity.h:56
line::fj::FJTsmCapacityResult::states
std::vector< std::vector< unsigned > > states
Definition
fj_tsm_capacity.h:55
line::fj::FJTsmCapacityResult::Lfcfs
T Lfcfs
Definition
fj_tsm_capacity.h:53
line::fj::FJTsmCapacityResult::fcfs_available
bool fcfs_available
Definition
fj_tsm_capacity.h:54
line::fj::FJTsmCapacityResult::Llp
T Llp
Definition
fj_tsm_capacity.h:52
line::lp::LpSolution
Definition
simplex.h:94
line::lp::LpSolution::ok
bool ok() const
Definition
simplex.h:99
line::lp::LpSolution::x
std::vector< T > x
primal solution in the ORIGINAL variable space
Definition
simplex.h:96
line::lp::LpSolution::status
LpStatus status
Definition
simplex.h:95
line::num_traits
Definition
number.h:123
include
line
api
fj
fj_tsm_capacity.h
Generated by
1.18.0