5#ifndef LINE_SOLVERS_MAM_SOLVER_MAM_PASSAGE_TIME_H
6#define LINE_SOLVERS_MAM_SOLVER_MAM_PASSAGE_TIME_H
80 "solver_mam_passage_time: the sojourn-time law comes from the age process, whose "
81 "first-return matrix is a tolerance-terminated Riccati doubling; rerun with "
82 "--arith double or --arith real");
91 if (!std::isinf(c.
population)) allopen =
false;
92 if (M != 2 || !allopen)
94 "solver_mam_passage_time: the MAM response-time distribution covers a single open "
95 "queue only (exactly two stations, a Source and one queue, every class open); this "
96 "model has " + std::to_string(M) +
97 " stations. The reference warns and returns no result at all for it");
99 std::size_t src = 0, q = 0;
100 for (std::size_t i = 1; i <= M; ++i) {
101 if (L.
stations[i - 1].sched == SchedStrategy::EXT) src = i;
104 if (src == 0 || q == 0)
106 "solver_mam_passage_time: the model must have a Source and one queueing station");
109 if (!(qs == SchedStrategy::FCFS || qs == SchedStrategy::HOL || qs == SchedStrategy::PS))
112 " discipline is not covered; the reference supports FCFS, HOL and "
117 if (qs == SchedStrategy::HOL) {
118 bool distinct =
false;
119 for (std::size_t r = 1; r < K; ++r)
123 "solver_mam_passage_time: non-identical class priorities under HOL route to "
124 "BUTools' MMAPPH1NPPR (MMAPPH1PRPR when preemptive), whose tabulated sojourn law "
125 "MATLAB, the JAR and python now serve; neither priority analyzer is ported to "
126 "C++, so this arm still refuses by name");
129 const std::size_t npts =
130 opt.num_cdf_pts > 0 ?
opt.num_cdf_pts :
static_cast<std::size_t
>(100);
135 std::vector<Mmap<T>> parts;
136 for (std::size_t r = 0; r < K; ++r) {
141 m.
Dc.assign(1, s.
D1);
145 for (std::size_t p = 1; p < parts.size(); ++p)
149 std::vector<RespTCdf<T>> out(K);
151 if (qs == SchedStrategy::PS) {
154 std::vector<T> mu(K, zero);
155 for (std::size_t r = 0; r < K; ++r) {
157 if (sv.
D0.rows() != 1)
159 "solver_mam_passage_time: a PS queue requires exponential (order-1) service "
160 "times; the MAP/M/1-PS sojourn law has no phase-type generalization here");
161 mu[r] = T(-sv.
D0(0, 0));
163 for (std::size_t r = 1; r < K; ++r)
167 "solver_mam_passage_time: multi-class PS requires identical service rates");
170 for (std::size_t c = 0; c < A.
classes(); ++c)
171 for (std::size_t i = 0; i < Dagg.
rows(); ++i)
172 for (std::size_t j = 0; j < Dagg.
cols(); ++j) Dagg(i, j) += A.
Dc[c](i, j);
174 const T rho = T(lambda / mu[0]);
177 "solver_mam_passage_time: the PS queue is unstable, so it has no sojourn-time "
179 const T mean = T(one / T(mu[0] * T(one - rho)));
181 std::vector<T> x(npts, zero);
182 for (std::size_t i = 0; i < npts; ++i)
183 x[i] = (npts == 1) ? xmax
185 static_cast<double>(i) /
186 static_cast<double>(npts - 1)));
188 for (std::size_t r = 0; r < K; ++r) {
190 out[r].F.resize(npts);
191 for (std::size_t i = 0; i < npts; ++i) out[r].F[i] = T(one - res.
w_bar[i]);
197 std::vector<PhService<T>> svc(K);
198 for (std::size_t r = 0; r < K; ++r) {
199 const double ns = L.
stations[q - 1].nservers;
201 const T target = std::isfinite(ns)
210 for (std::size_t r = 0; r < K; ++r) {
213 const std::size_t n = ph[r].A.rows();
215 for (std::size_t i = 0; i < n; ++i) {
217 for (std::size_t j = 0; j < n; ++j) s += ph[r].A(i, j);
218 for (std::size_t j = 0; j < n; ++j) D1(i, j) = T(-s * ph[r].alpha[j]);
220 const Map<T> RDph{ph[r].A, D1};
228 const std::vector<T> c =
map_cdf(RDph, std::vector<T>{probe});
232 "solver_mam_passage_time: the sojourn-time CDF did not reach one within 1000 "
233 "standard deviations");
236 std::vector<T> x(npts, zero);
237 for (std::size_t i = 0; i < npts; ++i)
238 x[i] = (npts == 1) ? xmax
240 static_cast<double>(i) /
241 static_cast<double>(npts - 1)));
264 if (cdf.
F.empty())
throw InputError(
"mam_percentiles_from_cdf: the CDF is empty");
265 std::vector<double> p, t;
266 for (std::size_t i = 0; i < cdf.
F.size(); ++i) {
268 if (!p.empty() && std::fabs(fi - p.back()) < 1e-15) {
275 std::vector<T> out(pcts.size(), zero);
276 for (std::size_t k = 0; k < pcts.size(); ++k) {
278 const double want = pcts[k] > 1.0 ? pcts[k] / 100.0 : pcts[k];
284 while (lo + 2 < p.size() && p[lo + 1] < want) ++lo;
285 const double denom = p[lo + 1] - p[lo];
286 const double frac = (std::fabs(denom) < 1e-300) ? 0.0 : (want - p[lo]) / denom;
NumericError(const std::string &what)
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
std::vector< std::vector< Distrib< T > > > service
service[i][r], 0-based station and class; a disabled entry marks a pair never visited.
std::vector< JobClass > classes
std::vector< Station< T > > stations
stations[k-1] is the k-th station
What refreshProcessRepresentations and refreshLST compute FROM a distribution: the (D0,...
The exception types the port throws.
The option and result types SolverMAM shares with its analyzers.
Cumulative distribution of the inter-arrival time of a MAP.
Sojourn time distribution in a MAP/M/1 processor-sharing queue.
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
Dense matrix and non-owning view.
The MMAP assembly primitives solver_mam_basic.m builds its per-station arrival stream from: mmap_expo...
The MMAP[K]/PH[K]/1 FCFS queue: per-class mean number in system and per-class queue-length distributi...
mam::Map< T > dist_to_map(const Distrib< T > &d)
SchedStrategy
Scheduling disciplines, with the values of MATLAB SchedStrategy.
const char * sched_to_text(SchedStrategy s)
std::vector< T > mam_percentiles_from_cdf(const RespTCdf< T > &cdf, const std::vector< double > &pcts)
Port of the CDF path of @@SolverMAM/getPerctRespT.m: linear interpolation of the response-time CDF at...
T map_mean(const Map< T > &m)
Mean inter-arrival time, 1/lambda.
T map_var(const Map< T > &m)
Variance of the inter-arrival time.
std::vector< RespTCdf< T > > solver_mam_passage_time(const qn::NetworkStruct< T > &L, const MamOptions &opt)
Port of solver_mam_passage_time.m.
std::vector< T > map_cdf(const Map< T > &m, const std::vector< T > &points)
Cumulative distribution of the inter-arrival time at the given points.
Map< T > map_scale(const Map< T > &in, const T &new_mean)
Rescale time so that the mean inter-arrival time becomes new_mean.
std::vector< T > map_pie(const Map< T > &m)
Phase distribution seen by an arriving job, pie = pi D1 / (pi D1 e).
std::vector< StDistrPh< T > > mmapph1fcfs_stdistr_ph(const Mmap< T > &arrival, const std::vector< PhService< T > > &svc, double precision=1e-14)
Per-class SOJOURN TIME as a continuous phase-type law, BUTools' 'stDistrPH'.
Mmap< T > mmap_super(const Mmap< T > &a, const Mmap< T > &b)
Superposition of two MMAPs: the phase process is the product chain, and the class list of the result ...
T map_lambda(const Map< T > &m)
Stationary arrival rate, lambda = pi D1 e.
MapM1psResult< T > map_m1ps_cdfrespt(const Matrix< T > &C, const Matrix< T > &D, const T &mu, const std::vector< T > &x, const T &epsilon, const T &epsilon_prime)
Complementary sojourn time distribution of a MAP/M/1-PS queue by the spectral-radius truncation (map_...
A queueing network and its refreshed NetworkStruct.
The MATLAB GlobalConstants, as reported by lineStart at its defaults.
static constexpr double FineTol
The options SolverMAM reads.
What the two MAP/M/1-PS sojourn entry points return.
std::vector< T > w_bar
Pr[W > x] at each requested point.
A MAP as the pair of matrices (D0, D1).
An MMAP: the underlying MAP plus the per-class arrival matrices.
std::size_t classes() const
std::vector< Matrix< T > > Dc
per-class matrices, sum_c Dc = D1
std::size_t order() const
One class's response-time CDF, the reference's RD{station, class} = [F, X].
std::vector< T > X
the points they are evaluated at
std::vector< T > F
CDF values.
One job class of the network.
double population
infinite for an open class