Class SolverJMT

Direct Known Subclasses:
JMT

public class SolverJMT extends NetworkSolver
Solver interface to the Java Modelling Tools (JMT) simulation engine.

SolverJMT provides integration with the JMT discrete-event simulation toolkit for analyzing queueing networks through simulation. JMT offers powerful simulation capabilities for complex network topologies and general service distributions that may not be analytically tractable.

Key JMT solver capabilities:

  • Discrete-event simulation via JMT engine
  • Complex network topology support (fork-join, finite capacity, etc.)
  • General service and interarrival time distributions
  • Statistical analysis with confidence intervals
  • Transient and steady-state performance metrics
  • Model export to JMT JSIMG format

Requirements: This solver requires JMT.jar to be available in the classpath. The solver can operate with or without the external JMT GUI application installed.

Since:
1.0
See Also:
  • Field Details

  • Constructor Details

  • Method Details

    • defaultOptions

      public static SolverOptions defaultOptions()
    • getFeatureSet

      public static FeatureSet getFeatureSet()
    • getJMVAFeatureSet

      public static FeatureSet getJMVAFeatureSet()
      What the JMVA ANALYTICAL engine accepts, which is much less than the JSIM simulator above.

      The envelope is derived from the writer rather than guessed: writeJMVA emits, per station, a <delaystation>, a <listation> or an <ldstation>, a per-chain <servicetime> and a per-chain <visit>, and at model level the closed populations, the open arrival rates and the reference station. NOTHING ELSE IN THE MODEL REACHES JMVA, so a construct whose whole effect is not carried by (station type, demand, visits, population) would be solved away silently -- which is how all eight closed-form jmva methods came to return an entirely zero table on a cache model, jmva.mva labelled 'exact' among them.

      Dropped from the JSIM set: the cache and its replacement strategies (no cache element exists), fork-join and the fan-out names (a visit ratio cannot express the join synchronization), the Petri-net sections, the finite capacity region, impatience, the setup/parallelism/heterogeneous server attributes, the non-BCMP disciplines (the writer emits NO discipline, so a priority, weighted, size-based or limited-sharing station would be solved as an ordinary load-independent one) and the state-dependent routings. The DISTRIBUTIONS are kept: JMVA consumes a mean service demand, so any renewal law with a finite mean is admissible, exactly as it is for SolverMVA and SolverNC.

      Returns:
      the JMVA feature envelope
    • jmvaIsClosedOnly

      public static boolean jmvaIsClosedOnly(String method)
      True for the JMVA algorithms that solve a CLOSED product-form network only.

      RECAL, CoMoM, Chow, Bard-Schweitzer (both spellings), AQL, Linearizer and De Souza-Muntz Linearizer. Measured against JMT 1.2.x: each answers an open or a mixed model with jmt.common.exception.UnsupportedModelException: The selected solver cannot handle open classes, please choose another. and a load-dependent one with the same exception naming load-dependent stations, while the exact MVA engine behind 'jmva' and 'jmva.mva' serves both.

      Parameters:
      method - the concrete method name
      Returns:
      true when the method is one of the eight closed-only algorithms
    • jmtMethodRefusal

      public static String jmtMethodRefusal(NetworkStruct sn, String method, SolverOptions options)
      The structural half of SolverJMT's method gate; empty when admissible.

      The two rules that decide whether a JMT METHOD can run this model and that no registry feature name can state. ONE PREDICATE, TWO CALLERS: supportsModelMethod asks it, so findSolver and SolverAUTO never offer a pair that would die at run time, and the analyzer asks it again -- the JMVA writer through setAlgTypeName, runAnalyzer before dispatch -- so a caller naming the method by hand gets the same sentence. The removed 'replication' method is refused here too, with its migration sentence.

      Parameters:
      nservers - the station server counts, sn.nservers
      method - the concrete method name
      options - the solver options, read for the timespan
      Returns:
      empty string when supported, otherwise the refusal
    • jmtReplications

      public static int jmtReplications(SolverOptions options)
      The transient ensemble size, options.config.replications, or 10 when unset.
      Parameters:
      options - the solver options
      Returns:
      the number of seeded JSIM runs the transient ensemble averages
    • jmtMethodRefusal

      public static String jmtMethodRefusal(NetworkStruct sn, String method, SolverOptions options, String engine)
      The same predicate, told WHO IS ASKING.

      IMMEDIATE FEEDBACK: a job that self-loops keeps its server instead of re-queueing, which neither JMT document can state. runAnalyzer used to WARN and return no solution, so the gate called the pair runnable and the table came back empty. The rule is keyed on the CALLER: without an ENGINE argument the asker is SolverJMT's own gate or analyzer. writeJMVA passes "jmva" on behalf of SolverLQNS too, which refuses the same feature in its own words (SnHasImmfeed through SolverLQNS), so this sentence must not be handed to it.

      Parameters:
      engine - the engine on whose behalf the question is asked, or null when SolverJMT asks for itself
    • jmtBufferCapacityRefusal

      public static String jmtBufferCapacityRefusal(NetworkStruct sn, boolean isJmva)
      A binding finite buffer, which NEITHER engine can carry; empty otherwise.

      The two engines fail it for opposite reasons, so the binding TEST is shared and the verdict is not.

      What makes a buffer BIND is not that sn.cap is finite: refreshCapacity DERIVES a finite cap for every station nobody capped. It is that the cap is strictly below the population that can REACH the station, which is the JSIM writer's own test, and an infinite-server station has no buffer at all. Both are the writer's own (SaveHandlers.jmtReachablePopulation), so the gate binds exactly where the writer binds.

      JSIM exports the buffer, but only for the rules JMT can read, and SaveHandlers.jmtStationCapRefusal -- the writer's own predicate -- is what decides which. An open loss buffer and a declared BAS one stay runnable; only the cases JMT would answer unconstrained go.

      JMVA is refused OUTRIGHT: writeJMVA emits a station type, a per-chain service demand and a per-chain visit count and nothing else, so the document has no capacity element for the buffer to ride in. Measured on a closed Delay+FCFS model, N=4, cap 2: every jmva method reported 2.19 jobs at a station that can hold 2, against the exact 1.33. SolverLQNS writes THIS SAME DOCUMENT and already refuses such a model, so the jmva arm was the one hole in that rule.

      Parameters:
      sn - the model struct
      method - the concrete method name
      Returns:
      empty string when supported, otherwise the refusal
    • viewModel

      public static void viewModel(String jmtPath, String filename, SolverJMT.ViewMode viewMode)
    • viewModel

      public static void viewModel(String jmtPath, String filename, SolverJMT.ViewMode viewMode, VerboseLevel verboseLevel)
    • viewModel

      public static void viewModel(String filename, SolverJMT.ViewMode viewMode)
    • writeJMVA

      public static String writeJMVA(NetworkStruct sn, String outputFileName, SolverOptions options)
    • getCdfRespT

      public Ret.DistributionResult getCdfRespT()
      Description copied from class: NetworkSolver
      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 [stations x classes]
    • getCdfRespT

      public Ret.DistributionResult getCdfRespT(AvgHandle RH)
      Description copied from class: NetworkSolver
      Returns cumulative distribution functions of response times at steady-state. Uses an exponential approximation based on average response times.
      Overrides:
      getCdfRespT in class NetworkSolver
      Parameters:
      RH - response time handles (optional)
      Returns:
      result containing CDFs for response times [stations x classes]
    • getFileName

      public String getFileName()
    • setFileName

      public void setFileName(String fileName)
    • getFilePath

      public String getFilePath()
    • setFilePath

      public void setFilePath(String filePath)
    • getJMVATempPath

      public String getJMVATempPath()
    • getJSIMTempPath

      public String getJSIMTempPath()
    • getJmtJarPath

      public String getJmtJarPath()
    • setJmtJarPath

      public void setJmtJarPath(String path)
    • getMaxEvents

      public long getMaxEvents()
    • setMaxEvents

      public void setMaxEvents(long maxEvents)
    • getMaxSamples

      public long getMaxSamples()
    • setMaxSamples

      public void setMaxSamples(long maxSamples)
    • getMaxSimulatedTime

      public double getMaxSimulatedTime()
    • setMaxSimulatedTime

      public void setMaxSimulatedTime(double maxSimulatedTime)
    • getSimulationTimeoutSeconds

      public long getSimulationTimeoutSeconds()
    • setSimulationTimeoutSeconds

      public void setSimulationTimeoutSeconds(long timeoutSeconds)
    • getProbAggr

      public double getProbAggr(Node node, Matrix state_a)
    • getProbAggr

      public double getProbAggr(Node node)
    • getProbNormConstAggr

      public Ret.ProbabilityResult getProbNormConstAggr()
      Description copied from class: NetworkSolver
      Returns the logarithm of the normalizing constant of state probabilities. This is an abstract method that must be implemented by concrete solver subclasses.
      Overrides:
      getProbNormConstAggr in class NetworkSolver
      Returns:
      result containing the log normalizing constant
    • getResults

      public SolverResult getResults()
      Description copied from class: Solver
      Returns the results from the most recent solver execution.
      Overrides:
      getResults in class Solver
      Returns:
      the solver results
    • getResultsJMVA

      public JMTResult getResultsJMVA()
    • getResultsJSIM

      public JMTResult getResultsJSIM()
    • getAvgNode

      public SolverResult getAvgNode()
      Computes average performance metrics at steady-state for all nodes. This method overrides NetworkSolver.getAvgNode() to use JMT simulation values for cache node throughputs and arrival rates instead of computing them from routing probabilities.
      Overrides:
      getAvgNode in class NetworkSolver
      Returns:
      solver result containing node-level average metrics
    • getSeed

      public long getSeed()
    • setSeed

      public void setSeed(int seed)
    • getSimConfInt

      public double getSimConfInt()
    • setSimConfInt

      public void setSimConfInt(double simConfInt)
    • getSimMaxRelErr

      public double getSimMaxRelErr()
    • setSimMaxRelErr

      public void setSimMaxRelErr(double simMaxRelErr)
    • getStruct

      public NetworkStruct getStruct()
    • getTranCdfPassT

      public Ret.DistributionResult getTranCdfPassT()
      Description copied from class: NetworkSolver
      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
    • getTranCdfPassT

      public Ret.DistributionResult getTranCdfPassT(AvgHandle R)
      Description copied from class: NetworkSolver
      Returns cumulative distribution functions of passage times during transient analysis. This is an abstract method that must be implemented by concrete solver subclasses.
      Overrides:
      getTranCdfPassT in class NetworkSolver
      Parameters:
      R - response time handles (optional)
      Returns:
      result containing transient CDFs for passage times
    • getTranCdfRespT

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

      public Ret.DistributionResult getTranCdfRespT(AvgHandle R)
      Description copied from class: NetworkSolver
      Returns cumulative distribution functions of response times during transient analysis. This is an abstract method that must be implemented by concrete solver subclasses.
      Overrides:
      getTranCdfRespT in class NetworkSolver
      Parameters:
      R - response time handles (optional)
      Returns:
      result containing transient CDFs for response times
    • getTranAvg

      public void getTranAvg()
      Computes transient average station metrics over the specified time interval. This method overrides NetworkSolver.getTranAvg() to provide JMT-specific transient analysis.

      Under method 'default' the analyzer runs the transient ensemble, averaging options.config.replications seeded JSIM runs (default 10). An explicit 'jsim' keeps a single logged run, whose series is one sample path.

      Overrides:
      getTranAvg in class NetworkSolver
    • getTranQLen

      public Matrix[][] getTranQLen()
      Returns transient queue length results from the last getTranAvg() call.
      Returns:
      Matrix array with transient queue length data [stations x classes]
    • getTranUtil

      public Matrix[][] getTranUtil()
      Returns transient utilization results from the last getTranAvg() call.
      Returns:
      Matrix array with transient utilization data [stations x classes]
    • getTranTput

      public Matrix[][] getTranTput()
      Returns transient throughput results from the last getTranAvg() call.
      Returns:
      Matrix array with transient throughput data [stations x classes]
    • hasAvgResults

      protected boolean hasAvgResults()
      Description copied from class: NetworkSolver
      Checks if the solver has computed steady-state average metrics.
      Overrides:
      hasAvgResults in class NetworkSolver
      Returns:
      true if steady-state results are available, false otherwise
    • jsimgView

      public void jsimgView()
    • jsimgView

      public void jsimgView(SolverOptions options)
    • jsimgView

      public void jsimgView(String jmtPath, SolverOptions options)
    • jsimgView

      public void jsimgView(String jmtPath)
    • jsimwView

      public void jsimwView(String jmtPath)
    • jsimwView

      public void jsimwView(String jmtPath, SolverOptions options)
    • jsimwView

      public void jsimwView() throws ParserConfigurationException
      Throws:
      ParserConfigurationException
    • listValidMethods

      public List<String> listValidMethods()
    • unsupportedMethodReason

      protected String unsupportedMethodReason(String method)
      The by-name refusal checkDeclaredMethod raises for a removed JMT method.
      Overrides:
      unsupportedMethodReason in class NetworkSolver
      Parameters:
      method - the requested method name
      Returns:
      the migration sentence for 'replication', otherwise ""
    • listValidMethods

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

      public double probSysStateAggr()
    • supportsTransientAnalysis

      public boolean supportsTransientAnalysis()
      Description copied from class: Solver
      Does this solver produce transient averages, i.e. does getTranAvg return trajectories on a finite options.timespan? Declared false here and overridden by the solvers that populate result.Tran (Fluid, CTMC, LDES, JMT). It is a capability claim, not a state test: it must answer before any run has taken place, because the MAP/MMPP random-environment fallback uses it to decide whether the environment stages can be coupled by the mean-field analyzer (which needs getTranAvg) or only by the two steady-state limits.
      Overrides:
      supportsTransientAnalysis in class Solver
      Returns:
      true if the solver can return transient averages
    • runAnalyzer

      public void runAnalyzer() throws ParserConfigurationException
      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
      Throws:
      ParserConfigurationException - if XML parsing configuration fails
    • getLastReplicationsRequested

      public int getLastReplicationsRequested()
      Replications the last transient ensemble (runAnalyzer or getTranProbAggr) asked for.
      Returns:
      options.config.replications as resolved at that run, or 0 before any ensemble ran
    • getLastReplicationsValid

      public int getLastReplicationsValid()
      Replications of the last transient ensemble that produced a usable sample path.
      Returns:
      the number of replications averaged, or 0 before any ensemble ran
    • sampleAggr

      public Ret.SampleResult sampleAggr(Node node, int numEvents, boolean markActivePassive) throws IOException
      Throws:
      IOException
    • sampleAggr

      public Ret.SampleResult sampleAggr(Node node, int numEvents) throws IOException
      Throws:
      IOException
    • sampleAggr

      public Ret.SampleResult sampleAggr(Node node) throws IOException
      Throws:
      IOException
    • sampleSysAggr

      public Ret.SampleResult sampleSysAggr(long numEvents, boolean markActivePassive)
    • sampleSysAggr

      public Ret.SampleResult sampleSysAggr(long numEvents)
    • sampleSysAggr

      public Ret.SampleResult sampleSysAggr(int numEvents)
      The int overload NetworkSolver declares, which refused outright: sampleSysAggr(options.samples) bound here rather than to the long overload, so every transient replication failed.
      Overrides:
      sampleSysAggr in class NetworkSolver
      Parameters:
      numEvents - the number of events to sample
      Returns:
      result containing sampled aggregated joint system state trajectories
    • sampleSysAggr

      public Ret.SampleResult sampleSysAggr()
    • getTranProbAggr

      public JMTResult.TransientProbabilityResult getTranProbAggr(Node node)
      Empirical transient probability of the per-class aggregate states at a station.

      Port of @SolverJMT/getTranProbAggr.m: options.config.replications (default 10) seeded sampleSysAggr runs, replication k (1-based) at seed + k - 1, are read on the union of their event times with previous-neighbour interpolation, and pi_t(k,j) is the fraction of replications whose aggregate state at t(k) is row j of SSnode_a. The grid runs from the latest first event to the earliest last event (the transient ensemble applies the upper rule), so every row averages every usable replication and sums to 1; the divisor is the usable count.

      Parameters:
      node - The station of interest (not a Source)
      Returns:
      Pi_t = [t, pi_t] and SSnode_a, the observed aggregate states (sorted, one column per class)
    • getProbSysAggr

      public Ret.ProbabilityResult getProbSysAggr()
      Gets probability of the current system state in aggregated form. Uses simulation sampling to estimate the probability.
      Overrides:
      getProbSysAggr in class NetworkSolver
      Returns:
      Probability of the current system state
    • 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
    • getMethodFeatureSet

      public FeatureSet getMethodFeatureSet(String method)
      SolverJMT drives TWO ENGINES, and they accept different models.

      'default' and 'jsim' run the JSIM SIMULATOR (at a finite timespan 'default' runs its transient ensemble), whose envelope is getFeatureSet(). The 'jmva.*' names run the JMVA ANALYTICAL engine, whose envelope is getJMVAFeatureSet(): it reads a document carrying only a station type, a per-chain demand, a per-chain visit count, the populations or arrival rates and a reference station, so declaring the JSIM envelope for jmva was a promise the writer could not keep.

      Defining this is also what lets the base gate NAME the offending features: with a null method feature set it falls back to the coarse supports(model), which returns "Some features are not supported" without saying which.

      Overrides:
      getMethodFeatureSet in class Solver
      Parameters:
      method - the concrete method name
      Returns:
      the per-method FeatureSet
    • supportsModelMethod

      public String supportsModelMethod(String method)
      Description copied from class: Solver
      Fine, method-aware gate. Returns an empty string when the model fits the concrete METHOD, else a human-readable reason. Base behavior derives the answer from getMethodFeatureSet(method); when that is null the solver's own supports(model) is used. Solvers with non-feature-set structural per-method rules override this.
      Overrides:
      supportsModelMethod in class Solver
      Parameters:
      method - the concrete method name
      Returns:
      empty string if supported, else the offending reason
    • isStochasticMethod

      public boolean isStochasticMethod(String method)
      Simulation-based methods (default, jsim) return stochastic estimates. The analytical JMVA methods do not, except for the sampling-based variants (e.g. jmva.ls).
      Overrides:
      isStochasticMethod in class Solver
      Parameters:
      method - the method name to classify
      Returns:
      true if the method returns stochastic estimates
    • writeJSIM

      public String writeJSIM(NetworkStruct sn, String outputFileName) throws ParserConfigurationException
      Throws:
      ParserConfigurationException
    • writeJSIM

      public String writeJSIM(NetworkStruct sn) throws ParserConfigurationException
      Throws:
      ParserConfigurationException
    • QN2JSIMG

      public String QN2JSIMG(NetworkStruct sn, String outputFileName) throws ParserConfigurationException
      Writes queueing network model to JMT JSIMG format. Delegates to the standalone QN2JSIMG class in the io package.
      Parameters:
      sn - the network structure
      outputFileName - the output file name
      Returns:
      the path to the JSIM file
      Throws:
      ParserConfigurationException - if XML parsing fails
    • QN2JSIMG

      public String QN2JSIMG(NetworkStruct sn) throws ParserConfigurationException
      Writes queueing network model to JMT JSIMG format. Delegates to the standalone QN2JSIMG class in the io package.
      Parameters:
      sn - the network structure
      Returns:
      the path to the JSIM file
      Throws:
      ParserConfigurationException - if XML parsing fails