api.sn
- qsys_serves_method(method)
BOOL = QSYS_SERVES_METHOD(METHOD)
ONE PREDICATE FOR THE INTERCEPTION AND THE RUN. The Source-Queue-Sink shape is claimed by solver_mva_qsys_analyzer, which answers this FIXED list of closed forms and refuses every other name – so each general network method listValidMethods offers on an open model was advertised on the one open shape it could not run on, and raised ‘Unsupported method for a model with 1 station and 1 class’ the moment it was asked for: mva, amva, sum, esum, lin, gflin, egflin, qli, fli, qd and qdlin, eleven of them. They are NETWORK methods, and the general branch solves a one-queue network exactly as it solves a larger one, so mvaDispatch stands aside for them rather than claiming a model it cannot answer. ‘qna’ was the first name found this way and used to be excluded by hand in mvaDispatch; it needs no special case now, having no arm here either.
Mirrors detail::qsys_serves_method in cpp/include/line/solvers/mva/mva_dispatch.h and its JAR and native python twins.
Copyright (c) 2012-2026, Imperial College London All rights reserved.
- sn_to_qrf_alpha(sn)
Returns the QRF load-dependent scaling alpha, and why it may not exist
The load-dependent QRF arms carry a scaling alpha(i,n) that multiplies EVERY rate out of station i while it holds n jobs, completions mu and background phase changes v alike – see the q construction in QRF_NOBLO_MMI_LD, which writes r(i,j)*mu*alpha off the diagonal and (v + r(i,i)*mu)*alpha on it. That is exactly the rate law of
an infinite server alpha(i,n) = n a c-server station alpha(i,n) = min(n, c_i) limited load dependence alpha(i,n) = sn.lldscaling(i,n)
so the three COMPOSE BY MULTIPLICATION and not one of them is an approximation: the relaxed chain is the model’s own, and the QRF answer keeps whatever status it had on a single-server model.
WHERE IT STOPS BEING THE MODEL’S OWN IS PHASE-TYPE SERVICE AT A STATION THAT SERVES SEVERAL JOBS AT ONCE. The QRF local state carries ONE phase per station, a faithful description of one job in service and of nothing else: min(n,c) jobs served in parallel each advance through a phase of their own, and no scaling of a single-phase process reproduces that joint motion. A multiserver or delay station must therefore be exponential. Scaling a PH server by min(n,c) would answer a DIFFERENT chain, so the relaxation would no longer contain the model’s stationary distribution and the number would not bound anything – which is the one failure this file exists to prevent.
Limited load dependence at a SINGLE server is exempt and admits PH freely: one job is in service whatever the rate, so alpha rescales that job’s whole phase process and the local state still describes it exactly.
The scaling is tabulated at n = 1..N. sn.lldscaling may be narrower than N, and is read clamped at its last column, the convention PFQN_LLDFUN uses.
THE UTILIZATION NORMALIZER IS THE DECLARED PEAK, NOT max(alpha). LINE reports U = T*S/peak at every station whose rate scales with the population, one convention shared by multiserver, lld and class dependence (see CD_PEAK_SCALING, “the same convention as solver_ncld does for lldscaling, U/max(lldscaling)”). PEAK is therefore nservers(i) times the largest lld scaling the model can REACH, and not max(alpha(i,:)): at c = 3 with N = 2 the reachable alpha peaks at 2 while the station still has three servers, and normalizing by 2 would report a utilization the model never attains. Inf at a delay, where LINE reports U = QN instead.
- Parameters:
sn – Network structure
- Returns:
alpha – (nstations x N) rate scaling at population n = 1..N msg: Empty on success, otherwise why alpha is not defined for this model ld: true when alpha is not identically 1, i.e. the model needs a load-dependent arm peak: (nstations x 1) utilization normalizer nservers(i)*max reachable lld scaling; Inf at a delay
Examples
[alpha, msg, ld, peak] = sn_to_qrf_alpha(sn)
- sn_compat_peak(counts, rates)
PEAK = SN_COMPAT_PEAK(COUNTS, RATES)
Rate a compatibility declaration clears with every pool active, sum_t counts(t)*rates(t).
Utilization at a rate-scaled station is reported as U = T*S/peak, and the peak is a property of the DECLARATION rather than of a state, so it is computed once and handed to the solver beside the rate handle rather than recovered from SN_COMPAT_RATE at a guessed state.
Copyright (c) 2012-2026, Imperial College London All rights reserved.
- sn_to_qrf_blocking(sn, options)
Builds the blocking configuration tables the QRF BAS bound needs
QRF_BAS describes a Blocking-After-Service network by a finite-capacity queue F and an enumeration of the BLOCKING CONFIGURATIONS reachable behind it. Everything in that enumeration is implied by the model, so this routine derives it rather than asking the caller to hand-build it; the caller keeps options.config.qrf_params as an explicit override.
The tables, and the constraint that reads each one in QRF_BAS:
f the ONE finite-capacity queue. The formulation carries a scalar f (ZERO4/ZERO7/ZERO8, THM30, THM3I, THM3L all index it), so a model with two binding buffers is refused here. F(i) min(buffer size, N) for every queue; N where the buffer is unbounded, since no queue can hold more than the population. BB(m,i) 1 iff queue i is blocked in configuration m. ZZ(m) nnz(BB(m,:)), the blocking depth of configuration m. MM(m,1) head of the FIFO blocking order: the queue that takes the slot when f completes. QRF_BAS reads ONLY column 1 of MM. MM1(m,j) index of the configuration reached from m when j becomes blocked. Read by THM3L alone, at depth ZM-1.
THREE INVARIANTS, each a correctness condition rather than a convention:
Configuration 1 MUST be the empty one. ZERO4 iterates m = 2:MR and ZERO5/ZERO7/ZERO8 test m >= 2 to mean “some queue is blocked”. 2. ZM = max(ZZ) MUST be the reachable maximum. QRF_BAS recomputes ZM from ZZ and closes the depth ladder there, so a truncated enumeration excises states the real chain visits and the polytope stops containing the true distribution – the bound stops bounding. The size guard below therefore REFUSES; it never truncates. 3. Blocking APPENDS at the tail: a queue that becomes blocked joins behind those already waiting, so MM1’s successor is the configuration with j appended, and the head – the queue MM(m,1) names – never moves.
THE ENUMERATION IS THE FULL ORDERED ONE, and it has to be. A (set, head) collapse looks sound – the LP reads configurations only through BB, ZZ, MM(:,1) and MM1, and both objective and readout sum over m – and it would shrink MR from sum_z P(B,z) to 1 + sum_z C(B,z)*z. It was tried and it is WRONG. Merging the depth-ZM configurations that share a set and a head makes several THM3L rows, one per depth-(ZM-1) predecessor, reference the SAME merged successor block. That is extra coupling the fine system does not have, so the collapsed polytope is strictly SMALLER, not a projection of the fine one, and it can cut off the true distribution. Measured on a 4-station model with three feeders (B=3, ZM=3, MR 13 collapsed vs 16 full), the collapse reported upper bounds of 0.681/0.979/0.768 where the full enumeration gives 0.709/0.982/0.800: tighter, from a coarser state space, which is the signature of a cut that is not valid. A coarser enumeration that returns a tighter bound is reporting a number it cannot justify.
So MR is factorial in the number of feeders B, and the size guard below is what keeps that honest: it REFUSES an oversized instance rather than trimming the enumeration, because trimming is the same unsound cut by another name (invariant 2).
WHO CAN BE BLOCKED is read from sn.isbasblocking / sn.isbasdestination, not from sn.droprule: LINE accepts the BAS declaration on the upstream station (cqn_bas_blocking.m) or on the full destination (the JMT/LDES form), and reading droprule at the capped station sees only the second. That is the BUG-83 distinction jmtIsBasDestination.m documents.
- Parameters:
sn – Network structure
options – Solver options; reads config.qrf_maxvars
- Returns:
blk – Struct with fields f, F, MR, BB, MM, ZZ, MM1, ZM, blockers; empty when MSG is set msg: Empty on success, otherwise the reason the tables cannot be derived
Examples
[blk, msg] = sn_to_qrf_blocking(sn, options)
- sn_nonmarkov_toph(sn, options)
SN = SN_NONMARKOV_TOPH(SN, OPTIONS) Convert non-Markovian distributions to PH using specified approximation method
This function scans all service and arrival processes in the network structure and converts non-Markovian distributions to Markovian Arrival Processes (MAPs) using the specified approximation method.
- Input:
sn: Network structure from getStruct() options: Solver options structure with fields:
config.nonmkv: Method for conversion (‘none’, ‘bernstein’)
config.nonmkvorder: Number of phases for approximation (default 20)
- Output:
sn: Updated network structure with converted processes
Copyright (c) 2012-2026, Imperial College London All rights reserved.
- sn_print(sn)
Prints comprehensive information about a NetworkStruct object
This function displays all fields, matrices, lists, and maps in a formatted manner useful for debugging and inspection of network structures.
- Parameters:
sn – Network structure to inspect
Examples
sn_print(sn)
- sn_has_blocking(sn)
Checks if the network has finite-buffer blocking or loss
Returns true when some station can refuse a job, either because its own buffer BINDS (Kendall’s K below the population that can reach it, whatever the drop rule: WAITQ, DROP, BAS, BBS, RSRD) or because a finite capacity region caps a set of stations jointly. Such a network is not product form: the truncation couples the station occupancies, so no BCMP factorization of the equilibrium distribution exists.
Only a buffer that can actually BIND counts, which is what SN_GET_BUFFER_SIZE decides: refreshCapacity derives a finite classcap (the chain population) at every station of every closed model, so a plain finiteness test would call every closed model blocking.
Two shapes are exempt. A Cache builds its own capped retrieval queues (classCap = 1), which the cache analyzers solve rather than treat as a buffer constraint, the same exemption NetworkSolver.checkBindingCapacity makes. And the single-station M/M/1/K loss system keeps the truncated geometric distribution, a product form over its one station, which qsys_mm1k_loss and qsys_mg1k_loss_mgs evaluate in closed form.
- Parameters:
sn – Network structure
- Returns:
bool – True if the network has binding finite buffers or regions
Examples
bool = sn_has_blocking(sn)
- sn_interlock_chain(sn, ILclass)
ILCHAIN = SN_INTERLOCK_CHAIN(SN, ILCLASS)
Aggregate a class-indexed interlock matrix to the chain basis the MVA solvers work in. ILCLASS(r,s) is the share of the class-s queue that a class-r arrival must not see, the interlocked flow of Franks (1999), Eq. (4.7). Two classes of the same chain belong to the same client, so the diagonal blocks carry no information and the chain diagonal is zero: an arrival always sees its own chain in full.
Reference: G. Franks, “Performance Analysis of Distributed Server Systems”, PhD thesis, Carleton University, 1999, Ch. 4.
- sn_schedule_nominal(sn, ist, r)
[D0BAR, D1BAR, BREAKPOINTS, SEGD0, SEGD1, CYCLIC] = SN_SCHEDULE_NOMINAL(SN, IST, R)
Unpacks the MAPt or PHt slot of sn.proc at station IST, class R and returns both the width-weighted time-averaged (D0, D1) pair and the per-segment pairs.
The slot is {breakpoints, segments1, segments2, cyclic}: for a MAPt the two cells are the D0 and D1 matrices; for a PHt they are the alpha row vectors and the sub-generators S, whose equivalent MAP pair is (S, s*alpha) with s = -S*e. The nominal is the stationary carrier of the phase structure that the schedule modulates, so its order is the phase count and it is what the fluid base rates are built from.
Copyright (c) 2012-2026, Imperial College London All rights reserved.
- sn_refresh_visits(sn, chains, rt, rtnodes)
Solves traffic equations to compute visit ratios
This function solves the traffic equations to compute the average number of visits to nodes and stations for each chain in the network.
- Parameters:
sn – Network structure
chains – Chain definitions
rt – Station routing matrix
rtnodes – Node routing matrix
- Returns:
visits – Cell array of visit ratios at stations per chain nodevisits: Cell array of visit ratios at nodes per chain sn: Updated network structure with visit fields populated
Examples
[visits, nodevisits, sn] = sn_refresh_visits(sn, chains, rt, rtnodes)
- sn_is_discrete_time(sn, options)
Decides whether a model lives on a discrete (slotted) time scale
A model is discrete-time when every enabled interarrival and service law is lattice-valued on a common slot length d, and at least one of them is intrinsically discrete. The lattice families are Geometric (support {1,2,…} slots), DMAP, DiscreteUniform with integral bounds, and Det whose value is a positive integral number of slots. Immediate is deliberately not a lattice law: a zero interval is not a point of {d,2d,…}, which is the same refusal the LDES slotted engine makes in slotSnap.
The test runs on sn.procid, sn.rates and sn.scv rather than on sn.proc, because refreshProcessRepresentations already replaced a Geometric by a continuous MAP fit through convertToMAP. procid keeps the requested family and (mean, SCV) identify the member of it exactly for every family above, so the discrete law can be rebuilt losslessly. DMAP is the exception: its (D0,D1) pair survives verbatim in sn.proc because it already has MAP shape.
- Parameters:
sn – Network structure
options – (Optional) solver options; reads config.timescale
- Returns:
bool – True when the model is discrete-time on slotLength slotLength: Slot length in model time units info: Struct with fields hasLattice, hasContinuous, mixed,
Examples
bool = sn_is_discrete_time(sn) [bool, slotLength, info] = sn_is_discrete_time(sn, options)
- sn_has_bursty_arrival(sn)
Checks whether any external arrival process is bursty, i.e. non-renewal
Returns true if any Source station has an arrival process with autocorrelated inter-arrival times (a non-renewal Markovian arrival process such as an MMPP/MAP), as opposed to a renewal process (Poisson, or any i.i.d. renewal process such as Erlang/HyperExp/Coxian/APH). Detection is exact: a MAP with matrices (D0,D1) is renewal iff D1 equals its rank-one renewal form t0*pie, where t0 = -D0*e and pie is the embedded stationary vector; any departure from that form signals correlation between successive inter-arrival times.
- Parameters:
sn – Network structure
- Returns:
bool – True if some external arrival process is non-renewal (bursty)
Examples
bool = sn_has_bursty_arrival(sn)
- sn_region_members(sn, f, Rmat, memvec)
MASK = SN_REGION_MEMBERS(SN, F, RMAT, MEMVEC) 1xM logical membership mask of finite capacity region F.
Membership is read from sn.regionmembers{f}, which refreshRegions records directly from the region’s node list. It cannot be derived from sn.region{f}: -1 there means “unbounded”, which is indistinguishable from “not a member”, so a region constrained only by regionlincon (or only by a memory budget) reads as empty and is silently ignored.
RMAT and MEMVEC provide the legacy derivation, used only for an sn built before regionmembers existed (for instance one deserialised from an older model file). That derivation carries the ambiguity above and is not equivalent.
- sn_pn_avg_rates(sn, QN, TN, AN, RN)
Place throughput, arrival rate and response time in tokens
A Place is a station and a token is the job it holds, so a firing that consumes two tokens is two departures, not one. The CTMC and SSA analyzers count firing events instead, which for unit arc multiplicities is the same number and for weighted arcs is not: the reported throughput is then not a token rate, and QLen over it is not a sojourn time. On a net where a Place is drained by an arc of weight 2 and another of weight 3, the event count gave RespT 1.6243 where Little’s law on tokens gives 0.7119, which is the value SolverJMT measures.
This function rescales the Place rows to tokens:
TN(p,k) tokens consumed from the Place per unit time AN(p,k) tokens produced into the Place per unit time RN(p,k) QN(p,k) / TN(p,k), Little’s law over the Place
Rows that do not belong to a Place are returned untouched, so a mixed Queue/Place model keeps its queueing metrics. When the firing rates cannot be recovered from the throughputs the inputs are returned unchanged rather than replaced by a guess.
- Parameters:
sn – Network structure
QN – Average queue lengths, i.e. mean token counts at the Places
TN – Average throughputs at stations, counting firing events
AN – Average arrival rates at stations, as computed by the caller
RN – Average response times at stations, as computed by the caller
- Returns:
TN – Throughputs, with the Place rows counting tokens AN: Arrival rates, with the Place rows counting tokens RN: Response times, with the Place rows following Little’s law
Examples
[TN, AN, RN] = sn_pn_avg_rates(sn, QN, TN, AN, RN)
- sn_is_phasetype(MAP, pie)
Tests whether {D0,D1,…} is a Markovian (phase-type / MAP) pair
A representation is Markovian when D0 has nonnegative off-diagonal entries, every D_k with k >= 1 is nonnegative, and the entry vector pie is nonnegative. Exactly under those conditions do sn.mu, sn.phi and sn.pie carry their probabilistic reading (mu_i = -D0(i,i) is a rate, phi_i is a completion probability, pie is a distribution over phases), which is what the CTMC state space, SSA and the fluid ODEs consume.
A matrix-exponential (ME) or rational (RAP) process fails the test: its moments, transforms and aggregated stationary measures remain exact, but the per-phase quantities are signed. See _kb/04-networkstruct.md.
- Parameters:
MAP – Cell array {D0,D1,…} of square matrices of equal size
pie – Optional entry vector to test for nonnegativity
- Returns:
tf – true when the representation is Markovian, false otherwise
Examples
tf = sn_is_phasetype(MAP) tf = sn_is_phasetype(MAP, pie)
- sn_is_mm1k_loss(sn)
BOOL = SN_IS_MM1K_LOSS(SN) Returns true for a single-class open Source-Queue-Sink system whose queue is a single-server exponential M/M/1/K with tail drop (DropStrategy.DROP). This is the exact regime shared by the closed-form loss scripts qsys_mm1k_loss (probability-based, used by SolverNC) and qsys_mg1k_loss_mgs (moment-based, used by SolverMVA), so both solvers gate their finite-capacity loss branch on this predicate.
- sn_has_classdep_routing(sn)
SN_HAS_CLASSDEP_ROUTING True when classes are not routed alike.
TF = SN_HAS_CLASSDEP_ROUTING(SN) returns true when the routing probabilities differ between job classes, either because a class switches class on a hop or because two classes leave the same station with different probabilities. It is false for a single-class model and for a multiclass model in which every class traverses the network identically.
This is the condition under which per-class visit ratios diverge, so a method that aggregates classes into a per-chain demand vector stops being exact. Used to gate Marie’s aggregation-decomposition in SolverMVA: with all classes routed alike that method reproduces the exact solution, and it degrades as the per-class demand vectors separate.
sn.rt is indexed station-major, (i-1)*K+r, matching sn_refresh_visits.
Copyright (c) 2012-2026, Imperial College London All rights reserved.
- sn_set_fork_fanout(sn, forkNodeIdx, fanOut)
Sets fork fanout for a Fork node
Updates the fanOut field in nodeparam for a Fork node.
- Parameters:
sn – Network structure
forkNodeIdx – Node index of the Fork node (1-based)
fanOut – Number of tasks per output link (>= 1)
- Returns:
sn – Modified network structure
Examples
sn = sn_set_fork_fanout(sn, forkNodeIdx, fanOut)
- sn_is_bas_model(sn)
Checks if the network is a closed single-class BAS model
Returns true for a closed, single-class network with Blocking-After-Service (BAS) finite-buffer blocking, which solver_sqd handles but exact/AMVA MVA does not. The Smith queue-decomposition approximation models a single circulating population, so an open class or more than one class disqualifies the model.
- Parameters:
sn – Network structure
- Returns:
bool – True if the model is a closed single-class BAS model
Examples
bool = sn_is_bas_model(sn)
- sn_set_service_batch(sn, rates, scvs, autoRefresh)
Sets service rates for multiple station-class pairs
Batch update of service rates. NaN values are skipped (not updated). More efficient than calling sn_set_service multiple times.
- Parameters:
sn – Network structure
rates – Matrix of new rates (nstations x nclasses), NaN = skip
scvs – Matrix of new SCVs (optional)
autoRefresh – If true, refresh process fields (default false)
- Returns:
sn – Modified network structure
Examples
sn = sn_set_service_batch(sn, rates) sn = sn_set_service_batch(sn, rates, scvs) sn = sn_set_service_batch(sn, rates, scvs, autoRefresh)
- sn_set_service(sn, stationIdx, classIdx, rate, scv, autoRefresh)
Sets service rate at a specific station and class
Directly modifies the service rate in NetworkStruct without rebuilding the full Network object. Useful for fast parameter updates in optimization.
- Parameters:
sn – Network structure
stationIdx – Station index (1-based)
classIdx – Class index (1-based)
rate – New service rate (must be positive)
scv – Squared coefficient of variation (default 1.0)
autoRefresh – If true, refresh process fields (default false)
- Returns:
sn – Modified network structure
Examples
sn = sn_set_service(sn, stationIdx, classIdx, rate) sn = sn_set_service(sn, stationIdx, classIdx, rate, scv) sn = sn_set_service(sn, stationIdx, classIdx, rate, scv, autoRefresh)
- sn_set_servers(sn, stationIdx, nServers)
Sets the number of servers at a station
Directly modifies the server count in NetworkStruct.
- Parameters:
sn – Network structure
stationIdx – Station index (1-based)
nServers – Number of servers (positive, or Inf)
- Returns:
sn – Modified network structure
Examples
sn = sn_set_servers(sn, stationIdx, nServers)
- sn_set_routing_prob(sn, fromStateful, fromClass, toStateful, toClass, prob, autoRefresh)
Sets a routing probability
Updates a single entry in the rt matrix.
- Parameters:
sn – Network structure
fromStateful – Source stateful node index (1-based)
fromClass – Source class index (1-based)
toStateful – Destination stateful node index (1-based)
toClass – Destination class index (1-based)
prob – Routing probability [0, 1]
autoRefresh – If true, refresh visit ratios (default false)
- Returns:
sn – Modified network structure
Examples
sn = sn_set_routing_prob(sn, fromStateful, fromClass, toStateful, toClass, prob) sn = sn_set_routing_prob(sn, fromStateful, fromClass, toStateful, toClass, prob, autoRefresh)
- sn_set_routing(sn, rt, autoRefresh)
Sets the routing matrix for stateful nodes
Replaces the rt matrix in NetworkStruct.
- Parameters:
sn – Network structure
rt – New routing matrix (nstateful*nclasses x nstateful*nclasses)
autoRefresh – If true, refresh visit ratios (default false)
- Returns:
sn – Modified network structure
Examples
sn = sn_set_routing(sn, rt) sn = sn_set_routing(sn, rt, autoRefresh)
- sn_set_priority(sn, classIdx, priority)
Sets the priority for a class
Directly modifies the class priority in NetworkStruct.
- Parameters:
sn – Network structure
classIdx – Class index (1-based)
priority – Priority value
- Returns:
sn – Modified network structure
Examples
sn = sn_set_priority(sn, classIdx, priority)
- sn_set_population(sn, classIdx, nJobs, autoRefresh)
Sets the number of jobs for a closed class
Directly modifies the job population in NetworkStruct and recalculates nclosedjobs.
- Parameters:
sn – Network structure
classIdx – Class index (1-based)
nJobs – Number of jobs (non-negative)
autoRefresh – If true, refresh visit ratios (default false)
- Returns:
sn – Modified network structure
Examples
sn = sn_set_population(sn, classIdx, nJobs) sn = sn_set_population(sn, classIdx, nJobs, autoRefresh)
- sn_set_arrival(sn, classIdx, rate, scv, autoRefresh)
Sets arrival rate for a class at the Source station
Directly modifies the arrival rate in NetworkStruct. Finds the Source station and updates its rate for the specified class.
- Parameters:
sn – Network structure
classIdx – Class index (1-based)
rate – New arrival rate (lambda)
scv – Squared coefficient of variation (default 1.0)
autoRefresh – If true, refresh process fields (default false)
- Returns:
sn – Modified network structure
Examples
sn = sn_set_arrival(sn, classIdx, rate) sn = sn_set_arrival(sn, classIdx, rate, scv) sn = sn_set_arrival(sn, classIdx, rate, scv, autoRefresh)
- sn_rtnodes_to_rtorig(sn)
Converts node routing matrix to the original routing matrix format
This function converts the node-level routing matrix to the original routing matrix format, excluding class-switching nodes.
- Parameters:
sn – Network structure
- Returns:
rtorigcell – Cell array representation of the routing matrix rtorig: Sparse matrix representation of the routing matrix
Examples
[rtorigcell, rtorig] = sn_rtnodes_to_rtorig(sn)
- sn_refresh_process_fields(sn, stationIdx, classIdx)
Refreshes process fields for a station-class pair
Updates mu, phi, proc, pie, phases based on current rate and SCV values. - SCV = 1.0: Exponential (1 phase) - SCV < 1.0: Erlang approximation - SCV > 1.0: Hyperexponential(2) approximation
- Parameters:
sn – Network structure
stationIdx – Station index (1-based)
classIdx – Class index (1-based)
- Returns:
sn – Modified network structure
Examples
sn = sn_refresh_process_fields(sn, stationIdx, classIdx)
- sn_print_routing_matrix(sn, onlyclass)
Prints the routing matrix of the network
This function displays the routing probabilities between nodes and classes in a human-readable format.
- Parameters:
sn – Network structure
onlyclass – (Optional) Filter printing for a specific class
Examples
sn_print_routing_matrix(sn) sn_print_routing_matrix(sn, onlyclass)
- sn_is_state_valid(sn)
Validates a network state
Checks if a given state vector represents a valid state for the network.
- Parameters:
sn – Network structure
- Returns:
bool – True if the state is valid for this network
Examples
bool = sn_is_state_valid(sn)
[ISVALID] = ISSTATEVALID()
- sn_is_population_model(sn)
Checks if the network is defined by populations
Returns true if the model is specified using population values rather than arrival rates.
- Parameters:
sn – Network structure
- Returns:
bool – True if model is population-based
Examples
bool = sn_is_population_model(sn)
- sn_compat_scaling(compat, counts, rates, n)
ETA = SN_COMPAT_SCALING(COMPAT, COUNTS, RATES, N)
Rate scaling a compatibility declaration imposes on its station.
This is what SolverLN carries onto the layer station, and it is NOT SN_COMPAT_RATE / SN_COMPAT_PEAK. The denominator is the rate the SAME population would obtain under FULL compatibility:
eta(n) = mu(n) / (peak * min(1, sum_j n(j) / S))
so ETA isolates the effect of the compatibility GRAPH and nothing else. The denominator DAMPS BY OCCUPANCY RELATIVE TO THE SERVER COUNT, min(1, N/S), because that is precisely what the solver’s own multiserver term contributes: it applies min(N,S) servers at the average server rate peak/S, so
min(N,S) * (peak/S) * eta(n) = mu(n)
and the station clears the activated-server rate exactly, at every state.
DAMPING BY min(1, N) INSTEAD – which this did until 2026-08-28 – leaves the effective law at min(N,S)/S * mu(n), which cancels the REDUNDANCY SPEED-UP the activated-server law exists to express: a pool of S servers facing one compatible job clears S, not 1, because every one of them works on it and the first to finish cancels the rest. Under the old normalization a fully compatible pool reduced to the plain multiserver, so the OI machinery did no work in the homogeneous case and LDES, which simulates mu(n) directly, disagreed with it by that factor.
ETA is therefore ABOVE ONE at low occupancy, which is not a defect: it is the speed-up carried by servers that would otherwise be idle.
Copyright (c) 2012-2026, Imperial College London All rights reserved.
- sn_compat_rate(compat, counts, rates, n)
MU = SN_COMPAT_RATE(COMPAT, COUNTS, RATES, N)
Total service rate of a station served by heterogeneous server pools with a class-compatibility graph. A pool t holds COUNTS(t) identical servers, each running at RATES(t), and may serve operand j when COMPAT(t,j) is nonzero. The rate the station clears in state N is
mu(n) = sum_t counts(t)*rates(t)*min(1, sum_{j: compat(t,j) ~= 0} n(j))
the ACTIVATED-SERVER law: a pool contributes its full rate as soon as it is compatible with at least one operand PRESENT. This is the order-independent reading of a compatibility structure – at an INTEGER state mu depends on n only through its SUPPORT, so it is invariant to the arrival order and to any permutation of the microstate, which is exactly the condition an OI station has to meet. It is also what PAS_COMPATIBILITY_5CLASS encodes for a flat Network, so the layered and flat readings of one compatibility matrix agree.
WHY min(1,.) AND NOT AN INDICATOR. At every integer state the two agree exactly – a pool with at least one compatible job present is fully active, one with none is idle – so nothing about the OI law on the real state lattice changes. They part company only at a FRACTIONAL argument, which is what a mean-value solver hands this function: AMVA evaluates the rate at a MEAN population, and under a hard indicator any operand with a mean above zero, however small, activates every pool it touches. A compatibility structure would then be invisible to AMVA whenever every operand is a little bit busy – which is nearly always. Scaling linearly below one job keeps the structure visible at the evaluation point while leaving the integer-state law untouched; it is the ordinary continuous relaxation of a step function, and the CTMC and simulation paths, which only ever evaluate at integer states, cannot tell the difference.
IT IS NOT A MATCHING. A pool of two servers compatible with a class holding ONE job contributes both servers here, which over-counts against a non-redundant system where one server serves one job. That is deliberate: the matching size depends on the counts and not only on the support, so it is NOT order independent and would take the station outside the product form the OI closure is built on. A model that means the matching wants a different station, not a different reading of this one.
Use SN_COMPAT_PEAK for the rate with every pool active, which normalizes the utilization of a rate-scaled station as U = T*S/peak.
- Reference:
Dorsman, Gardner (2024). New directions in pass-and-swap queues. Queueing Systems 107:205-256, Fig. 1.
Copyright (c) 2012-2026, Imperial College London All rights reserved.
- sn_to_qrf_capacity(sn)
Returns the QRF capacity vector F and which buffers actually bind
The QRF bounds index every marginal by 0..F(i), so F is an occupancy bound rather than a declared capacity: it is the station’s buffer where that buffer BINDS, and the population N everywhere else, since no queue of a closed model can hold more than N jobs.
Binding is decided by SN_GET_BUFFER_SIZE, the single place in LINE that makes that call: refreshCapacity derives a finite classcap (the chain population) at every station of every closed model, so a plain finiteness test on sn.cap would report a buffer at every station.
Both QRF blocking bounds need this. ‘qrf.bas’ needs it beside the blocking tables SN_TO_QRF_BLOCKING derives; ‘qrf.rsrd’ needs it ALONE, since its PBB constraint reads only which queues can be full and it carries no blocking tables at all.
- Parameters:
sn – Network structure
- Returns:
F – (nstations x 1) occupancy bound of each station, in jobs binding: (nstations x 1) logical, true where the buffer can refuse a job msg: Empty on success, otherwise why F is not defined for this model
Examples
[F, binding, msg] = sn_to_qrf_capacity(sn)
- sn_patience_handles(sn, ist, r)
H = SN_PATIENCE_HANDLES(SN, IST, R)
Patience (time-to-abandon) handles for station IST, class R.
The abandonment solvers need the patience law as FUNCTIONS – a complementary cdf and a hazard rate – not as moments, because that is what the underlying theory consumes: Whitt’s engineering solution reads the hazard near the origin, and the fluid models integrate the ccdf. LINE stores the law as a MAP/PH pair in sn.impatienceProc, from which both are available in closed form.
Returns [] when the station-class pair has no reneging patience configured, otherwise a struct with fields ccdf, pdf, hazard (function handles), mean, isExponential and rate.
See also:
python/line_solver/api/sn/patience.py
- sn_arrival_rate_fun(sn, ist, r)
[LAMBDAFUN, ISTIMEVARYING, PERIOD] = SN_ARRIVAL_RATE_FUN(SN, IST, R)
The arrival rate of station IST, class R AS A FUNCTION OF TIME.
The time-varying analyses (Mt/G/Inf, the modified offered load, the Gt/Mt/st+GI fluid queue) consume lambda(t) itself, not a mean rate: their whole content is the LAG between when work arrives and when it is felt, and a time-averaged rate has no lag. LINE carries a time-varying arrival as a MAPt or an NHPP, whose sn.proc slot is a piecewise-constant schedule, so lambda(t) is read off the segment in force at t.
For any other process the rate is constant and the handle returns it, which is what lets a caller ask for the time-varying analysis of a stationary model and get the stationary answer rather than an error.
- Parameters:
sn - NetworkStruct
ist - station index
r - class index
- Returns:
lambdaFun - handle lambda(t), vectorized over t isTimeVarying - whether the rate actually depends on t period - the cycle length when the schedule is cyclic, Inf otherwise
See also
SN_SCHEDULE_NOMINAL.
- sn_has_quorum_join(sn)
Checks if the network has a quorum (k-of-n) join
Returns true if some Join node declares a non-standard strategy with a positive required count in some class, i.e. it fires before every sibling has arrived. The sibling count is not re-derived here, so a declaration with k >= n reads as a quorum; use SN_JOIN_QUORUM where the branch count is known and the distinction matters, as the fork-join fixed point does.
- Parameters:
sn – Network structure
- Returns:
bool – True if some join declares a positive quorum
Examples
bool = sn_has_quorum_join(sn)
- sn_gd_balance(phi, cutoffs)
[VIOL, NWORST] = SN_GD_BALANCE(PHI, CUTOFFS)
Worst relative violation of the Whittle balance property by a globally state-dependent rate scaling PHI (the handle declared through setGlobalDependence). For every state n of the lattice 0..CUTOFFS and every pair of stations (s,t) populated in n, the property requires
phi_s(n) phi_t(n-e_s) = phi_t(n) phi_s(n-e_t).
When it holds, the chain is reversible with pi(n) ~ Phi(n) prod rho^n for the balance function Phi implied by phi, and the stationary law is insensitive to the service-time distribution beyond its mean. When it fails, the model is still solvable by SolverCTMC but has no product form and is sensitive.
PHI is evaluated on an (nstations x 1) population column, i.e. the single-class reading of the (nstations x nclasses) contract, and must return a scalar or an (nstations x 1) column. CUTOFFS is a scalar (same bound at every station) or an (nstations x 1) vector.
VIOL is the worst relative violation, NWORST the state attaining it.
Reference: P. Whittle, “Partial balance and insensitivity”, J. Appl. Prob. 22(1), 1985; T. Bonald, A. Proutiere, “Insensitivity in processor-sharing networks”, Perf. Eval. 49, 2002.
- sn_rt_stations(sn)
[RTST, VST] = SN_RT_STATIONS(SN)
Station-to-station routing probabilities and per-station visits.
sn.rt and sn.visits are indexed by STATEFUL node, so a solver that writes traffic equations over stations and indexes them by station index silently reads the wrong rows as soon as the model owns a stateful node that is not a station (Router, Cache, stateful class switch). RTST is obtained from sn.rt by absorbing those nodes,
Pst = P_AA + P_AB * (I - P_BB)^-1 * P_BA,
with A the station rows in station order and B the remaining stateful rows, which is exact because a non-station stateful node holds no jobs: it passes every arrival on instantaneously. When every stateful node is a station, RTST is sn.rt unchanged.
Copyright (c) 2012-2026, Imperial College London All rights reserved.
- sn_pn_firing_rates(sn, TN, tputIsTokens)
Recovers per-mode transition firing rates from the Place throughputs
The firing rates of a Petri net are not carried by the network structure, but they are determined by the Place throughputs together with the net structure. Writing x for the vector of per-mode firing rates, two families of equations hold at steady state, for every Place p and class k:
departure sum over the modes consuming (p,k) of x, weighted by the input arc multiplicity when TPUTISTOKENS is true and unweighted when it is false, equals TN(p,k) balance sum over all modes of x times (produced minus consumed) equals zero
The system is solved in least squares. That is deliberate: an exact solver supplies throughputs that satisfy it exactly and the fit is then the exact answer, whereas a simulator supplies estimates that satisfy it only up to sampling error and the least-squares fit is the right estimator there. A residual test would reject every simulated run.
- Parameters:
sn – Network structure
TN – Average throughputs at stations
tputIsTokens – True when TN counts tokens, false when it counts firing events
- Returns:
x – Firing rate per (transition, mode) pair, empty when undetermined consumed: Tokens consumed, indexed (mode, place, class) produced: Tokens produced, indexed (mode, place, class) placeNodes: Node indices of the Places, in the order used above
Examples
[x, consumed, produced, placeNodes] = sn_pn_firing_rates(sn, TN, tputIsTokens)
- sn_map_modulation(sn)
Collects the (D0,D1) modulation records of every non-renewal arrival or service process declared in the network
A MAP with matrices (D0,D1) is a Poisson-like point process modulated by the CTMC with generator Q = D0 + D1 (the phase process), whose conditional intensity in phase k is lambda(k) = sum_j D1(k,j). This function returns one record per modulating process, so that a solver-agnostic transformation can replace each of them by a random-environment stage set (see map2renv).
Only processes declared as MAP, MMPP2 or MMAP are reported: every other distribution is stored in sn.proc in (D0,D1) form as well (Erlang, Coxian, APH, …), but those are renewal processes that carry no modulation and are supported natively by the phase-type solvers.
Marked processes (MMAP) at a Source are reported as a single record whose classes vector lists every marked class, since all marks share one phase process; the per-class intensity comes from the mark-specific D1 matrices.
- Parameters:
sn – Network structure
- Returns:
mods – Struct array with fields ist, node, kind (‘arrival’|’service’),
Examples
mods = sn_map_modulation(sn)
- sn_is_open_model(sn)
Checks if the network is an open model
Returns true if all classes in the network have infinite population.
- Parameters:
sn – Network structure
- Returns:
bool – True if all classes have infinite population
Examples
bool = sn_is_open_model(sn)
- sn_is_mixed_model(sn)
Checks if the network is a mixed model
Returns true if the network contains both open and closed classes.
- Parameters:
sn – Network structure
- Returns:
bool – True if the network contains both open and closed classes
Examples
bool = sn_is_mixed_model(sn)
- sn_is_closed_model(sn)
Checks if the network is a closed model
Returns true if all classes in the network have finite population.
- Parameters:
sn – Network structure
- Returns:
bool – True if all classes have a finite population
Examples
bool = sn_is_closed_model(sn)
- sn_has_sjf(sn)
Checks if the network uses SJF scheduling
Returns true if any station in the network uses Shortest Job First scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses SJF scheduling
Examples
bool = sn_has_sjf(sn)
- sn_has_siro(sn)
Checks if the network uses SIRO scheduling
Returns true if any station uses Service In Random Order scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses SIRO scheduling
Examples
bool = sn_has_siro(sn)
- sn_has_single_class(sn)
Checks if the network has a single class
Returns true if the network has exactly one job class.
- Parameters:
sn – Network structure
- Returns:
bool – True if number of classes equals one
Examples
bool = sn_has_single_class(sn)
- sn_has_single_chain(sn)
Checks if the network has a single chain
Returns true if the network has exactly one chain.
- Parameters:
sn – Network structure
- Returns:
bool – True if number of chains equals one
Examples
bool = sn_has_single_chain(sn)
- sn_has_setf(sn)
Checks if the network uses SETF scheduling
Returns true if any station in the network uses Shortest Elapsed Time First (SETF) scheduling. SETF is the non-preemptive version of FB/LAS scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses SETF scheduling
Examples
bool = sn_has_setf(sn)
- sn_has_sept(sn)
Checks if the network uses SEPT scheduling
Returns true if any station uses Shortest Expected Processing Time scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses SEPT scheduling
Examples
bool = sn_has_sept(sn)
- sn_has_sd_routing(sn)
Checks if the network has state-dependent routing strategies
Returns true if the network contains routing strategies that are state-dependent and therefore violate the product-form assumption. State-dependent routing strategies include Round-Robin, Weighted Round-Robin, Join Shortest Queue, Power of K Choices, and Reinforcement Learning.
- Parameters:
sn – Network structure
- Returns:
bool – True if the network has state-dependent routing
Examples
bool = sn_has_sd_routing(sn)
- sn_has_ps_prio(sn)
Checks if the network uses PS with priorities
Returns true if any station uses Processor Sharing with priorities.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses PS with priorities
Examples
bool = sn_has_ps_prio(sn)
- sn_has_ps(sn)
Checks if the network uses PS scheduling
Returns true if any station in the network uses Processor Sharing scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses PS scheduling
Examples
bool = sn_has_ps(sn)
- sn_has_product_form_not_het_fcfs(sn, checkMeans)
Checks for product-form excluding heterogeneous FCFS
Returns true if the network has product-form solution excluding cases with heterogeneous FCFS.
- Parameters:
sn – Network structure
- Returns:
bool – True if product-form holds without heterogeneous FCFS
Examples
bool = sn_has_product_form_not_het_fcfs(sn)
CHECKMEANS (default true) also demands class-independent FCFS service means. Pass false only for an algorithm that models class-dependent FCFS itself (ab, schmidt, schmidt-ext), for which the exclusion is the whole point.
- sn_has_product_form(sn)
Checks if the network has product-form solution
Returns true if the network satisfies conditions for product-form equilibrium distribution.
- Parameters:
sn – Network structure
- Returns:
bool – True if the network has product-form solution
Examples
bool = sn_has_product_form(sn)
- sn_has_priorities(sn)
Checks if the network uses priority scheduling
Returns true if any station uses priority-based scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses priority scheduling
Examples
bool = sn_has_priorities(sn)
- sn_has_open_classes(sn)
Checks if the network contains open classes
Returns true if the network contains any open class (infinite population).
- Parameters:
sn – Network structure
- Returns:
bool – True if any class has infinite population
Examples
bool = sn_has_open_classes(sn)
- sn_has_multiple_closed_classes(sn)
Checks if the network has multiple closed classes
Returns true if the network has more than one closed (finite population) class.
- Parameters:
sn – Network structure
- Returns:
bool – True if there are multiple closed classes
Examples
bool = sn_has_multiple_closed_classes(sn)
- sn_has_multi_server(sn)
Checks if the network has multi-server stations
Returns true if any station has more than one server.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station has multiple servers
Examples
bool = sn_has_multi_server(sn)
- sn_has_multi_class_heter_fcfs(sn)
Checks for multi-class FCFS with heterogeneous service
Returns true if any FCFS station serves multiple classes with different service time distributions.
- Parameters:
sn – Network structure
- Returns:
bool – True if any multi-class FCFS station has heterogeneous service
Examples
bool = sn_has_multi_class_heter_fcfs(sn)
- sn_has_multi_class_heter_exp_fcfs(sn)
Checks for multi-class FCFS with heterogeneous exponential service
Returns true if any FCFS station serves multiple classes with different exponential service times.
- Parameters:
sn – Network structure
- Returns:
bool – True if any multi-class FCFS station has heterogeneous exponential service
Examples
bool = sn_has_multi_class_heter_exp_fcfs(sn)
Checks if the network has one or more stations with multiclass heterogeneous FCFS and exponential service times
- Parameters:
sn - NetworkStruct object for the queueing network model
- Returns:
bool - true if network has multiclass heterogeneous FCFS with exponential service
- sn_has_multi_class_fcfs(sn)
Checks if the network has multi-class FCFS stations
Returns true if any FCFS station serves multiple job classes.
- Parameters:
sn – Network structure
- Returns:
bool – True if any FCFS station is multi-class
Examples
bool = sn_has_multi_class_fcfs(sn)
- sn_has_multi_class(sn)
Checks if the network has multiple classes
Returns true if the network has more than one job class.
- Parameters:
sn – Network structure
- Returns:
bool – True if number of classes is greater than one
Examples
bool = sn_has_multi_class(sn)
- sn_has_multi_chain(sn)
Checks if the network has multiple chains
Returns true if the network has more than one chain.
- Parameters:
sn – Network structure
- Returns:
bool – True if number of chains is greater than one
Examples
bool = sn_has_multi_chain(sn)
- sn_has_mixed_classes(sn)
Checks if the network has both open and closed classes
Returns true if the network contains at least one open class and one closed class.
- Parameters:
sn – Network structure
- Returns:
bool – True if the network has both open and closed classes
Examples
bool = sn_has_mixed_classes(sn)
- sn_has_lps(sn)
Checks if the network uses LPS scheduling
Returns true if any station in the network uses Least Progress Scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses LPS scheduling
Examples
bool = sn_has_lps(sn)
- sn_has_load_dependence(sn)
Checks if the network has load-dependent service rates
Returns true if any station has service rates that depend on queue length.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station has load-dependent service
Examples
bool = sn_has_load_dependence(sn)
- sn_has_ljf(sn)
Checks if the network uses LJF scheduling
Returns true if any station in the network uses Longest Job First scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses LJF scheduling
Examples
bool = sn_has_ljf(sn)
- sn_has_lept(sn)
Checks if the network uses LEPT scheduling
Returns true if any station uses Longest Expected Processing Time scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses LEPT scheduling
Examples
bool = sn_has_lept(sn)
- sn_has_lcfs_pr(sn)
Checks if the network uses LCFS with preemptive-resume scheduling
Returns true if any station uses LCFS preemptive-resume scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses LCFS-PR scheduling
Examples
bool = sn_has_lcfs_pr(sn)
- sn_has_lcfs_pi(sn)
Checks if the network uses LCFS with preemptive-identical scheduling
Returns true if any station uses LCFS preemptive-identical scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses LCFS-PI scheduling
Examples
bool = sn_has_lcfs_pi(sn)
- sn_has_lcfs(sn)
Checks if the network uses LCFS scheduling
Returns true if any station in the network uses Last-Come First-Served scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses LCFS scheduling
Examples
bool = sn_has_lcfs(sn)
- sn_get_arvr_from_tput(sn, TN, TH)
Computes average arrival rates at stations from throughputs
This function calculates the average arrival rate at each station in steady-state from the station throughputs and routing matrix.
- Parameters:
sn – Network structure
TN – Average throughputs at stations
TH – Throughput handles (optional)
- Returns:
AN – Average arrival rates at stations
Examples
AN = sn_get_arvr_from_tput(sn, TN, TH)
- sn_has_inf(sn)
Checks if the network has infinite server stations
Returns true if any station in the network has an infinite number of servers.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station has infinite servers
Examples
bool = sn_has_inf(sn)
- sn_has_homogeneous_scheduling(sn, strategy)
Checks if all stations use the same scheduling policy
Returns true if all stations in the network use identical scheduling policies.
- Parameters:
sn – Network structure
- Returns:
bool – True if all stations use the same scheduling policy
Examples
bool = sn_has_homogeneous_scheduling(sn)
- sn_has_hol(sn)
Checks if the network uses HOL scheduling
Returns true if any station in the network uses Head-Of-Line scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses HOL scheduling
Examples
bool = sn_has_hol(sn)
- sn_has_gps_prio(sn)
Checks if the network uses GPS with priorities
Returns true if any station in the network uses Generalized Processor Sharing with priorities.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses GPS with priorities
Examples
bool = sn_has_gps_prio(sn)
- sn_has_gps(sn)
Checks if the network uses GPS scheduling
Returns true if any station in the network uses Generalized Processor Sharing.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses GPS scheduling
Examples
bool = sn_has_gps(sn)
- sn_has_fractional_populations(sn)
Checks if the network has fractional population values
Returns true if any class has a non-integer population value.
- Parameters:
sn – Network structure
- Returns:
bool – True if any class has fractional population
Examples
bool = sn_has_fractional_populations(sn)
Checks if the network has closed classes with non-integer populations
- sn_has_fork_join(sn)
Checks if the network contains fork-join nodes
Returns true if the network contains any fork or join nodes.
- Parameters:
sn – Network structure
- Returns:
bool – True if the network contains fork or join nodes
Examples
bool = sn_has_fork_join(sn)
- sn_has_fcfs(sn)
Checks if the network has FCFS scheduling
Returns true if any station in the network uses First-Come First-Served scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses FCFS scheduling
Examples
bool = sn_has_fcfs(sn)
- sn_has_dps_prio(sn)
Checks if the network uses DPS with priorities
Returns true if any station in the network uses Discriminatory Processor Sharing with priorities.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses DPS with priorities
Examples
bool = sn_has_dps_prio(sn)
- sn_has_dps(sn)
Checks if the network uses Discriminatory Processor Sharing
Returns true if any station in the network uses DPS scheduling.
- Parameters:
sn – Network structure
- Returns:
bool – True if any station uses DPS scheduling
Examples
bool = sn_has_dps(sn)
- sn_has_closed_classes(sn)
Checks if the network contains closed classes
Returns true if the network contains any closed class (finite population).
- Parameters:
sn – Network structure
- Returns:
bool – True if any class has a finite population
Examples
bool = sn_has_closed_classes(sn)
- sn_has_class_switching(sn)
Checks if the network has class switching
Returns true if the network has class switching, indicated by the number of classes differing from the number of chains.
- Parameters:
sn – Network structure
- Returns:
bool – True if number of classes differs from number of chains
Examples
bool = sn_has_class_switching(sn)
- sn_get_state_aggr(sn)
Returns the aggregated initial state of the network
This function extracts and aggregates the initial state of all stateful nodes in the network.
- Parameters:
sn – Network structure
- Returns:
initialStateAggr – Aggregated initial state cell array
Examples
initialStateAggr = sn_get_state_aggr(sn)
- sn_get_residt_from_respt(sn, RN, WH)
Computes residence times from response times
This function converts response times to residence times by accounting for visit ratios at each station.
- Parameters:
sn – Network structure
RN – Average response times
WH – Residence time handles
- Returns:
WN – Average residence times
Examples
WN = sn_get_residt_from_respt(sn, RN, WH)
- sn_get_product_form_params(sn)
Extracts standard product-form parameters from the network structure
This function extracts class-level parameters from a network structure for use in product-form queueing network analysis. The mu parameter includes extra elements beyond population |N| as required by MVALDMX.
- Parameters:
sn – Network structure
- Returns:
lambda – Arrival rates for open classes D: Service demands at queuing stations N: Population vector Z: Think times (service demands at delay stations) mu: Load-dependent service capacity scaling factors S: Number of servers at queuing stations V: Visit ratios
Examples
[lambda,D,N,Z,mu,S,V] = sn_get_product_form_params(sn)
- sn_get_product_form_chain_params(sn)
Extracts product-form parameters aggregated by chain
This function extracts parameters from a network structure and aggregates them by chain for use in product-form analysis methods. The mu parameter includes extra elements beyond population |N| as required by MVALDMX.
- Parameters:
sn – Network structure
- Returns:
lambda – Chain arrival rates D: Chain service demands at queuing stations N: Chain populations Z: Chain think times (service demands at delay stations) mu: Load-dependent service capacity scaling factors S: Number of servers at queuing stations V: Chain visit ratios
Examples
[lambda,D,N,Z,mu,S,V] = sn_get_product_form_chain_params(sn)
- sn_get_node_tput_from_tput(sn, TN, TH, ANn)
Computes average throughputs at nodes from station throughputs
This function calculates the average throughput at each node in steady-state from the station throughputs and node-level routing matrix.
- Parameters:
sn – Network structure
TN – Average throughputs at stations
TH – Throughput handles
ANn – (Optional) Average arrival rates at nodes; computed if missing
- Returns:
TNn – Average throughputs at nodes
Examples
TNn = sn_get_node_tput_from_tput(sn, TN, TH) TNn = sn_get_node_tput_from_tput(sn, TN, TH, ANn)
- sn_get_node_arvr_from_tput(sn, TN, TH, AN)
Computes average arrival rates at nodes from station throughputs
This function calculates the average arrival rate at each node in steady-state from the station throughputs, accounting for node-level routing and visits.
- Parameters:
sn – Network structure
TN – Average throughputs at stations
TH – Throughput handles
AN – (Optional) Average arrival rates at stations; computed if missing
- Returns:
ANn – Average arrival rates at nodes
Examples
ANn = sn_get_node_arvr_from_tput(sn, TN, TH) ANn = sn_get_node_arvr_from_tput(sn, TN, TH, AN)
- sn_get_demands_chain(sn)
Computes aggregated demand parameters per chain
This function aggregates class-level service demands and related parameters to chain-level parameters, computing total demands, service times, visits, and aggregation factors.
- Parameters:
sn – Network structure
- Returns:
Lchain – Total service demand per station per chain STchain: Mean service time per station per chain Vchain: Mean number of visits per station per chain alpha: Aggregation factors mapping classes to chains Nchain: Population of each chain SCVchain: Squared coefficient of variation of service times per station per chain refstatchain: Reference station index for each chain
Examples
[Lchain,STchain,Vchain,alpha,Nchain,SCVchain,refstatchain] = sn_get_demands_chain(sn)
- sn_get_buffer_size(sn, ist)
Returns the number of jobs a station can hold, in service included
Kendall’s K: the total occupancy bound of station IST, obtained as the tighter of the station capacity sn.cap(ist) and the per-class capacities sn.classcap(ist,:). Returns Inf when the station is unbounded. Both fields are populated by refreshCapacity, which already folds setCapacity, setClassCapacity, a finite orbit and the closed-chain population into them, so this is the single place that decides whether a buffer BINDS.
Only a buffer that can actually BIND is reported. refreshCapacity derives a FINITE classcap (the chain population) for EVERY closed model, so a plain finiteness test would report a buffer at every station of every closed model; a capacity at least as large as the total population can never refuse a job and is returned as Inf. sum(njobs) is Inf as soon as one class is open, so any finite capacity reachable by an open class binds.
- Parameters:
sn – Network structure
ist – Station index
- Returns:
N – Buffer size in jobs, Inf if unbounded
Examples
N = sn_get_buffer_size(sn, ist)
- sn_fj_visits_spn(sn)
SN_FJ_VISITS_SPN Compute fork-join node visit ratios via auxiliary SPN models
NODEVISITS = SN_FJ_VISITS_SPN(SN) builds, for each class that passes through a fork-join pair, an auxiliary closed Stochastic Petri Net capturing the fork/join synchronization semantics. The SPN is solved with SolverCTMC and the throughput ratios give the per-node visit ratios.
Population-preserving approach: the SPN uses population = B (number of fork branches). The pre-fork station consumes B tokens and produces 1 per branch. The Join consumes 1 per branch and produces B. This ensures token conservation and correct CTMC analysis.
- The function handles:
Multiple fork-join pairs (including serial fork-joins)
Multiple classes
- Returns:
- nodevisits - cell(1, nchains), each entry is (nnodes x nclasses)
with visit ratios normalized to reference station = 1
Copyright (c) 2012-2026, Imperial College London All rights reserved.
- sn_deaggregate_chain_results(sn, Lchain, ST, STchain, Vchain, alpha, Qchain, Uchain, Rchain, Tchain, Cchain, Xchain)
Deaggregates chain-level performance metrics to class-level metrics
This function converts chain-level performance metrics (queue lengths, utilizations, response times, throughputs) to class-level metrics using aggregation factors.
- Parameters:
sn – Network structure
Lchain – Chain demands
ST – Class service times
STchain – Chain service times
Vchain – Chain visits
alpha – Aggregation factors mapping classes to chains
Qchain – Chain queue lengths
Uchain – Chain utilizations
Rchain – Chain response times
Tchain – Chain throughputs
Cchain – Chain system response times
Xchain – Chain system throughputs
- Returns:
Q – Class queue lengths U: Class utilizations R: Class response times T: Class throughputs C: Class system response times X: Class system throughputs
Examples
[Q,U,R,T,C,X] = sn_deaggregate_chain_results(sn, Lchain, ST, STchain, Vchain, alpha, Qchain, Uchain, Rchain, Tchain, Cchain, Xchain)
- mexify_sn
Create configuration object of class ‘coder.CodeConfig’.