io.+linemodel

linemodel.str_to_sched_id(str)

Map a wire scheduling enum name to a SchedStrategy numeric ID.

SchedStrategy.fromText case-folds and resolves the FCFSPRIO/HOL, LAS/FB and SET/SETF aliases, and errors on an unknown name. Do not reintroduce a hand-rolled whitelist here: the previous one covered 23 of 40 strategies, silently degraded the rest to FCFS, and lacked the PAS/OI cases that linemodel_save itself emits.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.str_to_repl_id(str)

Map replacement strategy string to ReplacementStrategy numeric ID.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.servers_from_json(v)

Decode a server count. Inf crosses the wire as the string “Infinity” (the form Place numServers already used); a numeric value is taken verbatim.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.repl_to_str(id)

Map ReplacementStrategy numeric ID to the wire enum name.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.mat2json(M)

C = MAT2JSON(M) Cell of row cells, so jsonencode writes a 2-D ARRAY at every size. A bare numeric matrix collapses to a scalar at 1x1 and to a flat array at 1xn, and the readers on the other side of the interchange (line-cli, the Python loader) require nested arrays: a one-phase APH written as “T”: -1 aborts the C++ reader with ‘type must be array, but is number’.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.json2matcellseq(raw)

SEGS = JSON2MATCELLSEQ(RAW) A JSON array of matrices decodes either as a cell of rows or, when every segment has the same shape, as one numeric array with the segment on the first dimension. Normalise both to a 1-by-n cell of matrices.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.json2matcell(arr)

Convert a JSON array of 2D matrices (which jsondecode returns as a cell array of matrices, or collapses into a 3D numeric array when all matrices have equal size) into a cell array of 2D matrices.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.json2mat(arr)

Convert a JSON 2D array to a numeric matrix. jsondecode returns a numeric matrix for a rectangular array of numbers, but a cell array of row vectors when the rows differ in length or when the array was written through a cell wrapper.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.json2markcellseq(raw)

MARKS = JSON2MARKCELLSEQ(RAW) The MARK-MAJOR nesting of a marked schedule: an array over MARKS of an array over SEGMENTS. Each mark’s inner array goes through json2matcellseq, so the collapsed layouts jsondecode produces for equally-shaped segments are handled there once rather than twice. Returns a 1-by-K cell of 1-by-n cells.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.fluiddep_table_to_handle(levels, values)

H = FLUIDDEP_TABLE_TO_HANDLE(LEVELS, VALUES) The level-dependent multiplier written by FLUIDDEP_TABLE: the piecewise-linear interpolant of (LEVELS, VALUES), held constant beyond the last level.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.fluiddep_table(h, L, npts)

TAB = FLUIDDEP_TABLE(H, L, NPTS) Tabulate a level-dependent firing multiplier h(level) for model.json, which cannot carry a function handle: NPTS equally spaced levels on [0, L] and the multiplier at each. The reader interpolates linearly and holds the last value beyond L (FLUIDDEP_TABLE_TO_HANDLE), so the round trip is exact for a piecewise-linear h with knots on the grid and an approximation otherwise.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.json2markbatchcellseq(raw)

BLOCKS = JSON2MARKBATCHCELLSEQ(RAW) The MARK-MAJOR, then BATCH, then SEGMENT nesting of a batch marked schedule. Only the OUTER mark level is peeled here: what remains under one mark is an array over BATCH SIZES of an array over SEGMENTS, which is structurally the same shape json2markcellseq already reads, so the four collapsed layouts jsondecode can produce are handled there once rather than twice. Returns a 1-by-K cell of 1-by-B cells of 1-by-n cells.

reshape, never squeeze, to peel the mark: with one batch size or one segment squeeze would drop that axis too and the blocks would come back a level short.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.firingdep_table_eval(M, slotIdx, map, cutoffs)

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.firingdep_table_to_handle(frm, node_map, class_map)

Rebuild the firing-rate dependence handle g(M) from the materialized lattice written by FIRINGMOD_SCALING_TABLE (linemodel_save). M is the node-indexed marking matrix; the enabling (place,class) slots are read off, clamped to the cutoffs, and the tabulated multiplier is looked up (default 1 outside range).

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.cellify_string_array(arr)

Convert a JSON string array (which may be decoded as a char, cell, or struct array) into a cell array of character vectors.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.firingdep_scaling_table(g, slotIdx, caps, nnodes, nclasses)

