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)
    • 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. It is refused HERE, in the gate, so that the pair is never called runnable and then answered with an empty table. 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
    • jmtCachePromotionRefusal

      public static String jmtCachePromotionRefusal(NetworkStruct sn)
      The first Cache whose list dynamics the JSIM Cache section cannot state; empty otherwise.
      Parameters:
      sn - the model struct
      Returns:
      empty string when every cache is expressible, otherwise the writer's refusal
    • jmt150Refusal

      public static String jmt150Refusal(NetworkStruct sn, String method, String version)
      What a JSIM run cannot carry when the JMT.jar in use is release 1.5.0 or later; "" when the jar predates 1.5.0 (LINE's own patched JMT) or the model needs none of it.

      Stock JMT 1.5.0 lacks the engine patches LINE's JMT carries, and two of the gaps change the answer rather than failing loudly:

      • PREEMPTION. 1.5.0 has no PreemptiveServer(Integer, Integer[], ServiceStrategy[]) constructor, and when the station is given the 4-argument form it accepts, it serves the jobs non-preemptively: an M/M/1 SRPT queue reports E[N] 0.851 against the 0.717 of LINE's JMT, and a preemptive-priority class 0.847 against the exact 0.600. The FCFS-PI and LCFS-PI strategy classes are absent.
      • CACHES. The cache hit/miss class switch is keyed on JobClass instances that 1.5.0's XML loader does not share with the runtime, so every hit class reports a zero hit rate and zero throughput, and a closed cache model does not terminate.
      Parameters:
      sn - the model struct
      method - the concrete method name; JMVA methods are unaffected
      version - the JMT version, as SysUtils.jmtVersion(String)
      Returns:
      empty string when supported, otherwise the refusal
    • getJmtVersion

      public String getJmtVersion()
      The version of the JMT.jar this solver runs, "" when it declares none.
    • jmtCachePopularityRefusal

      public static String jmtCachePopularityRefusal(NetworkStruct sn)
      A non-uniform DiscreteSampler cache popularity, which JMT cannot express; empty otherwise.

      JMT's Cache section takes a parametric popularity (Zipf or uniform) and has no empirical discrete form, so a measured pmf, or the point mass that Cache.setItemReadClasses(jline.lang.JobClass[], jline.lang.JobClass[]) gives each per-item class of a cache network, would be exported as a uniform draw over all items and solved as a different model. MATLAB's JMTIO.saveCacheStrategy refuses the same.

    • 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)
    • getProbAggr

      public Ret.ProbabilityResult getProbAggr(int node, Matrix state)
      Node-index form of getProbAggr(Node, Matrix), the overload the CLI's prob-aggr analysis calls; without it the base class refused JMT by name.
      Overrides:
      getProbAggr in class NetworkSolver
      Parameters:
      node - the node index
      state - per-class job counts, or null for the node's own state
      Returns:
      scalar probability in [0,1]
    • 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. 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. 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
    • unsupportedRefusalId

      public ErrorId unsupportedRefusalId(String method, String reason)
      Description copied from class: Solver
      The id the feature gate throws when the model is refused for METHOD: LINE:unsupported:<first unsupported feature> in FeatureSet declaration order, or LINE:unsupported:Structure for a structural refusal that names no feature (see FeatureSet.refusalId(jline.lang.FeatureSet, jline.lang.FeatureSet, java.lang.String)).
      Overrides:
      unsupportedRefusalId in class Solver
      Parameters:
      method - the concrete method name
      reason - the gate's refusal sentence, or null
      Returns:
      the refusal id
    • 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
    • resolveMethod

      public String resolveMethod(SolverOptions options)
      'default' runs JSIM: the steady-state arm, or on a finite timespan the transient ensemble of JSIM runs. Both are the JSIM engine and its feature set, so the gate asks about 'jsim' and names it when it refuses, and findSolver reports jmt.default as running as jsim. Mirrors MATLAB SolverJMT.resolveMethod.
      Overrides:
      resolveMethod in class Solver
      Parameters:
      options - the solver options
      Returns:
      the concrete method
    • supportsModelMethod

      public String supportsModelMethod(String method)
      Structural gate for the one feature JMT admits in a RE-ENCODED form only. Limited load dependence has no representation of its own in either JMT document: saveNumberOfServers turns it into a server count and the JMVA writer into the matching <ldstation>, so alpha(n) = min(n,c) with an integer c is written exactly and any other scaling would be solved at a service rate JMT never saw.
      Overrides:
      supportsModelMethod in class Solver
      Parameters:
      method - the concrete method name
      Returns:
      an empty string when supported, otherwise the 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
      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