LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
da_cache_isolate.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_DA_DA_CACHE_ISOLATE_H
6#define LINE_API_DA_DA_CACHE_ISOLATE_H
7
8/**
9 * @file
10 * @ingroup api_da
11 * Isolated-cache input construction for the decomposition methods.
12 *
13 * Templated port of matlab/src/api/da/da_cache_isolate.m. The decomposition
14 * driver replaces a cache node embedded in a queueing network by the same
15 * cache in isolation, driven by the current per-class arrival rates. This
16 * routine builds that isolated model: it spreads each class rate lambda(v)
17 * over the items through the class read distribution pread{v}, attaches the
18 * access-cost (routing) matrices Rcost, and returns the access factors gamma
19 * that every cache algorithm of the family consumes.
20 *
21 * The MATLAB source reads the cache parameters off sn.nodeparam of the cache
22 * node; the port takes only the four fields it actually uses, in CacheParam,
23 * so nothing of the NetworkStruct layer is needed here.
24 *
25 * A note on lambda_cache: the reference fills every list position l = 1..h+1
26 * of item k with the same lambda(v) pread{v}(k). That is deliberate - the
27 * request rate for an item does not depend on which list currently holds it -
28 * and is reproduced verbatim, because cache_gamma_lp reads lambda(v,i,t) as
29 * "rate at which v requests item i while it sits at node t".
30 *
31 * Only products and sums (here and in cache_gamma_lp), so this is a finite
32 * field computation: instantiated at exact arithmetic the access factors of a
33 * rational cache model are exact rationals. No transcendental gate.
34 */
35
36#include <cstddef>
37#include <vector>
38
40#include "line/num/number.h"
41#include "line/util/error.h"
42#include "line/util/matrix.h"
43
44namespace line {
45namespace da {
46
47/**
48 * The fields of sn.nodeparam{cache} that da_cache_isolate reads.
49 *
50 * pread[v] is the read distribution of class v over the n items; an EMPTY
51 * vector encodes MATLAB's NaN placeholder, i.e. "class v does not read this
52 * cache", and leaves that class's rates at zero.
53 *
54 * accost[v][k] is the ((h+1) x (h+1)) list-to-list routing matrix of class v
55 * on item k. Leaving accost empty selects the reference default, the linear
56 * cache in which an item moves from list l to list l+1 on a hit and stays in
57 * the last list once it gets there.
58 */
59template <class T>
60struct CacheParam {
61 std::vector<int> itemcap; ///< (h) list capacities
62 std::size_t nitems = 0; ///< n
63 std::vector<std::vector<T>> pread; ///< (u) x (n), empty row = NaN
64 std::vector<std::vector<Matrix<T>>> accost; ///< (u) x (n) of (h+1)x(h+1), or empty
65};
66
67/** Return value of da_cache_isolate, mirroring [gamma,lambda_cache,Rcost]. */
68template <class T>
70 Matrix<T> gamma; ///< (n x h) access factors
71 std::vector<Matrix<T>> lambda_cache; ///< (u) matrices of size n x (h+1)
72 std::vector<std::vector<Matrix<T>>> Rcost; ///< (u x n) of (h+1)x(h+1)
73};
74
75/**
76 * @brief Isolated-cache input construction for the decomposition methods.
77 *
78 * @param ch cache node parameters
79 * @param lambda (u) per-class arrival rates at the cache
80 */
81template <class T>
82CacheIsolateResult<T> da_cache_isolate(const CacheParam<T>& ch, const std::vector<T>& lambda) {
83 const std::size_t h = ch.itemcap.size();
84 const std::size_t n = ch.nitems;
85 const std::size_t u = lambda.size();
86 if (h == 0) throw InputError("da_cache_isolate: the cache has no lists");
87 if (n == 0) throw InputError("da_cache_isolate: the cache has no items");
88 if (u == 0) throw InputError("da_cache_isolate: no arrival rates given");
89 if (ch.pread.size() != u)
90 throw InputError("da_cache_isolate: pread and lambda disagree on the class count");
91
92 const T zero = num_traits<T>::from_int(0);
93 const T one = num_traits<T>::from_int(1);
94
96 r.lambda_cache.assign(u, Matrix<T>(n, h + 1, zero));
97 for (std::size_t v = 0; v < u; ++v) {
98 if (ch.pread[v].empty()) continue; // MATLAB's isnan(pread{v}) branch
99 if (ch.pread[v].size() != n)
100 throw InputError("da_cache_isolate: pread has the wrong number of items");
101 for (std::size_t k = 0; k < n; ++k) {
102 const T rate = lambda[v] * ch.pread[v][k];
103 for (std::size_t l = 0; l <= h; ++l) r.lambda_cache[v](k, l) = rate;
104 }
105 }
106
107 if (!ch.accost.empty()) {
108 if (ch.accost.size() != u)
109 throw InputError("da_cache_isolate: accost and lambda disagree on the class count");
110 for (std::size_t v = 0; v < u; ++v) {
111 if (ch.accost[v].size() != n)
112 throw InputError("da_cache_isolate: accost has the wrong number of items");
113 for (std::size_t k = 0; k < n; ++k)
114 if (ch.accost[v][k].rows() != h + 1 || ch.accost[v][k].cols() != h + 1)
115 throw InputError("da_cache_isolate: an accost matrix is not (h+1) x (h+1)");
116 }
117 r.Rcost = ch.accost;
118 } else {
119 // Default linear cache routing: items flow from list l to list l+1,
120 // and the last list is absorbing.
121 Matrix<T> Rmat(h + 1, h + 1, zero);
122 for (std::size_t l = 0; l < h; ++l) Rmat(l, l + 1) = one;
123 Rmat(h, h) = one;
124 r.Rcost.assign(u, std::vector<Matrix<T>>(n, Rmat));
125 }
126
128 return r;
129}
130
131} // namespace da
132} // namespace line
133
134#endif // LINE_API_DA_DA_CACHE_ISOLATE_H
Access factors of a tree-structured multi-list cache.
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
Dense matrix and non-owning view.
CacheGammaResult< T > cache_gamma_lp(const std::vector< Matrix< T > > &lambda, const std::vector< std::vector< Matrix< T > > > &R)
Access factors of a tree-structured multi-list cache.
CacheIsolateResult< T > da_cache_isolate(const CacheParam< T > &ch, const std::vector< T > &lambda)
Isolated-cache input construction for the decomposition methods.
Number-type abstraction for the templated API port.
Return value of da_cache_isolate, mirroring [gamma,lambda_cache,Rcost].
std::vector< Matrix< T > > lambda_cache
(u) matrices of size n x (h+1)
Matrix< T > gamma
(n x h) access factors
std::vector< std::vector< Matrix< T > > > Rcost
(u x n) of (h+1)x(h+1)
The fields of sn.nodeparam{cache} that da_cache_isolate reads.
std::vector< int > itemcap
(h) list capacities
std::vector< std::vector< Matrix< T > > > accost
(u) x (n) of (h+1)x(h+1), or empty
std::vector< std::vector< T > > pread
(u) x (n), empty row = NaN