Stochastic Network Utilities
Network analysis and transformation utilities.
The sn module contains utility functions for stochastic networks, including
routing probability calculations, visit ratios, and network transformations.
Key function categories:
Network properties:
sn_has_product_form(),sn_has_class_switching(),sn_has_fork_join()Scheduling queries:
sn_has_fcfs(),sn_has_ps(),sn_has_lcfs(),sn_has_priorities()Model type queries:
sn_is_open_model(),sn_is_closed_model(),sn_is_mixed_model()Performance metrics:
sn_get_demands_chain(),sn_get_arvr_from_tput(),sn_get_residt_from_respt()State management:
sn_get_state_aggr(),sn_is_state_valid(),sn_deaggregate_chain_results()Routing utilities:
sn_refresh_visits(),sn_rtnodes_to_rtorig(),sn_print_routing_matrix()
Service Network (SN) utilities.
Native Python implementations for stochastic network structure analysis, validation, and parameter extraction.
- Key classes:
NetworkStruct: Data structure summarizing network characteristics SnGetDemandsResult: Result of sn_get_demands_chain calculation
- Key functions:
sn_get_demands_chain: Aggregate class-level parameters into chain-level sn_has_*: Network property predicates sn_is_*: Model type checks sn_get_*: Parameter extraction sn_validate: Check a NetworkStruct against its contract (sn_contract)
- class MatrixArray(input_array)[source]
Bases:
ndarrayNumpy array subclass with .get() and .set() methods for API compatibility.
Provides compatibility with the wrapper mode that uses JLine’s Matrix class which has get(i, j) and set(i, j, value) methods.
Create MatrixArray from existing array.
- __getitem__(key)[source]
Override indexing to handle 2D indexing on 1D arrays.
This provides compatibility with MATLAB-style row/column vectors where a 1D array can be indexed as (0, j) or (i, 0).
- class NetworkStruct(nstations=0, nstateful=0, nnodes=0, nclasses=0, nchains=0, nclosedjobs=0, njobs=<factory>, nservers=<factory>, cap=None, classcap=None, rates=<factory>, scv=<factory>, phases=None, phasessz=None, phaseshift=None, visits=<factory>, nodevisits=<factory>, inchain=<factory>, chains=<factory>, refstat=<factory>, refclass=<factory>, sched=<factory>, schedparam=None, routing=<factory>, rt=None, rtnodes=None, nodetype=<factory>, isstation=<factory>, isstateful=<factory>, isstatedep=None, sdr=None, hassetup=<factory>, nodeToStation=<factory>, nodeToStateful=<factory>, stationToNode=<factory>, stationToStateful=<factory>, statefulToNode=<factory>, statefulToStation=<factory>, state=<factory>, stateprior=<factory>, space=<factory>, lldscaling=None, cdscaling=None, cdscalingpeak=None, jdscaling=None, jdscalingpeak=None, gdscaling=None, gdscalingpeak=None, gdscalingcutoff=None, classprio=None, classdeadline=None, classspawn=None, isslc=None, issignal=None, signaltarget=None, signaltype=None, syncreply=None, replyblock=None, immfeed=None, signalremdist=None, arrivalbatch=None, signalrempolicy=None, iscatastrophe=None, connmatrix=None, nodenames=<factory>, classnames=<factory>, mu=None, phi=None, proc=None, isph=None, pie=None, procid=None, lst=None, fj=None, fjsync=None, fjclassmap=None, isfjaugmented=False, fjauxclass=None, droprule=None, nregions=0, region=None, regionrule=None, regionweight=None, regionsz=None, regionmaxmem=None, regionmembers=None, regionlincon=None, sync=None, gsync=None, nodeparam=None, routingweights=None, reward=None, rtorig=None, rt_visits=None, csmask=None, nvars=None, isbasblocking=None, isbasdestination=None, impatienceType=None, impatienceMu=None, impatienceClass=None, impatiencePhi=None, impatiencePhases=None, impatienceProc=None, impatiencePie=None, impatienceDist=None, batchRejectProb=None, balkingStrategy=None, balkingThresholds=None, retrialType=None, retrialMu=None, retrialPhi=None, retrialProc=None, retrialMaxAttempts=None, retrialPolicy=None, orbitMaxJobs=None, orbitImpatience=None, hasbreakdown=None, breakdownMu=None, repairMu=None, breakdownProc=None, repairProc=None, downServiceRates=None, varsparam=None, markidx=None)[source]
Bases:
objectData structure summarizing network characteristics.
Native Python equivalent of the MATLAB/JAR NetworkStruct. It contains all parameters needed by solvers to analyze a queueing network.
- Variables:
nstations (int) – Number of stations (queues, delays, sources, joins, places)
nstateful (int) – Number of stateful nodes
nnodes (int) – Total number of nodes
nclasses (int) – Number of job classes
nchains (int) – Number of chains (routing chains)
nclosedjobs (int) – Total number of jobs in closed classes
njobs (numpy.ndarray) – (1, K) Population per class (inf for open classes)
nservers (numpy.ndarray) – (M, 1) Number of servers per station
rates (numpy.ndarray) – (M, K) Service rates
scv (numpy.ndarray) – (M, K) Squared coefficient of variation
visits (Dict[int, numpy.ndarray]) – Dict[int, ndarray] - Chain ID -> (M, K) visit ratios
inchain (Dict[int, numpy.ndarray]) – Dict[int, ndarray] - Chain ID -> class indices in chain
chains (numpy.ndarray) – (K, 1) Chain membership per class
refstat (numpy.ndarray) – (K, 1) Reference station per class
refclass (numpy.ndarray) – (1, C) Reference class per chain
sched (Dict[int, int]) – Dict[int, SchedStrategy] - Station ID -> scheduling strategy
routing (numpy.ndarray) – (N, K) Routing strategy matrix
rt (numpy.ndarray | None) – Routing probability matrix
nodetype (List[int]) – List[NodeType] - Node types, (N+R): one FINITE_CAPACITY_REGION entry per finite capacity region after the N physical nodes
isstation (numpy.ndarray) – (N+R,) Boolean mask for stations (False on region rows)
isstateful (numpy.ndarray) – (N+R,) Boolean mask for stateful nodes (False on region rows)
hassetup (numpy.ndarray) – (M, 1) Boolean mask, STATION-indexed: queue stations that carry setup/delay-off times (function stations)
nodeToStation (numpy.ndarray) – (N, 1) Node index -> station index mapping
nodeToStateful (numpy.ndarray) – (N, 1) Node index -> stateful index mapping
stationToNode (numpy.ndarray) – (M, 1) Station index -> node index mapping
stationToStateful (numpy.ndarray) – (M, 1) Station index -> stateful index mapping
statefulToNode (numpy.ndarray) – (S, 1) Stateful index -> node index mapping
statefulToStation (numpy.ndarray) – (S, 1) Stateful index -> station index mapping
state (Dict[int, numpy.ndarray]) – Dict State per stateful node
lldscaling (numpy.ndarray | None) – (M, Nmax) Load-dependent scaling matrix
cdscaling (Dict | None) – Class-dependent (product-form) scaling functions beta_{i,r}
jdscaling (Dict | None) – Joint-dependent (non-product-form) scaling functions eta_i
cap (numpy.ndarray | None) – (M, 1) Station capacities
classcap (numpy.ndarray | None) – (M, K) Per-class capacities
connmatrix (numpy.ndarray | None) – (N, N) Connection matrix
nodenames (List[str]) – List[str] - Node names, (N+R): region names after the nodes
classnames (List[str]) – List[str] - Class names
- __setattr__(name, value)[source]
Override to convert numpy arrays to MatrixArray for API compatibility.
- validate()[source]
Validate structural consistency.
- Raises:
ValueError – If structural consistency is violated
- is_valid()[source]
Check if structure is valid.
- Returns:
True if structure passes validation, False otherwise
- Return type:
- get_station_indices()[source]
Get indices of station nodes.
- Returns:
Array of node indices that are stations
- Return type:
- get_stateful_indices()[source]
Get indices of stateful nodes.
- Returns:
Array of node indices that are stateful
- Return type:
- has_multi_server()[source]
Check if any station has multiple servers.
Infinite servers are delays, not multiserver queues: counting them made every model with a Delay read as multiserver (MATLAB sn_has_multi_server filters them out).
- property obj
Return self for compatibility with wrapper code that accesses .obj
- class NodeType(*values)[source]
Bases:
IntEnumNode types in a queueing network.
THE single definition; lang/base.py and api/sn/network_struct.py import it, and it is the numbering sn.nodetype carries. All three used to declare it: the two above agreed, with a note asking the next maintainer to keep them that way, while this module declared a CamelCase plain Enum with auto() values that matched neither – and a plain Enum member never compares equal to an IntEnum one whatever the numbers say, so the five sites that imported it silently answered False. They are fixed with this collapse: the console’s model kind never reported an SPN or a cache, SolverCTMC’s WAITQ-plus-SPN refusal never fired, SolverFLD’s hide_immediate treated every SPN as a plain queueing network (int() on a plain Enum raises, and the raise was swallowed), and SolverAG’s is_source was always False.
The NUMBERING is native python’s own and deliberately not MATLAB’s, which runs Queue=0, Source=1, …, Sink=-1, Join=-2. Nothing crosses a codebase boundary as an integer here: the JSON wire carries the node type as the STRING toText returns.
- SOURCE = 0
- SINK = 1
- QUEUE = 2
- DELAY = 3
- JOIN = 5
- CACHE = 6
- ROUTER = 7
- CLASSSWITCH = 8
- PLACE = 9
- TRANSITION = 10
- LOGGER = 11
- FINITE_CAPACITY_REGION = 12
- class SchedStrategy(*values)[source]
Bases:
IntEnumScheduling strategies for service stations.
THE single definition. lang/base.py and api/sn/network_struct.py import this class; until 2026-09-16 each declared a twin of its own and seven members carried different integers here than there (PSJF, FB, LAS, LRPT, FSP, PAS, OI), so an Enum member from this module never compared equal to the IntEnum member of the same name. The numbering kept below is the one lang/base.py and network_struct.py already agreed on, because that is the one every FSP/PAS/OI caller was reading.
Declared in ascending value order on purpose: toID is positional.
- LCFSPI = 3
- HOL = 9
- LPS = 17
- SETF = 18
- FCFSPR = 22
- EDF = 23
- JOIN = 25
- EDD = 27
- SRPT = 28
- SRPTPRIO = 29
- LCFSPRIO = 30
- LCFSPRPRIO = 31
- LCFSPIPRIO = 32
- FCFSPRPRIO = 33
- FCFSPIPRIO = 34
- FSP = 36
- PAS = 37
- OI = 38
- PSJF = 39
- FB = 40
- LAS = 40
- LRPT = 42
- FCFSPI = 43
- class RoutingStrategy(*values)[source]
Bases:
IntEnumStrategies for routing jobs between network nodes.
THE single definition. lang/base.py and api/sn/network_struct.py import this class; until 2026-09-17 each declared a twin of its own. All three agreed on every member AND every value, so the two IntEnum twins did compare equal to each other – but this one was a plain Enum, which compares equal to neither, and it is the copy the package exports (from line_solver import RoutingStrategy). So a member handed in by a caller tested False against every RoutingStrategy.X inside lang/ and api/sn/, silently.
Values must match MATLAB’s RoutingStrategy constants for JMT compatibility.
- SQ = 6
- SDR = 7
- class DropStrategy(*values)[source]
Bases:
IntEnumStrategies for handling queue overflow and capacity limits.
THE single definition; lang/base.py and api/sn/network_struct.py import it. All three used to declare it, each carrying a docstring asking the next maintainer to keep them numerically identical – and two of the three were plain Enum against IntEnum here, which never compare equal whatever the numbers say. Values are MATLAB’s DropStrategy constants and the JAR jline.lang.constant.DropStrategy ids, which are the interchange encoding of sn.droprule and sn.regionrule.
The short names are MATLAB’s spelling and the CamelCase ones the JAR’s, and both are kept as MATLAB keeps both: they are the same member, so a name from either codebase reads the same model.
- WAITQ = -1
- DROP = 1
- BAS = 2
- BBS = 3
- BlockingBeforeService = 3
- RSRD = 4
- ReServiceOnRejection = 4
- RETRIAL = 5
- Retrial = 5
- RETRIAL_WITH_LIMIT = 6
- RetrialWithLimit = 6
- sn_get_demands_chain(sn)[source]
Calculate new queueing network parameters after aggregating classes into chains.
Computes chain-level demands, service times, visit ratios, and other parameters by aggregating class-level data based on chain membership.
- Parameters:
sn (NetworkStruct) – NetworkStruct object for the queueing network model
- Returns:
Lchain: (M, C) chain-level demand matrix
STchain: (M, C) chain-level service time matrix
Vchain: (M, C) chain-level visit ratio matrix
alpha: (M, K) class-to-chain weighting matrix
Nchain: (1, C) population per chain
SCVchain: (M, C) chain-level squared coefficient of variation
refstatchain: (C, 1) reference station per chain
- Return type:
SnGetDemandsResult containing chain parameters
- sn_deaggregate_chain_results(sn, Lchain, ST, STchain, Vchain, alpha, Qchain, Uchain, Rchain, Tchain, Cchain, Xchain)[source]
Calculate class-based performance metrics from chain-level performance measures.
Disaggregates chain-level performance metrics (queue lengths, utilizations, response times, throughputs) to class-level metrics using the aggregation factors (alpha).
- Parameters:
sn (NetworkStruct) – NetworkStruct object for the queueing network model
Lchain (ndarray) – (M, C) Service demands per chain
ST (ndarray | None) – (M, K) Mean service times per class (optional, computed from rates if None)
STchain (ndarray) – (M, C) Mean service times per chain
Vchain (ndarray) – (M, C) Mean visits per chain
alpha (ndarray) – (M, K) Class aggregation coefficients
Qchain (ndarray | None) – (M, C) Mean queue-lengths per chain (optional)
Uchain (ndarray | None) – (M, C) Mean utilization per chain (optional)
Rchain (ndarray) – (M, C) Mean response time per chain
Tchain (ndarray) – (M, C) Mean throughput per chain
Cchain (ndarray | None) – (1, C) Mean system response time per chain. Must be None or empty, as in MATLAB: C is always derived from Little’s law (njobs/X) and a non-empty Cchain raises ValueError.
Xchain (ndarray) – (1, C) Mean system throughput per chain
- Returns:
Q: (M, K) queue lengths
U: (M, K) utilizations
R: (M, K) response times
T: (M, K) throughputs
C: (1, K) system response times (Little’s law: njobs/X)
X: (1, K) system throughputs
- Return type:
SnDeaggregateResult containing class-level performance metrics
- Raises:
ValueError – if a non-empty Cchain is supplied (as MATLAB errors).
- sn_rt_stations(sn)[source]
Station-to-station routing probabilities and per-station visits.
sn.rtandsn.visitsare 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). The returned routing matrix absorbs 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 the result is
sn.rtunchanged.- Parameters:
sn (NetworkStruct) – NetworkStruct
- Returns:
Tuple
(rt_stations, visits_stations)of shapes (M*K, M*K) and (M, K).
- sn_get_arvr_from_tput(sn, TN, TH=None)[source]
Compute average arrival rates at stations from throughputs.
Calculates the average arrival rate at each station in steady-state from the station throughputs and routing matrix.
- Parameters:
sn (NetworkStruct) – Network structure
TN (ndarray) – Average throughputs at stations (M x R)
TH (ndarray | None) – Throughput handles (optional)
- Returns:
Average arrival rates at stations (M x R)
- Return type:
AN
References
Original MATLAB: matlab/src/api/sn/sn_get_arvr_from_tput.m
- sn_is_closed_model(sn)[source]
Check if the network model is closed (all finite populations).
A closed model has all finite job populations.
- Parameters:
sn (NetworkStruct) – NetworkStruct object
- Returns:
True if the network is a closed model
- Return type:
- sn_is_open_model(sn)[source]
Check if the network model is open (all infinite populations).
An open model has only infinite (open) job classes.
- Parameters:
sn (NetworkStruct) – NetworkStruct object
- Returns:
True if the network is an open model
- Return type: