LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
cache_xi_fp.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_CACHE_XI_FP_H
6
#define LINE_API_CACHE_XI_FP_H
7
8
/**
9
* @file
10
* @ingroup api_cache
11
* Lagrange multipliers of a multi-list cache by fixed-point iteration.
12
*
13
* Templated port of matlab/src/api/cache/cache_xi_fp.m, cross-checked against
14
* jar/src/main/java/jline/api/cache/Cache_xi_fp.java.
15
*
16
* The asymptotic (large-cache) form of the list occupancy distribution is
17
*
18
* pij(k,l) = gamma(k,l) xi(l) / (1 + sum_s gamma(k,s) xi(s)),
19
* pi0(k) = 1 - sum_l pij(k,l),
20
*
21
* and the multipliers xi are fixed by the capacity constraints, which in this
22
* decoupled form read xi(l) = m(l) / sum_k pi0(k) gamma(k,l). Alternating the
23
* two updates from pi0 = 1/(h+1) is the iteration below; it stops when the
24
* relative change of pi0 falls under 1e-14 in the 1-norm.
25
*
26
* ARITHMETIC: every update is a field operation, but the iteration is stopped
27
* by a tolerance and the fixed point is not reached in finitely many exact
28
* steps, so the algorithm is inexact by nature. It is gated on transcendental
29
* arithmetic rather than offered at exact arithmetic, where a "1e-14" cutoff
30
* would be a rounding-free computation of a rounded answer.
31
*
32
* REFERENCE DEFECT (both codebases): the optional initial-xi argument is
33
* inert. MATLAB writes `xi=zeros(1,h);` before testing `nargin<3`, discarding
34
* the caller's vector, and in any case the first statement of the loop
35
* recomputes xi from pi0, so no initial xi can influence the result. The JAR
36
* has the same structure. The argument is therefore not offered here.
37
*/
38
39
#include <cstddef>
40
#include <vector>
41
42
#include "
line/num/number.h
"
43
#include "
line/util/error.h
"
44
#include "
line/util/matrix.h
"
45
46
namespace
line
{
47
namespace
cache
{
48
49
/** Return value of cache_xi_fp, mirroring [xi,pi0,pij,it]. */
50
template
<
class
T>
51
struct
CacheXiFpResult
{
52
std::vector<T>
xi
;
///< (h) Lagrange multipliers
53
std::vector<T>
pi0
;
///< (n) per-item miss probability
54
Matrix<T>
pij
;
///< (n x h) per-item per-list hit probability
55
int
it
;
///< iterations performed
56
};
57
58
/**
59
* @brief Lagrange multipliers of a multi-list cache by fixed-point iteration.
60
*
61
* @param gamma (n x h) access factors
62
* @param m (h) list capacities
63
*/
64
template
<
class
T>
65
CacheXiFpResult<T>
cache_xi_fp
(
const
Matrix<T>
& gamma,
const
std::vector<int>& m) {
66
static_assert
(
num_traits<T>::has_transcendental
,
67
"cache_xi_fp requires transcendental arithmetic"
);
68
const
std::size_t n = gamma.
rows
();
69
const
std::size_t h = gamma.
cols
();
70
if
(h != m.size())
throw
InputError
(
"cache_xi_fp: gamma and m disagree on the number of lists"
);
71
72
const
T zero =
num_traits<T>::from_int
(0);
73
const
T one =
num_traits<T>::from_int
(1);
74
const
T tol =
num_traits<T>::from_double
(1e-14);
75
76
std::vector<T> pi0(n, one /
num_traits<T>::from_int
(
static_cast<
long
>
(h + 1)));
77
std::vector<T> xi(h, zero);
78
Matrix<T>
pij(n, h, zero);
79
80
int
it = 1;
81
for
(; it <= 10000; ++it) {
82
const
std::vector<T> pi0_1 = pi0;
83
84
// xi(l) = m(l) / sum_k pi0(k) gamma(k,l)
85
for
(std::size_t l = 0; l < h; ++l) {
86
T d = zero;
87
for
(std::size_t k = 0; k < n; ++k) d += pi0_1[k] * gamma(k, l);
88
if
(d == zero)
89
throw
NumericError
(
"cache_xi_fp: a list has zero aggregate access factor"
);
90
xi[l] =
num_traits<T>::from_int
(
static_cast<
long
>
(m[l])) / d;
91
}
92
93
for
(std::size_t k = 0; k < n; ++k) {
94
T s = zero;
95
for
(std::size_t l = 0; l < h; ++l) s += gamma(k, l) * xi[l];
96
const
T den =
num_abs
(T(one + s));
97
T hits = zero;
98
for
(std::size_t l = 0; l < h; ++l) {
99
pij(k, l) =
num_abs
(T(gamma(k, l) * xi[l])) / den;
100
hits += pij(k, l);
101
}
102
const
T v = one - hits;
103
pi0[k] = v > tol ? v : tol;
104
}
105
106
T delta = zero;
107
for
(std::size_t k = 0; k < n; ++k) delta +=
num_abs
(T(one - pi0[k] / pi0_1[k]));
108
if
(delta < tol)
break
;
109
}
110
if
(it > 10000) it = 10000;
111
112
for
(std::size_t l = 0; l < h; ++l)
113
if
(xi[l] < zero) xi[l] = tol;
114
115
CacheXiFpResult<T>
r;
116
r.
xi
= xi;
117
r.
pi0
= pi0;
118
r.
pij
= pij;
119
r.
it
= it;
120
return
r;
121
}
122
123
}
// namespace cache
124
}
// namespace line
125
126
#endif
// LINE_API_CACHE_XI_FP_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::NumericError::NumericError
NumericError(const std::string &what)
Definition
error.h:45
error.h
The exception types the port throws.
matrix.h
Dense matrix and non-owning view.
line::cache
Definition
cache_cost.h:42
line::cache::cache_xi_fp
CacheXiFpResult< T > cache_xi_fp(const Matrix< T > &gamma, const std::vector< int > &m)
Lagrange multipliers of a multi-list cache by fixed-point iteration.
Definition
cache_xi_fp.h:65
line
Definition
aoi_dist2ph.h:52
line::num_abs
T num_abs(const T &v)
Definition
number.h:172
number.h
Number-type abstraction for the templated API port.
line::cache::CacheXiFpResult
Return value of cache_xi_fp, mirroring [xi,pi0,pij,it].
Definition
cache_xi_fp.h:51
line::cache::CacheXiFpResult::pi0
std::vector< T > pi0
(n) per-item miss probability
Definition
cache_xi_fp.h:53
line::cache::CacheXiFpResult::it
int it
iterations performed
Definition
cache_xi_fp.h:55
line::cache::CacheXiFpResult::xi
std::vector< T > xi
(h) Lagrange multipliers
Definition
cache_xi_fp.h:52
line::cache::CacheXiFpResult::pij
Matrix< T > pij
(n x h) per-item per-list hit probability
Definition
cache_xi_fp.h:54
line::num_traits
Definition
number.h:111
include
line
api
cache
cache_xi_fp.h
Generated by
1.18.0