solvers.wrappers.JMT
- jmtDeadlineRefusal(sn)
REASON = JMTDEADLINEREFUSAL(SN)
The due date an EDD or EDF station needs and LINE may not carry, as a sentence; ‘’ when every such station can be exported.
WHY THE RULE EXISTS. JMT 1.2.x serves EDD and EDF for real – the classes jmt.engine.NetStrategies.QueuePutStrategies.EDDStrategy and .EDFStrategy are in JMT.jar, the SIMmodeldefinition.xsd carries <classSoftDeadlines> under <node>, and jmt.engine.simEngine.SimLoader feeds it to Queue.setSoftDeadlines. Queue.process then sets each arriving job’s currentStationSoftDeadline to softDeadlines(classId) + now, and EDDStrategy orders the buffer by it. But the field is initialised to -1.0 in Job, and EDDStrategy.put THROWS on that value rather than degrading to FCFS:
java.lang.IllegalArgumentException: Attempting to schedule job with no soft deadline (EDDStrategy.java:19)
measured on 2026-09-05 by running jmt.commandline.Jmt on a two-class M/M/1 whose Queue put strategy was EDDStrategy and whose node carried no <classSoftDeadlines>. So a class without a due date is not an approximation here, it is an aborted run, and the model is refused by name instead.
The <userClass softDeadline=”…”> attribute saveClasses.m already writes does NOT satisfy this: SimLoader passes it to JobClass.setSoftDeadline, which feeds the SYSTEM tardiness and earliness measures only. The buffer ordering reads the per-node array and nothing else.
WHAT COUNTS AS SERVED. A class whose rate at the station is NaN is not served there and can never enter its buffer, so it needs no due date; that is the same test jmtStationCapRefusal applies. saveClassSoftDeadlines fills those slots with 0.0, which is never read.
ONE PREDICATE, TWO CALLERS. saveClassSoftDeadlines raises it while writing the JSIM document, and jmtMethodRefusal returns it so findSolver and SolverAUTO never offer a JSIM method on a model the writer will refuse.
- jmtStationCapRefusal(sn, ist)
REASON = JMTSTATIONCAPREFUSAL(SN, IST)
The binding station capacity JSIM cannot express, as a sentence; ‘’ when the buffer at station IST is exportable. Refused on two counts.
(1) THE RULE IS ONE JMT CANNOT READ. Its queue section recognizes exactly four dropStrategies strings – ‘drop’, ‘BAS blocking’, ‘waiting queue’, ‘retrial’ (a lookupswitch on String.hashCode in jmt/engine/NodeSections/Queue.class; the Storage section of a Place is even narrower and drops ‘retrial’). An unrecognized value falls through the default arm with NO flag set, so BBS, RSRD and retrial-with-limit are not approximated, they are IGNORED: the capacity stops being enforced and JMT returns the unconstrained answer. Those three are refused by name.
(2) THE RULE IS WAITQ AND A CLOSED CLASS CAN REACH THE LIMIT, for the same reason JMTCLASSCAPASSERT in saveRegions.m refuses the per-class one: JMT cannot hold a blocked closed job at its upstream station. Note this is the case where NO blocking rule is declared. That the limit CAN be reached is the caller’s to establish and is not retested here: both callers reach this function only for a capacity strictly below the reachable population, which is the one thing that makes a buffer a buffer. A model that does declare BAS is exported as JMT “BAS blocking”, which is the same queueing model, under either declaration form – see jmtIsBasDestination.
That entry advised expressing the limit as the STATION capacity instead. Measured on 2026-08-19, that advice was wrong, and neither of the two strategies that a WAITQ station maps onto reproduces the UNDECLARED case:
- waiting queue does not enforce <size> at all. On a closed 3-queue tandem,
N=6, Exp(1) FCFS, cap 2 at Q2, JMT returned the UNCONSTRAINED [2.03 1.99 1.98], X = 0.750, against the exact [3.6090 0.9711 1.4199], X = 0.6522.
- BAS blocking enforces it, but completes the service BEFORE blocking, so
the blocked job moves the instant room frees. That is a different queueing model, not a rounding: same fixture, [2.871 1.373 1.756], X = 0.7126.
With no rule declared LINE instead disables the upstream departure while the destination is full, which for exponential service is repetitive service (RS) and is what SolverCTMC, SolverSSA and SolverLDES all agree on. So THAT model is refused rather than exported as either of the two things JMT can say. See BUG-81. A declared-BAS model is a different model and is exported, not refused: blocking after service is precisely what JMT’s “BAS blocking” does.
ONE PREDICATE, TWO CALLERS. saveBufferCapacity raises it while writing the JSIM document, and jmtMethodRefusal returns it so that findSolver and SolverAUTO never offer jmt.jsim on a model the writer will refuse. It used to be a local function of the writer, which is why the gate could not see it.
- jmtReachablePopulation(sn, ist)
N = JMTREACHABLEPOPULATION(SN, IST)
The most jobs that can be present at station IST, read the way REFRESHCAPACITY derives the capacity itself: per CHAIN, because a chain’s whole population can reach a station that serves any one of its classes (class switching moves jobs between them), and a chain none of whose classes is served there cannot put a single job on it.
Deliberately NOT read off sn.classcap, which refreshCapacity has already clamped by the station’s own cap: comparing a capacity against a quantity derived from it would make every user-declared buffer look non-binding. Inf when an open chain is served here, which is what sum(sn.njobs) gave before and which sends the station to JMTSTATIONCAPREFUSAL, where the open classes are skipped by name.
Lifted out of @JMTIO/saveBufferCapacity.m so that JMTMETHODREFUSAL can apply the same binding test the writer applies: sn.cap is DERIVED for a station the user never capped, so “cap is finite” is not the question – “cap is below what can reach the station” is.
- jmtJmvaIsClosedOnly(method)
TF = JMTJMVAISCLOSEDONLY(METHOD)
True for the JMVA algorithms that solve a CLOSED product-form network only: RECAL, CoMoM, Chow, Bard-Schweitzer (both ‘jmva.bs’ and ‘jmva.amva’), 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.
The three consequences of that split are declared in one place each: getMethodFeatureSet drops OpenClass and LoadDependence for these names, jmtMethodRefusal refuses a multi-server station for them (a server count has no feature name), and writeJMVA raises the same sentence when asked by name.
- jmtMethodRefusal(sn, method, options, engine)
REASON = JMTMETHODREFUSAL(SN, METHOD, OPTIONS, ENGINE)
The structural half of SolverJMT’s method gate: the rules that decide whether a JMT METHOD can run this model and that no feature name can state. Returns ‘’ when the pair is admissible.
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 – writeJMVA for the JMVA arm, runAnalyzer for ‘replication’ – so a caller naming the method by hand gets the same sentence rather than a JMT stack trace. A second copy of either rule is how the gate and the run drift into two different answers.
THE RULES. A finite timespan for ‘replication’; single-server stations for the eight closed-form JMVA algorithms; a multi-chain model for ‘jmva.comom’, whose JMVA engine answers with an unseeded random perturbation of the model; immediate feedback (sn.immfeed), which neither JMT document can state; for the JMVA document, a fork or join and a non-exponential law at a station whose discipline is not insensitive, since that document carries a mean demand and a visit count per chain and nothing else; and a binding finite buffer, which neither engine carries – JSIM because no JMT drop strategy reproduces LINE’s blocking, JMVA because its document has no capacity element at all.
ENGINE (‘jsim’ or ‘jmva’) OVERRIDES the engine the METHOD name implies, and writeJMVA passes ‘jmva’ because it IS the JMVA writer whoever called it: SolverQNS reaches it with its own method names (‘default’, ‘conway’, …), and keying the buffer rule on the name handed a QNS run JSIM’s verdict, which threw before the .jmva file was written and left qnsolver reporting “Cannot open input file”. Omit it and the name decides; a name that is neither engine’s then gets no verdict at all, since the solver that owns it carries its own gate.
WHAT IS NOT HERE. Everything a feature name CAN state lives in SolverJMT.getMethodFeatureSet instead: the JMVA envelope is narrower than the JSIM one (no cache, no fork-join, no Petri net, no finite capacity region, no impatience, and only the BCMP disciplines survive a writer that emits a station type, a demand and a visit count), and the closed-only JMVA algorithms additionally drop OpenClass and LoadDependence.
- jmtIsBasDestination(sn, ist, r)
TF = JMTISBASDESTINATION(SN, IST, R)
True when station IST is the RECEIVING side of a true-BAS relation for class R, i.e. an arrival of R that finds IST full must block an upstream station rather than be lost.
LINE accepts the BAS declaration in two places – on the blocking (upstream) station, as cqn_bas_blocking.m does, or on the full destination, as a model read back from JMT does – and MNetwork/refreshLocalVars resolves both into sn.isbasdestination (BUG-83). Reading sn.droprule at the capped station sees only the second form, which is what made SolverJMT refuse the first one.
- jmtDropStrategyText(sn, ist, r)
TEXT = JMTDROPSTRATEGYTEXT(SN, IST, R)
The JMT dropStrategy/dropRule string for station IST, class R.
Beyond DropStrategy.toText this does two things.
It resolves the two ways LINE can declare BAS blocking onto the one way JMT can read it. JMT’s queue section says what happens to an arrival that finds THIS buffer full, so it only understands the rule on the destination; a WAITQ slot that jmtIsBasDestination marks is therefore written out as ‘BAS blocking’.
And it keeps the written file VALID. JMT recognizes exactly four strings – ‘drop’, ‘BAS blocking’, ‘waiting queue’, ‘retrial’ – so BBS, RSRD and retrial-with-limit are spelled ‘waiting queue’, JMT’s own no-limit default. That substitution is only ever reached where the rule cannot be consulted (infinite size, or a closed capacity equal to the population): a buffer that can actually fill under one of those three is refused outright by jmtStationCapAssert in saveBufferCapacity.
- solver_jmt_analysis(sn, options)
[QN,UN,RN,TN,CN,XN,runtime] = SOLVER_JMT_ANALYSIS(SN, OPTIONS)
- jsimwOpen()
RET = JSIMWOPEN() Open an empty JSIMwiz session
- jsimgOpen()
RET = JSIMGOPEN() Open an empty JSIMgraph session
- lineViewerGetPath()
VIEWERJAR = LINEVIEWERGETPATH
- jsimgEdit()
- jmtGetPath()
JMTPATH = JMTGETPATH
- jmtCleanTempDir