5#ifndef LINE_SOLVERS_MAM_SOLVER_MAM_PASSAGE_TIME_H
6#define LINE_SOLVERS_MAM_SOLVER_MAM_PASSAGE_TIME_H
82 "solver_mam_passage_time: the sojourn-time law comes from the age process, whose "
83 "first-return matrix is a tolerance-terminated Riccati doubling; rerun with "
84 "--arith double or --arith real");
93 if (!std::isinf(c.
population)) allopen =
false;
94 if (M != 2 || !allopen)
96 "solver_mam_passage_time: the MAM response-time distribution covers a single open "
97 "queue only (exactly two stations, a Source and one queue, every class open); this "
98 "model has " + std::to_string(M) +
99 " stations. The reference warns and returns no result at all for it");
101 std::size_t src = 0, q = 0;
102 for (std::size_t i = 1; i <= M; ++i) {
103 if (L.
stations[i - 1].sched == SchedStrategy::EXT) src = i;
106 if (src == 0 || q == 0)
108 "solver_mam_passage_time: the model must have a Source and one queueing station");
111 if (!(qs == SchedStrategy::FCFS || qs == SchedStrategy::HOL ||
112 qs == SchedStrategy::FCFSPRPRIO || qs == SchedStrategy::PS))
115 " discipline is not covered; the reference supports FCFS, HOL, "
116 "FCFSPRPRIO and PS only");
120 bool prio_distinct =
false;
121 if (qs == SchedStrategy::HOL || qs == SchedStrategy::FCFSPRPRIO)
122 for (std::size_t r = 1; r < K; ++r)
125 const std::size_t npts =
126 opt.num_cdf_pts > 0 ?
opt.num_cdf_pts :
static_cast<std::size_t
>(100);
131 std::vector<Mmap<T>> parts;
132 for (std::size_t r = 0; r < K; ++r) {
137 m.
Dc.assign(1, s.
D1);
141 for (std::size_t p = 1; p < parts.size(); ++p)
145 std::vector<RespTCdf<T>> out(K);
147 if (qs == SchedStrategy::PS) {
150 std::vector<T> mu(K, zero);
151 for (std::size_t r = 0; r < K; ++r) {
153 if (sv.
D0.rows() != 1)
155 "solver_mam_passage_time: a PS queue requires exponential (order-1) service "
156 "times; the MAP/M/1-PS sojourn law has no phase-type generalization here");
157 mu[r] = T(-sv.
D0(0, 0));
159 for (std::size_t r = 1; r < K; ++r)
163 "solver_mam_passage_time: multi-class PS requires identical service rates");
166 for (std::size_t c = 0; c < A.
classes(); ++c)
167 for (std::size_t i = 0; i < Dagg.
rows(); ++i)
168 for (std::size_t j = 0; j < Dagg.
cols(); ++j) Dagg(i, j) += A.
Dc[c](i, j);
170 const T rho = T(lambda / mu[0]);
173 "solver_mam_passage_time: the PS queue is unstable, so it has no sojourn-time "
175 const T mean = T(one / T(mu[0] * T(one - rho)));
177 std::vector<T> x(npts, zero);
178 for (std::size_t i = 0; i < npts; ++i)
179 x[i] = (npts == 1) ? xmax
181 static_cast<double>(i) /
182 static_cast<double>(npts - 1)));
184 for (std::size_t r = 0; r < K; ++r) {
186 out[r].F.resize(npts);
187 for (std::size_t i = 0; i < npts; ++i) out[r].F[i] = T(one - res.
w_bar[i]);
193 std::vector<PhService<T>> svc(K);
194 for (std::size_t r = 0; r < K; ++r) {
195 const double ns = L.
stations[q - 1].nservers;
197 const T target = std::isfinite(ns)
209 std::vector<std::size_t> iK(K);
210 for (std::size_t r = 0; r < K; ++r) iK[r] = r;
211 std::stable_sort(iK.begin(), iK.end(), [&L](std::size_t a, std::size_t b) {
212 return L.classes[a].prio > L.classes[b].prio;
214 for (std::size_t j = 1; j < K; ++j)
217 "solver_mam_passage_time: SolverMAM requires either identical priorities or "
218 "all distinct priorities");
222 std::vector<PhService<T>> sl;
223 for (std::size_t j = 0; j < K; ++j) {
224 pa.
Dc.push_back(A.
Dc[iK[j]]);
225 sl.push_back(svc[iK[j]]);
227 const bool pr = (qs == SchedStrategy::FCFSPRPRIO);
228 const std::vector<std::vector<T>> moms =
231 for (std::size_t j = 0; j < K; ++j) {
234 xmax = std::max(xmax, m1 + 10.0 * std::sqrt(std::max(m2 - m1 * m1, 0.0)));
236 std::vector<T> x(npts, zero);
237 for (std::size_t i = 0; i < npts; ++i)
240 static_cast<double>(npts - 1));
242 throw InputError(
"solver_mam_passage_time: the priority CDF grid needs at least two "
243 "points, since F(0) = 0 is prepended rather than evaluated");
244 const std::vector<T> pts(x.begin() + 1, x.end());
245 const std::vector<std::vector<T>> dist =
247 for (std::size_t j = 0; j < K; ++j) {
251 o.
F.insert(o.
F.end(), dist[j].begin(), dist[j].end());
258 for (std::size_t r = 0; r < K; ++r) {
261 const std::size_t n = ph[r].A.rows();
263 for (std::size_t i = 0; i < n; ++i) {
265 for (std::size_t j = 0; j < n; ++j) s += ph[r].A(i, j);
266 for (std::size_t j = 0; j < n; ++j) D1(i, j) = T(-s * ph[r].alpha[j]);
268 const Map<T> RDph{ph[r].A, D1};
276 const std::vector<T> c =
map_cdf(RDph, std::vector<T>{probe});
280 "solver_mam_passage_time: the sojourn-time CDF did not reach one within 1000 "
281 "standard deviations");
284 std::vector<T> x(npts, zero);
285 for (std::size_t i = 0; i < npts; ++i)
286 x[i] = (npts == 1) ? xmax
288 static_cast<double>(i) /
289 static_cast<double>(npts - 1)));
312 if (cdf.
F.empty())
throw InputError(
"mam_percentiles_from_cdf: the CDF is empty");
313 std::vector<double> p, t;
314 for (std::size_t i = 0; i < cdf.
F.size(); ++i) {
316 if (!p.empty() && std::fabs(fi - p.back()) < 1e-15) {
323 std::vector<T> out(pcts.size(), zero);
324 for (std::size_t k = 0; k < pcts.size(); ++k) {
326 const double want = pcts[k] > 1.0 ? pcts[k] / 100.0 : pcts[k];
332 while (lo + 2 < p.size() && p[lo + 1] < want) ++lo;
333 const double denom = p[lo + 1] - p[lo];
334 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...
The MMAP[K]/PH[K]/1 priority queue, preemptive resume (mmapph1prpr_*) and non-preemptive (mmapph1nppr...
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< std::vector< T > > mmapph1prpr_stdistr(const Mmap< T > &arrival, const std::vector< PhService< T > > &svc, const std::vector< T > &points, const PrioQueueOptions &opt=PrioQueueOptions())
Per-class sojourn-time CDF at the (strictly positive) points, preemptive resume priority.
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.
std::vector< std::vector< T > > mmapph1nppr_stdistr(const Mmap< T > &arrival, const std::vector< PhService< T > > &svc, const std::vector< T > &points, const PrioQueueOptions &opt=PrioQueueOptions())
Per-class sojourn-time CDF at the (strictly positive) points, non-preemptive priority.
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< std::vector< T > > mmapph1prpr_stmoms(const Mmap< T > &arrival, const std::vector< PhService< T > > &svc, std::size_t n, const PrioQueueOptions &opt=PrioQueueOptions())
Per-class sojourn-time moments 1..n, preemptive resume priority.
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 ...
std::vector< std::vector< T > > mmapph1nppr_stmoms(const Mmap< T > &arrival, const std::vector< PhService< T > > &svc, std::size_t n, const PrioQueueOptions &opt=PrioQueueOptions())
Per-class sojourn-time moments 1..n, non-preemptive priority.
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_...
Conservation laws of a layered queueing network, enumerated from its structure.
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