LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
sn_gd_balance.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_SN_SN_GD_BALANCE_H
6
#define LINE_API_SN_SN_GD_BALANCE_H
7
8
/**
9
* @file
10
* @ingroup api_sn
11
* Whittle balance check for a globally state-dependent rate scaling.
12
*
13
* For every state n of the lattice 0..cutoffs and every pair of stations (s,t)
14
* populated in n, the balance property requires
15
*
16
* phi_s(n) phi_t(n - e_s) = phi_t(n) phi_s(n - e_t).
17
*
18
* When it holds, the chain is reversible with pi(n) ~ Phi(n) prod rho^n for the
19
* balance function Phi implied by phi, and the stationary law is insensitive to
20
* the service-time distribution beyond its mean. When it fails the model is
21
* still solvable by SolverCTMC, but it has no product form and IS sensitive --
22
* which is exactly the distinction this routine exists to make checkable, since
23
* nothing in a `set_global_dependence` declaration announces it.
24
*
25
* Twin of matlab/src/api/sn/sn_gd_balance.m, python
26
* line_solver.api.sn.sn_gd_balance and jline.api.sn.SnGdBalance.
27
*
28
* Reference: P. Whittle, "Partial balance and insensitivity", J. Appl. Prob.
29
* 22(1), 1985; T. Bonald, A. Proutiere, "Insensitivity in processor-sharing
30
* networks", Perf. Eval. 49, 2002.
31
*/
32
33
#include <cmath>
34
#include <cstddef>
35
#include <functional>
36
#include <vector>
37
38
#include "
line/util/error.h
"
39
#include "
line/num/number.h
"
40
41
namespace
line
{
42
namespace
sn
{
43
44
/**
45
* Worst relative violation of the balance property over the given lattice.
46
*
47
* @param phi scaling evaluated on an (nstations) population vector,
48
* returning one scalar (broadcast) or one entry per station
49
* @param cutoffs per-station lattice bound, one entry per station
50
* @return the worst relative violation; 0 to rounding when phi is balanced
51
*/
52
template
<
class
T>
53
T
sn_gd_balance
(
const
std::function<std::vector<T>(
const
std::vector<T>&)>& phi,
54
const
std::vector<std::size_t>& cutoffs) {
55
if
(!phi)
throw
InputError
(
"sn_gd_balance: phi must be callable"
);
56
const
std::size_t S = cutoffs.size();
57
if
(S < 2)
58
throw
InputError
(
59
"sn_gd_balance: cutoffs must have one entry per station (at least two stations are "
60
"needed for a balance pair)"
);
61
62
std::size_t total = 1;
63
for
(std::size_t s = 0; s < S; ++s) total *= cutoffs[s] + 1;
64
65
const
T zero =
num_traits<T>::from_int
(0);
66
T viol = zero;
67
std::vector<T> n(S, zero);
68
const
std::function<std::vector<T>(
const
std::vector<T>&)> ev =
69
[&phi, S](
const
std::vector<T>& x) {
70
std::vector<T> v = phi(x);
71
if
(v.size() == 1)
return
std::vector<T>(S, v[0]);
72
if
(v.size() != S)
73
throw
InputError
(
"sn_gd_balance: phi must return a scalar or one entry per station"
);
74
return
v;
75
};
76
77
for
(std::size_t idx = 0; idx < total; ++idx) {
78
std::size_t rem = idx;
79
for
(std::size_t s = 0; s < S; ++s) {
80
n[s] =
num_traits<T>::from_int
(
static_cast<
long
>
(rem % (cutoffs[s] + 1)));
81
rem /= cutoffs[s] + 1;
82
}
83
for
(std::size_t s = 0; s < S; ++s) {
84
if
(
num_traits<T>::to_double
(n[s]) == 0)
continue
;
85
for
(std::size_t t = s + 1; t < S; ++t) {
86
if
(
num_traits<T>::to_double
(n[t]) == 0)
continue
;
87
const
std::vector<T> xn = ev(n);
88
std::vector<T> m = n;
89
m[s] = T(m[s] -
num_traits<T>::from_int
(1));
90
const
std::vector<T> xs = ev(m);
91
m = n;
92
m[t] = T(m[t] -
num_traits<T>::from_int
(1));
93
const
std::vector<T> xt = ev(m);
94
const
double
lhs =
num_traits<T>::to_double
(T(xn[s] * xs[t]));
95
const
double
rhs =
num_traits<T>::to_double
(T(xn[t] * xt[s]));
96
const
double
scale = std::max(std::fabs(lhs), std::fabs(rhs));
97
if
(scale > 0) {
98
const
double
v = std::fabs(lhs - rhs) / scale;
99
if
(v >
num_traits<T>::to_double
(viol)) viol =
num_traits<T>::from_double
(v);
100
}
101
}
102
}
103
}
104
return
viol;
105
}
106
107
}
// namespace sn
108
}
// namespace line
109
110
#endif
// LINE_API_SN_SN_GD_BALANCE_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
error.h
The exception types the port throws.
line::sn
Definition
sn_gd_balance.h:42
line::sn::sn_gd_balance
T sn_gd_balance(const std::function< std::vector< T >(const std::vector< T > &)> &phi, const std::vector< std::size_t > &cutoffs)
Worst relative violation of the balance property over the given lattice.
Definition
sn_gd_balance.h:53
line
Definition
aoi_dist2ph.h:52
number.h
Number-type abstraction for the templated API port.
line::num_traits
Definition
number.h:111
include
line
api
sn
sn_gd_balance.h
Generated by
1.18.0