Utilities and Constants

Helper functions, constants, and enumerations.

These modules provide utility functions, constants, and example models.

Utility Functions (line_solver.utils)

The utils module contains helper functions for working with LINE models.

Utility functions for LINE queueing network analysis.

This module provides helper functions for working with LINE models and results, including table manipulation, mathematical utilities, and data processing functions.

tget(df, *args)[source]

Extract specific rows/columns from LINE result tables.

This function filters and selects data from pandas DataFrames containing LINE solver results based on station names, job class names, or other identifiers.

Parameters:
  • df (pandas.DataFrame or IndexedTable) – Input DataFrame or IndexedTable with LINE results.

  • *args – Variable arguments specifying filters (station names, job classes, or other identifiers).

Returns:

Filtered DataFrame with selected rows and columns.

Return type:

pandas.DataFrame

Examples

>>> results = solver.avg_table()
>>> queue_results = tget(results, 'Queue')
>>> class1_results = tget(results, 'Class1')
circul(c)[source]

Generate a circulant matrix.

Creates a circulant matrix where each row is a cyclic permutation of the previous row. For a scalar input, creates a circulant matrix of size c x c with specific pattern.

Parameters:

c – Either an integer (size of matrix) or array-like (first row).

Returns:

The circulant matrix.

Return type:

numpy.ndarray

Examples

>>> circul(3)  # Creates a 3x3 circulant matrix
>>> circul([1, 2, 3])  # Creates circulant matrix with [1,2,3] as first row
class IndexedTable(dataframe)[source]

Bases: object

Enhanced pandas DataFrame wrapper with object-based filtering.

Wraps a MATLAB table to enable filtering using Station, Node, JobClass, and/or Chain objects, while maintaining full backward compatibility with standard pandas operations.

Variables:

data (pd.DataFrame) – The underlying pandas DataFrame

Initialize IndexedTable wrapper.

Parameters:

dataframe – A pandas DataFrame (typically from solver.avgTable(), etc.)

Raises:

TypeError – If input is not a pandas DataFrame

__init__(dataframe)[source]

Initialize IndexedTable wrapper.

Parameters:

dataframe – A pandas DataFrame (typically from solver.avgTable(), etc.)

Raises:

TypeError – If input is not a pandas DataFrame

__getattr__(name)[source]

Delegate attribute access to the underlying DataFrame.

Columns are accessible as attributes (table.QLen, table.Util, …) and any other DataFrame attribute/method (iterrows, to_string, values, …) is forwarded so IndexedTable is a drop-in for standard pandas usage.

__getitem__(key)[source]

Support direct indexing with objects: table[queue, jobclass]

Parameters:

key – Either a single object/tuple of objects for filtering, or standard pandas indexing (int, slice, list, etc.)

Returns:

Filtered result or standard pandas indexing result

Return type:

pd.DataFrame

filterBy(*args)[source]

Filter table by Station/Node and/or JobClass/Chain objects.

Intelligently filters based on table structure and object types.

Parameters:

*args – 1 or 2 arguments - Station/Node/JobClass/Chain objects

Returns:

Filtered DataFrame

Return type:

pd.DataFrame

Raises:

ValueError – If invalid argument types or counts provided

get(*args)[source]

Alias for filterBy - convenient shorthand syntax.

Parameters:

*args – Same as filterBy

Returns:

Filtered DataFrame

Return type:

pd.DataFrame

tget(*args)[source]

Alias for filterBy - backward compatibility with tget() function.

Parameters:

*args – Same as filterBy

Returns:

Filtered DataFrame

Return type:

pd.DataFrame

__len__()[source]

Return number of rows.

__repr__()[source]

Return string representation with MATLAB-style number formatting.

__str__()[source]

Return string representation with MATLAB-style number formatting.

tabulate()[source]

The underlying DataFrame.

Callers written before this wrapper existed test isinstance(t, DataFrame) and fall back to t.tabulate(), so a table that is neither raises inside pandas’ own __getattr__ with a message naming DataFrame rather than this class. Kept as the escape hatch that contract expects; .data is the same object under its current name.

to_string(index=False, **kwargs)[source]

MATLAB-style rendering, so print(t) and print(t.to_string()) agree.

