5#ifndef LINE_OPT_SENSITIVITY_H
6#define LINE_OPT_SENSITIVITY_H
39 if (
sn.classes.empty())
return std::nullopt;
41 if (!std::isinf(jobclass.
population))
return std::nullopt;
45 for (std::size_t i = 0; i <
sn.nstations; ++i) {
49 if (!delay && station.
nservers > 1.0)
return std::nullopt;
51 std::vector<double> demand(
sn.nclasses, 0.0), rho(
sn.nclasses, 0.0);
52 for (std::size_t r = 0; r <
sn.nclasses; ++r) {
53 const double rate =
sn.rates(i, r);
54 const double visits = pf.
V(i, r);
55 if (std::isfinite(rate) && rate > 0.0 && visits > 0.0) {
56 demand[r] = visits / rate;
57 rho[r] = pf.
lambda[r] * demand[r];
60 double utilization = 0.0;
62 for (
double value : rho) utilization += value;
63 const double denominator = 1.0 - utilization;
64 if (!delay && denominator <= 0.0)
return std::nullopt;
66 const std::string& station_name = station.
name;
67 for (std::size_t s = 0; s <
sn.nclasses; ++s) {
68 const double rate =
sn.rates(i, s);
69 if (std::isfinite(rate) && rate > 0.0 && pf.
V(i, s) > 0.0)
70 sensitivity.
add(
"Util", station_name,
75 for (std::size_t r = 0; r <
sn.nclasses; ++r) {
76 const double rate_r =
sn.rates(i, r);
77 if (pf.
V(i, r) <= 0.0 || !std::isfinite(rate_r) || rate_r <= 0.0)
continue;
79 station_name,
sn.classes[r].name);
80 for (std::size_t s = 0; s <
sn.nclasses; ++s) {
81 const double rate_s =
sn.rates(i, s);
82 if (!std::isfinite(rate_s) || rate_s <= 0.0 || pf.
V(i, s) <= 0.0)
85 station_name,
sn.classes[s].name);
86 const double d_utilization = delay ? 0.0 : -rho[s] / rate_s;
87 const double d_demand = s == r ? -demand[r] / rate_s : 0.0;
88 const double d_rho = s == r ? -rho[r] / rate_s : 0.0;
89 double d_response, d_queue;
91 d_response = d_demand;
94 d_response = (d_demand * denominator +
95 demand[r] * d_utilization) /
96 (denominator * denominator);
97 d_queue = (d_rho * denominator + rho[r] * d_utilization) /
98 (denominator * denominator);
100 sensitivity.
add(
"RespT", metric, parameter, d_response);
101 sensitivity.
add(
"QLen", metric, parameter, d_queue);
103 sensitivity.
add(
"Tput", metric,
112 if (
sn.classes.empty())
return std::nullopt;
113 std::vector<int> population(
sn.nclasses, 0);
114 for (std::size_t r = 0; r <
sn.nclasses; ++r) {
115 if (!std::isfinite(
sn.classes[r].population))
return std::nullopt;
116 population[r] =
static_cast<int>(std::llround(
sn.classes[r].population));
120 for (
double servers : pf.
S)
121 if (std::isfinite(servers) && servers > 1.0)
return std::nullopt;
122 std::vector<double> think_time(
sn.nclasses, 0.0);
123 for (std::size_t z = 0; z < pf.
Z.rows(); ++z)
124 for (std::size_t r = 0; r <
sn.nclasses; ++r)
125 think_time[r] += pf.
Z(z, r);
127 pf.
D, population, think_time);
134 std::vector<Parameter> parameters;
137 for (std::size_t s = 0; s <
sn.nclasses; ++s) {
138 const double rate =
sn.rates(station, s);
139 if (!std::isfinite(rate) || rate <= 0.0 || pf.
D(j, s) <= 0.0)
continue;
140 parameters.push_back({j *
sn.nclasses + s, -pf.
D(j, s) / rate,
142 sn.classes[s].name)});
149 const std::string& station_name =
sn.stations[station].name;
150 for (std::size_t r = 0; r <
sn.nclasses; ++r) {
151 if (pf.
D(i, r) <= 0.0)
continue;
153 station_name,
sn.classes[r].name);
154 for (
const Parameter& parameter : parameters) {
155 sensitivity.
add(
"RespT", metric, parameter.key,
156 result.
dR[parameter.index](i, r) * parameter.chain);
157 sensitivity.
add(
"QLen", metric, parameter.key,
158 result.
dQ[parameter.index](i, r) * parameter.chain);
159 sensitivity.
add(
"Tput", metric, parameter.key,
160 result.
dX(r, parameter.index) * parameter.chain);
161 sensitivity.
add(
"Util", station_name, parameter.key,
162 result.
dU[parameter.index](i, r) * parameter.chain);
177 }
catch (
const std::exception&) {
180 if (state_space.
empty())
return std::nullopt;
183 for (std::size_t pstation = 0; pstation < sn.
nstations; ++pstation) {
184 for (std::size_t pclass = 0; pclass < sn.
nclasses; ++pclass) {
185 const double rate = sn.
rates(pstation, pclass);
186 if (!std::isfinite(rate) || rate <= 0.0 ||
192 ctmc::CtmcSensParam<double> specification;
193 specification.name = parameter;
194 specification.value = rate;
195 specification.set = [pstation, pclass](qn::NetworkStruct<double>& changed,
198 changed.refresh_rates();
200 ctmc::CtmcSens<double> derivative;
203 }
catch (
const std::exception&) {
206 for (std::size_t i = 0; i < sn.
nstations; ++i) {
207 const std::string& station = sn.
stations[i].name;
208 for (std::size_t r = 0; r < sn.
nclasses; ++r) {
209 const std::size_t column = i * sn.
nclasses + r;
210 if (column >= state_space.
cols())
continue;
213 for (std::size_t state = 0; state < state_space.
rows(); ++state) {
214 if (!std::isfinite(state_space(state, column))) {
218 value += derivative.dpi[state] * state_space(state, column);
222 station, sn.
classes[r].name), parameter, value);
234 if (result)
return result;
236 if (result)
return result;
237 }
catch (
const std::exception&) {
void add(const std::string &kind, const std::string &metric, const std::string ¶meter, double value)
static std::string metric_key(const std::string &station, const std::string &jobclass)
static std::string parameter_key(const std::string &station, const std::string &jobclass)
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.
bool has_service_law(std::size_t i, std::size_t r) const
Does (station i, class r) have a service law an analyzer may convert?
std::vector< JobClass > classes
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 ...
A queueing network under construction.
const NetworkStruct< T > & get_struct()
The refreshed struct, MATLAB's model.getStruct().
CtmcSens< T > solver_ctmc_sensitivity(const NetworkStruct< T > &sn, const CtmcOptions &opt, const CtmcSensParam< T > ¶m, const std::vector< T > &reward=std::vector< T >(), const std::string &method="fd", const CtmcSymbolicOptions &symopt=CtmcSymbolicOptions())
Port of @@SolverCTMC/getSensitivity.
CtmcSolution< T > solver_ctmc_analyzer(const NetworkStruct< T > &sn_in, const CtmcOptions &opt)
Port of solver_ctmc_analyzer.m plus the fork-join wrapper of @@SolverCTMC/runAnalyzer....
Matrix< T > ctmc_state_space_aggr(const NetworkStruct< T > &sn, const std::vector< NetState< T > > &space)
Port of StateSpaceAggr: the per-(station, class) job counts of every state, as an (nstates x nstation...
PfParams< T > sn_get_product_form_params(const qn::NetworkStruct< T > &sn)
Port of sn_get_product_form_params.
std::optional< SensitivityData > open_sensitivities(qn::Network< double > &model)
std::optional< SensitivityData > closed_sensitivities(qn::Network< double > &model)
std::optional< SensitivityData > ctmc_sensitivities(qn::Network< double > &model, ctmc::CtmcOptions options={})
std::optional< SensitivityData > compute_model_sensitivities(qn::Network< double > model, bool use_ctmc=false)
SensResult< T > pfqn_sens(const Matrix< T > &L, const std::vector< int > &N, const std::vector< T > &Z, const std::vector< int > &mi)
Exact analytic derivatives of the mean performance measures {X,Q,U,R} of a closed product-form (BCMP)...
The Network constructor API: Queue, Delay, Source, Sink, Router, ClassSwitch, Cache,...
Exact analytic derivatives of the mean performance measures {X,Q,U,R} of a closed product-form (BCMP)...
What an evaluation and a solve return.
Port of matlab/src/api/sn/sn_get_product_form_params.m: the CLASS-level product-form parameters.
Port of @@SolverCTMC/getSensitivity and getSensitivityRanking: the parametric sensitivity of a steady...
The SolverCTMC knobs this port honours.
Everything one CTMC solve produces.
static Distrib exp_rate(const T &r)
The [lambda,D,N,Z,mu,S,V] of the reference.
std::vector< double > S
(Mq) server counts
Matrix< T > Z
(max(1,Mz) x R) demand at the delay stations
Matrix< T > V
(M x R) visits summed over chains
Matrix< T > D
(Mq x R) demand at the queueing stations
std::vector< std::size_t > queue_stations
(Mq) 1-based station indices
std::vector< T > lambda
(R) arrival rate, zero on a closed class
std::vector< Matrix< T > > dR
(P) matrices M x R
std::vector< Matrix< T > > dU
(P) matrices M x R
Matrix< T > dX
(R x P) dX(r)/dparam(p)
std::vector< Matrix< T > > dQ
(P) matrices M x R, dQ[p](i,r)
One job class of the network.
double population
infinite for an open class
One station of the network.
double nservers
may be infinite (a Delay, or an inf-scheduled task)