122 const std::vector<T>& lambda,
128 "retrieval_fpi_latency requires transcendental arithmetic: it is driven by "
129 "retrieval_fpi, a successive substitution stopped on a relative tolerance");
130 const std::size_t n = lambda.size();
131 const std::size_t S = station.size();
132 if (S == 0)
throw InputError(
"retrieval_fpi_latency: no retrieval station");
133 if (gamma.
rows() != n)
134 throw InputError(
"retrieval_fpi_latency: gamma and lambda disagree on the item count");
136 throw InputError(
"retrieval_fpi_latency: one routing matrix per item is required");
137 for (std::size_t i = 0; i < n; ++i)
138 if (R[i].rows() != S + 1 || R[i].cols() != S + 1)
139 throw InputError(
"retrieval_fpi_latency: routing matrices must be (S+1) x (S+1)");
141 std::vector<std::size_t> fsz(S);
142 for (std::size_t s = 0; s < S; ++s) {
143 fsz[s] = station[s].phases();
144 if (station[s].sub.
size() != n)
145 throw InputError(
"retrieval_fpi_latency: one subgenerator per item is required");
146 if (station[s].alpha.rows() != n)
147 throw InputError(
"retrieval_fpi_latency: alpha must have one row per item");
148 for (std::size_t i = 0; i < n; ++i)
149 if (station[s].sub[i].rows() != fsz[s] || station[s].sub[i].cols() != fsz[s])
150 throw InputError(
"retrieval_fpi_latency: subgenerator size disagrees with alpha");
156 "retrieval_fpi_latency: SIRO/FCFS retrieval stations require exponential "
157 "(single-phase) service");
162 for (std::size_t s = 0; s < S; ++s)
163 for (std::size_t i = 0; i < n; ++i) {
165 for (std::size_t k = 0; k < fsz[s]; ++k) arow(0, k) = station[s].alpha(i, k);
166 tau(i, s) = detail::ph_mean(arow, station[s].sub[i]);
170 for (std::size_t s = 0; s < S; ++s) {
174 double lo = 0.0, hi = 0.0;
175 for (std::size_t i = 0; i < n; ++i) {
177 if (i == 0 || x < lo) lo = x;
178 if (i == 0 || x > hi) hi = x;
180 if (hi - lo > 1e-9 * hi)
182 "retrieval_fpi_latency: SIRO/FCFS retrieval stations require class-independent "
183 "mean service rates");
187 std::vector<std::size_t> is_idx, ps_idx;
188 for (std::size_t s = 0; s < S; ++s) {
194 const std::size_t r = ps_idx.size();
198 for (std::size_t i = 0; i < n; ++i) {
200 for (std::size_t a = 0; a < S; ++a)
201 for (std::size_t b = 0; b < S; ++b)
206 for (std::size_t b = 0; b < S; ++b)
207 for (std::size_t a = 0; a < S; ++a) visits[b] += R[i](0, a + 1) * Vinv(a, b);
210 for (std::size_t s : is_idx) is_sum += visits[s] * tau(i, s);
212 for (std::size_t p = 0; p < r; ++p) eta(i, 1 + p) = visits[ps_idx[p]] * tau(i, ps_idx[p]);
220 for (std::size_t i = 0; i < n; ++i)
221 for (std::size_t s = 0; s <= r; ++s) out.
phi[i] += full.
pdh(s, i);
224 const std::size_t Phi = [&]() {
226 for (std::size_t s = 0; s < S; ++s) t += fsz[s];
229 std::vector<std::size_t> off(S, 0);
230 for (std::size_t s = 1; s < S; ++s) off[s] = off[s - 1] + fsz[s - 1];
232 for (std::size_t i = 0; i < n; ++i) {
234 std::vector<T> lambda_i;
235 lambda_i.reserve(n - 1);
239 for (std::size_t k = 0; k < n; ++k) {
240 if (k == i)
continue;
241 lambda_i.push_back(lambda[k]);
242 for (std::size_t c = 0; c <= r; ++c) eta_i(q, c) = eta(k, c);
243 for (std::size_t c = 0; c < gamma.
cols(); ++c) gamma_i(q, c) = gamma(k, c);
250 for (std::size_t p = 0; p < r; ++p) {
252 for (std::size_t k = 0; k + 1 < n; ++k) acc += without.
pdh(1 + p, k);
253 phitilde[ps_idx[p]] = acc;
260 for (std::size_t s = 0; s < S; ++s) {
266 for (std::size_t a = 0; a < fsz[s]; ++a)
267 for (std::size_t b = 0; b < fsz[s]; ++b) blk(a, b) = scale * station[s].sub[i](a, b);
268 for (std::size_t a = 0; a < fsz[s]; ++a)
269 for (std::size_t b = 0; b < fsz[s]; ++b) D0(off[s] + a, off[s] + b) += blk(a, b);
272 for (std::size_t a = 0; a < fsz[s]; ++a) {
274 for (std::size_t b = 0; b < fsz[s]; ++b) acc += blk(a, b);
277 for (std::size_t sp = 0; sp < S; ++sp)
278 for (std::size_t a = 0; a < fsz[s]; ++a)
279 for (std::size_t b = 0; b < fsz[sp]; ++b)
280 D0(off[s] + a, off[sp] + b) +=
281 compl_[a] * R[i](s + 1, sp + 1) * station[sp].alpha(i, b);
282 for (std::size_t a = 0; a < fsz[s]; ++a)
283 pe[off[s] + a] = R[i](0, s + 1) * station[s].alpha(i, a);
288 for (std::size_t a = 0; a < Phi; ++a)
289 for (std::size_t b = 0; b < Phi; ++b) A(a, b) = -D0(a, b);
291 const std::vector<std::size_t> piv =
lu_factor(LU);
294 std::vector<T> y2 = y;
297 for (std::size_t a = 0; a < Phi; ++a) {
303 throw NumericError(
"retrieval_fpi_latency: zero mean fetch period");
309 for (std::size_t i = 0; i < n; ++i) {
310 num += out.
phi[i] + out.
d[i];
311 den += lambda[i] * (out.
phi[i] + out.
pi0[i]);
314 throw NumericError(
"retrieval_fpi_latency: no fetching traffic, the latency is undefined");