5#ifndef LINE_LANG_QN_TAG_CHAIN_H
6#define LINE_LANG_QN_TAG_CHAIN_H
72 std::vector<std::size_t>
orig;
90 if (!
sn.nodeparam.empty())
92 "tag_chain: the model has a Cache node, whose item access costs and hit/miss routing "
93 "are indexed by class; a tagged twin of a read class has no entry in them");
94 if (!
sn.transparam.empty())
96 "tag_chain: the model has a Transition (SPN) node, whose enabling and firing arcs are "
97 "indexed by class and mode; the transform has no rule for the tagged twin's arcs");
98 if (
sn.has_fork() || !
sn.fj.empty())
100 "tag_chain: the model has a Fork/Join, where the tagged job becomes several sibling "
101 "tasks and the response time is no longer the passage of one job");
102 if (!
sn.regions.empty())
104 "tag_chain: the model has a finite capacity region, whose per-class caps and drop "
105 "rules are declared over the original class set and cannot be widened");
106 if (!
sn.retrialparam.empty())
108 "tag_chain: the model has a retrial station, whose orbit process is declared per "
110 if (!
sn.pollingparam.empty())
112 "tag_chain: the model has a polling station, whose switchover walks are declared per "
113 "buffer, one buffer per class");
114 if (!
sn.pasparam.empty())
116 "tag_chain: the model has a pass-and-swap / order-independent station, whose service "
117 "rate function and swap graph are indexed by class");
118 for (std::size_t r = 0; r <
sn.issignal.size(); ++r)
121 "tag_chain: the model has a G-network signal class, which can annihilate the "
122 "tagged job without a departure and leaves its passage undefined");
123 for (std::size_t r = 0; r <
sn.syncreply.size(); ++r)
124 if (
sn.syncreply[r] != 0)
126 "tag_chain: the model has synchronous call/reply blocking, whose reply class is "
127 "declared per calling class and has no tagged twin");
128 for (std::size_t i = 0; i <
sn.stations.size(); ++i) {
129 if (
sn.stations[i].cdscaling ||
sn.stations[i].jdscaling)
131 "' is class dependent; its scaling is a function of the "
132 "per-class population vector, whose width the tagging changes");
133 if (
sn.stations[i].svc_rate_fun)
135 "' carries a service rate function over ordered class lists, "
136 "which has no value at the tagged twin");
153 const std::string& suffix =
".tagged") {
154 if (chain == 0 || chain >
sn.inchain.size())
155 throw InputError(
"tag_chain: chain index out of range");
156 const std::vector<std::size_t>& ic =
sn.inchain[chain - 1];
157 if (jobclass == 0 || jobclass >
sn.classes.size())
158 throw InputError(
"tag_chain: class index out of range");
160 for (std::size_t a = 0; a < ic.size(); ++a)
161 if (ic[a] == jobclass) member =
true;
162 if (!member)
throw InputError(
"tag_chain: the class to tag does not belong to the given chain");
163 for (std::size_t a = 0; a < ic.size(); ++a)
164 if (!std::isfinite(
sn.classes[ic[a] - 1].population))
166 "' of the chain to tag is open; tagging moves one job out of a "
167 "finite population and an open chain has none");
168 if (
sn.classes[jobclass - 1].population < 1.0)
169 throw InputError(
"tag_chain: class '" +
sn.classes[jobclass - 1].name +
170 "' has no job to tag");
172 tag_detail::tag_chain_check(
sn);
177 const std::size_t I =
sn.nodes.size();
178 const std::size_t M =
sn.stations.size();
179 const double inf = std::numeric_limits<double>::infinity();
183 for (std::size_t a = 0; a < ic.size(); ++a) {
184 const std::size_t r = ic[a];
186 tc.
name =
sn.classes[r - 1].name + suffix;
189 const std::size_t K2 = V.
classes.size();
193 for (std::size_t i = 1; i <= M; ++i) {
205 st.
droprule[t - 1] =
static_cast<int>(DropStrategy::WAITQ);
230 for (std::size_t i = 0; i < I; ++i) {
232 if (nd.
routing.empty())
continue;
233 if (nd.
routing.size() < K2) nd.
routing.resize(K2, RoutingStrategy::PROB);
234 nd.
routing[t - 1] =
sn.nodes[i].routing.size() >= r ?
sn.nodes[i].routing[r - 1]
235 : RoutingStrategy::PROB;
242 for (std::size_t x = 0; x < ic.size(); ++x)
243 for (std::size_t y = 0; y < ic.size(); ++y)
244 for (std::size_t i = 1; i <= I; ++i)
245 for (std::size_t j = 1; j <= I; ++j) {
246 const T p =
sn.get_route(ic[x], ic[y], i, j);
255 const std::size_t K2 = V.
classes.size();
256 for (
typename std::map<std::size_t,
Matrix<T>>::iterator it = V.
csmatrix.begin();
260 for (std::size_t i = 0; i < old.
rows() && i < K2; ++i)
261 for (std::size_t j = 0; j < old.
cols() && j < K2; ++j) C(i, j) = old(i, j);
262 for (std::size_t x = 0; x < ic.size(); ++x)
263 for (std::size_t y = 0; y < ic.size(); ++y)
264 C(out.
tagged[x] - 1, out.
tagged[y] - 1) = old(ic[x] - 1, ic[y] - 1);
269 V.
classes[jobclass - 1].population -= 1.0;
UnsupportedError(const std::string &what)
A network plus its refreshed NetworkStruct.
void set_route(std::size_t r, std::size_t s, std::size_t i, std::size_t j, const T &p)
P{r,s}(i,j) = p, with 1-based NODE and class indices.
std::size_t add_class(const JobClass &cl)
Add a class and grow the service table.
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.
void set_service(std::size_t station, std::size_t cls, const Distrib< T > &d)
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.
TaggedChain< T > tag_chain(const NetworkStruct< T > &sn, std::size_t chain, std::size_t jobclass, const std::string &suffix=".tagged")
Tag one class of one chain.
A queueing network and its refreshed NetworkStruct.
static Distrib disabled_dist()
One job class of the network.
double population
infinite for an open class
std::vector< RoutingStrategy > routing
sn.routing, per class.
One station of the network.
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< 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.
The tagged model and the class bookkeeping a caller needs to read it back.
std::vector< std::size_t > tagged
std::vector< std::size_t > orig