LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
retrieval_nc.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_NC_H
6#define LINE_API_RETRIEVAL_RETRIEVAL_NC_H
7
8/**
9 * @file
10 * @ingroup api_retrieval
11 * Exact normalizing constant E(v,m) of a delayed-hit (list-based) cache.
12 *
13 * Templated port of matlab/src/api/retrieval/retrieval_nc.m, cross-checked
14 * against jar/src/main/java/jline/api/retrieval/Retrieval_nc.java.
15 *
16 * The cache holds h lists of capacities m(1..h) filled from n items, and a
17 * missed item is fetched by a retrieval system with one infinite-server
18 * station (index s=0) and r processor-sharing stations (s=1..r). The exact
19 * recurrence peels off item k:
20 *
21 * E(v,m) = (1 + lambda_k eta_{0,k}) E_k(v,m)
22 * + sum_{s=1}^r lambda_k eta_{s,k} (v_s+1) E_k(v+1_s, m)
23 * + sum_{j=1}^h m_j gamma_{k,j} E_k(v, m-1_j)
24 *
25 * with E_k the constant of the system without item k, E = 1 once no item is
26 * left, and E = 0 as soon as sum_j m_j exceeds the number of remaining items
27 * or some m_j is negative. The plain constant is E(m) = E(0,m); the vector v
28 * carries the moment order at each PS station, so E(1_s,m) is what the
29 * delayed-hit probability at station s needs.
30 *
31 * ARITHMETIC: every step is a multiplication and an addition of the inputs,
32 * so this is a finite field computation and the exact instantiation returns
33 * the true constant with no rounding at all. That is what makes it the oracle
34 * for retrieval_fpi, which only approximates the same quantities.
35 */
36
37#include <cstddef>
38#include <vector>
39
40#include "line/num/number.h"
41#include "line/util/error.h"
42#include "line/util/matrix.h"
43
44namespace line {
45namespace retrieval {
46
47namespace detail {
48
49/** E over items 1..k of the n-item system. */
50template <class T>
51T retrieval_nc_aux(std::vector<int>& v, std::vector<int>& m, const std::vector<T>& lambda,
52 const Matrix<T>& eta, const Matrix<T>& gamma, int k) {
53 const std::size_t r = v.size();
54 const std::size_t h = m.size();
55 long msum = 0;
56 int mmin = 0;
57 bool first = true;
58 for (int x : m) {
59 msum += x;
60 if (first || x < mmin) mmin = x;
61 first = false;
62 }
63 if (msum > k || mmin < 0) return num_traits<T>::from_int(0);
64 if (k == 0) return num_traits<T>::from_int(1);
65
66 const std::size_t ki = static_cast<std::size_t>(k - 1);
67
68 // item k out of the system, or fetched at the IS station s = 0
69 T E = (num_traits<T>::from_int(1) + lambda[ki] * eta(ki, 0)) *
70 retrieval_nc_aux(v, m, lambda, eta, gamma, k - 1);
71
72 // item k fetched at PS station s = 1..r
73 for (std::size_t s = 0; s < r; ++s) {
74 const int vs = v[s];
75 v[s] = vs + 1;
76 const T sub = retrieval_nc_aux(v, m, lambda, eta, gamma, k - 1);
77 v[s] = vs;
78 E += lambda[ki] * eta(ki, s + 1) * num_traits<T>::from_int(static_cast<long>(vs) + 1) * sub;
79 }
80
81 // item k stored in cache list j = 1..h
82 for (std::size_t j = 0; j < h; ++j) {
83 if (m[j] > 0) {
84 const int mj = m[j];
85 m[j] = mj - 1;
86 const T sub = retrieval_nc_aux(v, m, lambda, eta, gamma, k - 1);
87 m[j] = mj;
88 E += gamma(ki, j) * num_traits<T>::from_int(static_cast<long>(mj)) * sub;
89 }
90 }
91 return E;
92}
93
94} // namespace detail
95
96/**
97 * @brief Exact normalizing constant E(v,m) of a delayed-hit (list-based)
98 * cache.
99 *
100 * @param v (r) moment order at each PS station; all zeros for the plain constant
101 * @param m (h) cache list capacities
102 * @param lambda (n) per-item arrival rates
103 * @param eta (n x (r+1)) fetching demands, column 0 = IS station, columns 1..r = PS
104 * @param gamma (n x h) access factors
105 * @return E(v,m)
106 */
107template <class T>
108T retrieval_nc(const std::vector<int>& v, const std::vector<int>& m, const std::vector<T>& lambda,
109 const Matrix<T>& eta, const Matrix<T>& gamma) {
110 const std::size_t n = lambda.size();
111 if (eta.rows() != n) throw InputError("retrieval_nc: eta and lambda disagree on the item count");
112 if (gamma.rows() != n)
113 throw InputError("retrieval_nc: gamma and lambda disagree on the item count");
114 if (eta.cols() != v.size() + 1)
115 throw InputError("retrieval_nc: eta and v disagree on the number of PS stations");
116 if (gamma.cols() != m.size())
117 throw InputError("retrieval_nc: gamma and m disagree on the number of lists");
118 std::vector<int> vv = v;
119 std::vector<int> mm = m;
120 return detail::retrieval_nc_aux(vv, mm, lambda, eta, gamma, static_cast<int>(n));
121}
122
123} // namespace retrieval
124} // namespace line
125
126#endif // LINE_API_RETRIEVAL_RETRIEVAL_NC_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
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.
Number-type abstraction for the templated API port.