WITHOUT THIS, to_string fell through __getattr__ to pandas, which formats to display.precision DECIMAL PLACES (5, set in __init__.py) while every other codebase prints 5 SIGNIFICANT DIGITS. The two coincide only for values of order 1: a cache hit rate of 0.024273 printed as 0.02427, one digit short, and the parity comparator read a 1.2e-4 relative gap against MATLAB’s 0.024273 where the underlying values agreed to twelve digits. It looked like a solver defect and was a formatter.

A caller that explicitly wants the index, or passes any other pandas option, gets pandas’ own rendering: this override exists to fix the DEFAULT, not to reimplement DataFrame.to_string.

property shape

Return shape of underlying DataFrame.

property columns

Return columns of underlying DataFrame.

property index

Return index of underlying DataFrame.

head(n=5)[source]

Return first n rows.

tail(n=5)[source]

Return last n rows.

info()[source]

Print DataFrame info.

describe()[source]

Return statistical description.

to_csv(*args, **kwargs)[source]

Export to CSV.

to_excel(*args, **kwargs)[source]

Export to Excel.

Constants and Enumerations (line_solver.constants)

The constants module defines enumerations and global constants used throughout the LINE Solver package.

Scheduling Strategies

class SchedStrategy(*values)[source]

Bases: IntEnum

Scheduling 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 = 41
LRPT = 42
FCFSPI = 43
static fromString(obj)[source]
static fromLINEString(sched)[source]
static toID(sched)[source]
static to_feature(strategy)[source]

Convert a scheduling strategy to its feature name for solver support checking.

class SchedStrategyType(*values)[source]

Bases: IntEnum

Categories of scheduling strategies by preemption behavior.

THE single definition; lang/base.py imports it. Both the values and the member set are MATLAB’s (matlab/src/lang/constant/SchedStrategyType.m), which is ground truth: this module used to declare auto() values in the JAR’s declaration order (PR=1, PNR=2, NP=3, NPPrio=4) and lang/base.py a two-member IntEnum (NP=0, PR=1), so the two disagreed on every value they shared. lang/base.py’s numbering was the MATLAB one and is kept.

PRPrio = 4
PNRPrio = 5
static get_type_id(strategy)[source]

Classify a scheduling discipline by preemption and priority.

Port of MATLAB SchedStrategyType.getTypeId, and the classification the Queue constructor stores in _sched_policy. The three codebases keep ONE table each and all three call it: MATLAB’s Queue.m, the JAR’s Queue.java and Queue below all ask this question rather than answering it, because until 2026-09-17 they answered it separately and disagreed on eleven disciplines.

RAND and LAS are classified here but not in MATLAB, which has no RAND member and spells LAS as the same id as FB; native python declares all four, so both aliases need naming.

Raises ValueError on a discipline no Queue accepts (the node markers EXT, FORK, JOIN and REF), as MATLAB raises there.

static to_text(type_)[source]

Port of MATLAB SchedStrategyType.toText.

Distribution and Process Types

class ProcessType(*values)[source]

Bases: Enum

Types of stochastic processes for arrivals and service times.

BMAP = 22
MMAP = 23
DUNIFORM = 24
BERNOULLI = 25
PRIOR = 26
GEOMETRIC = 27
ME = 28
RAP = 29
DISCRETESAMPLER = 30
ZIPF = 31
DMAP = 32
EMPIRICALCDF = 33
NHPP = 34
MAPT = 35
PHT = 36
MPH = 37
MMAPT = 38
MPHT = 39
BMMAPT = 40
static isMarkovian(t)[source]

True when sn.proc carries an exact matrix representation of a process of type t: a genuine (D0, D1) pair, or its matrix-exponential analogue for ME/RAP.

The distinction is about sn.proc, NOT about what getProcess returns. getProcess hands back raw distribution PARAMETERS for several non-Markovian families – Gamma, Weibull, Lognormal, Pareto and Uniform return two scalars (Pareto {alpha, k}, Uniform {min, max}) – and the network refresh replaces those with map_erlang(mean, n) before storing them in sn.proc, where n = ceil(1/SCV) capped at 100 (n = 20 when SCV < CoarseTol). That fit matches the mean, and matches the SCV only when SCV <= 1: Pareto with SCV 64 gives n = 1, a single exponential of SCV 1. So for these types sn.proc is an approximation, not the law that was requested, and nothing on the cell says so – the only signal is sn.procid.

