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

Port of solver_mam_retrial.m, the customer-impatience analyzer of SolverMAM. More...

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <limits>
#include <map>
#include <string>
#include <vector>
#include "line/api/mam/map_moment.h"
#include "line/api/qsys/qsys_bmapphnn_retrial.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/util/error.h"
#include "line/util/matrix.h"
Include dependency graph for solver_mam_retrial.h:

Go to the source code of this file.

Classes

struct  line::mam::MamRetrialConfig
 The knobs solver_mam_retrial.m reads from options.config and from model fields the C++ NetworkStruct does not carry. More...
struct  line::mam::MamRetrialInfo
 What qsys_is_retrial.m returns: the station it found, or why it found none. More...

Namespaces

namespace  line
namespace  line::mam

Functions

template<class T>
MamRetrialInfo line::mam::mam_retrial_detect (const qn::NetworkStruct< T > &L)
 Port of qsys_is_retrial.m, plus the reneging gate of solver_mam_retrial.m.
template<class T>
std::string line::mam::mam_retrial_refusal (const qn::NetworkStruct< T > &L)
 The 'retrial' method's applicability as one sentence; empty when applicable.
template<class T>
mva::MvaSolution< T > line::mam::solver_mam_retrial (const qn::NetworkStruct< T > &L, const MamOptions &opt, const MamRetrialConfig &cfg=MamRetrialConfig())
 Port of solver_mam_retrial.m.

Detailed Description

Port of solver_mam_retrial.m, the customer-impatience analyzer of SolverMAM.

The reference file carries TWO analyzers behind one name, and tries them in this order:

  1. RENEGING, a MAP/M/s+G queue whose waiting jobs abandon after a generally distributed patience (Gursoy, Mehr and Akar). Solved as a multi-regime Markov fluid queue through MRMFQSolver.
  2. RETRIAL, the BMAP/PH/N/N bufferless orbit queue with flexible retrials admission control (Dudin et al., Mathematics 2025, 13(9), 1434). Solved by qsys_bmapphnn_retrial, which IS ported (api/qsys).

ONLY ROUTE 2 IS REACHABLE FROM C++, AND ROUTE 1 IS REFUSED BY NAME. The reneging gate reads sn.impatienceClass, sn.patienceProc and ImpatienceType.RENEGING, none of which the C++ NetworkStruct carries, so no model this port can BUILD is a reneging model. mam_retrial_detect says so explicitly instead of letting such a model fall through to the retrial generator, which would answer a queue with a waiting line as if it had an orbit.

WHAT THE ORBIT IS. A retrial station has no waiting room: the buffer equals the server count. A job that finds every server busy joins an ORBIT and re-attempts at rate alpha per orbiting job; a completion does NOT promote from the orbit. That is why the queue length reported here is L_orbit + N_server and not the marginal of an ordered buffer.

THE TRUNCATION IS THE ANSWER'S ACCURACY, AND IT IS ITERATED HERE. The orbit is unbounded, so qsys_bmapphnn_retrial truncates it; the reference does not accept the first truncation but doubles the level until the relative tail contribution truncLevel * mass(top level) / L_orbit falls under TailTolerance. The ported engine implements ONE solve at a given level and returns truncLevel, topLevelMass and L_orbit, which is exactly the triple that refinement test needs, so the loop lives here rather than being dropped. Without it a model is answered at the reference's FIXED default level, whose formula depends on neither alpha nor gamma – the two parameters that actually govern the tail decay – and the error is silent.

WHERE THIS IS STRICTER THAN THE REFERENCE, and why each is the honest outcome:

  • A NON-CONVERGED TRUNCATION IS AN ERROR, NOT A WARNING. When doubling hits the dimension cap before reaching the tolerance, solver_mam_retrial.m emits line_warning and returns the underestimate. The C++ port has no warning channel, so the same situation would return a number with nothing attached to it; it refuses instead, and names orbit_maxlevel as the way to ask for that number deliberately.
  • A NON-PHASE-TYPE SERVICE IS REFUSED, NOT APPROXIMATED. The reference's warnIfApproximated lets a Det, Replayer, Uniform, Gamma, Pareto, Weibull or Lognormal service through under an Erlang fit of matching mean and SCV, and says so in a warning. Everything but Det is already gated out by runner_detail::check_processes; Det reaches here, and dist_to_map would silently give it a 20-phase Erlang – which is not only a different model but blows the per-level block up by C(n + 19, 19) states per busy server.
  • A BOUNDED RETRY COUNT IS REFUSED. RetrialParam::max_attempts and DropStrategy::RETRIAL_WITH_LIMIT say a job gives up after k failed retries. The generator has no attempt counter in its state descriptor, so there is no level at which that job could be told apart from a persistent one.

WHAT THE C++ MODEL LAYER CANNOT SAY, so what is pinned at its reference default rather than read: the orbit abandonment rate gamma (sn.orbitImpatience, default 0), the batch rejection probability p (sn.batchRejectProb, default 0), the finite orbit sn.orbitMaxJobs, the CONSTANT retrial policy (sn.retrialPolicy; the ported engine is LINEAR-only, which is the reference's own default), and the admission threshold R, which the reference lowers below N-1 only from a Finite Capacity Region and NetworkStruct has no region field. Each is stated here so that a later model-layer addition has a list of what to wire, and none of them is invented from a capacity heuristic.

REFERENCE DEFECTS in solver_mam_retrial.m and qsys_bmapphnn_retrial.m:

  1. Tolerance IS PARSED AND NEVER USED. solver_mam_retrial.m reads options.tol, defaults it to 1e-10 and forwards it as 'Tolerance'; qsys_bmapphnn_retrial.m assigns it on line 83 and no later line reads it. The single dense solve behind the generator is direct, so there is no iteration for it to terminate. Not propagated: MamOptions::tol is likewise not forwarded here, and the comment records why rather than leaving a caller to wonder why lowering the tolerance changes nothing.
  2. THE DEFAULT RETRIAL RATE IS A MAGIC 0.1. When no retrial process is attached, alpha = 0.1 – a rate with no relation to the model. It is reproduced, because a station carrying only a RETRIAL drop rule is a model the reference accepts and would otherwise be answered differently by the two codebases, but a caller reaching it has almost certainly forgotten setRetrial.
  3. extractPHParams NORMALIZES A BAD beta INSTEAD OF REPORTING IT. When the entry vector recovered from D1 does not sum to one it is rescaled, and when it sums to zero it is replaced by the uniform vector. Both hide a malformed service representation. Not reproduced: map_pie is the codebase's own embedded entry vector and is exact for any Markovian pair, and a pair that is not Markovian is refused above by name.

ARITHMETIC. The generator is a rational expression in its inputs and the stationary law is one linear solve, so nothing here needs a transcendental function and this analyzer carries no has_transcendental gate – unlike solver_mam_basic, whose station solves run tolerance-terminated Riccati iterations. qsys_bmapphnn_retrial documents the same property, and the exact instantiation returns the stationary law of the truncated chain exactly.

Definition in file solver_mam_retrial.h.