5#ifndef LINE_SOLVERS_NC_SOLVER_NC_CFTP_H
6#define LINE_SOLVERS_NC_SOLVER_NC_CFTP_H
80 unsigned long seed = 23000;
105namespace cftp_detail {
109 if (method ==
"cftp" || method ==
"cftp.exact" || method.empty())
112 throw InputError(
"SolverNC(cftp): unknown cftp variant '" + method +
113 "'. Use 'cftp' or 'cftp.approx'");
136 const std::size_t M =
sn.nstations;
137 if (
sn.nclasses != 1)
139 "SolverNC(cftp): the cftp method supports single-class models only, this model has " +
140 std::to_string(
sn.nclasses) +
" classes");
141 const std::vector<double> njobs =
sn.njobs();
142 if (!std::isfinite(njobs[0]) || njobs[0] < 1.0)
143 return (
"SolverNC(cftp): the cftp method supports closed models only, "
144 "with a finite positive population");
146 return (
"SolverNC(cftp): the cftp method requires at least two stations");
147 for (std::size_t ind = 0; ind <
sn.nodes.size(); ++ind) {
152 "SolverNC(cftp): the cftp method supports Queue, Delay and Router nodes only, "
154 std::to_string(ind + 1) +
" is of a different type");
156 for (std::size_t i = 0; i < M; ++i) {
162 "SolverNC(cftp): the cftp method requires a product-form scheduling strategy "
163 "(INF, PS, FCFS, SIRO, LCFSPR) at station " +
164 std::to_string(i + 1));
167 "SolverNC(cftp): the cftp method requires exponential service times, station " +
168 std::to_string(i + 1) +
" has " + std::to_string(sn.
phases_of(i + 1, 1)) +
170 if (std::isfinite(sn.
cap[i]) && sn.
cap[i] < njobs[0])
172 "SolverNC(cftp): the cftp method requires infinite buffers, station " +
173 std::to_string(i + 1) +
" has capacity " + std::to_string(sn.
cap[i]));
174 if (!(sn.
rates(i, 0) > zero))
175 return (
"SolverNC(cftp): the cftp method requires a finite positive "
176 "service rate at station " +
177 std::to_string(i + 1));
180 return (
"SolverNC(cftp): the cftp method does not support "
181 "load-dependent, class-dependent or joint-dependent service "
186 "SolverNC(cftp): the cftp method does not support finite capacity regions");
187 for (std::size_t ind = 0; ind < sn.
nodes.size(); ++ind)
188 for (std::size_t r = 0; r < sn.
nodes[ind].routing.size(); ++r) {
193 "SolverNC(cftp): the cftp method requires Markovian routing (PROB, RAND), "
195 std::to_string(ind + 1) +
" uses a state-dependent strategy");
197 return std::string();
207void cftp_assert(
const qn::NetworkStruct<T>& sn) {
208 const std::string reason = cftp_supports_reason(sn);
227 return cftp_detail::cftp_supports_reason(
sn);
241 "solver_nc_cftp draws random states and forms the station balance functions "
242 "in the log domain, neither of which exists in exact rational arithmetic");
244 const std::size_t M =
sn.nstations, R =
sn.nclasses;
247 cftp_detail::cftp_assert(
sn);
249 throw InputError(
"SolverNC(cftp): the cftp method requires a finite positive number of "
250 "samples; pass --samples");
253 std::vector<T> L(M, zero);
254 for (std::size_t i = 0; i < M; ++i) L[i] = ch.
Lchain(i, 0);
255 const int N =
static_cast<int>(ch.
Nchain[0]);
256 std::vector<int> S(M, 1);
257 for (std::size_t i = 0; i < M; ++i)
260 :
static_cast<int>(
sn.stations[i].nservers);
270 o.
avg.XN.assign(R, zero);
271 o.
avg.CN.assign(R, zero);
275 std::vector<T> busy(M, zero);
276 for (std::size_t i = 0; i < M; ++i) {
278 for (std::size_t r = 0; r < cftpopt.
samples; ++r) {
279 const int n = s.
X(r, i);
289 if (o.
avg.XN[0] > zero)
292 for (std::size_t i = 0; i < M; ++i) {
293 o.
avg.QN(i, 0) = s.
Q[i];
298 if (o.
avg.TN(i, 0) > zero) o.
avg.RN(i, 0) = T(o.
avg.QN(i, 0) / o.
avg.TN(i, 0));
303 std::map<std::vector<int>, std::size_t> counts;
304 for (std::size_t r = 0; r < cftpopt.
samples; ++r) {
305 std::vector<int> row(M, 0);
306 for (std::size_t i = 0; i < M; ++i) row[i] = s.
X(r, i);
309 for (std::map<std::vector<int>, std::size_t>::const_iterator it = counts.begin();
310 it != counts.end(); ++it) {
352 d.
sol.lG = std::numeric_limits<double>::quiet_NaN();
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
std::size_t phases_of(std::size_t ist, std::size_t r) const
sn.phases(i,r): the order of the process representation.
std::vector< double > cap
sn.cap and sn.classcap: the total and per-class buffers.
std::vector< Station< T > > stations
stations[k-1] is the k-th station
Matrix< T > rates
(nstations x nclasses) service rates and SCVs, with a PARALLEL disabled flag instead of MATLAB's NaN ...
std::vector< NodeDef > nodes
every node, in creation order
std::vector< Region > regions
The exception types the port throws.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
Dense matrix and non-owning view.
SchedStrategy
Scheduling disciplines, with the values of MATLAB SchedStrategy.
RoutingStrategy
Routing strategies, with the values of MATLAB RoutingStrategy.
NodeType
Node kinds, with the values of MATLAB NodeType.
ChainDemands< T > sn_get_demands_chain(const qn::NetworkStruct< T > &L)
Port of sn_get_demands_chain.
NcCftpSolution< T > solver_nc_cftp(const qn::NetworkStruct< T > &sn, const NcSolverOptions &opt, const NcCftpOptions &cftpopt)
Solve with the cftp / cftp.approx method.
NcSolution< T > solver_nc_cftp_solution(const NcCftpSolution< T > &s)
A cftp solve in the shape every other SolverNC analyzer returns, so the runner's metric filter applie...
std::string solver_nc_cftp_supports(const qn::NetworkStruct< T > &sn)
The cftp model-class gate as a public predicate.
std::mt19937_64 McRng
The generator type every Monte Carlo entry point in this tree accepts.
constexpr int cftp_inf_servers
Sentinel for an infinite-server (delay) station, the reference's S = Inf.
CftpMethod
Which sampler to run.
@ Cftp
exact, monotone coupling from the past
@ Approx
the rapidly-mixing approximate sampler M_A
CftpResult< T > pfqn_cftp(const std::vector< T > &L, int N, const std::vector< int > &S, std::size_t nsamples, CftpMethod method, McRng &rng)
Perfect stationary state sampling for closed single-class multiserver product-form networks,...
Conservation laws of a layered queueing network, enumerated from its structure.
Controls and result shape shared by the normalizing-constant analyzers.
A queueing network and its refreshed NetworkStruct.
Number-type abstraction for the templated API port.
Perfect stationary state sampling for closed single-class multiserver product-form networks,...
Randomness scaffolding shared by the Monte Carlo normalizing-constant estimators (pfqn_mci,...
Chain aggregation and de-aggregation.
The chain-level view of a layer, as sn_get_demands_chain returns it.
std::vector< std::size_t > refstatchain
(C) 1-based reference station
std::vector< double > Nchain
(C) population, infinite for an open chain
Matrix< T > STchain
(M x C) mean service time
Matrix< T > Lchain
(M x C) demand
Matrix< T > Vchain
(M x C) visits
The means of one cftp solve, before the SolverNC metric filter.
std::vector< T > CN
(nclasses) system throughput and response time
Matrix< T > TN
(nstations x nclasses)
The knobs of one perfect-sampling run.
std::size_t samples
Number of iid stationary draws, SolverOptions('NC').samples by default.
unsigned long seed
Stream seed, so a row is reproducible within this port.
What one cftp solve produces beside the means.
Matrix< int > states
(samples x stations) the sampled states, one draw per row.
std::vector< long > horizon
(samples) per-draw coalescence horizon, or the mixing steps of M_A.
std::vector< std::vector< int > > distinct_states
The distinct sampled states, aligned with paggr.
std::vector< T > paggr
Empirical probability of each distinct sampled state.
The [Q,U,R,T,C,X,lG] of the reference, plus the algorithm that ran.
std::vector< std::vector< int > > cftp_space
mva::MvaSolution< T > sol
std::vector< T > cftp_prob
Matrix< int > cftp_states
Set only by the cftp / cftp.approx route (solver_nc_cftp.h), EMPTY for every other method: the sample...
std::vector< long > cftp_horizon
Controls, defaulting to SolverOptions('NC') in the reference.
Return value of pfqn_cftp, mirroring [Q, X, T].
Matrix< int > X
(nsamples x M) sampled states, rows sum to K
std::vector< T > Q
(M) empirical mean queue length
std::vector< long > horizon
(nsamples) coalescence horizon or step count