5#ifndef LINE_API_SN_SN_VALIDATE_H
6#define LINE_API_SN_SN_VALIDATE_H
59inline std::string idx2(std::size_t i, std::size_t j) {
60 return "[" + std::to_string(i) +
"," + std::to_string(j) +
"]";
68 const std::size_t M =
sn.nstations, K =
sn.nclasses;
69 std::vector<std::string> errors;
70 const std::string want =
71 " do not match (nstations=" + std::to_string(M) +
" x nclasses=" + std::to_string(K) +
")";
72 if (
sn.rates.rows() != M ||
sn.rates.cols() != K)
73 errors.push_back(
"rates matrix dimensions (" + std::to_string(
sn.rates.rows()) +
"x" +
74 std::to_string(
sn.rates.cols()) +
")" + want);
75 if (
sn.scv.rows() != M ||
sn.scv.cols() != K)
76 errors.push_back(
"scv matrix dimensions (" + std::to_string(
sn.scv.rows()) +
"x" +
77 std::to_string(
sn.scv.cols()) +
")" + want);
78 if (!
sn.disabled.empty()) {
79 if (
sn.disabled.size() != M)
80 errors.push_back(
"disabled has " + std::to_string(
sn.disabled.size()) +
81 " rows, expected nstations=" + std::to_string(M));
82 for (std::size_t i = 0; i <
sn.disabled.size(); ++i)
83 if (
sn.disabled[i].size() != K) {
84 errors.push_back(
"disabled row " + std::to_string(i) +
" has " +
85 std::to_string(
sn.disabled[i].size()) +
86 " entries, expected nclasses=" + std::to_string(K));
90 if (
sn.stations.size() != M)
91 errors.push_back(
"stations list holds " + std::to_string(
sn.stations.size()) +
92 " entries, expected nstations=" + std::to_string(M));
93 if (
sn.classes.size() != K)
94 errors.push_back(
"classes list holds " + std::to_string(
sn.classes.size()) +
95 " entries, expected nclasses=" + std::to_string(K));
102 std::vector<std::string> errors;
104 for (std::size_t i = 0; i <
sn.rates.rows(); ++i)
105 for (std::size_t j = 0; j <
sn.rates.cols(); ++j) {
106 if (i <
sn.disabled.size() && j <
sn.disabled[i].size() &&
sn.disabled[i][j])
continue;
107 if (
sn.rates(i, j) < zero)
108 errors.push_back(
"rates" + detail::idx2(i, j) +
" = " +
112 for (std::size_t i = 0; i <
sn.scv.rows(); ++i)
113 for (std::size_t j = 0; j <
sn.scv.cols(); ++j) {
114 if (i <
sn.disabled.size() && j <
sn.disabled[i].size() &&
sn.disabled[i][j])
continue;
115 if (
sn.scv(i, j) < zero)
116 errors.push_back(
"scv" + detail::idx2(i, j) +
" = " +
118 " is negative (SCV must be >= 0)");
126 std::vector<std::string> errors;
127 for (std::size_t k = 0; k <
sn.classes.size(); ++k) {
128 const double n =
sn.classes[k].population;
130 errors.push_back(
"njobs for class " + std::to_string(k) +
" is NaN");
131 else if (std::isfinite(n) && n < 0)
132 errors.push_back(
"njobs for class " + std::to_string(k) +
" = " + std::to_string(n) +
141 std::vector<std::string> errors;
143 const double tolerance = 1e-6;
144 for (std::size_t i = 0; i <
sn.rt.rows(); ++i) {
146 bool hasNonZero =
false;
147 for (std::size_t j = 0; j <
sn.rt.cols(); ++j) {
148 const T v =
sn.rt(i, j);
150 errors.push_back(
"rt" + detail::idx2(i, j) +
" = " +
152 if (v > zero) hasNonZero =
true;
156 if (hasNonZero && std::fabs(s - 1.0) > tolerance)
157 errors.push_back(
"rt row " + std::to_string(i) +
" sum = " + std::to_string(s) +
166 std::vector<std::string> errors;
167 for (std::size_t i = 0; i <
sn.stations.size(); ++i) {
168 const double n =
sn.stations[i].nservers;
170 errors.push_back(
"nservers[" + std::to_string(i) +
"] is NaN");
171 }
else if (n <= 0 && !std::isinf(n)) {
173 if (nt != qn::NodeType::Source && nt != qn::NodeType::Sink)
174 errors.push_back(
"nservers[" + std::to_string(i) +
"] = " + std::to_string(n) +
175 " must be positive");
193 std::vector<std::string> errors;
196 errors.insert(errors.end(), dims.begin(), dims.end());
199 errors.insert(errors.end(), r.begin(), r.end());
201 errors.insert(errors.end(), p.begin(), p.end());
203 errors.insert(errors.end(), rt.begin(), rt.end());
205 errors.insert(errors.end(), ns.begin(), ns.end());
213 const std::string& paramName =
"stationIdx") {
214 if (ist >=
sn.nstations)
215 return paramName +
"=" + std::to_string(ist) +
" is out of bounds [0, " +
216 std::to_string(
sn.nstations == 0 ? 0 :
sn.nstations - 1) +
"]";
217 return std::string();
222 const std::string& paramName =
"classIdx") {
223 if (r >=
sn.nclasses)
224 return paramName +
"=" + std::to_string(r) +
" is out of bounds [0, " +
225 std::to_string(
sn.nclasses == 0 ? 0 :
sn.nclasses - 1) +
"]";
226 return std::string();
231 const std::string& paramName =
"nodeIdx") {
232 const std::size_t n =
sn.nodes.size();
234 return paramName +
"=" + std::to_string(ind) +
" is out of bounds [0, " +
235 std::to_string(n == 0 ? 0 : n - 1) +
"]";
236 return std::string();
242 if (ind >=
sn.nodes.size())
243 return "nodeIdx=" + std::to_string(ind) +
" is out of bounds";
245 if (actual != expected)
248 return std::string();
A network plus its refreshed NetworkStruct.
Enumerations and the minimal distribution descriptor shared by the model layer of the C++ port.
std::vector< std::string > sn_validate_population(const qn::NetworkStruct< T > &sn)
Class populations are neither NaN nor negative; an open class may be Inf.
std::string sn_validate_node_type(const qn::NetworkStruct< T > &sn, std::size_t ind, qn::NodeType expected)
std::vector< std::string > sn_validate(const qn::NetworkStruct< T > &sn, ValidationLevel level=ValidationLevel::Full)
Consistency checks on a NetworkStruct, a port of jar/src/main/java/jline/api/sn/SnValidate....
std::string sn_validate_class_index(const qn::NetworkStruct< T > &sn, std::size_t r, const std::string ¶mName="classIdx")
std::vector< std::string > sn_validate_routing(const qn::NetworkStruct< T > &sn)
Every non-empty row of rt is a probability vector summing to one.
std::vector< std::string > sn_validate_rates(const qn::NetworkStruct< T > &sn)
Rates and SCVs are non-negative wherever the pair is enabled.
std::string sn_validate_station_index(const qn::NetworkStruct< T > &sn, std::size_t ist, const std::string ¶mName="stationIdx")
std::vector< std::string > sn_validate_dimensions(const qn::NetworkStruct< T > &sn)
The (nstations x nclasses) matrices agree with the declared dimensions.
ValidationLevel
How much of the struct to check; the reference's ValidationLevel.
std::vector< std::string > sn_validate_servers(const qn::NetworkStruct< T > &sn)
Server counts are positive, except at a Source or a Sink.
std::string sn_validate_node_index(const qn::NetworkStruct< T > &sn, std::size_t ind, const std::string ¶mName="nodeIdx")
const char * node_type_to_text(NodeType t)
Name of a node kind, for diagnostics.
NodeType
Node kinds, with the values of MATLAB NodeType.
A queueing network and its refreshed NetworkStruct.
Number-type abstraction for the templated API port.