Class SolverMAM

Direct Known Subclasses:
MAM

public class SolverMAM extends NetworkSolver
Solver for Matrix Analytic Methods (MAM) applied to queueing networks.

SolverMAM implements matrix-analytic techniques for analyzing queueing networks with Markovian arrival processes (MAP), phase-type service distributions, and other non-exponential characteristics that go beyond product-form assumptions.

Key MAM solver capabilities:

  • Markovian Arrival Process (MAP) modeling
  • Phase-type (PH) service distribution analysis
  • Matrix-geometric solution methods
  • Quasi-Birth-Death (QBD) process analysis
  • Non-product-form queueing network solutions
  • Passage time distribution computation

This solver is particularly useful for networks with correlated arrivals, general service times, and complex dependency structures that cannot be analyzed using traditional product-form methods.

Since:
1.0
See Also:
  • Constructor Details

  • Method Details

    • defaultOptions

      public static SolverOptions defaultOptions()
    • getMAMResult

      public MAMInternals getMAMResult()
      Intermediate quantities of the matrix-analytic analysis of a single-queue model, in addition to the mean performance measures returned by getAvg.

      Mean values alone hide the objects the method is actually built on, so a matrix-analytic result cannot be inspected, taught, or checked against a published derivation. This accessor returns them.

      For a BMAP (or MAP) arrival stream feeding an exponential single server the result is that of Qsys_bmapm1 and carries the M/G/1-type quantities: the phase-process stationary vectors theta and alpha, the randomized blocks A0, A1, B0 and Bk, the matrix G, the drift, the measured decay rate and the level probabilities. For a retrial station the result is that of Qsys_bmapphnn_retrial and carries the orbit-level stationary distribution together with the truncation level and its residual.

      Returns:
      the matrix-analytic internals
    • getFeatureSet

      public static FeatureSet getFeatureSet()
      Returns the feature set supported by the MAM solver
      Returns:
      - the feature set supported by the MAM solver
    • methodFeatureSet

      public static FeatureSet methodFeatureSet(String method)
      Per-method feature deltas on the base MAM envelope. Only 'mna' resolves a round-robin split (Npfqn_traffic_split_rr in Solver_mna_open); the closed branch has no counterpart and is rejected in supportsModelMethod. Mirrors the MATLAB/Python SolverMAM.getMethodFeatureSet.
      Parameters:
      method - the concrete method name
      Returns:
      the per-method FeatureSet
    • bufferRefusal

      public static String bufferRefusal(NetworkStruct sn)
      Why no MAM method can answer a model whose finite buffer a CLOSED class can fill, or "" when every binding buffer is reached by open classes only.

      A MAM analyzer represents a finite buffer as a LOSS buffer: Solver_mam_basic (default, dec.source, dec.poisson) solves an M/M/c/K or an MMAP[K]/G/1/K, and Solver_mam (dec.mmap), Solver_mam_basic_mmap (dec.source.mmap) and Solver_mna_open (mna) truncate and renormalize the same way. That is the right model for an OPEN class, whose refused arrival is lost. A closed job that finds no room BLOCKS instead -- LINE disables the upstream departure and holds the job where it is -- and no MAM analyzer blocks: the loss formulas answer a different system, and the closed routes of "default" (Solver_mam_ldqbd, Solver_mam_bgchain, Solver_mna_closed) read no sn.cap or sn.classcap at all. So the pair is refused rather than answered.

      ONE PREDICATE, TWO CALLERS: supportsModelMethod(java.lang.String) reports it and Solver_mam_analyzer raises it. Only a buffer that can BIND counts, which is what SnGetBufferSize decides: refreshCapacity derives a finite classcap (the chain population) at every station of every closed model, so a plain finiteness test would refuse every closed model. A Cache builds its own capped retrieval queues and is exempt, as in SnHasBlocking. Mirrors MATLAB mam_buffer_refusal.

      Parameters:
      sn - the network structure
      Returns:
      empty string when no closed class can fill a binding buffer
    • getMethodFeatureSet

      public FeatureSet getMethodFeatureSet(String method)
      Description copied from class: Solver
      Per-method feature set, or null to signal "this solver does not diverge per method" (the coarse supports(model) is then used, preserving any structural checks it carries). Divergent solvers (e.g. MVA, MAM, NC) override this to return the base envelope with per-method deltas applied.
      Overrides:
      getMethodFeatureSet in class Solver
      Parameters:
      method - the concrete method name
      Returns:
      the per-method FeatureSet, or null
    • getStruct

      public NetworkStruct getStruct()
    • listValidMethods

      public List<String> listValidMethods(Network model)
    • listValidMethods

      public List<String> listValidMethods()
    • getTranAvg

      public void getTranAvg()
      Description copied from class: NetworkSolver
      Computes transient average station metrics over the specified time interval. The timespan is defined in the solver options.
      Overrides:
      getTranAvg in class NetworkSolver
    • runAnalyzer

      public void runAnalyzer()
      Description copied from class: Solver
      Executes the solver algorithm to analyze the model. This abstract method must be implemented by concrete solver classes.
      Specified by:
      runAnalyzer in class Solver
    • supports

      public boolean supports(Network model)
      Description copied from class: Solver
      Checks if this solver supports the given network model. Default implementation returns true; subclasses should override to provide specific feature validation.
      Overrides:
      supports in class Solver
      Parameters:
      model - the network model to check
      Returns:
      true if the model is supported, false otherwise
    • supportsModelMethod

      public String supportsModelMethod(String method)
      Method-aware gate for the genuine per-method restrictions of the MAM analyzer (mirrors the guards in Solver_mam_analyzer and the MATLAB SolverMAM.supportsModelMethod): 'mna' does not support mixed open/closed models, and 'ldqbd' requires a single-class model. All other methods rely on the coarse MAM feature set and the analyzer's topology-based routing (a Fork-Join model is routed to the FJ solver, not rejected). Returns an empty string when supported, otherwise the reason.
      Overrides:
      supportsModelMethod in class Solver
      Parameters:
      method - the concrete method name
      Returns:
      empty string if supported, else the offending reason
    • unsupportedMethodReason

      protected String unsupportedMethodReason(String method)
      The forwarding address for the RCAT names, which are SolverAG's now.

      Asks nothing of the model, so checkDeclaredMethod can call it before the struct is built; supportsModelMethod(String) returns the same string, so a caller gets one answer whichever gate it meets first.

      Overrides:
      unsupportedMethodReason in class NetworkSolver
      Parameters:
      method - the requested method name
      Returns:
      the explanation, or "" when the solver has none
    • mamRetrialRefusal

      public static String mamRetrialRefusal(NetworkStruct sn)
      Can the 'retrial' method answer this model? Empty string when it can.

      THE RULE IS A "MUST BE PRESENT" ONE, which is why it cannot live in a feature set: a FeatureSet says "I accept this construct", so it can refuse a model for HAVING something and never for LACKING it. Solver_mam_retrial needs the BMAP/PH/N/N bufferless retrial topology of Dudin et al. (Mathematics 13(9), 2025) to analyze, and a model without one is not a smaller retrial model, it is a different one.

      ONE PREDICATE, TWO CALLERS: supportsModelMethod asks it so the method is not offered by findSolver or SolverAUTO on a model it cannot answer, and Solver_mam_analyzer's 'retrial' arm asks it so a caller naming the method by hand gets the identical sentence.

      Unlike MATLAB, this port has NO MAP/M/s+G reneging arm behind the method, so a reneging patience does not make it applicable here.

      Parameters:
      sn - the model struct
      Returns:
      empty string when applicable, otherwise the refusal
    • mamHasRetrial

      public static boolean mamHasRetrial(NetworkStruct sn)
      True when some station-class pair configures a retrial orbit (Queue.setRetrial / setOrbit), read off sn.retrialProc, which the refresh fills only for a configured delay that is not the Disabled placeholder. retrialProc is the ambiguity-free test: retrialType is 0 both for "none" and, in MATLAB, for an exponential delay (see CLAUDE.md).

      mamRetrialRefusal(jline.lang.NetworkStruct) answers about the SHAPE Solver_mam_retrial needs, not about whether an orbit EXISTS, and a model with an orbit outside that shape falls through to Solver_mam_basic, which reads no sn.retrial* field and answers with the refused jobs simply lost. Mirrors MATLAB mam_has_retrial.

      Parameters:
      sn - the network structure
      Returns:
      true when any station-class pair carries an orbit delay
    • getCdfRespT

      public Ret.DistributionResult getCdfRespT(AvgHandle R)
      Returns cumulative distribution functions of response times at steady-state. This method computes response time distributions using matrix-analytic methods.
      Overrides:
      getCdfRespT in class NetworkSolver
      Parameters:
      R - response time handles (optional)
      Returns:
      result containing CDFs for response times
    • getCdfRespT

      public Ret.DistributionResult getCdfRespT()
      Returns cumulative distribution functions of response times at steady-state. Uses default response time handles.
      Overrides:
      getCdfRespT in class NetworkSolver
      Returns:
      result containing CDFs for response times
    • getCdfPassT

      public Ret.DistributionResult getCdfPassT(AvgHandle R)
      Returns cumulative distribution functions of passage times at steady-state.
      Overrides:
      getCdfPassT in class NetworkSolver
      Parameters:
      R - response time handles (optional)
      Returns:
      result containing CDFs for passage times
    • getCdfPassT

      public Ret.DistributionResult getCdfPassT()
      Returns cumulative distribution functions of passage times at steady-state. Uses default response time handles.
      Overrides:
      getCdfPassT in class NetworkSolver
      Returns:
      result containing CDFs for passage times
    • getTranCdfPassT

      public Ret.DistributionResult getTranCdfPassT(AvgHandle R)
      Returns cumulative distribution functions of passage times during transient analysis.
      Overrides:
      getTranCdfPassT in class NetworkSolver
      Parameters:
      R - response time handles (optional)
      Returns:
      result containing transient CDFs for passage times
    • getTranCdfPassT

      public Ret.DistributionResult getTranCdfPassT()
      Returns cumulative distribution functions of passage times during transient analysis. Uses default response time handles.
      Overrides:
      getTranCdfPassT in class NetworkSolver
      Returns:
      result containing transient CDFs for passage times
    • getProb

      public Ret.ProbabilityResult getProb(int node, Matrix state)
      Joint (level, phase) state probability, port of @SolverMAM/getProb.m.

      The level marginal comes from MMAPPH1FCFS over an aggregate MMAP built from the class throughputs; the phase factor is the arrival-weighted TIME-STATIONARY phase distribution map_prob, not map_pie. map_pie is the embedded equilibrium at departure instants -- the phase a service STARTS in -- so for an Erlang-2 it is [1 0] and the joint gave P(phase 2) = 0 at every level for a server spending half its busy time in phase 2.

      Phases are taken independent of level, where an exact QBD would have pi_n = pi_1 R^(n-1). That approximation is the reference's and is reproduced rather than improved.

      Overrides:
      getProb in class NetworkSolver
      Parameters:
      node - node index (0-based)
      state - [level, phase] pair, or null for the whole matrix
      Returns:
      probability of the state, or the (levels x phases) matrix
    • getProbMarg

      public Ret.ProbabilityResult getProbMarg(int node, int jobclass, Matrix state_m)
      Description copied from class: NetworkSolver
      Probability distribution for queue length of a SINGLE class at a station. Returns P(n jobs of class r) for n=0,1,...,N(r).

      Compare with NetworkSolver.getProbAggr(int, jline.util.matrix.Matrix): returns probability of a specific per-class distribution, e.g., P(2 class-1, 1 class-2) as a scalar.

      Overrides:
      getProbMarg in class NetworkSolver
      Parameters:
      node - the node index for which to compute probabilities
      jobclass - the job class index for marginalization
      state_m - specific states to query, or null for all
      Returns:
      vector where element n+1 = P(n jobs of this class)
    • getProbMarg

      public Ret.ProbabilityResult getProbMarg(int node, int jobclass)
      Get marginal queue-length probability distribution for a job class (all states).

      Delegates to getProbMarg(int, int, Matrix) with state_m == null (all levels). Supported for single-queue models via QBD/MMAPPH1FCFS analysis; a network with multiple queue stations is rejected there, matching the MATLAB @SolverMAM/getProbMarg.m behaviour.

      Overrides:
      getProbMarg in class NetworkSolver
      Parameters:
      node - Station/node index (0-based)
      jobclass - Job class index (0-based)
      Returns:
      Probability result containing the marginal queue-length distribution
      Throws:
      UnsupportedOperationException - if the model has more than one queue station
      See Also:
    • getPerctRespT

      public List<MainFJ.FJPercentileResult> getPerctRespT(double[] percentiles)
      Get response time percentiles from Fork-Join analysis

      This method retrieves percentile values computed by the FJ_codes algorithm for Fork-Join queueing systems. It automatically detects FJ topology and computes percentiles using the algorithm from "Beyond the Mean in Fork-Join Queues" (IFIP Performance 2015).

      Requirements:

      • Model must have valid Fork-Join topology: Source → Fork → K Queues → Join → Sink
      • Solver must have been run first (runAnalyzer() called)
      • Homogeneous service distributions across parallel queues
      Parameters:
      percentiles - Array of percentile levels (0-100 scale, e.g., {50, 90, 95, 99})
      Returns:
      List of FJPercentileResult, one per job class, containing: - jobClass: class index - percentiles: requested percentile levels - values: computed percentile values - K: number of parallel queues - method: algorithm used (e.g., "FJ_NARE")
      Throws:
      IllegalStateException - if model is not Fork-Join or solver not run
    • getPerctRespT

      public List<MainFJ.FJPercentileResult> getPerctRespT()
      Get response time percentiles using default values [50, 90, 95, 99]
      Returns:
      List of FJPercentileResult for default percentiles
      Throws:
      IllegalStateException - if model is not Fork-Join or solver not run
      See Also:
    • getLibrariesUsed

      public List<String> getLibrariesUsed(NetworkStruct sn, SolverOptions options)
      Bundled third-party libraries used by the matrix-analytic solver: MAMSolver for the M/G/1 and GI/M/1-type decompositions, Q-MAM for the RCAT-based methods, and BUTools wherever a MAP/PH process is present. Mirrors SolverMAM.getLibrariesUsed in MATLAB.
      Overrides:
      getLibrariesUsed in class NetworkSolver
      Parameters:
      sn - the model structure, may be null
      options - the solver options, may be null
      Returns:
      the library names, possibly empty