139 const std::string& method, std::size_t samples) {
142 bool multiserver_ok =
true;
143 const std::string algname = detail::alg_type_name(method, &multiserver_ok);
144 if (!multiserver_ok) {
145 for (std::size_t i = 0; i < M; ++i) {
146 const double c = L.
stations[i].nservers;
147 if (std::isfinite(c) && c > 1.0)
149 " does not support multi-server stations");
154 auto dv = [](
const Matrix<T>& A, std::size_t i, std::size_t j) {
163 std::vector<bool> is_source_station(M,
false);
164 std::size_t nsources = 0;
165 for (std::size_t i = 0; i < M; ++i)
166 if (L.
stations[i].nodetype == qn::NodeType::Source) {
167 is_source_station[i] =
true;
171 std::ofstream f(path.c_str());
172 if (!f)
throw InputError(
"writeJMVA: cannot open '" + path +
"' for writing");
173 f <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
174 f <<
"<model xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
175 <<
" xsi:noNamespaceSchemaLocation=\"JMTmodel.xsd\">\n";
176 f <<
" <parameters>\n";
179 f <<
" <classes number=\"" << C <<
"\">\n";
180 for (std::size_t c = 0; c < C; ++c) {
181 double sum_njobs = 0.0;
182 for (std::size_t k : L.
inchain[c]) sum_njobs += L.
classes[k - 1].population;
183 if (std::isfinite(sum_njobs)) {
184 f <<
" <closedclass population=\"" << detail::num_text(d.
Nchain[c])
185 <<
"\" name=\"" << detail::chain_name(c + 1) <<
"\"/>\n";
188 for (std::size_t i = 0; i < M; ++i) {
189 if (!is_source_station[i])
continue;
190 for (std::size_t k : L.
inchain[c]) {
191 const double r = dv(L.
rates, i, k - 1);
192 if (std::isfinite(r)) rate += r;
195 f <<
" <openclass rate=\"" << detail::num_text(rate) <<
"\" name=\""
196 << detail::chain_name(c + 1) <<
"\"/>\n";
199 f <<
" </classes>\n";
202 f <<
" <stations number=\"" << (M - nsources) <<
"\">\n";
206 bool any_open =
false;
207 for (std::size_t k = 0; k < K; ++k)
208 if (!std::isfinite(L.
classes[k].population)) any_open =
true;
209 double total_njobs = 0.0;
210 for (std::size_t k = 0; k < K; ++k)
211 if (std::isfinite(L.
classes[k].population)) total_njobs += L.
classes[k].population;
213 for (std::size_t i = 0; i < M; ++i) {
215 if (nt != qn::NodeType::Queue && nt != qn::NodeType::Delay)
continue;
216 const std::string name =
223 double servers = L.
stations[i].nservers;
224 for (
const T& s : L.
stations[i].lldscaling)
226 const bool is_ld = (nt == qn::NodeType::Queue) && !(servers == 1.0);
227 const char* tag = nt == qn::NodeType::Delay
229 : (is_ld ?
"ldstation" :
"listation");
231 f <<
" <" << tag <<
" name=\"" << name <<
"\"";
232 if (nt == qn::NodeType::Queue) f <<
" servers=\"1\"";
235 f <<
" <servicetimes>\n";
236 for (std::size_t c = 0; c < C; ++c) {
237 const double st = dv(d.
STchain, i, c);
239 const double limit = any_open ? servers : total_njobs;
240 std::string s = detail::num_text(st);
241 for (
double n = 2.0; n <= limit; n += 1.0)
242 s +=
";" + detail::num_text(st / std::min(n, servers));
243 f <<
" <servicetimes customerclass=\"" << detail::chain_name(c + 1)
244 <<
"\">" << s <<
"</servicetimes>\n";
246 f <<
" <servicetime customerclass=\"" << detail::chain_name(c + 1)
247 <<
"\">" << detail::num_text(st) <<
"</servicetime>\n";
250 f <<
" </servicetimes>\n";
253 for (std::size_t c = 0; c < C; ++c) {
254 const double st = dv(d.
STchain, i, c);
255 const double v = st > 0.0 ? dv(d.
Lchain, i, c) / st : 0.0;
256 f <<
" <visit customerclass=\"" << detail::chain_name(c + 1) <<
"\">"
257 << detail::num_text(v) <<
"</visit>\n";
260 f <<
" </" << tag <<
">\n";
262 f <<
" </stations>\n";
269 f <<
" <ReferenceStation number=\"" << C <<
"\">\n";
270 for (std::size_t c = 0; c < C; ++c) {
272 if (L.
stations[ref - 1].nodetype == qn::NodeType::Source) {
273 for (std::size_t i = 0; i < M; ++i) {
275 if (nt != qn::NodeType::Source && nt != qn::NodeType::Sink) {
281 f <<
" <Class name=\"" << detail::chain_name(c + 1) <<
"\" refStation=\""
284 f <<
" </ReferenceStation>\n";
285 f <<
" </parameters>\n";
287 f <<
" <algParams>\n";
288 f <<
" <algType name=\"" << detail::xml_escape(algname)
289 <<
"\" tolerance=\"1.0E-7\" maxSamples=\"" << samples <<
"\"/>\n";
290 f <<
" <compareAlgs value=\"false\"/>\n";
291 f <<
" </algParams>\n";
294 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).