LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
fj_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_SOLVERS_FJ_METRICS_H
6#define LINE_SOLVERS_FJ_METRICS_H
7
8/**
9 * @file
10 * @ingroup line_solvers
11 * Fork-join section metrics: FJQLen, FJRespT and FJTput of every Fork/Join pair.
12 *
13 * The reference keeps them in `self.result.FJ` (struct forks, joins, QLen, RespT,
14 * Tput) and reports them through `getAvgFJ` and `getAvgFJTable`, separately from
15 * the average table, whose layout is unchanged on a fork-join model. A PAIR is a
16 * nonzero (f, j) of `sn.fj`, and the pairs are ordered by fork node and then by
17 * join node, which is `sortrows([forks joins])` in `fjFixedPoint.m`.
18 *
19 * FJRespT(p,r) mean time from a class-r job's arrival at the Fork of pair p to
20 * its departure from the matching Join;
21 * FJTput(p,r) class-r throughput through the pair;
22 * FJQLen(p,r) mean number of class-r jobs inside the section.
23 *
24 * Who fills it: MVA, NC and Fluid from the fork-join fixed point (fj_driver.h,
25 * FJQLen = FJTput * FJRespT exactly), JMT from its 'Fork Join Response Time' and
26 * 'Fork Join Number of Customers' measures, and LDES from the per-fork-job
27 * sojourns it measures. Every other solver leaves it EMPTY, and so does every
28 * model without a Fork/Join pair: absent is not zero.
29 */
30
31#include <algorithm>
32#include <cstddef>
33#include <utility>
34#include <vector>
35
36#include "line/util/matrix.h"
37
38namespace line {
39namespace solvers {
40
41/** `self.result.FJ`: one row per Fork/Join pair, one column per class. */
42template <class T>
43struct FjMetrics {
44 std::vector<std::size_t> forks; ///< 1-based fork node of each pair
45 std::vector<std::size_t> joins; ///< 1-based join node of each pair
46 Matrix<T> QLen; ///< FJQLen, P x R
47 Matrix<T> RespT; ///< FJRespT, P x R
48 Matrix<T> Tput; ///< FJTput, P x R
49 /** Whether a solver reported the metrics at all; false on a model without pairs. */
50 bool computed = false;
51 /** No pair to report: a model without Fork/Join, or a solver that does not compute them. */
52 bool empty() const { return !computed || forks.empty(); }
53 std::size_t npairs() const { return forks.size(); }
54};
55
56/**
57 * The Fork/Join pairs of a struct, `sortrows([forks joins])` over `find(sn.fj)`:
58 * ascending in fork node, then in join node, with duplicates removed. `S` is any
59 * struct carrying `fj` as a vector of 1-based (fork, join) pairs.
60 */
61template <class S>
62std::vector<std::pair<std::size_t, std::size_t>> fj_sorted_pairs(const S& sn) {
63 std::vector<std::pair<std::size_t, std::size_t>> p;
64 for (const auto& e : sn.fj)
65 if (e.first != 0 && e.second != 0) p.push_back(e);
66 std::sort(p.begin(), p.end());
67 p.erase(std::unique(p.begin(), p.end()), p.end());
68 return p;
69}
70
71/** An empty-but-shaped result: every pair of `sn`, all three matrices zero. */
72template <class T, class S>
73FjMetrics<T> fj_metrics_zero(const S& sn, std::size_t nclasses) {
74 FjMetrics<T> out;
75 const std::vector<std::pair<std::size_t, std::size_t>> p = fj_sorted_pairs(sn);
76 for (const auto& e : p) {
77 out.forks.push_back(e.first);
78 out.joins.push_back(e.second);
79 }
80 const T zero = num_traits<T>::from_int(0);
81 out.QLen = Matrix<T>(p.size(), nclasses, zero);
82 out.RespT = Matrix<T>(p.size(), nclasses, zero);
83 out.Tput = Matrix<T>(p.size(), nclasses, zero);
84 out.computed = true;
85 return out;
86}
87
88/** The same metrics in double precision, for the facade and the CLI. */
89template <class T>
92 out.forks = in.forks;
93 out.joins = in.joins;
94 out.computed = in.computed;
95 const Matrix<T>* src[3] = {&in.QLen, &in.RespT, &in.Tput};
96 Matrix<double>* dst[3] = {&out.QLen, &out.RespT, &out.Tput};
97 for (int m = 0; m < 3; ++m) {
98 *dst[m] = Matrix<double>(src[m]->rows(), src[m]->cols(), 0.0);
99 for (std::size_t i = 0; i < src[m]->rows(); ++i)
100 for (std::size_t j = 0; j < src[m]->cols(); ++j)
101 (*dst[m])(i, j) = num_traits<T>::to_double((*src[m])(i, j));
102 }
103 return out;
104}
105
106} // namespace solvers
107} // namespace line
108
109#endif // LINE_SOLVERS_FJ_METRICS_H
std::size_t cols() const
Definition matrix.h:90
std::size_t rows() const
Definition matrix.h:89
Dense matrix and non-owning view.
std::vector< std::pair< std::size_t, std::size_t > > fj_sorted_pairs(const S &sn)
The Fork/Join pairs of a struct, sortrows([forks joins]) over find(sn.fj): ascending in fork node,...
Definition fj_metrics.h:62
FjMetrics< double > fj_metrics_to_double(const FjMetrics< T > &in)
The same metrics in double precision, for the facade and the CLI.
Definition fj_metrics.h:90
FjMetrics< T > fj_metrics_zero(const S &sn, std::size_t nclasses)
An empty-but-shaped result: every pair of sn, all three matrices zero.
Definition fj_metrics.h:73
Conservation laws of a layered queueing network, enumerated from its structure.
Definition aoi_dist2ph.h:52
self.result.FJ: one row per Fork/Join pair, one column per class.
Definition fj_metrics.h:43
std::vector< std::size_t > forks
1-based fork node of each pair
Definition fj_metrics.h:44
bool computed
Whether a solver reported the metrics at all; false on a model without pairs.
Definition fj_metrics.h:50
Matrix< T > Tput
FJTput, P x R.
Definition fj_metrics.h:48
bool empty() const
No pair to report: a model without Fork/Join, or a solver that does not compute them.
Definition fj_metrics.h:52
Matrix< T > QLen
FJQLen, P x R.
Definition fj_metrics.h:46
std::size_t npairs() const
Definition fj_metrics.h:53
std::vector< std::size_t > joins
1-based join node of each pair
Definition fj_metrics.h:45
Matrix< T > RespT
FJRespT, P x R.
Definition fj_metrics.h:47