Solvers that read sn.proc as if it were the exact law must gate on this predicate. It is the procid-level counterpart of the JAR’s Distribution.isMarkovian(), i.e. of the Markovian class hierarchy, so the two lists must stay in step.

static isMarked(t)[source]

True when the type carries PER-MARK arrival blocks, i.e. an event of this process is labelled and the label is meaningful to the model. At a Source the label selects the class of the arriving job (Source.set_marked_arrival, sn.markidx).

static isMarkedStationary(t)[source]

True when sn.proc holds the STATIONARY marked cell, the M3A layout {D0, D1agg, D11, ..., D1K}.

MPH is the renewal special case of MMAP and lowers to exactly that cell (D0 = S, D1k = s_k*alpha), so every consumer that reads the M3A layout serves both and must gate on this predicate rather than on equality with MMAP.

static isMarkedSchedule(t)[source]

True when sn.proc holds the MARKED SCHEDULE slot {breakpoints, D0segs, D1aggsegs, cyclic, markSegs}.

MPHt is stored lowered to MMAPt form segment by segment, so one walk serves both, exactly as one MAPt walk serves MAPt and PHt.

BMMAPT IS INCLUDED, and its slot is that one with the batch blocks appended, so a consumer gated on this predicate reads a BMMAPt as the MMAPt it aggregates down to. That is right for anything time-blind or batch-blind and WRONG for anything that releases jobs: an arrival or service sampler must branch on isBatch() as well, or it silently delivers one job per epoch.

static isBatch(t)[source]

True when an EVENT of this process releases (or, as a service process, completes) a BATCH of jobs whose size the process itself carries in its blocks.

This is the batch twin of isMarkedStationary() and isMarkedSchedule(), and the same rule applies: a procid test that should serve every batch family is a MEMBERSHIP test, never equality with BMAP.

It is disjoint from sn.arrivalbatch, which is a SEPARATE batch-size law bolted onto a renewal stream by Source.set_arrival_batch. A process that is isBatch already carries its own sizes, so the two are mutually exclusive by construction.

static fromString(obj)[source]

Node Types

class NodeType(*values)[source]

Bases: IntEnum

Node 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
static toText(node_type)[source]

Convert node type to text representation.

Job Class Types

class JobClassType(*values)[source]

Bases: IntEnum

Types of job classes in queueing networks.

THE single definition; lang/base.py imports it. Values are MATLAB’s (matlab/src/lang/constant/JobClassType.m), which is ground truth. This module used to declare a plain Enum with auto() values (OPEN=1) and lang/base.py an IntEnum with OPEN=0, CLOSED=1 and a SIGNAL member no codebase carries – and no DISABLED, so DisabledClass raised AttributeError on every construction while this copy, which had DISABLED, was the one nothing imported. SIGNAL is gone with the copy: a Signal class is stored as CLOSED (see Network._refresh_signals).

  • OPEN: jobs arrive from outside the system and depart it

  • CLOSED: a fixed population circulating in the system

  • DISABLED: an inactive class the solvers do not process

Routing Strategies

class RoutingStrategy(*values)[source]

Bases: IntEnum

Strategies 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
static to_feature(strategy)[source]

Convert a routing strategy to its feature name for solver support checking.

Service Strategies

class ServiceStrategy(*values)[source]

Bases: Enum

Service strategies defining service time dependence.

Solver Types

class SolverType(*values)[source]

Bases: Enum

Types of solvers available in LINE.

BA = 2
LDES = 4

Metric Types

class MetricType(*values)[source]

Bases: Enum

Types of performance metrics that can be computed.

SysDropR = 11
SysPower = 13
Tard = 24
SysTard = 25

Drop and Replacement Strategies

class DropStrategy(*values)[source]

Bases: IntEnum

Strategies 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
class ReplacementStrategy(*values)[source]

Bases: IntEnum

Cache replacement strategies.

Determines which item to evict when the cache is full and a new item needs to be stored.

