5#ifndef LINE_API_FJ_FJ_CODES_MATRICES_H
6#define LINE_API_FJ_FJ_CODES_MATRICES_H
100 if (m == 0)
throw InputError(
"fj_build_index: m must be positive");
102 std::size_t total = 1;
103 for (std::size_t k = 1; k <= cr; ++k) total = total * (cr + m - k) / k;
105 idx(0, 0) =
static_cast<double>(cr);
106 for (std::size_t row = 1; row < total; ++row) {
108 for (std::size_t j = 0; j < m; ++j)
109 if (idx(row - 1, j) > 0.0) {
114 for (std::size_t j = 0; j < m; ++j) idx(row, j) = idx(row - 1, j);
115 idx(row, k + 1) += 1.0;
116 idx(row, 0) = idx(row, k) - 1.0;
117 for (std::size_t j = 1; j <= k; ++j) idx(row, j) = 0.0;
131 if (row.size() != matrix.
cols())
132 throw InputError(
"fj_vectmatch: the probe and the table have different widths");
133 for (std::size_t i = 0; i < matrix.
rows(); ++i) {
135 for (std::size_t j = 0; j < matrix.
cols(); ++j)
136 if (matrix(i, j) != row[j]) {
142 throw NumericError(
"fj_vectmatch: the target phase is not in the phase table, so the "
143 "fork-join state space is not closed under its own transitions");
148 const std::size_t m = service.
tau_st.size();
150 for (std::size_t i = 0; i < m; ++i) {
152 for (std::size_t j = 0; j < m; ++j) s += service.
ST(i, j);
153 for (std::size_t j = 0; j < m; ++j) A(i, j) = -s * service.
tau_st[j];
160 const std::size_t m = service.
tau_st.size();
161 if (m == 0)
throw InputError(
"fj_build_service_h: the service process has no phases");
167 for (std::size_t i = 0; i < m; ++i)
168 for (std::size_t j = 0; j < m; ++j) {
169 for (std::size_t c = 0; c < m; ++c) {
175 h.
beta.assign(m * m, 0.0);
176 for (std::size_t i = 0; i < m; ++i)
177 for (std::size_t j = 0; j < m; ++j)
193 throw InputError(
"fj_build_sa: the FJ_codes truncation C must be at least 1 (the "
194 "reference indexes the c = C - 1 block unconditionally)");
195 const std::size_t dim = h.
beta.size();
196 const std::size_t m = service.
tau_st.size();
197 const std::size_t dim_C = C + 1;
198 const std::size_t newdim = dim_C * dim;
204 for (std::size_t b = 0; b < dim_C; ++b)
205 for (std::size_t i = 0; i < dim; ++i)
206 for (std::size_t j = 0; j < dim; ++j) out.
S(b * dim + i, b * dim + j) = h.
S(i, j);
212 for (std::size_t row = 0; row < dim; ++row)
213 for (std::size_t i = 0; i < m; ++i) {
215 if (cnt <= 0.0)
continue;
216 for (std::size_t j = 0; j < m; ++j) {
217 std::vector<double> to(2 * m);
218 for (std::size_t c = 0; c < 2 * m; ++c) to[c] = h.
service_phases(row, c);
224 for (std::size_t b = 0; b + 1 < dim_C; ++b)
225 for (std::size_t i = 0; i < dim; ++i)
226 for (std::size_t j = 0; j < dim; ++j)
227 out.
S(b * dim + i, (b + 1) * dim + j) = S_Cminus1(i, j);
232 for (std::size_t row = 0; row < dim; ++row)
233 for (std::size_t i = m; i < 2 * m; ++i) {
235 for (std::size_t j = m; j < 2 * m; ++j) {
236 std::vector<double> to(2 * m);
237 for (std::size_t c = 0; c < 2 * m; ++c) to[c] = h.
service_phases(row, c);
243 for (std::size_t b = 1; b + 1 < dim_C; ++b)
244 for (std::size_t i = 0; i < dim; ++i)
245 for (std::size_t j = 0; j < dim; ++j)
246 out.
A_jump(b * dim + i, (b - 1) * dim + j) = A_Cplus1(i, j);
247 for (std::size_t i = 0; i < dim; ++i)
248 for (std::size_t j = 0; j < dim; ++j) out.
A_jump(i, j) = A_Cplus1(i, j);
253 for (std::size_t row = 0; row < dim; ++row)
254 for (std::size_t k = 0; k < 2; ++k)
255 for (std::size_t i = 0; i < m; ++i) {
257 if (cnt <= 0.0)
continue;
258 std::vector<double> other(m);
259 for (std::size_t c = 0; c < m; ++c)
261 for (std::size_t j = 0; j < m; ++j) {
262 std::vector<double> to(2 * m, 0.0);
263 for (std::size_t c = 0; c < m; ++c) to[c] = other[c];
268 for (std::size_t i = 0; i < dim; ++i)
269 for (std::size_t j = 0; j < dim; ++j)
270 out.
A_jump(C * dim + i, (C - 1) * dim + j) = A_last(i, j);
287 const std::size_t dim = h.
beta.size();
288 const std::size_t m = service.
tau_st.size();
289 const std::size_t dim_NB = idle_phases.
rows();
293 for (std::size_t row = 0; row < dim; ++row)
294 for (std::size_t i = m; i < 2 * m; ++i) {
296 if (cnt <= 0.0)
continue;
297 std::vector<double> to(m);
298 for (std::size_t c = 0; c < m; ++c) to[c] = h.
service_phases(row, c);
299 S_long(row,
fj_vectmatch(to, idle_phases)) += cnt * service.
St[i - m];
302 for (std::size_t row = 0; row < dim; ++row)
303 for (std::size_t k = 0; k < 2; ++k)
304 for (std::size_t i = k * m; i < (k + 1) * m; ++i) {
306 if (cnt <= 0.0)
continue;
307 std::vector<double> to(m);
308 for (std::size_t c = 0; c < m; ++c)
310 S_last(row,
fj_vectmatch(to, idle_phases)) += cnt * service.
St[i - k * m];
318 const std::size_t dim = h.
beta.size();
319 const std::size_t m = service.
tau_st.size();
321 const std::size_t dim_NB = idle.
rows();
322 const std::size_t dim_C = C + 1;
330 std::vector<double> t(n, 0.0);
331 for (std::size_t i = 0; i < dim_NB; ++i) t[n - dim_NB + i] = service.
St[i];
333 for (std::size_t i = 0; i < out.
newdim; ++i)
334 for (std::size_t j = 0; j < out.
newdim; ++j) out.
T(i, j) = S(i, j);
339 for (std::size_t b = 0; b + 1 < dim_C; ++b)
340 for (std::size_t i = 0; i < dim; ++i)
341 for (std::size_t j = 0; j < dim_NB; ++j)
342 out.
T(b * dim + i, out.
newdim + b * dim_NB + j) = S_long(i, j);
343 for (std::size_t i = 0; i < dim; ++i)
344 for (std::size_t j = 0; j < dim_NB; ++j)
345 out.
T((dim_C - 1) * dim + i, out.
newdim + (dim_C - 1) * dim_NB + j) = S_last(i, j);
347 for (std::size_t b = 0; b < dim_C; ++b)
348 for (std::size_t i = 0; i < dim_NB; ++i)
349 for (std::size_t j = 0; j < dim_NB; ++j)
350 out.
T(out.
newdim + b * dim_NB + i, out.
newdim + b * dim_NB + j) = service.
ST(i, j);
353 for (std::size_t b = 0; b + 1 < dim_C; ++b)
354 for (std::size_t i = 0; i < dim_NB; ++i)
355 for (std::size_t j = 0; j < dim_NB; ++j)
356 out.
T(out.
newdim + b * dim_NB + i, out.
newdim + (b + 1) * dim_NB + j) = A(i, j);
358 for (std::size_t row = out.
newdim; row < n; ++row) {
359 out.
T(row, row) = 0.0;
361 for (std::size_t j = 0; j < n; ++j) s += out.
T(row, j);
362 out.
T(row, row) = -s - t[row];
372 throw InputError(
"fj_construct_not_all_busy: the FJ_codes truncation C must be at least 1");
373 const std::size_t m = service.
tau_st.size();
375 const std::size_t dim_C = C + 1;
376 const std::size_t n = (dim_C - 1) * dim_NB + 1;
379 for (std::size_t b = 0; b + 1 < dim_C; ++b)
380 for (std::size_t i = 0; i < dim_NB; ++i)
381 for (std::size_t j = 0; j < dim_NB; ++j)
382 out(b * dim_NB + i, b * dim_NB + j) = service.
ST(i, j);
385 for (std::size_t b = 0; b + 2 < dim_C; ++b)
386 for (std::size_t i = 0; i < dim_NB; ++i)
387 for (std::size_t j = 0; j < dim_NB; ++j)
388 out(b * dim_NB + i, (b + 1) * dim_NB + j) = A(i, j);
391 for (std::size_t i = 0; i < dim_NB; ++i)
392 out((dim_C - 2) * dim_NB + i, n - 1) = service.
St[i];
394 for (std::size_t row = 0; row < n; ++row) {
397 for (std::size_t j = 0; j < n; ++j) s += out(row, j);
406 if (C < 1)
throw InputError(
"fj_construct_srk: the FJ_codes truncation C must be at least 1");
407 const std::size_t dim = h.
beta.size();
408 const std::size_t m = service.
tau_st.size();
410 const std::size_t dim_NB = idle.
rows();
411 const std::size_t dim_C = C + 1;
412 const std::size_t newdim = dim_C * dim;
413 const std::size_t dim_notbusy = (dim_C - 1) * dim_NB + 1;
414 const std::size_t n = newdim + dim_notbusy;
419 for (std::size_t i = 0; i < newdim; ++i)
420 for (std::size_t j = 0; j < newdim; ++j) out.
Se(i, j) = S(i, j);
429 for (std::size_t i = 0; i < dim; ++i)
430 for (std::size_t j = 0; j < dim_NB; ++j) out.
Se(i, newdim + j) = S_long(i, j);
431 for (std::size_t b = 1; b + 1 < dim_C; ++b)
432 for (std::size_t i = 0; i < dim; ++i)
433 for (std::size_t j = 0; j < dim_NB; ++j)
434 out.
Se(b * dim + i, newdim + (b - 1) * dim_NB + j) = S_long(i, j);
435 for (std::size_t i = 0; i < dim; ++i)
436 for (std::size_t j = 0; j < dim_NB; ++j)
437 out.
Se((dim_C - 1) * dim + i, newdim + (dim_C - 2) * dim_NB + j) = S_last(i, j);
439 for (std::size_t i = 0; i < newdim; ++i)
440 for (std::size_t j = newdim; j < n; ++j) out.
Sestar(i, j) = out.
Se(i, j);
442 for (std::size_t b = 0; b + 1 < dim_C; ++b)
443 for (std::size_t i = 0; i < dim_NB; ++i)
444 for (std::size_t j = 0; j < dim_NB; ++j)
445 out.
Se(newdim + b * dim_NB + i, newdim + b * dim_NB + j) = service.
ST(i, j);
448 for (std::size_t b = 0; b + 2 < dim_C; ++b)
449 for (std::size_t i = 0; i < dim_NB; ++i)
450 for (std::size_t j = 0; j < dim_NB; ++j)
451 out.
Se(newdim + b * dim_NB + i, newdim + (b + 1) * dim_NB + j) = A(i, j);
453 for (std::size_t i = 0; i < dim_NB; ++i)
454 out.
Se(newdim + (dim_C - 2) * dim_NB + i, n - 1) = service.
St[i];
456 for (std::size_t row = newdim; row < n; ++row) {
457 out.
Se(row, row) = 0.0;
459 for (std::size_t j = 0; j < n; ++j) s += out.
Se(row, j);
460 out.
Se(row, row) = -s;
468 for (std::size_t row = 0; row < dim_NB; ++row)
469 for (std::size_t i = 0; i < m; ++i) {
470 std::vector<double> to(2 * m, 0.0);
471 for (std::size_t c = 0; c < m; ++c) to[c] = idle(row, c);
475 for (std::size_t b = 0; b + 1 < dim_C; ++b)
476 for (std::size_t i = 0; i < dim_NB; ++i)
477 for (std::size_t j = 0; j < dim; ++j)
478 out.
R0(newdim + b * dim_NB + i, b * dim + j) = R_NB(i, j);
479 for (std::size_t j = 0; j < dim; ++j) out.
R0(n - 1, newdim - dim + j) = h.
beta[j];
482 for (std::size_t i = 0; i < newdim; ++i) out.
Ke(i, i) = 1.0;
484 for (std::size_t i = 0; i < newdim; ++i) out.
Kc(i, i) = 1.0;
NumericError(const std::string &what)
The exception types the port throws.
Conversion of a LINE MAP into the arrival or service descriptor of the fork-join response-time-tail a...
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
Dense matrix and non-owning view.
Marked MAP (MMAP) algebra: per-class rates, class probabilities, superposition, normalization and sca...
std::size_t fj_vectmatch(const std::vector< double > &row, const Matrix< double > &matrix)
Port of vectmatch.m: the row of matrix equal to row.
Matrix< double > fj_restart_matrix(const FjDist< double > &service)
The reference's A = -sum(ST, 2) * tau_st: complete, then restart.
FjCodesSRK fj_construct_srk(std::size_t C, const FjDist< double > &service, const FjCodesServiceH &h, const Matrix< double > &S)
Port of constructSRK.m.
FjCodesServiceH fj_build_service_h(const FjDist< double > &service)
Port of build_Service_h.m.
FjCodesGenService fj_generate_service(const FjDist< double > &service, const FjCodesServiceH &h, std::size_t C, const Matrix< double > &S)
Port of generateService.m.
void fj_busy_to_idle(const FjDist< double > &service, const FjCodesServiceH &h, const Matrix< double > &idle_phases, Matrix< double > &S_long, Matrix< double > &S_last)
The busy-to-not-busy blocks S_long and S_last, shared verbatim by generateService....
Matrix< double > fj_construct_not_all_busy(std::size_t C, const FjDist< double > &service, const FjCodesServiceH &h)
Port of constructNotAllBusy.m.
FjCodesSA fj_build_sa(const FjDist< double > &service, const FjCodesServiceH &h, std::size_t C)
Port of build_SA.m.
Matrix< double > fj_build_index(std::size_t m, std::size_t cr)
Port of build_index.m: the compositions of cr into m non-negative parts, one per row,...
Matrix< T > krons(const Matrix< T > &A, const Matrix< T > &B)
Kronecker sum, MATLAB's krons: kron(A, I_nb) + kron(I_na, B).
generateService.m: the service process seen by a tagged job.
Matrix< double > T
(newdim + dim_notbusy) square
std::size_t newdim
the all-busy part
std::size_t dim_notbusy
the not-all-busy part
build_SA.m: the level-constant generator and the head-of-line jump.
Matrix< double > A_jump
a job completes and the next enters service
Matrix< double > S
no job completes, ((C+1) m^2) square
constructSRK.m: the extended generator and the busy/idle projectors.
Matrix< double > R0
not-busy to busy, on an arrival
Matrix< double > Se
busy and not-busy phases together
Matrix< double > Sestar
the busy-to-not-busy block of Se, in place
Matrix< double > Ke
newdim x (newdim + dim_notbusy), the busy rows
Matrix< double > Kc
(newdim + dim_notbusy) x newdim, the busy columns
build_Service_h.m: the two-subtask phase process of one fork-join job.
Matrix< double > service_phases
(m^2) x (2m) count vectors, [long, short]
std::vector< double > beta
kron(tau_st, tau_st), length m^2
Matrix< double > S
kronsum(ST, ST), (m^2) x (m^2)
Descriptor of an arrival or a service process.