Materialize the firing-rate dependence handle g(M) over the box lattice of the enabling (place,class) slots, 0 <= count(s) <= caps(s). M is the full node-indexed marking matrix (nnodes x nclasses); only the enabling slots vary, all other entries are held at 0. Keyed by the comma-joined 0-based slot counts, matching the JAR/Python readers. g returns a positive scalar multiplier.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.cd_state_key(n)

Copyright (c) 2012-2026, Imperial College London All rights reserved.

linemodel.cell2mat_or_vec(x)

jsondecode yields a numeric column for a homogeneous array but a cell when the writer emitted num2cell; normalize both to a row vector.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

class linemodel.NodeCodec

NODECODEC The model.json codec of every node type, as a registry.

One codec class per node type lives in +linemodel/+node and carries both directions of everything specific to that type, so adding a node type to the interchange is one new file there. A codec subclasses linemodel.NodeCodecBase and defines:

classes(), types() MATLAB classes it writes, wire types it reads create(model, nd, name) the node, from its JSON object

and overrides, when the type has fields of its own, any of

encode(node, nj, ctx) -> nj (linemodel_save, per node) link(node, nd, ctx) (linemodel_load, after all nodes exist) configure(node, nd, ctx) (linemodel_load, after classes/services) finish(node, nd, ctx) (linemodel_load, after impatience)

Fields every node or station shares (scheduling, servers, buffer, service, dependence, state, …) stay in linemodel_save/linemodel_load.

A node of a class without its own codec is written by the codec of its nearest registered superclass (DelayStation as a Delay, QueueingStation as a Queue), and one with none at all is refused by name.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

Method Summary
static configure(node, nd, ctx)
static create(model, nd, name, ntype)
static encode(node, nj, ctx)
static finish(node, nd, ctx)
static forNode(node)

CODEC = FORNODE(NODE) codec class of NODE’s class, else of its nearest registered superclass.

static registry()

[BYCLASS, BYTYPE] = REGISTRY() class -> codec and wire type -> codec, built once from the classes of +linemodel/+node.

static typeOf(node)

S = TYPEOF(NODE) the wire type NODE is written as.

class linemodel.DistCodec

DISTCODEC The model.json codec of every distribution, as a registry.

One codec class per distribution family lives in +linemodel/+dist and carries BOTH directions, so adding a distribution to the interchange is one new file there (or one row of +dist/ScalarCodec.m for a family that is a plain list of scalar parameters), with no edit to linemodel_save or linemodel_load. Each codec class defines four static methods:

classes() MATLAB class names it writes (builtin(‘class’, dist)) types() wire “type” values it reads encode(dist, cn) -> dictionary for the JSON writer decode(d) -> Distribution, or [] when the document does not

carry this codec’s representation

The registry is built once by scanning the package, and refuses a class or a type claimed by two codecs.

DECODE ORDER is part of the format and is the one linemodel_load always had: the codec named by d.type first, then the type-independent representations (REPRESENTATIONS: ph, map, mph, mmap, in that order), then a ‘fit’ specification, then a mean/SCV fallback for a type this reader does not know.

Copyright (c) 2012-2026, Imperial College London All rights reserved.

Property Summary
REPRESENTATIONS

field of the document -> codec reading it whatever its type

Method Summary
static cyclic(p)

Absent ‘cyclic’ means cyclic, matching the schedule constructors.

static decode(d)

DIST = DECODE(D) the Distribution a decoded JSON struct describes.

static encode(dist)

D = ENCODE(DIST) the dictionary written for DIST ([] for none).

static hasParams(d)

TF = HASPARAMS(D) true when D carries a non-empty “params” object, the precondition of every parameter-list representation.

static registry()

[BYCLASS, BYTYPE] = REGISTRY() class name -> codec and wire type -> codec, built once from the classes of +linemodel/+dist.

class linemodel.NodeCodecBase

NODECODECBASE Defaults of a node codec (see linemodel.NodeCodec): a node type with nothing beyond the fields every node shares overrides only classes(), types() and create().

Copyright (c) 2012-2026, Imperial College London All rights reserved.

Method Summary
static configure(~, ~, ~)

CONFIGURE(NODE, ND, CTX) restore the node type’s own fields, after classes and service processes. CTX.node_map, .class_map, .model.

static encode(~, nj, ~)

NJ = ENCODE(NODE, NJ, CTX) add the node type’s own fields to NJ.

static finish(~, ~, ~)

FINISH(NODE, ND, CTX) restore what needs every node’s configuration first (a Transition’s modes). Same CTX.

LINK(NODE, ND, CTX) restore node-to-node references, after every node exists and before any class does. CTX.node_map, CTX.model.