LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
cache_sojourn.h
Go to the documentation of this file.
1
/**
2
* @file cache_sojourn.h
3
* @brief Grid-independent sojourn-weighted average of a cache mean-field transient.
4
*
5
* Twin of MATLAB `cache_sojourn_ode.m`, JAR `CacheSojourn` and Python
6
* `api/cache/sojourn.py`. For a drift dx/dt = f(x) and a phase-type clock with
7
* row phase vector phi, dphi/dt = phi A, density g(t) = phi(t) c, it returns
8
*
9
* xbar = int_{t0}^{t1} x g dt / int_{t0}^{t1} g dt, wtot = int_{t0}^{t1} g dt,
10
*
11
* by augmenting the state with phi, int g x and int g, so the integrator itself
12
* carries the integral. The value is accurate to the ODE tolerance and does NOT
13
* depend on any output grid: a Riemann sum over the grid did, and that is what
14
* made the adaptive (MATLAB, C++) and fixed-grid (JAR, Python) ENV cache mean
15
* fields differ in the third digit.
16
*
17
* Copyright (c) 2012-2026, Imperial College London
18
* All rights reserved.
19
*/
20
21
#ifndef LINE_API_CACHE_CACHE_SOJOURN_H
22
#define LINE_API_CACHE_CACHE_SOJOURN_H
23
24
#include <cstddef>
25
#include <vector>
26
27
#include "
line/num/number.h
"
28
#include "
line/util/matrix.h
"
29
#include "
line/util/ode.h
"
30
31
namespace
line
{
32
namespace
cache
{
33
34
/** A phase-type clock: dphi/dt = phi A, phi(t0) = phi0, density phi c. Empty = no clock. */
35
template
<
class
T>
36
struct
CacheSojournClock
{
37
Matrix<T>
A
;
38
std::vector<T>
phi0
;
39
std::vector<T>
c
;
40
bool
empty
()
const
{
return
phi0
.empty(); }
41
};
42
43
/** A sojourn average: `xbar` (empty when `wtot` is not positive), clock mass, per-user miss rate. */
44
template
<
class
T>
45
struct
CacheSojournResult
{
46
std::vector<T>
xbar
;
47
T
wtot
=
num_traits<T>::from_int
(0);
48
std::vector<T>
MU
;
///< per-user miss rate of xbar, filled by the policy
49
std::vector<T>
tout
;
///< the reference's tout: accepted time points of the integration
50
Matrix<T>
xtraj
;
///< the reference's xtraj: (n x nt) occupancy at tout
51
bool
empty
()
const
{
return
xbar
.empty(); }
52
};
53
54
/**
55
* The holding-time clock of a random-environment stage whose holding time has
56
* sub-generator D0 and entry vector pie, in a drift time unit that is `lam` times
57
* real time: A = D0/lam, c = -D0 1/lam, phi0 = pie, so int_0^T g = F(T/lam).
58
*/
59
template
<
class
T>
60
CacheSojournClock<T>
cache_sojourn_clock
(
const
Matrix<T>
& D0,
const
std::vector<T>& pie,
double
lam) {
61
CacheSojournClock<T>
clk;
62
const
std::size_t nph = D0.
rows
();
63
const
T L =
num_traits<T>::from_double
(lam);
64
clk.
A
=
Matrix<T>
(nph, nph,
num_traits<T>::from_int
(0));
65
clk.
c
.assign(nph,
num_traits<T>::from_int
(0));
66
clk.
phi0
= pie;
67
for
(std::size_t i = 0; i < nph; ++i) {
68
T rs =
num_traits<T>::from_int
(0);
69
for
(std::size_t j = 0; j < nph; ++j) {
70
clk.
A
(i, j) = T(D0(i, j) / L);
71
rs = T(rs + D0(i, j));
72
}
73
clk.
c
[i] = T(-rs / L);
74
}
75
return
clk;
76
}
77
78
/** Integrates dx/dt = f(t, x) over [t0, t1] from x0 together with `clk`; see the file comment. */
79
template
<
class
T,
class
F>
80
CacheSojournResult<T>
cache_sojourn_ode
(
const
F& f,
const
T& t0,
const
T& t1,
81
const
std::vector<T>& x0,
const
CacheSojournClock<T>
& clk) {
82
const
std::size_t n = x0.size(), nph = clk.
phi0
.size();
83
const
std::size_t dim = 2 * n + nph + 1;
84
const
T zero =
num_traits<T>::from_int
(0);
85
const
auto
rhs = [&](
const
T& t,
const
std::vector<T>& z) {
86
std::vector<T> x(z.begin(), z.begin() +
static_cast<
std::ptrdiff_t
>
(n));
87
const
std::vector<T> dx = f(t, x);
88
std::vector<T> dz(dim, zero);
89
for
(std::size_t i = 0; i < n; ++i) dz[i] = dx[i];
90
T g = zero;
91
for
(std::size_t j = 0; j < nph; ++j) {
92
T s = zero;
93
for
(std::size_t i = 0; i < nph; ++i) s = T(s + T(z[n + i] * clk.
A
(i, j)));
94
dz[n + j] = s;
95
g = T(g + T(z[n + j] * clk.
c
[j]));
96
}
97
for
(std::size_t i = 0; i < n; ++i) dz[n + nph + i] = T(g * x[i]);
98
dz[dim - 1] = g;
99
return
dz;
100
};
101
std::vector<T> z0(dim, zero);
102
for
(std::size_t i = 0; i < n; ++i) z0[i] = x0[i];
103
for
(std::size_t j = 0; j < nph; ++j) z0[n + j] = clk.
phi0
[j];
104
OdeOptions<T>
opt
;
105
opt
.rtol =
num_traits<T>::from_double
(1e-8);
106
opt
.atol =
num_traits<T>::from_double
(1e-10);
107
opt
.store_trajectory =
true
;
108
const
OdeSolution<T>
sol =
ode_rosenbrock4
(rhs, t0, t1, z0,
opt
);
109
const
std::vector<T> z1 = sol.
final_state
();
110
CacheSojournResult<T>
r;
111
r.
wtot
= z1[dim - 1];
112
if
(
num_traits<T>::to_double
(r.
wtot
) > 0.0) {
113
r.
xbar
.assign(n, zero);
114
for
(std::size_t i = 0; i < n; ++i) r.
xbar
[i] = T(z1[n + nph + i] / r.
wtot
);
115
}
116
// the reference's [tout, xtraj]: xtraj = Z(:, 1:n)', one column per time point
117
r.
tout
= sol.
t
;
118
r.
xtraj
=
Matrix<T>
(n, sol.
y
.size(), zero);
119
for
(std::size_t k = 0; k < sol.
y
.size(); ++k)
120
for
(std::size_t i = 0; i < n; ++i) r.
xtraj
(i, k) = sol.
y
[k][i];
121
return
r;
122
}
123
124
/**
125
* The reference's clock-less form, cache_sojourn_ode(drift, tspan, x0): a plain
126
* integration of dx/dt = f(t, x) over [t0, t1] from x0 with ode15s's default
127
* tolerances as the reference passes them (RelTol 1e-8, AbsTol 1e-10). Only
128
* `tout` and `xtraj` are filled; `xbar` stays empty and `wtot` zero, which is
129
* the reference's `sj = []`.
130
*/
131
template
<
class
T,
class
F>
132
CacheSojournResult<T>
cache_sojourn_ode
(
const
F& f,
const
T& t0,
const
T& t1,
133
const
std::vector<T>& x0) {
134
const
std::size_t n = x0.size();
135
const
T zero =
num_traits<T>::from_int
(0);
136
OdeOptions<T>
opt
;
137
opt
.rtol =
num_traits<T>::from_double
(1e-8);
138
opt
.atol =
num_traits<T>::from_double
(1e-10);
139
opt
.store_trajectory =
true
;
140
const
OdeSolution<T>
sol =
ode_rosenbrock4
(f, t0, t1, x0,
opt
);
141
CacheSojournResult<T>
r;
142
r.
tout
= sol.
t
;
143
r.
xtraj
=
Matrix<T>
(n, sol.
y
.size(), zero);
144
for
(std::size_t k = 0; k < sol.
y
.size(); ++k)
145
for
(std::size_t i = 0; i < n; ++i) r.
xtraj
(i, k) = sol.
y
[k][i];
146
return
r;
147
}
148
149
}
// namespace cache
150
}
// namespace line
151
152
#endif
// LINE_API_CACHE_CACHE_SOJOURN_H
line::Matrix
Definition
matrix.h:56
line::Matrix::Matrix
Matrix()
Definition
matrix.h:58
line::Matrix::rows
std::size_t rows() const
Definition
matrix.h:89
matrix.h
Dense matrix and non-owning view.
line::cache
Definition
cache_cost.h:42
line::cache::cache_sojourn_clock
CacheSojournClock< T > cache_sojourn_clock(const Matrix< T > &D0, const std::vector< T > &pie, double lam)
The holding-time clock of a random-environment stage whose holding time has sub-generator D0 and entr...
Definition
cache_sojourn.h:60
line::cache::cache_sojourn_ode
CacheSojournResult< T > cache_sojourn_ode(const F &f, const T &t0, const T &t1, const std::vector< T > &x0, const CacheSojournClock< T > &clk)
Integrates dx/dt = f(t, x) over [t0, t1] from x0 together with clk; see the file comment.
Definition
cache_sojourn.h:80
line::opt
Definition
bisection_solver.h:31
line
Conservation laws of a layered queueing network, enumerated from its structure.
Definition
aoi_dist2ph.h:52
line::ode_rosenbrock4
OdeSolution< T > ode_rosenbrock4(const F &f, const J &jac, const T &t0, const T &t1, const std::vector< T > &y0, const OdeOptions< T > &opt)
Integrate y' = f(t,y) from t0 to t1 with an analytic Jacobian.
Definition
ode.h:303
number.h
Number-type abstraction for the templated API port.
ode.h
Adaptive stiff ODE integrator: a four-stage Rosenbrock method of order four with an embedded order-th...
line::OdeOptions
Integration controls.
Definition
ode.h:117
line::OdeSolution
Result of an integration.
Definition
ode.h:142
line::OdeSolution::y
std::vector< std::vector< T > > y
y[i] is the state at t[i]
Definition
ode.h:144
line::OdeSolution::t
std::vector< T > t
accepted time points, t[0] = t0
Definition
ode.h:143
line::OdeSolution::final_state
const std::vector< T > & final_state() const
Definition
ode.h:150
line::cache::CacheSojournClock
A phase-type clock: dphi/dt = phi A, phi(t0) = phi0, density phi c.
Definition
cache_sojourn.h:36
line::cache::CacheSojournClock::A
Matrix< T > A
Definition
cache_sojourn.h:37
line::cache::CacheSojournClock::empty
bool empty() const
Definition
cache_sojourn.h:40
line::cache::CacheSojournClock::phi0
std::vector< T > phi0
Definition
cache_sojourn.h:38
line::cache::CacheSojournClock::c
std::vector< T > c
Definition
cache_sojourn.h:39
line::cache::CacheSojournResult
A sojourn average: xbar (empty when wtot is not positive), clock mass, per-user miss rate.
Definition
cache_sojourn.h:45
line::cache::CacheSojournResult::MU
std::vector< T > MU
per-user miss rate of xbar, filled by the policy
Definition
cache_sojourn.h:48
line::cache::CacheSojournResult::xtraj
Matrix< T > xtraj
the reference's xtraj: (n x nt) occupancy at tout
Definition
cache_sojourn.h:50
line::cache::CacheSojournResult::empty
bool empty() const
Definition
cache_sojourn.h:51
line::cache::CacheSojournResult::tout
std::vector< T > tout
the reference's tout: accepted time points of the integration
Definition
cache_sojourn.h:49
line::cache::CacheSojournResult::xbar
std::vector< T > xbar
Definition
cache_sojourn.h:46
line::cache::CacheSojournResult::wtot
T wtot
Definition
cache_sojourn.h:47
line::num_traits
Definition
number.h:123
include
line
api
cache
cache_sojourn.h
Generated by
1.18.0