LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
retrieval_metrics.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_RETRIEVAL_RETRIEVAL_METRICS_H
6#define LINE_API_RETRIEVAL_RETRIEVAL_METRICS_H
7
8/**
9 * @file
10 * @ingroup api_retrieval
11 * Exact miss, hit and delayed-hit metrics of a delayed-hit (list-based) cache.
12 *
13 * Templated port of matlab/src/api/retrieval/retrieval_metrics.m,
14 * cross-checked against
15 * jar/src/main/java/jline/api/retrieval/Retrieval_metrics.java.
16 *
17 * With E(m) = E(0,m) the normalizing constant of the whole system and E_i the
18 * constant of the system without item i (both from retrieval_nc):
19 *
20 * miss ratio pi_{i,0} = E_i(m)/E(m)
21 * hit ratio at list j pi_{i,j} = m_j gamma_{i,j} E_i(m-1_j)/E(m)
22 * delayed hit at IS phi_{0,i} = lambda_i eta_{0,i} E_i(m)/E(m)
23 * delayed hit at PS s phi_{s,i} = lambda_i eta_{s,i} E_i(1_s,m)/E(m)
24 *
25 * and every item satisfies the balance
26 * pi_{i,0} + sum_s phi_{s,i} + sum_j pi_{i,j} = 1.
27 *
28 * ARITHMETIC: ratios of exact normalizing constants, so a finite field
29 * computation. In the exact instantiation the balance above holds as an
30 * identity between rationals, not to within a tolerance.
31 */
32
33#include <cstddef>
34#include <vector>
35
37#include "line/num/number.h"
38#include "line/util/error.h"
39#include "line/util/matrix.h"
40
41namespace line {
42namespace retrieval {
43
44/** Mirrors the [pmiss, phit, pdh] return list of the MATLAB function. */
45template <class T>
47 std::vector<T> pmiss; ///< (n) miss ratios pi_{i,0}
48 Matrix<T> phit; ///< (h x n) hit ratios pi_{i,j}
49 Matrix<T> pdh; ///< ((r+1) x n) delayed-hit probabilities phi_{s,i}, s = 0..r
50};
51
52namespace detail {
53
54/** Row i deleted from an (n x c) matrix, i.e. MATLAB's A([1:i-1,i+1:n],:). */
55template <class T>
56Matrix<T> drop_row(const Matrix<T>& A, std::size_t i) {
57 Matrix<T> B(A.rows() - 1, A.cols());
58 std::size_t r = 0;
59 for (std::size_t a = 0; a < A.rows(); ++a) {
60 if (a == i) continue;
61 for (std::size_t b = 0; b < A.cols(); ++b) B(r, b) = A(a, b);
62 ++r;
63 }
64 return B;
65}
66
67} // namespace detail
68
69/**
70 * @brief Exact miss, hit and delayed-hit metrics of a delayed-hit
71 * (list-based) cache.
72 *
73 * @param m (h) cache list capacities
74 * @param lambda (n) per-item arrival rates
75 * @param eta (n x (r+1)) fetching demands, column 0 = IS station, columns 1..r = PS
76 * @param gamma (n x h) access factors
77 */
78template <class T>
79RetrievalMetricsResult<T> retrieval_metrics(const std::vector<int>& m, const std::vector<T>& lambda,
80 const Matrix<T>& eta, const Matrix<T>& gamma) {
81 const std::size_t n = lambda.size();
82 const std::size_t h = m.size();
83 if (eta.rows() != n || gamma.rows() != n)
84 throw InputError("retrieval_metrics: eta/gamma and lambda disagree on the item count");
85 if (eta.cols() == 0) throw InputError("retrieval_metrics: eta has no columns");
86 const std::size_t r = eta.cols() - 1;
87 const std::vector<int> v0(r, 0);
88
89 const T E = retrieval_nc(v0, m, lambda, eta, gamma);
90 if (E == num_traits<T>::from_int(0))
91 throw NumericError("retrieval_metrics: the normalizing constant is zero");
92
94 out.pmiss.assign(n, num_traits<T>::from_int(0));
96 out.pdh = Matrix<T>(r + 1, n, num_traits<T>::from_int(0));
97
98 for (std::size_t i = 0; i < n; ++i) {
99 std::vector<T> lambda_i;
100 lambda_i.reserve(n - 1);
101 for (std::size_t k = 0; k < n; ++k)
102 if (k != i) lambda_i.push_back(lambda[k]);
103 const Matrix<T> eta_i = detail::drop_row(eta, i);
104 const Matrix<T> gamma_i = detail::drop_row(gamma, i);
105
106 const T Ei = retrieval_nc(v0, m, lambda_i, eta_i, gamma_i);
107 out.pmiss[i] = Ei / E;
108 out.pdh(0, i) = lambda[i] * eta(i, 0) * Ei / E;
109
110 for (std::size_t s = 0; s < r; ++s) {
111 std::vector<int> vs(r, 0);
112 vs[s] = 1;
113 const T Eis = retrieval_nc(vs, m, lambda_i, eta_i, gamma_i);
114 out.pdh(s + 1, i) = lambda[i] * eta(i, s + 1) * Eis / E;
115 }
116
117 for (std::size_t j = 0; j < h; ++j) {
118 if (m[j] > 0) {
119 std::vector<int> mj = m;
120 mj[j] -= 1;
121 const T Eij = retrieval_nc(v0, mj, lambda_i, eta_i, gamma_i);
122 out.phit(j, i) =
123 num_traits<T>::from_int(static_cast<long>(m[j])) * gamma(i, j) * Eij / E;
124 }
125 }
126 }
127 return out;
128}
129
130} // namespace retrieval
131} // namespace line
132
133#endif // LINE_API_RETRIEVAL_RETRIEVAL_METRICS_H
InputError(const std::string &what)
Definition error.h:39
std::size_t cols() const
Definition matrix.h:90
std::size_t rows() const
Definition matrix.h:89
NumericError(const std::string &what)
Definition error.h:45
The exception types the port throws.
Dense matrix and non-owning view.
T retrieval_nc(const std::vector< int > &v, const std::vector< int > &m, const std::vector< T > &lambda, const Matrix< T > &eta, const Matrix< T > &gamma)
Exact normalizing constant E(v,m) of a delayed-hit (list-based) cache.
RetrievalMetricsResult< T > retrieval_metrics(const std::vector< int > &m, const std::vector< T > &lambda, const Matrix< T > &eta, const Matrix< T > &gamma)
Exact miss, hit and delayed-hit metrics of a delayed-hit (list-based) cache.
Number-type abstraction for the templated API port.
Exact normalizing constant E(v,m) of a delayed-hit (list-based) cache.
Mirrors the [pmiss, phit, pdh] return list of the MATLAB function.
Matrix< T > phit
(h x n) hit ratios pi_{i,j}
Matrix< T > pdh
((r+1) x n) delayed-hit probabilities phi_{s,i}, s = 0..r
std::vector< T > pmiss
(n) miss ratios pi_{i,0}