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:

  1. 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’.