LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
solver_mna.h File Reference

Port of solver_mna_open.m and solver_mna_closed.m, the two analyzers behind SolverMAM's mna method. More...

#include <algorithm>
#include <cmath>
#include <limits>
#include <string>
#include <utility>
#include <vector>
#include "line/api/da/da_fpi.h"
#include "line/api/da/da_traffic_superpos.h"
#include "line/api/mam/aph_fit_moments.h"
#include "line/api/mam/map_moment.h"
#include "line/api/mam/mmap_assemble.h"
#include "line/api/mam/mmap_lambda.h"
#include "line/api/mam/mmapph1fcfs.h"
#include "line/api/npfqn/npfqn_traffic_split_rr.h"
#include "line/api/qsys/qsys_mmck.h"
#include "line/lang/distribution.h"
#include "line/lang/qn/network_struct.h"
#include "line/solvers/mam/mam_types.h"
#include "line/solvers/mam/solver_mam_basic.h"
#include "line/solvers/mam/solver_mam_bmap.h"
#include "line/util/error.h"
#include "line/util/matrix.h"
Include dependency graph for solver_mna.h:

Go to the source code of this file.

Classes

struct  line::mam::MnaConfig
 The options.config fields the two MNA analyzers read. More...

Namespaces

namespace  line
namespace  line::mam

Functions

template<class T>
mva::MvaSolution< T > line::mam::solver_mna_open (const qn::NetworkStruct< T > &L, const MamOptions &opt, const MnaConfig &cfg=MnaConfig())
 Port of solver_mna_open.m.
template<class T>
mva::MvaSolution< T > line::mam::solver_mna_closed (const qn::NetworkStruct< T > &L, const MamOptions &opt)
 Port of solver_mna_closed.m.

Detailed Description

Port of solver_mna_open.m and solver_mna_closed.m, the two analyzers behind SolverMAM's mna method.

THE METHOD. MNA is QNA's flow decomposition with QNA's isolated-station solution REPLACED, at every FCFS station, by a matrix-analytic one. Each sweep superposes the per-class flows into a station as a rate a1(i,r) and a squared coefficient of variation a2(i,r), solves the station in isolation, and splits the departure stream along the outgoing arcs with the exact Bernoulli-thinning rule f2 = 1 + p (d2 - 1). What makes it MAM rather than QNA is the last step: the converged (a1, a2) pair is turned back into a phase-type arrival process – one APH per class fitted to those two moments, marked and superposed into an MMAP – and the station's queue length comes from MMAP[K]/PH[K]/1 FCFS rather than from a Whitt waiting-time formula. The flow SCVs d2 that drive the NEXT sweep still come from QNA's departure formula, so the fixed point is QNA's and only the reported queue lengths are matrix-analytic.

THE TWO ANALYZERS DIFFER IN WHAT DRIVES THE OUTER LOOP, not in the sweep. The open one has its arrival rates fixed by the sources and runs a single flow fixed point. The closed one has no source: it wraps the same flow fixed point in an OUTER BISECTION on the per-class throughput, bracketed below by 0 and above by the slowest service rate over the finite-server stations, and driven against the population target N. That is why the closed analyzer evaluates the matrix-analytic station solve once per outer step, and why it asks for the queue-length DISTRIBUTION (truncated at the class population) where the open one asks only for the mean.

WHAT THE REFERENCE GETS WRONG, REPRODUCED RATHER THAN CORRECTED. Three things, each of which changes reported numbers:

  • A PS STATION IN THE OPEN ANALYZER REPORTS NOTHING. solver_mna_open.m's PS branch assigns to TN, UN, QN, RN, which are fresh undefined variables in that function – the metrics it returns are T, U, Q, R. So a PS station keeps the zeros it was initialised with, and its departure SCV d2 is never set either. The closed analyzer's PS branch writes the right names and does work. Reproduced: silently redirecting the writes would report queue lengths MATLAB does not report.
  • THE CLOSED ANALYZER READS ONE CLASS'S DISTRIBUTION FOR EVERY CLASS. [pdistr] = MMAPPH1FCFS(..., 'ncDistr', maxLevel) captures only the FIRST output, i.e. class 1's marginal, and the per-class truncation loop then truncates THAT at each class's own population. The reference labels the block "rough approximation" itself.
  • THROUGHPUT IS NEVER REPORTED. Both analyzers initialise X = zeros(1,K) and never assign it, so getAvg's per-class throughput column is zero however the model is solved. Station throughputs in T are correct; it is only the class-level X that is dead.

ONE REFERENCE BRANCH IS REFUSED RATHER THAN REPRODUCED. config.dep_scv = 'etaqa' is dead in MATLAB – qbd_depproc_jointmom raises on every input it can be handed, so the try/catch around it always takes the QNA fallback – while the ported qbd_depproc_jointmom works. Answering with the working one would report a departure SCV the reference never produces, so the option is refused by name instead; see solver_mna_open.

REFERENCE INDEXING, CHECKED RATHER THAN ASSUMED, exactly as solver_qna.h does for the same reason: both files index the STATEFUL-indexed sn.rt with station indices, and the closed one additionally indexes the CLASS-indexed sn.njobs and the length-C lambda with the same running index. Both are silently correct only on the model shapes the method is advertised for, and are refused by name otherwise.

SELF-LOOPING CLASSES. sn.isslc guards three blocks in the closed analyzer. The C++ JobClassType is OPEN or CLOSED only, so no model this port can build enters them and they are not transcribed.

Arithmetic: DOUBLE-ONLY, gated the way solver_mam_basic.h gates it. The flow fixed point stops on a tolerance, the APH fit takes a ceiling of a real reciprocal, and MMAP[K]/PH[K]/1 runs the ADDA doubling iteration.

Definition in file solver_mna.h.