Variables:
  • RR – Random Replacement - evict a random item

  • FIFO – First-In-First-Out - evict oldest item

  • SFIFO – Strict FIFO - FIFO eviction, no reinsertion/promotion on hit

  • LRU – Least Recently Used - evict least recently accessed item

HLRU = 4
CLIMB = 5
QLRU = 6
static to_string(strategy)[source]

Convert a replacement strategy to its string representation.

static to_feature(strategy)[source]

Convert a replacement strategy to its feature name for solver support checking.

Join Strategies

class JoinStrategy(*values)[source]

Bases: IntEnum

Enumeration of join strategies.

PARTIAL is the canonical name of the k-of-n join, as in the MATLAB JoinStrategy class, so that .name serializes straight to the interchange spelling; QUORUM is kept as an alias for it because that is how the JAR (jline.lang.constant.JoinStrategy.Quorum) spells the same strategy. Only the names cross codebases, in the JSON joinStrategy field and the .lqnx path; the numeric values are compared solely against this enum, so they need not match the MATLAB or JAR ids.

QUORUM = 1
CANDJOIN = 2

Layered Network Types

class CallType(*values)[source]

Bases: IntEnum

Types of calls between tasks in layered networks.

THE single definition; layered.py and the LN solver import it. Values are MATLAB’s (matlab/src/lang/constant/CallType.m) and are what lsn.calltype carries. layered.py used to declare a third copy with STRING values, and being the last one the package imported it was the one line_solver.CallType resolved to – so a caller comparing it against a member from either of the other two got False whichever way round they wrote it.

  • SYNC: Synchronous call (caller waits for response)

  • ASYNC: Asynchronous call (caller continues immediately)

  • FWD: Forward call (caller terminates, response goes to caller’s caller)

class ActivityPrecedenceType(*values)[source]

Bases: Enum

Types of activity precedence relationships in layered networks.

These specify how activities are ordered and synchronized: - PRE_SEQ: Sequential prerequisite (must complete before) - PRE_AND: AND prerequisite (all must complete before) - PRE_OR: OR prerequisite (any must complete before) - POST_SEQ: Sequential post-condition - POST_AND: AND post-condition - POST_OR: OR post-condition - POST_LOOP: Loop post-condition - POST_CACHE: Cache post-condition

Polling Types

class PollingType(*values)[source]

Bases: Enum

Polling strategies for polling systems.

DECREMENTING = 4
static fromString(obj)[source]

Event and Timing Types

class EventType(*values)[source]

Bases: Enum

Types of events in discrete-event simulation.

  • INIT: Initialization event

  • LOCAL: Local processing event

  • ARV: Job arrival event

  • DEP: Job departure event

  • PHASE: Phase transition event in multi-phase processes

  • READ: Cache read event

  • STAGE: Staging area event

READ = 6
ENABLE = 8
FIRE = 9
PRE = 10
POST = 11
RENEGE = 12
RETRY = 13
SWITCH = 14
FAILURE = 15
REPAIR = 16
START = 17
PREEMPT = 18
class TimingStrategy(*values)[source]

Bases: IntEnum

Timing strategies for Petri net transitions.

Verbose Level

class VerboseLevel(*values)[source]

Bases: Enum

Verbosity levels for LINE solver output.

Global Constants

class GlobalConstants[source]

Bases: object

Global constants and configuration for the LINE solver.

ArcTol = 1e-12
Immediate = 100000000.0
classmethod isLibraryAttributionShown()[source]

True if the library attribution has already been printed.

classmethod setLibraryAttributionShown(value=True)[source]

Record that the library attribution has been printed.

classmethod getInstance()[source]

Get the singleton instance of GlobalConstants.

classmethod get_instance()

Get the singleton instance of GlobalConstants.

classmethod getVerbose()[source]

Get the current verbosity level.

classmethod get_verbose()

Get the current verbosity level.

classmethod setVerbose(verbosity)[source]

Set the verbosity level for solver output.

classmethod set_verbose(verbosity)

Set the verbosity level for solver output.

classmethod getConstants()[source]

Get a dictionary of all global constants.

classmethod get_constants()

Get a dictionary of all global constants.