66 <<
"LDES: discrete-event simulation engine for LINE models.\n\n"
67 <<
"Usage: ldes solve <model.json> [-o <result.json>] [options]\n\n"
69 <<
" -s, --samples N service completions to simulate (default 200000)\n"
70 <<
" -e, --maxevents N event budget; overrides --samples\n"
71 <<
" --maxtime SECONDS wall-clock budget\n"
72 <<
" --seed N run seed (default 23000; -1 draws one)\n"
73 <<
" --method NAME engine method (default 'default')\n"
74 <<
" --cnvgon stop on the convergence check\n"
75 <<
" --cnvgtol X relative tolerance of that check\n"
76 <<
" --cnvgbatch N batches before the first check\n"
77 <<
" --cnvgchk N events between checks\n"
78 <<
" --tranfilter NAME mser5 | fixed | none\n"
79 <<
" --mserbatch N MSER batch size\n"
80 <<
" --warmupfrac X warmup fraction, for --tranfilter fixed\n"
81 <<
" --tranobs N transient observation points over --timespan\n"
82 <<
" --cimethod NAME obm | bm | spectral | none\n"
83 <<
" --obmoverlap X overlap of the batch means\n"
84 <<
" --ciminbatch N batches below which no CI is reported\n"
85 <<
" --ciminobs N observations below which no CI is reported\n"
86 <<
" --spectrallowfreqfrac X low-frequency fraction of the spectral CI\n"
87 <<
" --slotted run on the slot lattice\n"
88 <<
" --slotlength X slot length (implies --slotted)\n"
89 <<
" --replications N independent replications\n"
90 <<
" --numthreads N threads across replications\n"
91 <<
" --timespan T0,T1 transient run over [T0,T1]\n"
92 <<
" --busyperiod K busy-period orders 1..K\n"
93 <<
" --busyperiod-subnet i,j,... an extra busy-period target\n"
94 <<
" --initsol V initial state, station-major, comma separated\n"
95 <<
" --initjobs J job-level initial state, one row per job, rows ';'\n"
96 <<
" separated: station,class,remaining,elapsed,qage,sage,order[,id]\n"
97 <<
" --trackjobs export the final job-level state and tagged departures\n"
98 <<
" --export-histogram fill the state histogram block\n"
99 <<
" --trajectory fill the state trajectory block\n"
100 <<
" --respt-samples record every per-visit response time\n"
101 <<
" -h, --help this text\n";
104[[noreturn]]
void fail(
const std::string& msg) {
105 std::cerr <<
"Error: " << msg <<
"\n";
110[[noreturn]]
void refuse(
const std::string& flag,
const std::string& why) {
111 std::cerr <<
"Error: " << flag <<
" is accepted by the Java engine but not by this one: "
112 << why <<
".\nRun the model through common/ldes.jar for it, rather than "
113 "taking a silently different simulation.\n";
117std::string need_value(
int argc,
char** argv,
int& i,
const std::string& flag) {
118 if (i + 1 >= argc) fail(flag +
" requires a value.");
119 return std::string(argv[++i]);
122std::vector<double> parse_doubles(
const std::string& csv) {
123 std::vector<double> out;
124 std::stringstream ss(csv);
126 while (std::getline(ss, tok,
',')) {
127 if (!tok.empty()) out.push_back(std::atof(tok.c_str()));
132std::vector<std::size_t> parse_indices(
const std::string& csv) {
133 std::vector<std::size_t> out;
134 std::stringstream ss(csv);
136 while (std::getline(ss, tok,
',')) {
137 if (!tok.empty()) out.push_back(
static_cast<std::size_t
>(std::atol(tok.c_str())));
143std::string num(
double v) {
144 if (std::isnan(v))
return "null";
145 if (std::isinf(v))
return v > 0 ?
"1e999" :
"-1e999";
147 std::snprintf(buf,
sizeof(buf),
"%.17g", v);
148 return std::string(buf);
154 for (std::size_t i = 0; i < rows; ++i) {
157 for (std::size_t j = 0; j < cols; ++j) {
159 const bool inside = (i < m.
rows() && j < m.
cols());
160 s += num(inside ? m(i, j) : 0.0);
169std::string respt_samples_json(
const LdesResult& r) {
170 if (r.respTimeSamples.empty())
return std::string();
172 for (std::size_t i = 0; i < r.respTimeSamples.size(); ++i) {
175 for (std::size_t k = 0; k < r.respTimeSamples[i].size(); ++k) {
178 for (std::size_t j = 0; j < r.respTimeSamples[i][k].size(); ++j) {
180 s += num(r.respTimeSamples[i][k][j]);
190std::string str_json(
const std::string& s) {
191 std::string out =
"\"";
193 if (c ==
'"' || c ==
'\\') {
196 }
else if (c ==
'\n') {
214std::string result_json(
const LdesResult& r,
const LdesOptions& o,
double runtime,
215 std::size_t events) {
216 const std::size_t S = r.nstations, C = r.nclasses;
219 s +=
" \"format\": \"ldes-result\",\n";
220 s +=
" \"version\": \"1.0\",\n";
221 s +=
" \"solver\": \"SolverLDES\",\n";
222 s +=
" \"method\": " + str_json(o.method) +
",\n";
223 s +=
" \"runtime\": " + num(runtime) +
",\n";
224 s +=
" \"converged\": false,\n";
225 s +=
" \"stoppingReason\": \"max_events\",\n";
226 s +=
" \"convergenceBatches\": 0,\n";
227 s +=
" \"totalSimulatedEvents\": " + std::to_string(events) +
",\n";
229 s +=
" \"dimensions\": {\"nstations\": " + std::to_string(S) +
230 ", \"nclasses\": " + std::to_string(C) +
", \"nchains\": " + std::to_string(r.nchains) +
231 ", \"stationNames\": [";
232 for (std::size_t i = 0; i < r.station_names.size(); ++i) {
234 s += str_json(r.station_names[i]);
236 s +=
"], \"classNames\": [";
237 for (std::size_t i = 0; i < r.class_names.size(); ++i) {
239 s += str_json(r.class_names[i]);
243 s +=
" \"metrics\": {";
244 s +=
"\"QN\": " + mat_json(r.QN, S, C);
245 s +=
", \"UN\": " + mat_json(r.UN, S, C);
246 s +=
", \"RN\": " + mat_json(r.RN, S, C);
247 s +=
", \"TN\": " + mat_json(r.TN, S, C);
248 s +=
", \"AN\": " + mat_json(r.AN, S, C);
249 s +=
", \"WN\": " + mat_json(r.WN, S, C);
250 s +=
", \"CN\": " + mat_json(r.CN, 1, C);
251 s +=
", \"XN\": " + mat_json(r.XN, 1, C);
256 if (!r.DropRateJoin.empty()) s +=
", \"DropRateJoin\": " + mat_json(r.DropRateJoin, S, C);
267 if (o.export_histogram && r.histogram_space.rows() > 0 && r.histogram_time.rows() > 0) {
268 s +=
" \"stateHistogram\": {";
269 s +=
"\"space\": " + mat_json(r.histogram_space, r.histogram_space.rows(),
270 r.histogram_space.cols());
271 s +=
", \"time\": " + mat_json(r.histogram_time, r.histogram_time.rows(), 1);
272 if (r.traj_space.rows() > 0 && r.traj_time.rows() > 0) {
273 s +=
", \"trajSpace\": " +
274 mat_json(r.traj_space, r.traj_space.rows(), r.traj_space.cols());
275 s +=
", \"trajTime\": " + mat_json(r.traj_time, r.traj_time.rows(), 1);
280 if (!r.busy_periods.empty()) {
281 s +=
" \"busyPeriods\": {\"orders\": " +
282 std::to_string(r.busy_periods[0].mean.size()) +
", \"targets\": [";
283 for (std::size_t ti = 0; ti < r.busy_periods.size(); ++ti) {
284 const LdesResult::BusyPeriodTarget& t = r.busy_periods[ti];
286 s +=
"{\"name\": " + str_json(t.name) +
", \"stations\": [";
287 for (std::size_t k = 0; k < t.stations.size(); ++k) {
289 s += std::to_string(t.stations[k]);
291 s +=
"], \"class\": " + std::to_string(t.job_class) +
", \"mean\": [";
292 for (std::size_t k = 0; k < t.mean.size(); ++k) {
296 s +=
"], \"count\": [";
297 for (std::size_t k = 0; k < t.count.size(); ++k) {
299 s += num(t.count[k]);
307 if (o.track_jobs || o.init_jobs.rows() > 0) {
308 s +=
" \"jobState\": {\"finalJobs\": " +
309 mat_json(r.finalJobs, r.finalJobs.rows(), r.finalJobs.cols());
310 s +=
", \"jobDepartures\": " +
311 mat_json(r.jobDepartures, r.jobDepartures.rows(), r.jobDepartures.cols()) +
"},\n";
314 if (!r.cache_metrics.empty()) {
315 s +=
" \"cacheMetrics\": {";
317 for (std::map<std::string, line::ldes::LdesCacheMetrics>::const_iterator it =
318 r.cache_metrics.begin();
319 it != r.cache_metrics.end(); ++it) {
320 if (!first) s +=
", ";
323 s += str_json(it->first) +
": {";
336 if (r.QNfcr.rows() > 0) {
337 const std::size_t G = r.QNfcr.rows();
338 s +=
" \"fcr\": {\"nregions\": " + std::to_string(G);
339 s +=
", \"QNfcr\": " + mat_json(r.QNfcr, G, C);
340 s +=
", \"UNfcr\": " + mat_json(r.UNfcr, G, C);
341 s +=
", \"RNfcr\": " + mat_json(r.RNfcr, G, C);
342 s +=
", \"TNfcr\": " + mat_json(r.TNfcr, G, C);
343 s +=
", \"ANfcr\": " + mat_json(r.ANfcr, G, C);
344 s +=
", \"WNfcr\": " + mat_json(r.WNfcr, G, C);
345 s +=
", \"WeightNfcr\": " + mat_json(r.WeightNfcr, G, C);
346 s +=
", \"MemOccNfcr\": " + mat_json(r.MemOccNfcr, G, C);
347 s +=
", \"DropRateNfcr\": " + mat_json(r.DropRateNfcr, G, C);
353 if (r.t.empty() && !r.fj_forks.empty() && r.FJTput.rows() == r.fj_forks.size()) {
354 const std::size_t
P = r.fj_forks.size();
355 s +=
" \"forkJoin\": {\"forks\": [";
356 for (std::size_t p = 0; p <
P; ++p) s += (p ?
", " :
"") + str_json(r.fj_forks[p]);
357 s +=
"], \"joins\": [";
358 for (std::size_t p = 0; p <
P; ++p) s += (p ?
", " :
"") + str_json(r.fj_joins[p]);
360 s +=
", \"FJQLen\": " + mat_json(r.FJQLen, P, C);
361 s +=
", \"FJRespT\": " + mat_json(r.FJRespT, P, C);
362 s +=
", \"FJTput\": " + mat_json(r.FJTput, P, C);
373 const std::string respt_json = respt_samples_json(r);
374 if (o.export_trajectory && !r.t.empty()) {
375 s +=
" \"transient\": {\"t\": [";
376 for (std::size_t k = 0; k < r.t.size(); ++k) {
381 const char* keys[3] = {
"QNt",
"UNt",
"TNt"};
382 const std::vector<std::vector<line::Matrix<double>>>* src[3] = {&r.QNt, &r.UNt, &r.TNt};
383 for (
int q = 0; q < 3; ++q) {
384 s += std::string(
", \"") + keys[q] +
"\": [";
385 for (std::size_t i = 0; i < src[q]->size(); ++i) {
388 for (std::size_t k = 0; k < (*src[q])[i].size(); ++k) {
391 s += mat_json(mm, mm.
rows(), mm.
cols());
397 if (!respt_json.empty()) s +=
", \"respTimeSamples\": " + respt_json;
401 if (o.export_respt && !respt_json.empty())
402 s +=
" \"respTimeSamples\": " + respt_json +
",\n";
403 s +=
" \"sampleCounts\": {";
404 s +=
"\"QNSamples\": " + mat_json(r.QNSamples, S, C);
405 s +=
", \"UNSamples\": " + mat_json(r.UNSamples, S, C);
406 s +=
", \"RNSamples\": " + mat_json(r.RNSamples, S, C);
407 s +=
", \"TNSamples\": " + mat_json(r.TNSamples, S, C);
410 s +=
" \"confidenceIntervals\": {";
411 s +=
"\"QNCI\": " + mat_json(r.QNCI, S, C);
412 s +=
", \"UNCI\": " + mat_json(r.UNCI, S, C);
413 s +=
", \"RNCI\": " + mat_json(r.RNCI, S, C);
414 s +=
", \"TNCI\": " + mat_json(r.TNCI, S, C);
415 s +=
", \"ANCI\": " + mat_json(r.ANCI, S, C);
416 s +=
", \"WNCI\": " + mat_json(r.WNCI, S, C);
419 s +=
" \"relativePrecision\": {";
420 s +=
"\"QNRelPrec\": " + mat_json(r.QNRelPrec, S, C);
421 s +=
", \"UNRelPrec\": " + mat_json(r.UNRelPrec, S, C);
422 s +=
", \"RNRelPrec\": " + mat_json(r.RNRelPrec, S, C);
423 s +=
", \"TNRelPrec\": " + mat_json(r.TNRelPrec, S, C);
426 s +=
" \"impatience\": {";
427 s +=
"\"renegedCustomers\": " + mat_json(r.renegedCustomers, S, C);
428 s +=
", \"avgRenegingWaitTime\": " + mat_json(r.avgRenegingWaitTime, S, C);
429 s +=
", \"renegingRate\": " + mat_json(r.renegingRate, S, C);
430 s +=
", \"balkedCustomers\": " + mat_json(r.balkedCustomers, S, C);
431 s +=
", \"balkingProbability\": " + mat_json(r.balkingProbability, S, C);
432 s +=
", \"retriedCustomers\": " + mat_json(r.retriedCustomers, S, C);
433 s +=
", \"retrialDropped\": " + mat_json(r.retrialDropped, S, C);
434 s +=
", \"avgOrbitSize\": " + mat_json(r.avgOrbitSize, S, C);
442 std::string s =
"[[";
443 for (std::size_t k = 1; k <= nidx; ++k) {
444 if (k > 1) s +=
", ";
445 s += num(k < m.
rows() ? m(k, 0) : 0.0);
461 double runtime,
bool respt) {
462 const std::size_t n = lsn.
nidx;
469 for (std::size_t k = 1; k <= n; ++k) {
474 std::string s =
"{\"format\": \"ldes-result\", \"version\": \"1.0\", "
475 "\"modelType\": \"LayeredNetwork\", \"solver\": \"LDES\", ";
476 s +=
"\"method\": " + str_json(o.method) +
", \"runtime\": " + num(runtime) +
", ";
477 s +=
"\"dimensions\": {\"nidx\": " + std::to_string(n) +
478 ", \"nhosts\": " + std::to_string(lsn.
nhosts) +
479 ", \"ntasks\": " + std::to_string(lsn.
ntasks) +
480 ", \"nentries\": " + std::to_string(lsn.
nentries) +
481 ", \"nacts\": " + std::to_string(lsn.
nacts) +
482 ", \"ncalls\": " + std::to_string(lsn.
ncalls) +
483 ", \"tshift\": " + std::to_string(lsn.
tshift) +
484 ", \"eshift\": " + std::to_string(lsn.
eshift) +
485 ", \"ashift\": " + std::to_string(lsn.
ashift) +
", \"names\": [";
486 for (std::size_t k = 1; k <= n; ++k) {
487 if (k > 1) s +=
", ";
488 s += str_json(k < lsn.
names.size() ? lsn.
names[k] :
"Element" + std::to_string(k - 1));
490 s +=
"]}, \"metrics\": {";
491 s +=
"\"QLN\": " + ln_row_json(QLN, n) +
", \"ULN\": " + ln_row_json(ULN, n);
492 s +=
", \"RLN\": " + ln_row_json(RLN, n) +
", \"WLN\": " + ln_row_json(r.
WLN, n);
493 s +=
", \"TLN\": " + ln_row_json(r.
TLN, n) +
", \"ALN\": " + ln_row_json(r.
ALN, n);
494 s +=
", \"ZLN\": " + ln_row_json(r.
ZLN, n) +
"}, ";
495 s +=
"\"confidenceIntervals\": {\"QLNCI\": null, \"ULNCI\": null, \"RLNCI\": null, "
498 s +=
", \"cacheMetrics\": [";
499 for (std::size_t i = 0; i < r.
cache_task.size(); ++i) {
501 s +=
"{\"cacheTaskIdx\": " + std::to_string(r.
cache_task[i] - 1) +
502 ", \"itemEntryIdx\": " + std::to_string(r.
cache_entry[i] - 1) +
503 ", \"hitProb\": " + num(r.
cache_hit[i]) +
", \"missProb\": " +
510 s +=
", \"entryRespTimeSamples\": [";
527int main(
int argc,
char** argv) {
532 const std::string cmd = argv[1];
533 if (cmd ==
"-h" || cmd ==
"--help") {
537 if (cmd !=
"solve") {
538 std::cerr <<
"Error: unknown command '" << cmd <<
"'. The only command is 'solve'.\n";
541 if (argc < 3) fail(
"solve requires a model file.");
543 const std::string model_path = argv[2];
544 std::string output_path;
546 bool have_samples =
false, have_events =
false;
547 std::vector<std::string> given;
549 for (
int i = 3; i < argc; ++i) {
550 const std::string a = argv[i];
553 output_path = need_value(argc, argv, i, a);
554 }
else if (a ==
"-s" || a ==
"--samples") {
555 o.samples =
static_cast<std::size_t
>(std::atol(need_value(argc, argv, i, a).c_str()));
557 }
else if (a ==
"-e" || a ==
"--maxevents") {
558 o.events =
static_cast<std::size_t
>(std::atol(need_value(argc, argv, i, a).c_str()));
560 }
else if (a ==
"--maxtime") {
561 o.timeout = std::atof(need_value(argc, argv, i, a).c_str());
562 }
else if (a ==
"--seed") {
563 o.seed = std::atol(need_value(argc, argv, i, a).c_str());
564 }
else if (a ==
"--method") {
565 o.method = need_value(argc, argv, i, a);
566 }
else if (a ==
"--cnvgon") {
568 }
else if (a ==
"--cnvgtol") {
569 o.cnvgtol = std::atof(need_value(argc, argv, i, a).c_str());
570 }
else if (a ==
"--cnvgbatch") {
571 o.cnvgbatch = std::atoi(need_value(argc, argv, i, a).c_str());
572 }
else if (a ==
"--cnvgchk") {
573 o.cnvgchk = std::atoi(need_value(argc, argv, i, a).c_str());
574 }
else if (a ==
"--tranfilter") {
575 o.tranfilter = need_value(argc, argv, i, a);
576 }
else if (a ==
"--mserbatch") {
577 o.mserbatch = std::atoi(need_value(argc, argv, i, a).c_str());
578 }
else if (a ==
"--tranobs") {
579 o.tranobs = std::atoi(need_value(argc, argv, i, a).c_str());
580 if (o.tranobs <= 0) fail(
"--tranobs must be positive.");
581 }
else if (a ==
"--warmupfrac") {
582 o.warmupfrac = std::atof(need_value(argc, argv, i, a).c_str());
583 }
else if (a ==
"--cimethod") {
584 o.cimethod = need_value(argc, argv, i, a);
585 }
else if (a ==
"--obmoverlap") {
586 o.obmoverlap = std::atof(need_value(argc, argv, i, a).c_str());
587 }
else if (a ==
"--ciminbatch") {
588 o.ciminbatch = std::atoi(need_value(argc, argv, i, a).c_str());
589 }
else if (a ==
"--ciminobs") {
590 o.ciminobs = std::atoi(need_value(argc, argv, i, a).c_str());
591 }
else if (a ==
"--spectrallowfreqfrac") {
592 o.spectral_low_freq_frac = std::atof(need_value(argc, argv, i, a).c_str());
593 }
else if (a ==
"--slotted") {
595 }
else if (a ==
"--slotlength") {
596 o.slot_length = std::atof(need_value(argc, argv, i, a).c_str());
598 }
else if (a ==
"--replications") {
599 o.replications = std::atoi(need_value(argc, argv, i, a).c_str());
600 }
else if (a ==
"--numthreads") {
601 o.numthreads = std::atoi(need_value(argc, argv, i, a).c_str());
602 }
else if (a ==
"--timespan") {
603 const std::vector<double> t = parse_doubles(need_value(argc, argv, i, a));
604 if (t.size() != 2) fail(
"--timespan takes T0,T1.");
605 o.has_timespan =
true;
608 }
else if (a ==
"--busyperiod") {
609 o.busy_period_orders = std::atoi(need_value(argc, argv, i, a).c_str());
610 }
else if (a ==
"--busyperiod-subnet") {
611 o.busy_period_subnets.push_back(parse_indices(need_value(argc, argv, i, a)));
612 }
else if (a ==
"--initsol") {
613 o.init_sol = parse_doubles(need_value(argc, argv, i, a));
614 }
else if (a ==
"--initjobs") {
615 const std::string v = need_value(argc, argv, i, a);
616 std::vector<std::vector<double>> rows;
618 while (at <= v.size()) {
619 const std::size_t semi = std::min(v.find(
';', at), v.size());
620 if (semi > at) rows.push_back(parse_doubles(v.substr(at, semi - at)));
623 const std::size_t ncols = rows.empty() ? 0 : rows[0].size();
624 for (std::size_t r = 0; r < rows.size(); ++r)
625 if (rows[r].size() != ncols) fail(
"--initjobs rows must have the same length.");
627 for (std::size_t r = 0; r < rows.size(); ++r)
628 for (std::size_t c = 0; c < ncols; ++c) o.init_jobs(r, c) = rows[r][c];
629 }
else if (a ==
"--trackjobs") {
631 }
else if (a ==
"--export-histogram") {
632 o.export_histogram =
true;
633 }
else if (a ==
"--trajectory") {
634 o.export_trajectory =
true;
635 }
else if (a ==
"--respt-samples") {
636 o.export_respt =
true;
637 }
else if (a ==
"--rest") {
638 refuse(a,
"server mode belongs to line-cli, not to this binary");
639 }
else if (a ==
"-h" || a ==
"--help") {
643 fail(
"unknown option '" + a +
"'.");
646 if (have_events && !have_samples) o.samples = o.events;
654 static const char*
const network_only[] = {
655 "--timespan",
"--tranobs",
"--trajectory",
"--export-histogram",
"--busyperiod",
656 "--busyperiod-subnet",
"--initsol",
"--initjobs",
"--trackjobs",
"--slotted",
657 "--slotlength",
"--replications"};
658 for (
const std::string& g : given)
659 for (
const char* f : network_only)
661 fail(g +
" is a Network-path option; the layered engine reports the steady "
662 "state of one replication only.");
663 if (o.method !=
"default")
664 fail(
"method '" + o.method +
"' is not a layered LDES method; use 'default'.");
667 const std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
669 const double runtime =
670 std::chrono::duration<double>(std::chrono::steady_clock::now() - t0).count();
671 const std::string doc = ln_result_json(lsn, r, o, runtime, o.export_respt);
672 if (output_path.empty()) {
675 std::ofstream out(output_path.c_str());
676 if (!out) fail(
"cannot write '" + output_path +
"'.");
679 std::cerr <<
"LDES analysis [method: default; type: approximate, randomized; lang: cpp; "
680 "native LN engine] completed in " << runtime <<
"s. Iterations: "
689 const std::chrono::steady_clock::time_point t_start = std::chrono::steady_clock::now();
691 const double runtime =
692 std::chrono::duration<double>(std::chrono::steady_clock::now() - t_start).count();
694 const std::string doc = result_json(r, o, runtime, o.samples);
695 if (output_path.empty()) {
698 std::ofstream out(output_path.c_str());
699 if (!out) fail(
"cannot write '" + output_path +
"'.");
702 std::cerr <<
"LDES analysis [method: " << o.method
703 <<
"; type: approximate, randomized; lang: cpp] completed in " << runtime
704 <<
"s. Iterations: " << o.samples <<
".\n";
707 std::cerr <<
"Error: [" << e.
id() <<
"] " << e.what() <<
"\n";
711 std::cerr <<
"Error: [" << e.
id() <<
"] " << e.what() <<
"\n";
713 }
catch (
const std::exception& e) {
714 std::cerr <<
"Error: " << e.what() <<
"\n";
Base error for the multiprecision C++ port.
const std::string & id() const noexcept
The full identifier, e.g.
A refusal: the feature, method or analysis is not covered: LINE:unsupported:<kind>.
A network plus its refreshed NetworkStruct.
A queueing network under construction.
const NetworkStruct< T > & get_struct()
The refreshed struct, MATLAB's model.getStruct().
The exception types the port throws.
int main(int argc, char **argv)
The NATIVE LDES discrete-event engine.
The NATIVE LDES engine for LAYERED (LQN) models, the C++ twin of jline/solvers/ldes/handlers/Solver_s...
The option and result records of SolverLDES, the discrete-event simulator.
model.json with type: "LayeredNetwork" -> LqnStruct, via LqnBuilder.
bool is_layered_json(const std::string &path)
True when a file is a LayeredNetwork model.json rather than an .lqnx.
qn::Network< T > read_network_json(const std::string &path)
Parse a model.json file into a qn::Network<T>.
lqn::LqnStruct< T > read_layered_model(const std::string &path)
Read a layered model from any of its interchanges: the LINE model.json, the LQNS ....
LdesResult ldes_engine_solve(const qn::NetworkStruct< T > &sn, const LdesOptions &o)
Simulate sn, over independent REPLICATIONS when options.replications > 1.
engine::LnResult ldes_ln_engine_solve(const lqn::LqnStruct< T > &lsn, const LdesOptions &o)
Simulate a layered model in process.
Reader for the LINE model.json interchange (a Network model) into a qn::Network<T> built through the ...
Per-cache hit/miss/latency, as the cacheMetrics block carries them.
Matrix< double > listCost
(1 x nlists) mean storage cost held per list
Matrix< double > latency
(1 x nclasses) expected retrieval latency
Matrix< double > hitList
(nclasses x nlists) hit probability by list
Matrix< double > itemProb
(nitems x nlists+1) item position law
Matrix< double > delayed
(1 x nclasses) delayed-hit probability
Matrix< double > miss
(1 x nclasses) miss probability
Matrix< double > hit
(1 x nclasses) hit probability
The knobs of one LDES run.
One ldes-result document, parsed.
The layered result: per element, the mean measures.
std::vector< double > cache_read_rate
Matrix< double > ZLN
Think time per element, Solver_ssj_ln's ZLN: Little's law on a task's thread pool read backwards,...
std::vector< double > cache_miss
Matrix< double > ALN
Arrival rate per element, Solver_ssj_ln's ALN: an entry's request rate (its throughput,...
Matrix< double > WLN
Residence time per element, the ResidT column: the time an activity holds ITS HOST PROCESSOR per visi...
std::vector< std::size_t > cache_entry
std::vector< double > cache_hit
std::vector< std::vector< double > > entry_resp_samples
Every per-request ENTRY response time observed, one vector per entry in LOCAL index space (0....
std::vector< std::size_t > cache_task
Cache measures, one row per ItemEntry that was read, pooled over the replicas of its cache task as So...
long long events
Activity completions over the whole run, warmup included: what the budget counts.
std::vector< double > cache_delayed
std::vector< std::string > names
(nidx+1) declared name
double host_reach_mult(std::size_t idx) const
Servers of the host of element idx that its work can reach: the divisor of every LQN Util column (Sol...