138 const std::string& method, std::size_t samples) {
141 bool multiserver_ok =
true;
142 const std::string algname = detail::alg_type_name(method, &multiserver_ok);
143 if (!multiserver_ok) {
144 for (std::size_t i = 0; i < M; ++i) {
145 const double c = L.
stations[i].nservers;
146 if (std::isfinite(c) && c > 1.0)
148 " does not support multi-server stations");
153 auto dv = [](
const Matrix<T>& A, std::size_t i, std::size_t j) {
162 std::vector<bool> is_source_station(M,
false);
163 std::size_t nsources = 0;
164 for (std::size_t i = 0; i < M; ++i)
165 if (L.
stations[i].nodetype == qn::NodeType::Source) {
166 is_source_station[i] =
true;
170 std::ofstream f(path.c_str());
171 if (!f)
throw InputError(
"writeJMVA: cannot open '" + path +
"' for writing");
172 f <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
173 f <<
"<model xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
174 <<
" xsi:noNamespaceSchemaLocation=\"JMTmodel.xsd\">\n";
175 f <<
" <parameters>\n";
178 f <<
" <classes number=\"" << C <<
"\">\n";
179 for (std::size_t c = 0; c < C; ++c) {
180 double sum_njobs = 0.0;
181 for (std::size_t k : L.
inchain[c]) sum_njobs += L.
classes[k - 1].population;
182 if (std::isfinite(sum_njobs)) {
183 f <<
" <closedclass population=\"" << detail::num_text(d.
Nchain[c])
184 <<
"\" name=\"" << detail::chain_name(c + 1) <<
"\"/>\n";
187 for (std::size_t i = 0; i < M; ++i) {
188 if (!is_source_station[i])
continue;
189 for (std::size_t k : L.
inchain[c]) {
190 const double r = dv(L.
rates, i, k - 1);
191 if (std::isfinite(r)) rate += r;
194 f <<
" <openclass rate=\"" << detail::num_text(rate) <<
"\" name=\""
195 << detail::chain_name(c + 1) <<
"\"/>\n";
198 f <<
" </classes>\n";
201 f <<
" <stations number=\"" << (M - nsources) <<
"\">\n";
205 bool any_open =
false;
206 for (std::size_t k = 0; k < K; ++k)
207 if (!std::isfinite(L.
classes[k].population)) any_open =
true;
208 double total_njobs = 0.0;
209 for (std::size_t k = 0; k < K; ++k)
210 if (std::isfinite(L.
classes[k].population)) total_njobs += L.
classes[k].population;
212 for (std::size_t i = 0; i < M; ++i) {
214 if (nt != qn::NodeType::Queue && nt != qn::NodeType::Delay)
continue;
215 const std::string name =
222 double servers = L.
stations[i].nservers;
223 for (
const T& s : L.
stations[i].lldscaling)
225 const bool is_ld = (nt == qn::NodeType::Queue) && !(servers == 1.0);
226 const char* tag = nt == qn::NodeType::Delay
228 : (is_ld ?
"ldstation" :
"listation");
230 f <<
" <" << tag <<
" name=\"" << name <<
"\"";
231 if (nt == qn::NodeType::Queue) f <<
" servers=\"1\"";
234 f <<
" <servicetimes>\n";
235 for (std::size_t c = 0; c < C; ++c) {
236 const double st = dv(d.
STchain, i, c);
238 const double limit = any_open ? servers : total_njobs;
239 std::string s = detail::num_text(st);
240 for (
double n = 2.0; n <= limit; n += 1.0)
241 s +=
";" + detail::num_text(st / std::min(n, servers));
242 f <<
" <servicetimes customerclass=\"" << detail::chain_name(c + 1)
243 <<
"\">" << s <<
"</servicetimes>\n";
245 f <<
" <servicetime customerclass=\"" << detail::chain_name(c + 1)
246 <<
"\">" << detail::num_text(st) <<
"</servicetime>\n";
249 f <<
" </servicetimes>\n";
252 for (std::size_t c = 0; c < C; ++c) {
253 const double st = dv(d.
STchain, i, c);
254 const double v = st > 0.0 ? dv(d.
Lchain, i, c) / st : 0.0;
255 f <<
" <visit customerclass=\"" << detail::chain_name(c + 1) <<
"\">"
256 << detail::num_text(v) <<
"</visit>\n";
259 f <<
" </" << tag <<
">\n";
261 f <<
" </stations>\n";
268 f <<
" <ReferenceStation number=\"" << C <<
"\">\n";
269 for (std::size_t c = 0; c < C; ++c) {
271 if (L.
stations[ref - 1].nodetype == qn::NodeType::Source) {
272 for (std::size_t i = 0; i < M; ++i) {
274 if (nt != qn::NodeType::Source && nt != qn::NodeType::Sink) {
280 f <<
" <Class name=\"" << detail::chain_name(c + 1) <<
"\" refStation=\""
283 f <<
" </ReferenceStation>\n";
284 f <<
" </parameters>\n";
286 f <<
" <algParams>\n";
287 f <<
" <algType name=\"" << detail::xml_escape(algname)
288 <<
"\" tolerance=\"1.0E-7\" maxSamples=\"" << samples <<
"\"/>\n";
289 f <<
" <compareAlgs value=\"false\"/>\n";
290 f <<
" </algParams>\n";
293 if (!f)
throw InputError(
"writeJMVA: failed to write '" + path +
"'");
std::string write_jmva(const qn::NetworkStruct< T > &L, const std::string &path, const std::string &method, std::size_t samples)
Port of writeJMVA(sn, outputFileName, options).