5#ifndef LINE_API_SN_SN_REMOVE_CLASS_H
6#define LINE_API_SN_SN_REMOVE_CLASS_H
78namespace remove_class_detail {
90void erase_slot(std::vector<V>& v, std::size_t K, std::size_t r) {
91 if (v.size() != K)
return;
92 v.erase(v.begin() +
static_cast<std::ptrdiff_t
>(r - 1));
97void erase_row_col(Matrix<T>& C, std::size_t K, std::size_t r) {
98 if (C.rows() != K || C.cols() != K)
return;
103 Matrix<T> R(K - 1, K - 1, num_traits<T>::from_int(0));
105 for (std::size_t a = 0; a < K; ++a) {
106 if (a == r - 1)
continue;
108 for (std::size_t b = 0; b < K; ++b) {
109 if (b == r - 1)
continue;
124inline void reindex_class_list(std::vector<std::size_t>& list, std::size_t r) {
125 std::vector<std::size_t> keep;
126 keep.reserve(list.size());
127 for (std::size_t a = 0; a < list.size(); ++a) {
128 const std::size_t m = list[a];
129 if (m == r)
continue;
130 keep.push_back(m > r ? m - 1 : m);
137void remove_class_check(
const qn::NetworkStruct<T>& sn) {
140 if (!sn.nodeparam.empty())
142 "sn_remove_class: cannot dynamically remove classes in models with caches. You need "
143 "to re-instantiate the model.");
144 if (sn.has_fork() || !sn.fj.empty() || !sn.forkparam.empty() || !sn.joindecl.empty())
146 "sn_remove_class: a Fork carries per-class branch probabilities and forking levels, "
147 "and a Join a per-class quorum, none of which is a plain per-class vector; rebuild "
148 "the model without the class instead");
149 if (!sn.transparam.empty() || !sn.initmarking.empty() || !sn.statespace.empty() ||
150 !sn.stateprior.empty())
152 "sn_remove_class: a Petri-net Place or Transition indexes its modes, its arc "
153 "multiplicities and its initial marking by token class; rebuild the model without "
154 "the class instead");
155 if (!sn.regions.empty())
157 "sn_remove_class: a finite-capacity region carries a per-class capacity row and "
158 "per-class weights; rebuild the model without the class instead");
159 if (!sn.retrialparam.empty())
160 throw UnsupportedError(
"sn_remove_class: a retrial orbit is parameterized per class");
161 if (!sn.pollingparam.empty())
163 "sn_remove_class: a polling station serves one buffer per class and carries a "
164 "per-class switchover schedule");
165 if (!sn.pasparam.empty())
167 "sn_remove_class: a pass-and-swap station is parameterized by the ordered microstate "
168 "of class indices, which no slice can rewrite");
169 if (!sn.setupparam.empty())
170 throw UnsupportedError(
"sn_remove_class: a setup / delayoff schedule is per class");
171 if (!sn.reward.empty())
173 "sn_remove_class: a reward function names its classes and would be silently "
174 "re-pointed by the shift");
175 for (std::size_t r = 0; r < sn.issignal.size(); ++r)
178 "sn_remove_class: a G-network signal names a TARGET class, which the shift would "
179 "re-point at a different class");
180 for (std::size_t r = 0; r < sn.syncreply.size(); ++r)
181 if (sn.syncreply[r] != 0)
183 "sn_remove_class: a synchronous reply names its reply class, which the shift "
184 "would re-point at a different class");
187 "sn_remove_class: a global-dependence function takes a population vector of width "
188 "nclasses and cannot be narrowed");
189 for (std::size_t i = 0; i < sn.stations.size(); ++i) {
190 if (sn.stations[i].cdscaling || sn.stations[i].jdscaling)
192 "' carries a class- or joint-dependent scaling function, "
193 "whose argument is a population vector of width nclasses");
194 if (sn.stations[i].svc_rate_fun)
196 "' carries a service-rate function of the ordered microstate "
197 "of class indices, which no slice can rewrite");
211 using namespace remove_class_detail;
212 const std::size_t K =
sn.classes.size();
213 if (cls == 0 || cls > K)
214 throw InputError(
"sn_remove_class: class index " + std::to_string(cls) +
219 "The network has a single class, it cannot be removed from the model.");
220 remove_class_check(
sn);
223 const std::size_t r = cls;
226 for (std::size_t i = 0; i < V.
nodes.size(); ++i) {
243 for (
typename std::map<std::size_t,
Matrix<T> >::iterator it = V.
csmatrix.begin();
245 erase_row_col(it->second, K, r);
248 for (std::size_t i = 0; i < V.
stations.size(); ++i) {
266 for (std::size_t k = 0; k < st.
server_types.size(); ++k) {
279 for (std::size_t i = 0; i < V.
service.size(); ++i) erase_slot(V.
service[i], K, r);
282 V.
classes.erase(V.
classes.begin() +
static_cast<std::ptrdiff_t
>(r - 1));
283 for (std::size_t q = 0; q < V.
classes.size(); ++q) {
284 std::size_t& sp = V.
classes[q].spawn;
300 std::map<std::pair<std::size_t, std::size_t>,
Matrix<T> > P2;
301 for (
typename std::map<std::pair<std::size_t, std::size_t>,
Matrix<T> >::const_iterator it =
303 it != V.
P.end(); ++it) {
304 const std::size_t a = it->first.first, b = it->first.second;
305 if (a == r || b == r)
continue;
306 P2[std::make_pair(a > r ? a - 1 : a, b > r ? b - 1 : b)] = it->second;
328 for (std::size_t r = 0; r <
sn.classes.size(); ++r)
330 throw InputError(
"sn_remove_class: the model has no class named '" + name +
"'");
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
std::map< std::pair< std::size_t, std::size_t >, Matrix< T > > P
P[(r,s)] is an (nnodes x nnodes) block; absent means all zero.
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
void refresh_struct()
The whole chain, in MATLAB's refreshStruct order.
std::map< std::pair< std::size_t, std::size_t >, Matrix< T > > Peff
The routing after refresh_routing() has expanded the non-PROB strategies and folded the class switche...
std::vector< NodeDef > nodes
every node, in creation order
std::map< std::size_t, Matrix< T > > csmatrix
The class-switch matrix of a ClassSwitch node, by 1-based NODE index.
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.
qn::NetworkStruct< T > sn_remove_class(const qn::NetworkStruct< T > &sn, std::size_t cls)
The model without class cls (1-based), leaving sn untouched.
A queueing network and its refreshed NetworkStruct.
Number-type abstraction for the templated API port.
std::vector< int > routing_param
The scalar parameter of a parameterized dispatcher, per class: the d of a power-of-d (SQ) choice.
std::vector< std::map< std::size_t, double > > routing_weights
The per-destination weights of a WRROBIN dispatcher, per class: a map from 1-based destination NODE i...
std::vector< RoutingStrategy > routing
sn.routing, per class.
One station of the network.
std::vector< Distrib< T > > orbit_impatience
Queue.setOrbitImpatience(class, dist): abandonment from the RETRIAL ORBIT, which is a different popul...
std::vector< T > jdscalingpeak
sn.jdscalingpeak for this station: the declared peak joint-dependent scaling per class.
std::vector< BalkingParam > balking
std::vector< T > batch_reject
Queue.setBatchRejectProbability: per-class rejection of a whole batch.
std::vector< Distrib< T > > patience
Queue.setPatience(class, dist): the abandonment timer of a WAITING job, with impatience[r] naming whi...
std::vector< std::size_t > server_parallelism
Queue.setServerParallelism(class, n): the servers a job seizes for the whole of its service,...
std::vector< int > droprule
Per-class blocking rule as an INT, with 0 meaning "not set".
std::vector< T > cdscalingpeak
sn.cdscalingpeak for this station: the DECLARED peak rate scaling per class, empty when the station i...
std::vector< std::size_t > marked_classes
Source.markedClasses: the 1-based class of each mark of an MMAP arrival.
std::vector< lang::ImpatienceType > impatience
std::vector< T > schedparam
sn.schedparam, per class: the DPS / GPS weight, or the SEPT / LEPT rank.
std::vector< double > classcap
Per-class buffer from setChainCapacity; infinite where unset.
std::vector< lang::DepartureDiscipline > departure_discipline
Place.departureDiscipline, per class.
std::vector< Distrib< T > > arrival_batch
Source.setArrivalBatch(class, dist): the batch-size law released at each arrival epoch.
std::vector< bool > immfeed
Node-level immediate feedback, per class; empty when the station sets none.
std::vector< ServerType > server_types