LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
line::qn Namespace Reference

Classes

struct  BreakdownParam
 Server breakdown and repair of a station whose server fails and is repaired. More...
struct  CacheParam
struct  Distrib
struct  EventOutcome
 What one event produces at one node: the successor rows, their rates and their probabilities, all three the same length. More...
class  FeatureSet
 A subset of the registry: MATLAB's SolverFeatureSet, whose list is a flag per field. More...
struct  FjJoinParam
 sn.nodeparam{j}.fj: what a Join node needs to fire on identity. More...
struct  FjSync
 One fork firing synchronization: sn.fjsync{k}. More...
struct  FjTagged
 The augmented struct and everything needed to read its results back. More...
struct  ForkParam
 Variable forking levels, the twin of MATLAB sn.nodeparam{f}.fanOutLink / .fanOutProb / .fanOutDist. More...
struct  GlobalConstants
 The MATLAB GlobalConstants, as reported by lineStart at its defaults. More...
struct  GlobalOutcome
 What one global event produces: a whole network state per outcome. More...
struct  GlobalSync
 A GLOBAL synchronization: an SPN mode event and the place arcs it drives. More...
struct  JobClass
 One job class of the network. More...
class  Layer
 A layer network: everything a NetworkStruct holds, plus the LQN back-mapping. More...
struct  Marginal
 What State.toMarginal returns for one station and one state row. More...
struct  ModeEvent
 One half of a GLOBAL synchronization: a mode event at a node. More...
struct  NetState
 One network state: the per-stateful-node local rows it is composed of. More...
class  Network
 A queueing network under construction. More...
class  NetworkStruct
 A network plus its refreshed NetworkStruct. More...
struct  NodeDef
 A node of the network. More...
struct  PollingInfo
 Port of State.pollingInfo: the derived description of a polling controller. More...
struct  PrioPop
 The population the *PRIO disciplines actually share the server among. More...
struct  ReplyBlockInfo
 Where node ind keeps its reply-block counters inside the local vars. More...
struct  RetrialParam
 The parameters of a retrial station: MATLAB sn.retrialProc and friends. More...
class  RoutingMatrix
 The routing matrix a model script fills in, MATLAB's P cell array. More...
struct  RowLayout
 How a station's state row splits into [buffer | server | local vars]. More...
struct  SetupDelayOffParam
 Setup and delay-off of a station that powers down when it falls idle. More...
struct  Station
 One station of the network. More...
struct  SupportResult
 The outcome of the gate: the verdict, the offending features, the message. More...
struct  Sync
 One synchronization: an ACTIVE event and the PASSIVE event it drives. More...
struct  SyncEvent
 One half of a synchronization: an event at a node, in a class. More...
struct  TaggedChain
 The tagged model and the class bookkeeping a caller needs to read it back. More...
struct  TransitionParam
 The parameters of a Cache node, MATLAB's sn.nodeparam{ind} for a Cache. More...

Typedefs

template<class T>
using CdScaling
 A class-dependent scaling map, sn.cdscaling.
template<class T>
using GdScaling
 A globally state-dependent scaling, sn.gdscaling.

Enumerations

enum class  Feature : int { COUNT }
 One language feature. More...
enum class  DropStrategy
 Blocking and loss rules, with the values of MATLAB DropStrategy. More...
enum class  JobClassType
 Job class kinds, with the values of MATLAB JobClassType. More...
enum class  ReplacementStrategy
 Cache replacement policies, with the values of MATLAB ReplacementStrategy. More...
enum class  NodeType
 Node kinds, with the values of MATLAB NodeType. More...
enum class  ProcessType
 Distribution kinds, with the values of MATLAB ProcessType. More...
enum class  RoutingStrategy
 Routing strategies, with the values of MATLAB RoutingStrategy. More...
enum class  SchedStrategy
 Scheduling disciplines, with the values of MATLAB SchedStrategy. More...
enum class  ProcessType
 Distribution kinds, with the values of MATLAB ProcessType. More...
enum class  SchedStrategy
 Scheduling disciplines, with the values of MATLAB SchedStrategy. More...
enum class  EventType
 The events a state can undergo, with the values of MATLAB EventType. More...

Functions

constexpr std::size_t feature_count ()
 The number of registered features, MATLAB numel(SolverFeatureSet.fields).
const char * feature_name (Feature f)
 The canonical registry name, byte for byte the MATLAB field name.
std::string feature_phrase (Feature f)
 A human-readable phrase for the reason string, e.g.
Feature feature_generalization (Feature f)
 The registry name a specialization falls back to when it is not declared.
SupportResult feature_set_supports (const std::string &solver, const FeatureSet &declared, const FeatureSet &used)
 SolverFeatureSet.supports: is every feature the model uses declared?
Feature feature_of_process (ProcessType p)
 The feature name of a distribution, MATLAB serviceProcess{r}{3}.name.
Feature feature_of_sched (SchedStrategy s)
 SchedStrategy.toFeature.
Feature feature_of_routing (RoutingStrategy r)
 RoutingStrategy.toFeature.
Feature feature_of_replacement (ReplacementStrategy s)
 ReplacementStrategy.toFeature.
Feature feature_of_server_section (SchedStrategy s)
 The SERVER section a Queue gets for a discipline, MATLAB Queue.m:79-108.
template<class T>
bool has_binding_capacity (const NetworkStruct< T > &sn)
 getUsedLangFeatures: the features the MODEL uses.
template<class T>
FeatureSet used_lang_features (const NetworkStruct< T > &sn)
template<class T>
void feature_gate (const std::string &solver, const FeatureSet &declared, const NetworkStruct< T > &sn, const std::string &requested_method="", const std::string &resolved_method="")
 runAnalyzerChecks: refuse a model the solver does not declare, by name.
std::string capacity_str (double v)
 g for a capacity, so the message reads 2 and not 2.000000.
std::string capacity_fallback_advice (bool is_open_class)
 NetworkSolver.checkBindingCapacity (NetworkSolver.m:1172-1228): the shared structural gate for finite station capacity (setCapacity) and finite per-class buffers (classCap), used by the product-form solvers.
template<class T>
std::string binding_capacity_reason (const std::string &solver, const NetworkStruct< T > &sn)
 The refusal check_binding_capacity raises, as a string, or empty when no buffer binds.
template<class T>
void check_binding_capacity (const std::string &solver, const NetworkStruct< T > &sn)
template<class T>
void sn_fj_validate (const NetworkStruct< T > &sn)
 Port of sn_fj_validate: is this fork-join model inside the exact solver's reach?
template<class T>
std::string sn_fj_supports (const NetworkStruct< T > &sn)
 Can the exact fork-join construction be asked for this model?
template<class T>
FjTagged< T > fj_tag (const NetworkStruct< T > &sn)
 Port of ModelAdapter.fjtag.
template<class T>
void cache_retrieval_class_map (const CacheParam< T > &cp, std::vector< std::size_t > &rc_list, std::vector< std::size_t > &rc_items, std::vector< std::size_t > &rc_orig)
 Port of State.cacheRetrievalClassMap: the canonical order of a cache's retrieval classes, which is the column order of block B.
template<class T>
Matrix< T > station_swap_graph (const NetworkStruct< T > &sn, std::size_t ist)
 The swap graph of a PAS / OI station, with the defaults refreshLocalVars.m installs applied.
template<class T>
bool station_swap_graph_is_zero (const NetworkStruct< T > &sn, std::size_t ist)
 True when the station's materialized swap graph is entirely zero.
template<class T>
PollingInfo< T > polling_info (const NetworkStruct< T > &sn, std::size_t ind)
std::string mva_base_method (const std::string &method)
 SolverMVA.getFeatureSet, plus getMethodFeatureSet's per-method deltas.
bool mva_is_closed_population_method (const std::string &method)
 The AMVA algorithms whose recursion is over a CLOSED population vector.
void mva_unset_non_bcmp_sched (FeatureSet &f)
 Drops every scheduling name OUTSIDE the BCMP set {INF, PS, FCFS, SIRO, LCFS-PR} that the base MVA envelope declares.
FeatureSet mva_feature_set (const std::string &raw_method)
template<class T>
FeatureSet mva_feature_set (const std::string &raw_method, const NetworkStruct< T > &sn)
 mva_feature_set on a MODEL, i.e.
FeatureSet nc_feature_set (const std::string &method)
 SolverNC.getFeatureSet, 48 names, transcribed unchanged.
FeatureSet ctmc_feature_set (const std::string &method)
 SolverCTMC.getFeatureSet, the reference's 104 MATLAB names in full.
FeatureSet ssa_feature_set (const std::string &)
 SolverSSA.getFeatureSet, 98 MATLAB names.
FeatureSet fluid_feature_set (const std::string &method)
 SolverFLD.getFeatureSet, transcribed, MINUS what the requested method cannot evaluate – the port of @@SolverFLD/getMethodFeatureSet.
FeatureSet mam_feature_set (const std::string &method)
 SolverMAM.getFeatureSet, the union of its four setTrue calls: 55 MATLAB names, WIDENED for 'default'/'ldqbd' only, and NARROWED by one name no MAM path ever serves.
FeatureSet ag_feature_set (const std::string &)
 SolverAG.getFeatureSet: what the RCAT decomposition can represent.
FeatureSet env_feature_set (const std::string &)
 SolverENV.supports's inline set, 28 names, transcribed unchanged.
FeatureSet ldes_feature_set (const std::string &)
 SolverLDES.getFeatureSet, transcribed WHOLE.
bool jmva_is_closed_only (const std::string &method)
 Port of SolverJMT.getFeatureSet (@@SolverJMT/SolverJMT.m:180-290).
FeatureSet jmt_feature_set (const std::string &method)
std::string ba_family_of (const std::string &method)
 SolverBA.getFeatureSet, transcribed name for name.
std::string ba_resolve_method_name (const std::string &method)
 The 'default'/'auto'/'qr'/'lr' aliases, duplicated from ba::resolve_method for the same reason ba_family_of sits here: this header is included BY the solver and cannot include it back.
FeatureSet ba_feature_set (const std::string &method)
FeatureSet qns_feature_set (const std::string &)
 SolverQNS.getFeatureSet, transcribed WHOLE.
template<class T>
Marginal< T > to_marginal (const NetworkStruct< T > &sn, std::size_t ist, const std::vector< T > &state_i, const std::vector< std::size_t > &phasesz, const std::vector< std::size_t > &phaseshift, std::size_t nvar=0)
 Port of State.toMarginal for a STATION, one state row at a time.
template<class T>
std::vector< double > station_populations (const NetworkStruct< T > &sn, const std::vector< std::vector< T > > &local)
 Total jobs held by every STATION at one network state, indexed by station.
template<class T>
Matrix< T > rt_state (const NetworkStruct< T > &sn, const std::vector< std::vector< T > > &local)
 Port of sn.rtfun: the routing over the stateful nodes AT ONE STATE.
template<class T>
std::vector< std::vector< T > > cartesian (const std::vector< std::vector< T > > &a, const std::vector< std::vector< T > > &b)
 Port of State.cartesian: pair every row of a with every row of b.
template<class T>
std::vector< std::vector< T > > space_closed_single (std::size_t m, std::size_t n)
 Port of State.spaceClosedSingle: the ways to place n jobs over m phases.
template<class T>
void space_closed_single_capped_rec (std::size_t m, long n, const std::vector< long > &caps, std::size_t off, std::vector< T > &row, std::vector< std::vector< T > > &out)
 space_closed_single with a PER-SLOT bound, the reference's spaceClosedSingle(M, N, caps).
template<class T>
std::vector< std::vector< T > > space_closed_single_capped (std::size_t m, std::size_t n, const std::vector< long > &caps)
std::vector< std::vector< std::size_t > > pas_multiset_perms (const std::vector< std::size_t > &vec)
 Port of matlab/util/multiset_perms.m on an ASCENDING multiset, ROW ORDER INCLUDED.
template<class T>
std::vector< std::vector< T > > from_marginal_core (const NetworkStruct< T > &sn, std::size_t ist, const std::vector< std::size_t > &n, const std::vector< std::size_t > &phases)
 Port of State.fromMarginal for the station families CTMC enumerates: every local state in which station ist holds exactly n[r] class-r jobs.
template<class T>
std::vector< std::vector< T > > polling_blocks (const PollingInfo< T > &pi, std::size_t srvclass, const std::vector< std::size_t > &nbuf)
 Port of State.pollingBlocks + State.pollingProject: every controller configuration compatible with one (buffer, server) row.
template<class T>
std::vector< std::vector< T > > append_local_vars (const NetworkStruct< T > &sn, std::size_t ist, std::vector< std::vector< T > > rows, const std::vector< std::size_t > &n, const std::vector< std::size_t > &phases)
 Append the trailing local-variable block to every row the core builders produce, which is what makes a state row as wide as nvars_of declares.
template<class T>
std::vector< std::vector< T > > from_marginal (const NetworkStruct< T > &sn, std::size_t ist, const std::vector< std::size_t > &n, const std::vector< std::size_t > &phases)
template<class T>
std::vector< std::vector< T > > from_marginal_and_started_core (const NetworkStruct< T > &sn, std::size_t ist, const std::vector< std::size_t > &n, const std::vector< std::size_t > &s, const std::vector< std::size_t > &phases)
 Port of State.fromMarginalAndStarted: ONE state realizing both a per-class occupancy n and a per-class STARTED count s.
template<class T>
std::vector< std::vector< T > > from_marginal_and_started (const NetworkStruct< T > &sn, std::size_t ist, const std::vector< std::size_t > &n, const std::vector< std::size_t > &s, const std::vector< std::size_t > &phases)
 State.fromMarginalAndStarted with the trailing local-variable block appended, i.e.
template<class T>
std::vector< std::vector< T > > from_marginal_node (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< std::size_t > &n, const std::vector< std::size_t > &phases)
 Port of State.fromMarginal at its OWN signature: the reference indexes by NODE, not by station, and derives the station internally.
template<class T>
std::vector< std::vector< T > > from_marginal_node_and_started (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< std::size_t > &n, const std::vector< std::size_t > &s, const std::vector< std::size_t > &phases)
 Port of State.fromMarginalAndStarted at its OWN signature, which indexes by NODE rather than by station, mirroring from_marginal_node.
template<class T>
std::vector< std::vector< T > > from_marg_node (const NetworkStruct< T > &sn, std::size_t ind, std::size_t ntot, const std::vector< std::size_t > &phases)
 Port of State.fromMarg: the state space with a given TOTAL queue length.
template<class T>
std::vector< std::vector< T > > from_marg_node_started (const NetworkStruct< T > &sn, std::size_t ind, std::size_t ntot, std::size_t stot, const std::vector< std::size_t > &phases)
 Port of State.fromMargAndStarted: the states with a given TOTAL queue length AND a given TOTAL number of started jobs.
template<class T>
bool from_marginal_node_first (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< std::size_t > &n, const std::vector< std::size_t > &phases, std::vector< T > &out)
 The FIRST row from_marginal_node emits, BUILT rather than enumerated.
template<class T>
std::vector< std::vector< T > > space_closed_multi (std::size_t M, const std::vector< std::size_t > &N, const std::vector< std::vector< long > > &caps=std::vector< std::vector< long > >())
 Port of State.spaceClosedMulti: how N[r] class-r jobs distribute over M stateful nodes, for every class, as the cartesian fold of the per-class placements.
template<class T>
std::vector< std::vector< T > > space_closed_multi_cs (std::size_t M, const std::vector< std::size_t > &N, const std::vector< std::vector< bool > > &chains, const std::vector< std::vector< long > > &caps=std::vector< std::vector< long > >())
 Port of State.spaceClosedMultiCS: the same, but a CHAIN's population is shared among its classes, so the split between them is itself enumerated.
template<class T>
std::size_t state_initial_occupancy (const NetworkStruct< T > &sn, std::size_t ind, std::size_t r)
 Port of State.initialOccupancy: the class-r jobs node ind holds in the DECLARED initial state, or 0 when there is none.
template<class T>
std::vector< std::vector< std::size_t > > space_capacity_c (const NetworkStruct< T > &sn, const std::vector< std::size_t > &cutoff, const std::vector< std::vector< std::size_t > > &cutoff_mat=std::vector< std::vector< std::size_t > >())
 Port of the capacityc table of State.spaceGeneratorNodes: the largest class-r marginal node ind may hold in the enumerated space.
template<class T>
std::vector< NetState< T > > space_generator (const NetworkStruct< T > &sn, const std::vector< std::size_t > &cutoff, std::size_t maxst=3000000, const std::vector< std::vector< std::size_t > > &cutoff_mat=std::vector< std::vector< std::size_t > >())
 Port of State.spaceGenerator: every network state, reachable or not.
template<typename T>
void tag_last (EventOutcome< T > &out, std::size_t start_cls, std::size_t preempt_cls)
 Tag the successor row just appended to OUT: START_CLS begins service on it and PREEMPT_CLS is displaced by it, either 0 for none.
template<typename T>
void pad_tags (EventOutcome< T > &out)
 Bring the tag vectors up to one entry per successor, so a caller can index them exactly like space.
template<class T>
std::pair< T, std::vector< T > > to_marginal_aggr (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &state_i)
 Port of State.toMarginalAggr: the job counts of one node's state row, without the per-phase detail to_marginal also computes.
template<class T>
bool is_physical_capacity (const NetworkStruct< T > &sn, std::size_t ist, std::size_t cls)
 Port of State.isPhysicalCapacity: true when the bound at (ist, class) is a PHYSICAL capacity rather than a state-space CUTOFF on an open class.
template<class T>
bool arrival_is_lost (const NetworkStruct< T > &sn, std::size_t ist, std::size_t cls)
 Port of State.arrivalIsLost: true when an arrival that finds no room is LOST, false when it must BLOCK the upstream instead.
template<class T>
RowLayout< T > row_layout (const NetworkStruct< T > &sn, std::size_t ind, std::size_t width)
template<class T>
std::vector< T > entry_phase_dist (const NetworkStruct< T > &sn, std::size_t ist, std::size_t cls)
 The entry-phase distribution pie{ist}{class}: which phase a service STARTS in.
template<class T>
void polling_get (const PollingInfo< T > &pi, const std::vector< T > &var, std::size_t srvclass, std::size_t &pos, std::size_t &swk, long &ctr)
 Defined below; the polling branches of ARV, DEP and SWITCH use these.
template<class T>
std::vector< T > polling_set (const PollingInfo< T > &pi, std::vector< T > var, std::size_t pos, std::size_t swk, long ctr)
 Write (pos, swk, ctr) back into the local-variable block.
template<class T>
void polling_next (const PollingInfo< T > &pi, std::size_t pos, const std::vector< long > &nbuf, std::size_t R, bool arrived, std::size_t &q, int &mode, long &budget)
 Port of State.pollingNext: where the server goes from buffer pos.
template<class T>
void polling_land (const NetworkStruct< T > &sn, std::size_t ist, const PollingInfo< T > &pi, std::size_t q, int mode, long budget, const std::vector< T > &buf, const std::vector< T > &srv, const std::vector< T > &var, const RowLayout< T > &L, std::vector< std::vector< T > > &rows, std::vector< T > &probs)
 Port of State.pollingLand: the states the walk lands in, with weights.
template<class T>
double reply_blocked (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &var)
 Defined below; the reply block subtracts held servers in the ARV branch.
template<class T>
ReplyBlockInfo reply_block_info (const NetworkStruct< T > &sn, std::size_t ind)
 Defined below; the departure branch records a server held for a reply.
template<class T>
EventOutcome< T > after_event_station_pas (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
 Defined below; the ARV and DEP branches divert to it before any slicing.
template<class T>
EventOutcome< T > after_event_station_arv (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
 Port of the ARV branch of State.afterEventStation: an arriving class-cls job joins node ind, whose local state is inspace.
template<class T>
std::pair< std::vector< T >, std::vector< T > > phase_rates (const NetworkStruct< T > &sn, std::size_t ist, std::size_t cls)
 sn.mu and sn.phi for one (station, class), derived as MATLAB's Markovian.getMu / getPhi derive them from the (D0, D1) pair:
template<class T>
lld_factor (const NetworkStruct< T > &sn, std::size_t ist, double n)
 The limited-load-dependent multiplier at population n, 1 when unset.
template<class T>
cd_factor (const NetworkStruct< T > &sn, std::size_t ist, const std::vector< T > &nir, std::size_t cls)
 Port of State.cdclassfactor: the class-dependence multiplier of a class-cls rate at the per-class population nir.
template<class T>
PrioPop< T > prio_pop (const NetworkStruct< T > &sn, std::size_t ist, const Marginal< T > &m, std::size_t cls, double ni, double S)
 Compute the *PRIO effective population; a no-op for every other discipline.
template<class T>
service_share (const NetworkStruct< T > &sn, std::size_t ist, const Marginal< T > &m, std::size_t cls, double ni, double S)
 Defined below; DEP and PHASE must share one definition of the share.
template<class T>
EventOutcome< T > after_event_station_dep (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls, bool no_promote=false)
 Port of the DEP branch of State.afterEventStation: a class-cls job completes service at station ind.
template<class T>
EventOutcome< T > after_event_station_phase (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
 Port of the PHASE branch of State.afterEventStation: service advances a phase WITHOUT completing.
template<class T>
EventOutcome< T > after_event_station_renege (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls, const T &impatience_mu)
 Port of the RENEGE branch: a WAITING class-cls job abandons the queue.
template<class T>
EventOutcome< T > after_event_station_retry (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls, const T &retrial_mu, bool constant_policy=false)
 Port of the RETRY branch: an ORBITING class-cls job retries entry.
template<class T>
EventOutcome< T > after_event_station_breakdown (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, bool up, const T &mu)
 Port of the FAILURE and REPAIR branches: the server goes down, or comes back.
template<class T>
EventOutcome< T > after_event_fork (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
 Port of State.afterEventFork: an event at a STATEFUL Fork node.
template<class T>
EventOutcome< T > after_event_join (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
 Port of State.afterEventJoin: an event at a Join node of an FJ-augmented struct.
template<class T>
void rr_advance_row (const NetworkStruct< T > &sn, std::size_t ind, std::size_t cls, std::vector< std::vector< T > > &rows)
 Port of State.afterEventStation's dispatch: the successors of one event at one station.
template<class T>
EventOutcome< T > after_event_router (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
 Port of State.afterEventRouter: a Router holds a job for the instant it takes to decide where it goes.
template<class T>
EventOutcome< T > after_event_station (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls, bool no_promote=false, const T &aux_rate=num_traits< T >::from_int(0))
template<class T>
EventOutcome< T > after_event_transition (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t mode)
 Port of State.afterEventTransition, the PHASE arm: one running server of the given mode advances its firing phase (cls is interpreted as the MODE, as in the reference).
template<class T>
EventOutcome< T > after_event (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls, bool no_promote=false, const T &aux_rate=num_traits< T >::from_int(0))
 Port of State.afterEvent: the successors of one event at one NODE.
template<class T>
std::pair< std::vector< std::size_t >, std::vector< T > > signal_batch_pmf (const NetworkStruct< T > &sn, std::size_t cls, std::size_t ntot)
 Port of State.signalBatchPMF: the batch size a negative signal removes.
template<class T>
EventOutcome< T > after_event_station_signal (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
 Port of State.afterEventStationSignal: a G-network signal arrives.
template<class T>
std::pair< std::vector< std::size_t >, std::size_t > pass_and_swap (const std::vector< std::size_t > &c, std::size_t p, const std::vector< std::vector< bool > > &G)
 Port of State.passAndSwap: the transition a service completion triggers at a pass-and-swap station (Dorsman and Gardner 2024, Sect.
template<class T, class F>
std::vector< double > pas_increments (const F &mu_fun, const std::vector< std::size_t > &c)
 Port of State.afterEventStationPAS: events at a pass-and-swap station.
template<class T, class F>
void pas_tag_started (EventOutcome< T > &out, const F &mu_fun, const std::vector< std::size_t > &cold, const std::vector< std::size_t > &cnew)
 Tag the successor just appended to OUT with the PAS positions that started service on it: those of CNEW that are served (Delta_mu > 0) and were not served in COLD.
template<class T>
EventOutcome< T > after_event_station_reply (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
 Port of State.afterEventStationReply: a REPLY signal completes a synchronous call at the station holding the server for it.
template<class T>
long polling_budget (const PollingInfo< T > &pi, long nbufq)
 Port of State.pollingBudget: how many services this visit may perform.
template<class T>
EventOutcome< T > after_event_station_switch (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, std::size_t cls)
 Port of the SWITCH branch: a polling server advances its switchover timer.
template<class T>
EventOutcome< T > after_event_cache (const NetworkStruct< T > &sn, std::size_t ind, const std::vector< T > &inspace, EventType event, std::size_t cls)
 Port of State.afterEventCache: events at a Cache node.
template<class T>
std::vector< GlobalSync< T > > refresh_global_sync (const NetworkStruct< T > &sn)
 Port of MNetwork.refreshGlobalSync: the ENABLE and FIRE synchronizations.
template<class T>
GlobalOutcome< T > after_global_event (const NetworkStruct< T > &sn, const NetState< T > &glspace, const GlobalSync< T > &gl)
 Port of State.afterGlobalEvent: an SPN mode ENABLEs or FIREs.
template<class T>
std::vector< Sync< T > > refresh_sync (const NetworkStruct< T > &sn, const std::vector< std::vector< bool > > &impatience_classes=std::vector< std::vector< bool > >(), const std::vector< std::size_t > &breakdown_nodes=std::vector< std::size_t >())
 Port of MNetwork.refreshSync: the synchronization list.
template<class T>
GlobalOutcome< T > after_fj_event (const NetworkStruct< T > &sn, const FjSync< T > &e, const NetState< T > &gl)
 Port of State.afterFJEvent: fire ONE entry of the fork firing list.
template<class T>
TaggedChain< T > tag_chain (const NetworkStruct< T > &sn, std::size_t chain, std::size_t jobclass, const std::string &suffix=".tagged")
 Tag one class of one chain.
const char * routing_to_text (RoutingStrategy r)

Typedef Documentation

◆ CdScaling

template<class T>
using line::lang::CdScaling

A class-dependent scaling map, sn.cdscaling.

It takes the per-class population vector at one station and returns the per-class rate multipliers, which is the signature pfqn_cdfun consumes; the alias resolves to the same std::function type as pfqn::CdScaling, so a map built here is passed straight through to the api layer.

Definition at line 639 of file lang_types.h.

◆ GdScaling

template<class T>
using line::lang::GdScaling

A globally state-dependent scaling, sn.gdscaling.

Unlike CdScaling it is declared on the NETWORK, not on a station: the argument is the FULL population matrix, given row-major as nstations rows of nclasses entries, and the result is either one scalar, one entry per station, or one entry per (station, class) in the same row-major order. This is the Whittle primitive – a rate that reads the whole state – and no per-station scaling can express it when one route holds several resources at once.

Definition at line 652 of file lang_types.h.

Enumeration Type Documentation

◆ DropStrategy

enum class line::lang::DropStrategy
strong

Blocking and loss rules, with the values of MATLAB DropStrategy.

WAITQ is -1 and is also the marker refreshCapacity writes where the rule is never consulted (an unbounded station, or a closed class), so it means two different things depending on the station's capacity; see the comment in refresh_capacity().

Definition at line 424 of file lang_types.h.

◆ EventType

enum class line::lang::EventType
strong

The events a state can undergo, with the values of MATLAB EventType.

An event is ACTIVE at the node that schedules it and PASSIVE at the node that receives it: a DEP at one station is the ARV at the next, and only the active half carries a rate. The passive half is marked with a rate of -1, which the generator assembly replaces with the active rate – a convention that only reads as a sentinel because a rate can never be negative.

Definition at line 111 of file lang_types.h.

◆ Feature

enum class line::qn::Feature : int
strong

One language feature.

COUNT is the registry size and is not a feature.

Enumerator
COUNT 

Definition at line 289 of file feature_set.h.

◆ JobClassType

enum class line::lang::JobClassType
strong

Job class kinds, with the values of MATLAB JobClassType.

Definition at line 367 of file lang_types.h.

◆ NodeType

enum class line::lang::NodeType
strong

Node kinds, with the values of MATLAB NodeType.

Definition at line 324 of file lang_types.h.

◆ ProcessType [1/2]

enum class line::lang::ProcessType
strong

Distribution kinds, with the values of MATLAB ProcessType.

Definition at line 483 of file lang_types.h.

◆ ProcessType [2/2]

enum class line::lang::ProcessType
strong

Distribution kinds, with the values of MATLAB ProcessType.

Definition at line 483 of file lang_types.h.

◆ ReplacementStrategy

Cache replacement policies, with the values of MATLAB ReplacementStrategy.

Definition at line 378 of file lang_types.h.

◆ RoutingStrategy

enum class line::lang::RoutingStrategy
strong

Routing strategies, with the values of MATLAB RoutingStrategy.

Definition at line 389 of file lang_types.h.

◆ SchedStrategy [1/2]

enum class line::lang::SchedStrategy
strong

Scheduling disciplines, with the values of MATLAB SchedStrategy.

Definition at line 181 of file lang_types.h.

◆ SchedStrategy [2/2]

enum class line::lang::SchedStrategy
strong

Scheduling disciplines, with the values of MATLAB SchedStrategy.

Definition at line 181 of file lang_types.h.

Function Documentation

◆ after_event()

template<class T>
EventOutcome< T > line::qn::after_event ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
EventType event,
std::size_t cls,
bool no_promote = false,
const T & aux_rate = num_traits<T>::from_int(0) )

Port of State.afterEvent: the successors of one event at one NODE.

The reference's body is mostly slicing – it cuts inspace into buffer, server and local-variable blocks and hands the pieces to the per-node-type handler. This port slices inside each handler instead (row_layout), so what remains here is the dispatch itself and the guards that precede it.

A class the station does not accept short-circuits: phases_of is zero there, and every downstream index into the server block would be out of range. That guard is the reference's K(class) == 0 test.

cls IS A MODE, NOT A CLASS, on a Transition's PHASE action; see the guard.

Definition at line 1948 of file state_events.h.

References after_event(), after_event_cache(), after_event_fork(), after_event_join(), after_event_router(), after_event_station(), after_event_transition(), line::InputError::InputError(), line::qn::NodeDef::name, line::qn::NodeDef::nodetype, line::qn::NodeDef::stateful, line::qn::NodeDef::station, and line::UnsupportedError::UnsupportedError().

Referenced by after_event(), line::ssa::SsaEventCache< T >::after_event(), after_fj_event(), line::ctmc::reachable_space_generator(), line::ctmc::solver_ctmc(), and line::ssa::ssa_find_enabled().

◆ after_event_cache()

template<class T>
EventOutcome< T > line::qn::after_event_cache ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
EventType event,
std::size_t cls )

Port of State.afterEventCache: events at a Cache node.

A Cache is stateful but is NOT a station, so its row is [per-class counts | cache contents | retrieval bitmap] with no buffer or server block. The contents region holds one column per cached slot, laid out list by list; cpos(i,j) is position j of list i.

A READ is INSTANTANEOUS: every branch fires at GlobalConstants::Immediate, because the read is a routing decision rather than a service. The job enters in its read class and leaves in the hit or miss class, so the transition both moves the job between classes and rewrites the cache contents.

Definition at line 2855 of file state_events.h.

References line::qn::CacheParam< T >::accost, after_event_cache(), cache_retrieval_class_map(), line::Matrix< T >::cols(), line::lang::FIFO, line::qn::CacheParam< T >::hitclass, line::qn::GlobalConstants::Immediate, line::InputError::InputError(), line::qn::CacheParam< T >::itemcap, line::Matrix< T >::Matrix(), line::qn::CacheParam< T >::max_pending_retrieval, line::qn::CacheParam< T >::missclass, line::qn::CacheParam< T >::nitems, line::qn::CacheParam< T >::pread, line::qn::EventOutcome< T >::prob, line::lang::QLRU, line::qn::CacheParam< T >::qlru, line::qn::EventOutcome< T >::rate, line::qn::CacheParam< T >::replacestrat, line::qn::CacheParam< T >::retrieval_capacity, line::qn::CacheParam< T >::retrieval_classes, line::Matrix< T >::rows(), line::lang::RR, line::lang::SFIFO, and line::qn::EventOutcome< T >::space.

Referenced by after_event(), and after_event_cache().

◆ after_event_fork()

template<class T>
EventOutcome< T > line::qn::after_event_fork ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
EventType event,
std::size_t cls )

Port of State.afterEventFork: an event at a STATEFUL Fork node.

The fork's state is a plain per-class count of PARENT jobs momentarily held between their arrival and the firing. An arrival buffers one; a DEPARTURE DOES NOT EXIST, because the multi-branch emission is atomic across several nodes and cannot be decomposed into a departure here plus an arrival there – refresh_sync emits no DEP sync for a Fork and after_fj_event fires instead.

The arrival rate is left UNSET (the reference writes -1) because an ARV is the PASSIVE half of a synchronization: the rate belongs to the active departure upstream.

Definition at line 1602 of file state_events.h.

References after_event_fork(), line::InputError::InputError(), line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, and line::qn::EventOutcome< T >::space.

Referenced by after_event(), and after_event_fork().

◆ after_event_join()

template<class T>
EventOutcome< T > line::qn::after_event_join ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
EventType event,
std::size_t cls )

Port of State.afterEventJoin: an event at a Join node of an FJ-augmented struct.

The join's state is a plain per-class count vector of BUFFERED jobs, so it bypasses the buffer/server/local slicing every other station takes – a join performs no service, it performs a rendezvous.

ARV buffers the arriving job or sibling. DEP in an ORIGINAL class r fires when either a plain (never-forked) class-r job is buffered, or some tag has its full required sibling multiset present; the firing consumes the siblings of the LOWEST complete tag, which is the same canonical choice the fork's allocation makes and is what keeps the two in step. DEP in an AUXILIARY class is refused outright: a sibling never departs on its own, it is consumed by the parent's firing, and letting it depart would release a job the fork never emitted.

Definition at line 1638 of file state_events.h.

References after_event_join(), line::qn::FjJoinParam::auxmatrix, line::lang::GlobalConstants::Immediate, line::InputError::InputError(), line::qn::FjJoinParam::origclasses, line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, line::qn::FjJoinParam::required, and line::qn::EventOutcome< T >::space.

Referenced by after_event(), after_event_join(), and line::ctmc::ctmc_find_vanishing_states().

◆ after_event_router()

template<class T>
EventOutcome< T > line::qn::after_event_router ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
EventType event,
std::size_t cls )

Port of State.afterEventRouter: a Router holds a job for the instant it takes to decide where it goes.

The row is [per-class counts | local vars], with no buffer and no phase: a Router serves nothing, so there is no service state to carry. An ARRIVAL adds the job at an UNSPECIFIED rate (-1), which is the reference's marker for a passive half whose rate the active half sets; a DEPARTURE removes it at the Immediate rate and advances the dispatch pointer, so the router never holds a job for a positive length of time.

Definition at line 1742 of file state_events.h.

References after_event_router(), line::lang::GlobalConstants::Immediate, line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, rr_advance_row(), and line::qn::EventOutcome< T >::space.

Referenced by after_event(), and after_event_router().

◆ after_event_station()

◆ after_event_station_arv()

template<class T>
EventOutcome< T > line::qn::after_event_station_arv ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
std::size_t cls )

Port of the ARV branch of State.afterEventStation: an arriving class-cls job joins node ind, whose local state is inspace.

The event is PASSIVE – the upstream departure sets the rate – so every row returned carries the -1 sentinel. It is nevertheless the branch with the most successors, because the entering job chooses its service phase, and under the preemptive disciplines it also chooses which job to displace.

ONE ROW IN, MANY ROWS OUT. The reference threads a whole matrix of input rows through this handler and partitions them with logical masks (idle_srv, all_busy_srv). Every caller in the CTMC and SSA paths passes a single row, so those masks degenerate to a branch, which is what this port writes. The successor set is identical.

Definition at line 414 of file state_events.h.

References after_event_station_arv(), after_event_station_pas(), arrival_is_lost(), line::qn::RowLayout< T >::bufw, entry_phase_dist(), line::InputError::InputError(), is_physical_capacity(), line::qn::RowLayout< T >::K, line::qn::RowLayout< T >::Ks, pad_tags(), polling_get(), polling_info(), polling_next(), polling_set(), line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, reply_blocked(), row_layout(), line::lang::sched_to_text(), line::qn::EventOutcome< T >::space, line::qn::RowLayout< T >::srvw, tag_last(), to_marginal_aggr(), and line::UnsupportedError::UnsupportedError().

Referenced by after_event_station(), and after_event_station_arv().

◆ after_event_station_breakdown()

template<class T>
EventOutcome< T > line::qn::after_event_station_breakdown ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
bool up,
const T & mu )

Port of the FAILURE and REPAIR branches: the server goes down, or comes back.

Only the STATUS column moves, which is the trailing local variable. Jobs in service are NOT lost: service is memoryless here, so an interrupted job resumes on repair with no state to remember. The passive half of the synchronization is LOCAL, so no job moves anywhere in the network either.

Parameters
uptrue for REPAIR (0 -> 1), false for FAILURE (1 -> 0)
mubreakdownMu for a failure, repairMu for a repair
snthe refreshed network struct
indindex of the station the event fires at
inspacethe state the event is applied to

Definition at line 1569 of file state_events.h.

References after_event_station_breakdown(), line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, and line::qn::EventOutcome< T >::space.

Referenced by after_event_station(), and after_event_station_breakdown().

◆ after_event_station_dep()

template<class T>
EventOutcome< T > line::qn::after_event_station_dep ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
std::size_t cls,
bool no_promote = false )

Port of the DEP branch of State.afterEventStation: a class-cls job completes service at station ind.

This is the ACTIVE half, so unlike ARV it carries real rates, and the rate is where the disciplines actually differ – the state update is nearly the same for all of them. Two rate conventions appear, and they are not interchangeable:

mu(k)*phi(k)*kir – the processor-sharing family, where the completion rate is the phase rate times the share of the server D1(k,kdest)*kir – the FCFS family, where the MAP matrix already encodes both the completion and the phase the NEXT service starts in, so the destination phase is enumerated

Definition at line 904 of file state_events.h.

References after_event_station_dep(), after_event_station_pas(), line::qn::RowLayout< T >::bufw, cd_factor(), line::lang::Distrib< T >::D1, line::lang::DECREMENTING, entry_phase_dist(), line::lang::EXHAUSTIVE, line::lang::GATED, line::InputError::InputError(), line::qn::RowLayout< T >::K, line::qn::Marginal< T >::kir, line::lang::KLIMITED, line::qn::RowLayout< T >::Ks, lld_factor(), line::qn::PrioPop< T >::masked, line::qn::PrioPop< T >::ni, line::qn::Marginal< T >::nir, line::qn::PrioPop< T >::nir, line::qn::RowLayout< T >::nvar, pad_tags(), phase_rates(), polling_get(), polling_info(), polling_land(), polling_next(), prio_pop(), line::qn::EventOutcome< T >::prob, line::qn::PollingInfo< T >::ptype, line::qn::EventOutcome< T >::rate, reply_block_info(), reply_blocked(), row_layout(), line::lang::sched_to_text(), service_share(), line::qn::Marginal< T >::sir, line::qn::ReplyBlockInfo::slot, line::qn::EventOutcome< T >::space, line::qn::RowLayout< T >::srvw, tag_last(), to_marginal(), and line::UnsupportedError::UnsupportedError().

Referenced by after_event_station(), and after_event_station_dep().

◆ after_event_station_pas()

template<class T>
EventOutcome< T > line::qn::after_event_station_pas ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
EventType event,
std::size_t cls )

◆ after_event_station_phase()

template<class T>
EventOutcome< T > line::qn::after_event_station_phase ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
std::size_t cls )

Port of the PHASE branch of State.afterEventStation: service advances a phase WITHOUT completing.

The rate is D0(k, kdest), the off-diagonal of the hidden generator, times the same server share a completion gets. Keeping PHASE and DEP on one share is what makes a phase-type service slow down consistently under contention; a phase advance at full speed under PS would shorten the effective service.

Definition at line 1397 of file state_events.h.

References after_event_station_phase(), line::qn::RowLayout< T >::bufw, cd_factor(), line::lang::Distrib< T >::D0, line::InputError::InputError(), line::qn::RowLayout< T >::K, line::qn::Marginal< T >::kir, line::qn::RowLayout< T >::Ks, lld_factor(), line::qn::Marginal< T >::nir, line::qn::RowLayout< T >::nvar, line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, row_layout(), service_share(), line::qn::EventOutcome< T >::space, and to_marginal().

Referenced by after_event_station(), and after_event_station_phase().

◆ after_event_station_renege()

template<class T>
EventOutcome< T > line::qn::after_event_station_renege ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
std::size_t cls,
const T & impatience_mu )

Port of the RENEGE branch: a WAITING class-cls job abandons the queue.

Patience is exponential, so every waiting job abandons at the same rate and the aggregate out of this state is (waiting count) * mu. Which job leaves is therefore immaterial – waiting jobs are exchangeable under memoryless patience – so the reference removes the first tagged slot and re-pads a zero on the left, keeping the buffer in the right-aligned form the arrival handler expects.

Definition at line 1452 of file state_events.h.

References after_event_station_renege(), line::qn::RowLayout< T >::bufw, line::InputError::InputError(), line::qn::RowLayout< T >::K, line::qn::RowLayout< T >::Ks, line::qn::Marginal< T >::nir, line::qn::RowLayout< T >::nvar, line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, row_layout(), line::qn::Marginal< T >::sir, line::qn::EventOutcome< T >::space, and to_marginal().

Referenced by after_event_station(), and after_event_station_renege().

◆ after_event_station_reply()

template<class T>
EventOutcome< T > line::qn::after_event_station_reply ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
std::size_t cls )

Port of State.afterEventStationReply: a REPLY signal completes a synchronous call at the station holding the server for it.

A REPLY is not a negative customer. It releases one held server and then JOINS as an ordinary job carrying the call result onward, so unlike NEGATIVE or CATASTROPHE it is not annihilated.

PASS-THROUGH is the subtle part: the released server is taken by the reply ITSELF, never by a waiting job. The reply is work this station already paid for, so queueing it behind the residents both misreports its residence and steals capacity. Its service is typically Immediate, so the server is handed straight back and the ordinary departure path then promotes the head of line – which also keeps the occupancy within the server count, unlike admitting the reply on top of a promoted job.

Definition at line 2560 of file state_events.h.

References after_event_station_reply(), line::qn::RowLayout< T >::bufw, line::qn::ReplyBlockInfo::classes, entry_phase_dist(), line::InputError::InputError(), line::qn::RowLayout< T >::K, line::qn::RowLayout< T >::Ks, line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, reply_block_info(), reply_blocked(), row_layout(), line::qn::ReplyBlockInfo::slot, line::qn::EventOutcome< T >::space, and line::qn::RowLayout< T >::srvw.

Referenced by after_event_station(), and after_event_station_reply().

◆ after_event_station_retry()

template<class T>
EventOutcome< T > line::qn::after_event_station_retry ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
std::size_t cls,
const T & retrial_mu,
bool constant_policy = false )

Port of the RETRY branch: an ORBITING class-cls job retries entry.

The retry succeeds only when a server is free; otherwise the job stays in orbit and the event is not generated at all, which is exactly what distinguishes a retrial queue from a queue whose buffer is called an orbit.

Parameters
constant_policyCONSTANT retrial: one controller retries for the whole orbit, so the rate does NOT scale with the orbit size. Under the default LINEAR policy every orbiting job carries its own timer and the aggregate rate is (orbit size) * mu.
snthe refreshed network struct
indindex of the station the event fires at
inspacethe state the event is applied to
clsclass of the retrying job
retrial_muretrial rate of that class

Definition at line 1504 of file state_events.h.

References after_event_station_retry(), line::qn::RowLayout< T >::bufw, entry_phase_dist(), line::InputError::InputError(), line::qn::RowLayout< T >::K, line::qn::RowLayout< T >::Ks, line::qn::Marginal< T >::nir, line::qn::RowLayout< T >::nvar, pad_tags(), line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, row_layout(), line::qn::Marginal< T >::sir, line::qn::EventOutcome< T >::space, line::qn::RowLayout< T >::srvw, tag_last(), and to_marginal().

Referenced by after_event_station(), and after_event_station_retry().

◆ after_event_station_signal()

template<class T>
EventOutcome< T > line::qn::after_event_station_signal ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
std::size_t cls )

Port of State.afterEventStationSignal: a G-network signal arrives.

A signal NEVER joins the station. It removes jobs already there and is annihilated, so the event is passive throughout and the successors differ only in which victims were taken.

Victim selection has two tiers, and conflating them is the trap: FCFS and LCFS rank by AGE, which only an ordered buffer records, so at a per-class count buffer an age policy degenerates to a uniform draw. They also drain the waiting line completely before touching a server, whereas RANDOM draws uniformly across waiting and in-service jobs alike.

Definition at line 2075 of file state_events.h.

References after_event_station_signal(), line::qn::RowLayout< T >::bufw, line::lang::CATASTROPHE, line::lang::FCFS, line::InputError::InputError(), line::qn::RowLayout< T >::K, line::qn::RowLayout< T >::Ks, line::lang::LCFS, line::qn::Marginal< T >::nir, line::qn::RowLayout< T >::nvar, line::qn::EventOutcome< T >::prob, line::lang::RANDOM, line::qn::EventOutcome< T >::rate, row_layout(), signal_batch_pmf(), line::qn::EventOutcome< T >::space, line::qn::RowLayout< T >::srvw, and to_marginal().

Referenced by after_event_station(), and after_event_station_signal().

◆ after_event_station_switch()

template<class T>
EventOutcome< T > line::qn::after_event_station_switch ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
std::size_t cls )

Port of the SWITCH branch: a polling server advances its switchover timer.

Unlike PHASE, which carries only the internal transitions of a phase-type and leaves the absorption to DEP, this event carries BOTH – a completed switchover moves no job, so there is no departure to attach the absorption to. It is therefore emitted even for a single-phase switchover, where it consists of the absorption alone.

Definition at line 2771 of file state_events.h.

References after_event_station_switch(), line::qn::RowLayout< T >::bufw, line::qn::PollingInfo< T >::has_sw, line::InputError::InputError(), line::qn::PollingInfo< T >::ksw, pad_tags(), polling_get(), polling_info(), polling_land(), polling_next(), polling_set(), line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, row_layout(), line::qn::EventOutcome< T >::space, line::qn::RowLayout< T >::srvw, line::qn::PollingInfo< T >::sw_d0, line::qn::PollingInfo< T >::sw_d1, tag_last(), and line::qn::PollingInfo< T >::valid.

Referenced by after_event_station(), and after_event_station_switch().

◆ after_event_transition()

template<class T>
EventOutcome< T > line::qn::after_event_transition ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & inspace,
EventType event,
std::size_t mode )

Port of State.afterEventTransition, the PHASE arm: one running server of the given mode advances its firing phase (cls is interpreted as the MODE, as in the reference).

ENABLE and FIRE are global events handled by after_global_event, so they return an empty outcome here, matching the reference's no-op arms.

RATE. The MATLAB body multiplies the phase-k move rate by BOTH kir(:,mode,k) and nir(mode) (afterEventTransition.m:38-40), but nir is the sum of kir over the phases, so the extra factor counts the running servers twice; the JAR and the native python carry D0(k,kdest) * kir alone, and this port follows them.

The row layout is the one after_global_event slices: [buf(nmodes) | srv(sum fK) | fired(nmodes) | var].

Definition at line 1888 of file state_events.h.

References after_event_transition(), line::qn::TransitionParam< T >::firingphases, line::qn::TransitionParam< T >::firingproc, line::InputError::InputError(), line::qn::TransitionParam< T >::nmodes, line::qn::EventOutcome< T >::prob, line::qn::EventOutcome< T >::rate, and line::qn::EventOutcome< T >::space.

Referenced by after_event(), and after_event_transition().

◆ after_fj_event()

template<class T>
GlobalOutcome< T > line::qn::after_fj_event ( const NetworkStruct< T > & sn,
const FjSync< T > & e,
const NetState< T > & gl )

Port of State.afterFJEvent: fire ONE entry of the fork firing list.

A fork firing is atomic across several nodes – it consumes the parent at the fork and places one sibling at each branch head in the same instant – so unlike every ordinary transition it cannot be decomposed into an active half and a passive half. It therefore takes the whole network state, exactly as an SPN global synchronization does.

THE TWO ENABLING CONDITIONS.

  1. The fork holds at least one class-r parent.
  2. This entry's tag is the LOWEST FREE tag for this (fork, class). A tag is free when its auxiliary classes have zero occupancy NETWORK-WIDE, which is why the test scans every stateful node and not just the branches: a sibling in transit is still outstanding. Without the canonical choice every firing would produce one successor per free tag, all of them relabellings of each other, and the chain would carry a factorial number of duplicate states.

The emission is applied SEQUENTIALLY over a growing outcome list rather than branch-by-branch into one state, because that is what handles the three cases a single pass would get wrong: two branches sharing a head node, weight > 1 repeated emissions on one branch, and a non-exponential sibling service whose phase-entry mixture makes one arrival into several outcomes.

Definition at line 3857 of file state_events.h.

References after_event(), after_fj_event(), line::qn::FjSync< T >::auxall, line::qn::FjSync< T >::auxclasses, line::qn::FjSync< T >::branchheads, line::qn::FjSync< T >::cls, line::qn::GlobalOutcome< T >::completion, line::qn::FjSync< T >::fork, line::lang::GlobalConstants::Immediate, line::qn::NetState< T >::local, line::qn::EventOutcome< T >::prob, line::qn::FjSync< T >::prob, line::qn::GlobalOutcome< T >::prob, line::qn::GlobalOutcome< T >::rate, line::qn::EventOutcome< T >::space, line::qn::GlobalOutcome< T >::space, line::qn::FjSync< T >::tag, to_marginal_aggr(), line::qn::FjSync< T >::weight, and line::qn::FjSync< T >::weightlink.

Referenced by after_fj_event(), line::ctmc::reachable_space_generator(), and line::ctmc::solver_ctmc().

◆ after_global_event()

template<class T>
GlobalOutcome< T > line::qn::after_global_event ( const NetworkStruct< T > & sn,
const NetState< T > & glspace,
const GlobalSync< T > & gl )

Port of State.afterGlobalEvent: an SPN mode ENABLEs or FIREs.

This is the one handler that rewrites SEVERAL nodes at once, because a firing is atomic across all its arcs. The Transition's own row records how many servers of each mode are idle, running (and in which firing phase), and have just fired; the places are rewritten through the PRE and POST passives.

Definition at line 3309 of file state_events.h.

References line::qn::GlobalSync< T >::active, after_global_event(), line::qn::ModeEvent< T >::cls, line::Matrix< T >::cols(), line::qn::GlobalOutcome< T >::completion, line::mam::Map< T >::D0, line::mam::Map< T >::D1, line::qn::TransitionParam< T >::enabling, line::qn::ModeEvent< T >::event, line::qn::TransitionParam< T >::fireweight, line::qn::TransitionParam< T >::firingdep, line::qn::TransitionParam< T >::firingphases, line::qn::TransitionParam< T >::firingproc, line::lang::IMMEDIATE, line::qn::GlobalConstants::Immediate, line::qn::TransitionParam< T >::inhibiting, line::InputError::InputError(), line::qn::NetState< T >::local, line::mam::map_pie(), line::qn::GlobalConstants::MaxInt, line::qn::TransitionParam< T >::nmodes, line::qn::TransitionParam< T >::nmodeservers, line::qn::ModeEvent< T >::node, line::qn::GlobalSync< T >::passive, line::qn::GlobalOutcome< T >::prob, line::qn::GlobalOutcome< T >::rate, line::Matrix< T >::rows(), line::qn::GlobalOutcome< T >::space, line::qn::TransitionParam< T >::timing, to_marginal_aggr(), and line::qn::ModeEvent< T >::weight.

Referenced by after_global_event(), line::ctmc::ctmc_find_vanishing_states(), line::ctmc::reachable_space_generator(), line::ctmc::solver_ctmc(), and line::ssa::ssa_find_enabled().

◆ ag_feature_set()

FeatureSet line::qn::ag_feature_set ( const std::string & )
inline

SolverAG.getFeatureSet: what the RCAT decomposition can represent.

THE G-NETWORK NAMES LIVE HERE AND NOWHERE ELSE. solver_ag.h's build_rcat is the only code in LINE that reads issignal, so declaring the signal features on any other solver would promise what that solver cannot deliver – it would answer with every signal turned into an ordinary customer.

Every AG method is the same decomposition, differing only in how the reversed rate is read off an agent, so the envelope does not vary by method; the genuine restrictions (Markovian service law, single server) are structural and are applied in ag::runner_detail::check_model_method.

Definition at line 1227 of file solver_feature_sets.h.

References ag_feature_set(), and line::qn::FeatureSet::set().

Referenced by ag_feature_set(), and line::ag::solver_ag_solve().

◆ append_local_vars()

template<class T>
std::vector< std::vector< T > > line::qn::append_local_vars ( const NetworkStruct< T > & sn,
std::size_t ist,
std::vector< std::vector< T > > rows,
const std::vector< std::size_t > & n,
const std::vector< std::size_t > & phases )

Append the trailing local-variable block to every row the core builders produce, which is what makes a state row as wide as nvars_of declares.

Shared by from_marginal and from_marginal_and_started: the two differ in how the (buffer, server) split is chosen, never in what follows it, so the controller, the BAS marker and the reply counters are appended once here.

WITHOUT THIS THE ROWS ARE ONE BLOCK TOO NARROW and every slicer that takes nvar clear of the right-hand end reads the server block from the wrong offset. Measured on a two-class EXHAUSTIVE polling station: the controller was absent from the enumerated space entirely and the station behaved as a capacity-one queue, reporting Tput 0.16/0.24 against MATLAB's 0.20/0.30.

The polling controller is enumerated per row (polling_blocks), and so is the ROUND-ROBIN POINTER: which link the next job takes is a coordinate of the state, so a space that emitted it at zero would carry one configuration of a dispatcher that has several, and the chain could never leave it. RROBIN enumerates its outlinks and WRROBIN the positions of its weighted cycle, exactly as State.fromMarginal's sub_routevars does.

The modulating phase and the REPLY blocked-server counters are still emitted at zero: exact for a model that declares none of them, and width-correct rather than enumerated for one that does; see 14-cpp-multiprecision.md.

Definition at line 1022 of file state.h.

References append_local_vars(), line::qn::PollingInfo< T >::off, polling_blocks(), polling_info(), line::qn::PollingInfo< T >::valid, and line::qn::PollingInfo< T >::width.

Referenced by append_local_vars(), and from_marginal_and_started().

◆ arrival_is_lost()

template<class T>
bool line::qn::arrival_is_lost ( const NetworkStruct< T > & sn,
std::size_t ist,
std::size_t cls )

Port of State.arrivalIsLost: true when an arrival that finds no room is LOST, false when it must BLOCK the upstream instead.

Every refusal path branches on this, and the two outcomes are encoded differently:

LOST -> leave the state UNCHANGED, a self-loop. The event still fires, so the OFFERED job reaches the arrival-rate statistic and the loss appears as ArvR - Tput. A self-loop cancels on the generator diagonal, so it cannot move the stationary law. BLOCKED -> return NO rows. That disables the upstream departure until room frees, which is what the become-blocked edge tests for.

The rule is the CLASS TYPE, not the drop rule: a closed network's population is a defining invariant, so a closed job can never be dropped. An explicit BAS/BBS/RSRD rule asks for blocking for any class.

Definition at line 268 of file state_events.h.

References arrival_is_lost().

Referenced by after_event_station_arv(), and arrival_is_lost().

◆ ba_family_of()

std::string line::qn::ba_family_of ( const std::string & method)
inline

SolverBA.getFeatureSet, transcribed name for name.

WHAT MAKES A DISTRIBUTION ADMISSIBLE HERE IS ITS MEAN, which is why the list of laws is longer than any product-form solver's and shorter than a simulator's. solver_ba_analyzer reads sn.rates and sn.visits and nothing else: every bound in the ABA/BJB/PB/GB/SB/Harel/MWBA families is a function of the demands D = V./rates and the think time, so any renewal law with a finite mean is admissible whatever its higher moments. solver_ba_qrf_analyzer is the one that needs more, and what it needs is the {D0,D1} pair, which the phase-type laws below carry; it refuses the rest through sn_to_qrf_blocking's own message rather than through this set.

THE MODULATED PROCESSES (MAP, MMPP2, MMAP, BMAP) ARE DELIBERATELY OUT. Their mean rate exists, so the utilization law still holds, but the bounds are derived for a product-form network in which the correlation between successive services does not exist: bounding such a model would report a bracket for a DIFFERENT system rather than refuse it. The same reasoning keeps Cache, Fork/Join and the Petri-net constructs out, none of which the analyzer represents at all.

THE STRUCTURAL NARROWING IS NOT HERE. ba::list_valid_methods(L) already drops the reduction bounds off a model that is not a single-class closed network of single servers, and the three open-network families off a closed one; a flat feature set cannot express either, and duplicating the shape test here is how the two drift apart.

THE ONE ADDITION TO THE MATLAB LIST IS THE SUB-NODE SECTIONS, and it is not a widening. MNetwork.getUsedLangFeatures emits no Buffer, Dispatcher, Server, InfiniteServer, SharedServer, JobSink, RandomSource or ServiceTunnel – its node loop marks the distribution, the discipline and the routing and stops – while used_lang_features here marks all of them for every Queue, Delay, Source and Sink. Transcribing the MATLAB list literally therefore refused EVERY model, an ordinary closed exponential network included, on Buffer; env_feature_set and ag_feature_set carry the same eight names for the same reason. The JAR has MATLAB's list and a JAR-side emitter that behaves like this one, which is why SolverAUTO.listValidMethods there offers no 'ba.*' method name on a model whose bounds SolverBA computes: the same defect, unfixed. The family prefix of a bound method name: everything before the first dot.

Local to this header so ba_feature_set can apply its per-method deltas without reaching into line/solvers/ba, which includes this file.

Definition at line 1620 of file solver_feature_sets.h.

References ba_family_of().

Referenced by ba_family_of(), ba_feature_set(), and line::ba::method_refusal().

◆ ba_feature_set()

FeatureSet line::qn::ba_feature_set ( const std::string & method)
inline

◆ ba_resolve_method_name()

std::string line::qn::ba_resolve_method_name ( const std::string & method)
inline

The 'default'/'auto'/'qr'/'lr' aliases, duplicated from ba::resolve_method for the same reason ba_family_of sits here: this header is included BY the solver and cannot include it back.

The two are one line apiece and are asserted equal in cpp/tests/test_gate_ba.cpp.

Definition at line 1631 of file solver_feature_sets.h.

References ba_resolve_method_name().

Referenced by ba_feature_set(), ba_resolve_method_name(), line::ba::method_degenerate(), and line::ba::method_refusal().

◆ binding_capacity_reason()

template<class T>
std::string line::qn::binding_capacity_reason ( const std::string & solver,
const NetworkStruct< T > & sn )

The refusal check_binding_capacity raises, as a string, or empty when no buffer binds.

Split out so that a caller which must DECIDE on the same rule – fluid_resolve_method, which sends a blocked model to the one method that carries the constraint – asks the gate's own question rather than a second copy of it that could drift from it.

Definition at line 1047 of file feature_set.h.

References binding_capacity_reason(), line::qn::Station< T >::cap, capacity_fallback_advice(), capacity_str(), line::qn::Station< T >::classcap, line::qn::Station< T >::name, line::qn::NodeDef::nodetype, line::qn::Station< T >::nodetype, and line::qn::JobClass::population.

Referenced by binding_capacity_reason(), check_binding_capacity(), and has_binding_capacity().

◆ cache_retrieval_class_map()

template<class T>
void line::qn::cache_retrieval_class_map ( const CacheParam< T > & cp,
std::vector< std::size_t > & rc_list,
std::vector< std::size_t > & rc_items,
std::vector< std::size_t > & rc_orig )

Port of State.cacheRetrievalClassMap: the canonical order of a cache's retrieval classes, which is the column order of block B.

Block B keys the merged requests by RETRIEVAL CLASS rather than by item so that the originating class, hence its hit class, is recoverable when the fetch completes and the merged requests are released as delayed hits.

Definition at line 554 of file network_struct.h.

References cache_retrieval_class_map(), and line::qn::CacheParam< T >::retrieval_classes.

Referenced by after_event_cache(), cache_retrieval_class_map(), from_marginal_node(), from_marginal_node_first(), and line::qn::NetworkStruct< T >::refresh_local_vars().

◆ capacity_fallback_advice()

std::string line::qn::capacity_fallback_advice ( bool is_open_class)
inline

NetworkSolver.checkBindingCapacity (NetworkSolver.m:1172-1228): the shared structural gate for finite station capacity (setCapacity) and finite per-class buffers (classCap), used by the product-form solvers.

There is no LINE_QN_FEATURE_LIST enumerator for plain capacity – it is a NUMBER on a station, not a construct – so feature_gate above cannot see it, and a product-form solver has no representation of a finite buffer. Without this check the solve returns the UNCONSTRAINED answer (QLen=4 where the M/M/1/2 value is 0.8525), which is a wrong number rather than a refusal.

The test reads the STATION-level cap/classcap the user set, never the derived sn.cap/sn.classcap: refresh_capacity gives every closed model a finite derived classcap (the chain population), so an sn-level test would reject every closed model.

Only a capacity that can actually BIND is refused. A closed model whose station capacity is at least the total population can never block a job, so the declaration is a no-op and the product-form answer stays exact – a common idiom is setCapacity(N) on a station of an N-job closed model. The population is infinite for an open class, so any finite capacity an open class reaches binds.

Cache models are exempt: a Cache sets classcap=1 on the retrieval queues it builds, and MVA/NC solve those through their cache analyzers rather than as a buffer constraint. Which solvers to point at when a finite capacity is refused.

The two lists differ, and naming the wrong one sends the user to a solver that also refuses. An OPEN refused arrival is LOST, which SolverJMT reproduces (its queue section carries the drop rule directly). A CLOSED one BLOCKS: LINE disables the upstream departure and holds the job where it is, and no JMT drop strategy expresses that – 'waiting queue' does not enforce the size at all and 'BAS blocking' completes the service before blocking, a different queueing model. The JMT writer refuses the closed case by name (assert_station_cap_exportable in jmt_writer.h, BUG-81), so it must not be advertised here for it.

Definition at line 1034 of file feature_set.h.

References capacity_fallback_advice().

Referenced by binding_capacity_reason(), and capacity_fallback_advice().

◆ capacity_str()

std::string line::qn::capacity_str ( double v)
inline

g for a capacity, so the message reads 2 and not 2.000000.

Definition at line 988 of file feature_set.h.

References capacity_str().

Referenced by binding_capacity_reason(), and capacity_str().

◆ cartesian()

template<class T>
std::vector< std::vector< T > > line::qn::cartesian ( const std::vector< std::vector< T > > & a,
const std::vector< std::vector< T > > & b )

Port of State.cartesian: pair every row of a with every row of b.

An empty a is the identity, as in the reference, so a fold over classes can start from nothing. Row order is a's outer, b's inner – the same order fromMarginal relies on when it appends the server block after the buffer.

Definition at line 415 of file state.h.

References cartesian().

Referenced by cartesian(), from_marginal_and_started_core(), from_marginal_core(), from_marginal_node(), and space_closed_multi().

◆ cd_factor()

template<class T>
T line::qn::cd_factor ( const NetworkStruct< T > & sn,
std::size_t ist,
const std::vector< T > & nir,
std::size_t cls )

Port of State.cdclassfactor: the class-dependence multiplier of a class-cls rate at the per-class population nir.

cdscaling maps a 1 x R population vector to the R dimensionless scalings beta_r(n); the component of the class whose service is firing is the factor. A handle returning a SCALAR is the neutral case and yields 1 for every class, which is why the read is clamped to the vector's last entry rather than indexed blindly – the reference's v(min(class, numel(v))).

jdscaling is folded in multiplicatively here, exactly as State.afterEventInit folds eta_i into the effective per-station handle. Doing it at the point of use rather than by rewriting the struct keeps the two fields distinguishable for the product-form tests elsewhere.

Definition at line 816 of file state_events.h.

References cd_factor(), line::qn::Station< T >::cdscaling, line::InputError::InputError(), and line::qn::Station< T >::jdscaling.

Referenced by after_event_station_dep(), after_event_station_phase(), and cd_factor().

◆ check_binding_capacity()

template<class T>
void line::qn::check_binding_capacity ( const std::string & solver,
const NetworkStruct< T > & sn )

◆ ctmc_feature_set()

FeatureSet line::qn::ctmc_feature_set ( const std::string & method)
inline

SolverCTMC.getFeatureSet, the reference's 104 MATLAB names in full.

Balking, Reneging and Breakdown stay declared and are INERT: they are call parameters of state_events.h rather than struct fields, so used_lang_features cannot emit them and the declaration is unenforced.

Definition at line 475 of file solver_feature_sets.h.

References ctmc_feature_set(), line::qn::FeatureSet::set(), and line::qn::FeatureSet::unset().

Referenced by line::autosolver::auto_supports(), ctmc_feature_set(), line::ctmc::solver_ctmc_analyzer(), and line::ctmc::solver_ctmc_analyzer_any().

◆ entry_phase_dist()

template<class T>
std::vector< T > line::qn::entry_phase_dist ( const NetworkStruct< T > & sn,
std::size_t ist,
std::size_t cls )

The entry-phase distribution pie{ist}{class}: which phase a service STARTS in.

This is map_pie, the equilibrium embedded at DEPARTURE instants, and NOT map_prob, the time-stationary law of D0+D1 – the two differ whenever the process is not exponential (for Erlang-2, entry is [1,0] while the time-stationary law is [0.5,0.5]).

A Place has no service process, so its "phases" carry no rate; the reference falls back on a uniform choice there rather than leaving the vector NaN.

Definition at line 330 of file state_events.h.

References line::lang::Distrib< T >::D0, line::mam::Map< T >::D0, line::lang::Distrib< T >::D1, line::mam::Map< T >::D1, line::lang::Distrib< T >::disabled, entry_phase_dist(), and line::mam::map_pie().

Referenced by after_event_station_arv(), after_event_station_dep(), after_event_station_reply(), after_event_station_retry(), entry_phase_dist(), and polling_land().

◆ env_feature_set()

FeatureSet line::qn::env_feature_set ( const std::string & )
inline

SolverENV.supports's inline set, 28 names, transcribed unchanged.

The narrowest declared set in the codebase. RoutingStrategy_RROBIN is marked "with SolverJMT" upstream and was kept here while the CTMC stage solver declared it; it is now DROPPED, because ctmc_feature_set no longer does. env_dispatch.h:164 routes the statevec coupling to that same CTMC, so declaring round robin here would promise what the stage cannot deliver.

Definition at line 1262 of file solver_feature_sets.h.

References env_feature_set(), and line::qn::FeatureSet::set().

Referenced by env_feature_set().

◆ feature_count()

std::size_t line::qn::feature_count ( )
inlineconstexpr

The number of registered features, MATLAB numel(SolverFeatureSet.fields).

Definition at line 297 of file feature_set.h.

References COUNT, and feature_count().

Referenced by feature_count(), feature_set_supports(), and line::qn::FeatureSet::FeatureSet().

◆ feature_gate()

template<class T>
void line::qn::feature_gate ( const std::string & solver,
const FeatureSet & declared,
const NetworkStruct< T > & sn,
const std::string & requested_method = "",
const std::string & resolved_method = "" )

runAnalyzerChecks: refuse a model the solver does not declare, by name.

Throws UnsupportedError, which is what every other by-name refusal in this port throws and what the CLI reports without a stack.

THE TWO MESSAGE FORMS, NetworkSolver.m:184-190. The reference emits a different message when resolveMethod changed the method under the user's feet than when the user named it:

method == options.method "features not supported by the solver" otherwise "features not supported by the solver's '%s' method"

That distinction is not cosmetic. The only resolution today is MVA's default -> rqna upgrade, and rqna's set WITHDRAWS ClosedClass and SelfLoopingClass, so a user who asked for nothing but default can be refused for having a closed class. Without the method in the message the refusal cannot be understood, because nothing the user typed mentions rqna.

Both method arguments default to empty, which selects the plain form and leaves every call site that does not resolve a method unchanged.

Definition at line 978 of file feature_set.h.

References feature_gate(), feature_set_supports(), line::qn::SupportResult::ok, line::qn::SupportResult::reason, line::UnsupportedError::UnsupportedError(), and used_lang_features().

Referenced by feature_gate(), line::ag::solver_ag_solve(), line::ctmc::solver_ctmc_analyzer(), line::ctmc::solver_ctmc_analyzer_any(), line::fluid::solver_fluid_run_analyzer(), line::fluid::solver_fluid_run_transient(), line::mam::solver_mam_get_tran_avg(), line::mam::solver_mam_solve(), line::mva::solver_mva_run_analyzer(), and line::nc::solver_nc_solve().

◆ feature_generalization()

Feature line::qn::feature_generalization ( Feature f)
inline

The registry name a specialization falls back to when it is not declared.

Some registry names denote a SPECIAL CASE of another name rather than a capability of their own: a Cox2 is a Coxian restricted to two phases, and a Trace is a Replayer under another class name. Recording only the general name left the specific entry unreachable – dead registry surface that no model could ever set (see _kb/06-solver-catalog.md, "A registered name nothing emits gates nothing"). Recording the specific name instead would silently REJECT those models at every solver that declares only the general one, which is every solver that accepts them today.

So the recorder emits the most specific name it can, and the gate resolves an undeclared specific name against its generalization here. A solver that genuinely supports only the special case (two-phase Coxian, say) keeps the option of declaring the specialization alone: the fallback is consulted only when the specific name is missing, never in the other direction.

COUNT means "no generalization"; the feature stands on its own.

Definition at line 443 of file feature_set.h.

References COUNT, and feature_generalization().

Referenced by feature_generalization(), and feature_set_supports().

◆ feature_name()

const char * line::qn::feature_name ( Feature f)
inline

The canonical registry name, byte for byte the MATLAB field name.

Definition at line 300 of file feature_set.h.

References feature_name(), LINE_QN_FEATURE_LIST, and LINE_QN_FEATURE_NAME.

Referenced by feature_name(), and feature_phrase().

◆ feature_of_process()

Feature line::qn::feature_of_process ( ProcessType p)
inline

The feature name of a distribution, MATLAB serviceProcess{r}{3}.name.

Immediate and Disabled return COUNT: they are internal placeholders, not user-facing distributions, and getUsedLangFeatures excludes them by name. Expolynomial and Normal have no ProcessType in MATLAB either, so those two registry entries can never be emitted by this port.

Definition at line 507 of file feature_set.h.

References COUNT, and feature_of_process().

Referenced by feature_of_process(), and used_lang_features().

◆ feature_of_replacement()

Feature line::qn::feature_of_replacement ( ReplacementStrategy s)
inline

ReplacementStrategy.toFeature.

Definition at line 616 of file feature_set.h.

References COUNT, and feature_of_replacement().

Referenced by feature_of_replacement(), and used_lang_features().

◆ feature_of_routing()

Feature line::qn::feature_of_routing ( RoutingStrategy r)
inline

RoutingStrategy.toFeature.

FIRING and DISABLED are internal markers, not user-selectable capabilities, and map to no registry name (RoutingStrategy.m:132-139).

Definition at line 602 of file feature_set.h.

References COUNT, and feature_of_routing().

Referenced by feature_of_routing(), and used_lang_features().

◆ feature_of_sched()

Feature line::qn::feature_of_sched ( SchedStrategy s)
inline

SchedStrategy.toFeature.

FORK and NONE are internal markers with no registry name; MATLAB aliases FCFSPRIO to HOL, so HOL covers both.

Definition at line 553 of file feature_set.h.

References COUNT, and feature_of_sched().

Referenced by feature_of_sched(), and used_lang_features().

◆ feature_of_server_section()

Feature line::qn::feature_of_server_section ( SchedStrategy s)
inline

The SERVER section a Queue gets for a discipline, MATLAB Queue.m:79-108.

The section class name is itself a feature: MNetwork.addNode registers class(node.server) alongside class(node), which is where SharedServer, InfiniteServer and Server enter the used set. PreemptiveServer and PollingServer are absent from the registry, so those disciplines contribute only their SchedStrategy_ name, exactly as in the reference.

Definition at line 638 of file feature_set.h.

References COUNT, and feature_of_server_section().

Referenced by feature_of_server_section(), and used_lang_features().

◆ feature_phrase()

std::string line::qn::feature_phrase ( Feature f)
inline

A human-readable phrase for the reason string, e.g.

"a Finite Capacity Region". Structured names are derived from their suffix so that the whole SchedStrategy_ / RoutingStrategy_ / ReplacementStrategy_ / SignalType_ / ActivityPrecedence_ families need no per-entry table to stay in step.

Definition at line 318 of file feature_set.h.

References feature_name(), and feature_phrase().

Referenced by feature_phrase(), and feature_set_supports().

◆ feature_set_supports()

SupportResult line::qn::feature_set_supports ( const std::string & solver,
const FeatureSet & declared,
const FeatureSet & used )
inline

SolverFeatureSet.supports: is every feature the model uses declared?

solver names the solver in the reason so the message is actionable on its own; MATLAB gets that name from the mfilename of the raising runAnalyzer.

Definition at line 468 of file feature_set.h.

References COUNT, feature_count(), feature_generalization(), feature_phrase(), feature_set_supports(), line::qn::FeatureSet::has(), line::qn::SupportResult::missing, line::qn::SupportResult::ok, and line::qn::SupportResult::reason.

Referenced by line::autosolver::auto_family_refusal(), line::autosolver::auto_supports(), feature_gate(), and feature_set_supports().

◆ fj_tag()

template<class T>
FjTagged< T > line::qn::fj_tag ( const NetworkStruct< T > & sn)

Port of ModelAdapter.fjtag.

Parameters
sna refreshed struct whose Fork nodes all have a matched Join

Per-branch tasksPerLink, empty when every branch carries w.

Definition at line 302 of file fj_tag.h.

References line::qn::NetworkStruct< T >::add_class(), line::qn::FjSync< T >::auxall, line::qn::FjSync< T >::auxclasses, line::qn::FjJoinParam::auxmatrix, line::qn::FjSync< T >::branchheads, line::qn::Station< T >::cdscalingpeak, line::qn::NetworkStruct< T >::chains, line::qn::NetworkStruct< T >::classcap, line::qn::Station< T >::classcap, line::qn::NetworkStruct< T >::classes, line::qn::FjSync< T >::cls, line::Matrix< T >::cols(), line::qn::JobClass::completes, line::qn::NetworkStruct< T >::csmatrix, line::qn::Station< T >::droprule, line::qn::ForkParam< T >::fan_out_link, fj_tag(), line::qn::FjTagged< T >::fjbranchmap, line::qn::FjTagged< T >::fjclassmap, line::qn::NetworkStruct< T >::fjclassmap, line::qn::FjTagged< T >::fjforkmap, line::qn::FjTagged< T >::fjjoinmap, line::qn::NetworkStruct< T >::fjjoinparam, line::qn::FjTagged< T >::fjsync, line::qn::FjTagged< T >::fjtagmap, line::qn::FjJoinParam::fork, line::qn::FjSync< T >::fork, line::InputError::InputError(), line::qn::JobClass::is_ref_class, line::qn::NetworkStruct< T >::isfjaugmented, line::qn::Station< T >::jdscalingpeak, line::qn::FjSync< T >::join, line::qn::FjTagged< T >::joinparam, line::qn::FjTagged< T >::korig, line::qn::JobClass::name, line::qn::NetworkStruct< T >::nchains, line::qn::NetworkStruct< T >::nclasses, line::qn::NetworkStruct< T >::nodes, line::qn::NetworkStruct< T >::nodevisits, line::qn::FjJoinParam::origclasses, line::lang::PARTIAL, line::qn::JobClass::population, line::qn::NetworkStruct< T >::refresh_struct(), line::qn::FjJoinParam::required, line::qn::NodeDef::routing, line::Matrix< T >::rows(), line::qn::Station< T >::schedparam, line::qn::NetworkStruct< T >::set_route(), line::qn::NetworkStruct< T >::set_service(), sn_fj_validate(), line::qn::NetworkStruct< T >::stateful_index(), line::qn::NetworkStruct< T >::stateful_nodes, line::qn::NetworkStruct< T >::stations, line::qn::FjSync< T >::tag, line::qn::JobClass::type, line::UnsupportedError::UnsupportedError(), line::qn::FjTagged< T >::V, line::qn::NetworkStruct< T >::visits, line::qn::FjSync< T >::weight, and line::qn::FjSync< T >::weightlink.

Referenced by fj_tag(), line::ctmc::solver_ctmc_analyzer(), and line::ssa::solver_ssa_serial_analyzer().

◆ fluid_feature_set()

FeatureSet line::qn::fluid_feature_set ( const std::string & method)
inline

SolverFLD.getFeatureSet, transcribed, MINUS what the requested method cannot evaluate – the port of @@SolverFLD/getMethodFeatureSet.

THE PER-METHOD SUBTRACTION IS NOT COSMETIC. A station whose discipline has no branch in ode_rates_closing_factors keeps g = x, i.e. it is integrated as an INFINITE SERVER, and the answer is wrong with no warning at all: on Delay(Z=1) -> Queue(c=1), N=4, whose exact Q2 is 3.0154, the fall-through returns 2.0000. The closing family therefore has to reject the disciplines it lacks a branch for rather than accept them into the wrong drift. Only the closing family is affected: matrix/pnorm build a PS drift, which is the right aggregate for any work-conserving discipline.

CacheRetrieval is DELIBERATELY absent upstream (SolverFLD.m:95-101 records the flow-conservation failure on examples/basic/cacheModel/retrieval_simple). NHPP, MAPt and PHt are the time-inhomogeneous families. Every method accepts them, as the reference does: the first-order methods integrate the time-averaged NOMINAL pair, kp integrates the schedule itself, and a time-varying rate multiplier is refused on the options rather than here. What the C++ fluid solver ignores silently (Region, Fork/Join, Router, Retrial, Place/Transition, the signals, ClassDependence) is already absent from the MATLAB set.

Definition at line 835 of file solver_feature_sets.h.

References fluid_feature_set(), line::qn::FeatureSet::set(), and line::qn::FeatureSet::unset().

Referenced by line::autosolver::auto_supports(), fluid_feature_set(), line::fluid::solver_fluid_run_analyzer(), and line::fluid::solver_fluid_run_transient().

◆ from_marg_node()

template<class T>
std::vector< std::vector< T > > line::qn::from_marg_node ( const NetworkStruct< T > & sn,
std::size_t ind,
std::size_t ntot,
const std::vector< std::size_t > & phases )

Port of State.fromMarg: the state space with a given TOTAL queue length.

This is the class-summed counterpart of from_marginal_node. Where that one fixes how many jobs of EACH class the node holds, this one fixes only how many it holds ALTOGETHER and returns the union over every class split of ntot the node can hold.

A class DISABLED at the station has classcap 0 and is excluded from the split enumeration up front rather than after the fact. Asking from_marginal_node for a job of such a class yields an EMPTY local space, and space_closed_single(0,1) returning no rows empties the whole cartesian product, so the job would silently disappear – the trap documented at space_closed_single above.

ntot == 0 has the single empty split, which from_marginal_node answers with the per-discipline empty state; the width is NOT re-derived here.

The buffer is RIGHT-aligned, so sub-spaces of different width are padded on the LEFT before they are stacked, exactly as the reference does for the reply-block sub-spaces. Rows are then uniqued and reversed, which puts the empty state first and the states with jobs in phase 1 earlier.

The twin over BOTH totals is from_marg_node_started below.

Definition at line 1798 of file state.h.

References from_marg_node(), from_marginal_node(), line::InputError::InputError(), line::pfqn::multichoose_rows(), and line::qn::NodeDef::station.

Referenced by from_marg_node().

◆ from_marg_node_started()

template<class T>
std::vector< std::vector< T > > line::qn::from_marg_node_started ( const NetworkStruct< T > & sn,
std::size_t ind,
std::size_t ntot,
std::size_t stot,
const std::vector< std::size_t > & phases )

Port of State.fromMargAndStarted: the states with a given TOTAL queue length AND a given TOTAL number of started jobs.

Where from_marginal_node_and_started takes one per-class occupancy and one per-class started vector and builds ONE row, this takes only the two totals and returns the union of that row over every pair consistent with them: sum(n) == ntot, sum(s) == stot, and s <= n elementwise.

The started counts are drawn with multichoosecon from the jobs actually present rather than from multichoose_rows over all classes, so a split is never proposed that puts more of a class in service than the station holds. Classes disabled at the station are excluded through classcap for the reason documented on from_marg_node: an empty local space is ABSORBED by the cartesian product instead of annihilating it, so the job would silently disappear rather than the state being rejected.

Widths are unified on the LEFT and the rows uniqued and reversed, exactly as from_marg_node does, since the buffer is right-aligned.

Definition at line 1919 of file state.h.

References from_marg_node_started(), from_marginal_node_and_started(), line::InputError::InputError(), line::pfqn::multichoose_rows(), and line::qn::NodeDef::station.

Referenced by from_marg_node_started().

◆ from_marginal()

template<class T>
std::vector< std::vector< T > > line::qn::from_marginal ( const NetworkStruct< T > & sn,
std::size_t ist,
const std::vector< std::size_t > & n,
const std::vector< std::size_t > & phases )

◆ from_marginal_and_started()

template<class T>
std::vector< std::vector< T > > line::qn::from_marginal_and_started ( const NetworkStruct< T > & sn,
std::size_t ist,
const std::vector< std::size_t > & n,
const std::vector< std::size_t > & s,
const std::vector< std::size_t > & phases )

State.fromMarginalAndStarted with the trailing local-variable block appended, i.e.

the counterpart of from_marginal for a prescribed service split. A Join of an FJ-augmented struct carries its per-class counts and no split, exactly as in from_marginal.

Definition at line 1446 of file state.h.

References append_local_vars(), from_marginal_and_started(), and from_marginal_and_started_core().

Referenced by from_marginal_and_started(), and from_marginal_node_and_started().

◆ from_marginal_and_started_core()

template<class T>
std::vector< std::vector< T > > line::qn::from_marginal_and_started_core ( const NetworkStruct< T > & sn,
std::size_t ist,
const std::vector< std::size_t > & n,
const std::vector< std::size_t > & s,
const std::vector< std::size_t > & phases )

Port of State.fromMarginalAndStarted: ONE state realizing both a per-class occupancy n and a per-class STARTED count s.

HOW IT DIFFERS FROM from_marginal_core, which is the reason it is a separate builder rather than a filter over it. from_marginal ENUMERATES every (buffer, server) split consistent with a marginal, because the marginal alone does not determine which jobs hold the servers. Here the split is GIVEN: s says how many jobs of each class are in service, so exactly one split is meant and the buffer contents follow as n - s. Filtering the enumeration would be both quadratic and wrong at an empty station, where the reference emits a row of a prescribed width rather than selecting one.

EVERY STARTED JOB IS PLACED IN PHASE ONE, which is what makes the result an INITIAL state rather than a member of the stationary space: a job that has just started service has not advanced through its phase-type law yet.

ONE BUFFER ORDERING IS EMITTED under the ordered-buffer disciplines, the descending-sorted one. The reference enumerates every permutation and then keeps the lexicographic maximum through its trailing unique/flip, so building that row directly is the same answer without the factorial.

A SHARED SERVER IGNORES s ENTIRELY. Under INF/PS/DPS/GPS/LPS and their priority variants every job present is in a server, so the state holds n, not s; writing s there would lose the queued jobs. That is not a simplification but the reference's own branch, and it was a real defect in the Python twin until 2026-08-09.

PAS/OI ignores s for a different reason: its local state is the ordered class-index list of the jobs present, which carries no service split at all, so this delegates to the marginal builder there.

Parameters
snthe network struct
iststation index (1-based)
nper-class occupancy
sper-class started count; must satisfy s[r] <= n[r]
phasesper-class phase counts

The server block: cnt[r] jobs of class r, all of them in phase one.

Definition at line 1282 of file state.h.

References cartesian(), from_marginal_and_started_core(), from_marginal_core(), line::InputError::InputError(), line::qn::Station< T >::nodetype, line::qn::Station< T >::nservers, and line::qn::Station< T >::sched.

Referenced by from_marginal_and_started(), and from_marginal_and_started_core().

◆ from_marginal_core()

template<class T>
std::vector< std::vector< T > > line::qn::from_marginal_core ( const NetworkStruct< T > & sn,
std::size_t ist,
const std::vector< std::size_t > & n,
const std::vector< std::size_t > & phases )

Port of State.fromMarginal for the station families CTMC enumerates: every local state in which station ist holds exactly n[r] class-r jobs.

COVERED: Queue, Delay, Source and Place under the disciplines whose buffer is either absent (INF/PS/DPS/GPS) or a per-class count. The row is laid out [buffer | server] to match to_marginal, and the server block is the cartesian fold of space_closed_single(phases[r], n[r]) over classes.

Retrial stations are covered here too, by the (in-service, orbit) split, and PAS/OI by the ordered class-index list that to_marginal already decoded. Transition nodes are NOT: a Transition is stateful but is not a station, so it never carries a station index – from_marginal_node handles it, which is also where the reference puts it.

REFUSED BY NAME, because a wrong guess is indistinguishable from a correct one downstream: a station carrying a MAP/MMPP2 arrival process under a discipline whose encoding does not carry the modulating phase.

Definition at line 574 of file state.h.

References cartesian(), from_marginal_core(), line::InputError::InputError(), line::qn::Station< T >::nodetype, line::qn::Station< T >::nservers, pas_multiset_perms(), line::qn::Station< T >::sched, space_closed_single(), and line::UnsupportedError::UnsupportedError().

Referenced by from_marginal_and_started_core(), and from_marginal_core().

◆ from_marginal_node()

template<class T>
std::vector< std::vector< T > > line::qn::from_marginal_node ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< std::size_t > & n,
const std::vector< std::size_t > & phases )

Port of State.fromMarginal at its OWN signature: the reference indexes by NODE, not by station, and derives the station internally.

That distinction is load-bearing, not cosmetic – a Transition is stateful but is NOT a station, so it carries no station index and the station-indexed overload can never reach it. Routing every caller through here is what makes the Transition branch below live rather than dead code.

A node that is not stateful holds no jobs and contributes no local state.

Definition at line 1473 of file state.h.

References cache_retrieval_class_map(), cartesian(), line::qn::TransitionParam< T >::firingphases, from_marginal(), from_marginal_node(), line::qn::CacheParam< T >::hitclass, line::InputError::InputError(), line::qn::CacheParam< T >::itemcap, line::qn::CacheParam< T >::max_pending_retrieval, line::qn::GlobalConstants::MaxInt, line::qn::CacheParam< T >::missclass, line::qn::CacheParam< T >::nitems, line::qn::TransitionParam< T >::nmodes, line::qn::TransitionParam< T >::nmodeservers, line::qn::NodeDef::nodetype, line::qn::CacheParam< T >::retrieval_capacity, space_closed_single(), line::qn::NodeDef::stateful, and line::qn::NodeDef::station.

Referenced by from_marg_node(), from_marginal_node(), from_marginal_node_and_started(), from_marginal_node_first(), and space_generator().

◆ from_marginal_node_and_started()

template<class T>
std::vector< std::vector< T > > line::qn::from_marginal_node_and_started ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< std::size_t > & n,
const std::vector< std::size_t > & s,
const std::vector< std::size_t > & phases )

Port of State.fromMarginalAndStarted at its OWN signature, which indexes by NODE rather than by station, mirroring from_marginal_node.

A Petri-net element is REFUSED BY NAME, as the reference refuses it: a Transition's local state is per MODE, not per class, and a Place holds tokens, so neither has a notion of a started job to prescribe. A node that is not stateful holds no jobs and contributes no local state.

Definition at line 1754 of file state.h.

References from_marginal_and_started(), from_marginal_node(), from_marginal_node_and_started(), line::InputError::InputError(), line::qn::NodeDef::nodetype, line::qn::NodeDef::stateful, line::qn::NodeDef::station, and line::UnsupportedError::UnsupportedError().

Referenced by from_marg_node_started(), and from_marginal_node_and_started().

◆ from_marginal_node_first()

template<class T>
bool line::qn::from_marginal_node_first ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< std::size_t > & n,
const std::vector< std::size_t > & phases,
std::vector< T > & out )

The FIRST row from_marginal_node emits, BUILT rather than enumerated.

Every caller that seeds a sample path takes row 0 and discards the rest, and for a Cache the rest is the ordered placement of distinct items into its slots – (nitems+1)*nitems*(nitems-1)*... rows. Materializing that to read one row's contents is what took SolverSSA on tut06_cache_lru_zipf (1000 items, 50 slots) to 12 GB and an OOM kill of the whole host; the peak is invariant in samples precisely because the walk itself is lazy and only the SEED costs this. A simulator must not pay an exact solver's enumeration to start.

Row 0 holds items 1..tcc in slot order, by construction and not by choice: cartesian emits a[0] ++ b[0], the contents loop offers the lowest admissible item first at every slot and its duplicate test rejects the ones already placed, and the delayed-hit occupancy bits start clear. So the row is the per-class counts, the first tcc items, then zeros – bit for bit what the enumeration returned, which is what lets the CTMC find its declared initial state in the space. A cache with more slots than items cannot fill and starts empty, as the enumeration also has it. Every other node kind delegates, its first row already being cheap.

Returns
false when the node admits no state at all, as an empty return does

Definition at line 2005 of file state.h.

References cache_retrieval_class_map(), from_marginal_node(), from_marginal_node_first(), line::InputError::InputError(), line::qn::CacheParam< T >::itemcap, line::qn::CacheParam< T >::nitems, line::qn::NodeDef::nodetype, line::qn::CacheParam< T >::retrieval_capacity, space_closed_single(), line::qn::NodeDef::stateful, and line::qn::NodeDef::station.

Referenced by from_marginal_node_first().

◆ has_binding_capacity()

template<class T>
bool line::qn::has_binding_capacity ( const NetworkStruct< T > & sn)

getUsedLangFeatures: the features the MODEL uses.

Does any station buffer BIND?

MATLAB derives them from the Network OBJECT, where a node still knows its MATLAB class and its section classes; this port derives them from the refreshed struct, which is the only thing a C++ solver runner holds. The two agree because the section classes are a pure function of the node kind and the discipline (Queue.m:48-108, Source.m:66-68, Cache.m:54-76, Fork.m:106-109, Join.m:33-35, Place.m:27-31, Transition.m:29-36), which is what feature_of_server_section and the node switch below encode.

FEATURES THIS PORT CANNOT EMIT, because NetworkStruct carries no field for them. Each is a real MATLAB feature, and a model using one reaches a C++ solver unflagged; the fix is a struct field, not a proxy here. SetupDelayOff MATLAB Queue.setupTime / delayoffTime, carried by NetworkStruct::setupparam and solved by solver_mam_basic. Reneging MATLAB Queue.impatienceTypes. state_events.h takes the reneging classes as a CALL PARAMETER, so the struct does not record them and they cannot be derived here. Balking MATLAB Queue.balkingStrategies. No struct field. QueueingPlace MATLAB Place.queueing. add_place() builds every Place as an INF station with no queueing flag. Breakdown was on this list until 2026-08-15, when NetworkStruct::breakdownparam was added for the LDES engine; it is derived below like any other field-backed feature. state_events.h still takes the breakdown nodes as a call parameter, which is why the CTMC declaration of it stays inert – the two are independent.

FEATURES EMITTED HERE THAT MATLAB DOES NOT EMIT. LoadDependence is in the registry and is declared by solvers, but getUsedLangFeatures never set it, so in MATLAB it was unenforced. Deriving it from lldscaling is a strict tightening: the solvers that declare it are unaffected, and the ones that do not now refuse instead of silently dropping the scaling. Retrial was in this paragraph until 2026-09-05, when MATLAB's recorder gained the same arm.

The gate's own question, asked without raising.

Definition at line 1083 of file feature_set.h.

References binding_capacity_reason(), and has_binding_capacity().

Referenced by has_binding_capacity(), and used_lang_features().

◆ is_physical_capacity()

template<class T>
bool line::qn::is_physical_capacity ( const NetworkStruct< T > & sn,
std::size_t ist,
std::size_t cls )

Port of State.isPhysicalCapacity: true when the bound at (ist, class) is a PHYSICAL capacity rather than a state-space CUTOFF on an open class.

The distinction decides what a refused arrival means. The producer's capacity arguments have the cutoff folded in – solver_ssa overwrites cap/classcap with min(cutoff, physical) – so at a cutoff boundary they read finite even with no physical cap. Treating that as physical would turn a state-space TRUNCATION into a self-loop loss, which reports a wrong arrival rate and perturbs the sample path.

The in-producer signal is the DROP RULE: refreshCapacity sets a non-WAITQ rule exactly when the capacity is physical, and a cutoff-bounded open class keeps the WAITQ default.

Definition at line 245 of file state_events.h.

References is_physical_capacity().

Referenced by after_event_station_arv(), and is_physical_capacity().

◆ jmt_feature_set()

FeatureSet line::qn::jmt_feature_set ( const std::string & method)
inline

◆ jmva_is_closed_only()

bool line::qn::jmva_is_closed_only ( const std::string & method)
inline

Port of SolverJMT.getFeatureSet (@@SolverJMT/SolverJMT.m:180-290).

JMT IS THE REFERENCE FCR ENGINE – every other solver's finite-capacity refusal points users here – so Region is declared, and so is the whole SPN section family, which JMT simulates natively.

WHAT IS NARROWED AGAINST THE REFERENCE, and why each is a transcription of a refusal this port already makes rather than a feature JMT lacks: Normal the reference lists it, and saveServiceStrategy has no branch for it: a Normal service would reach the analytic switch with no javaClass and error. It is not declared. HLRU/CLIMB/QLRU JMT has cache objects for RR, FIFO, SFIFO and LRU only; save_cache_strategy refuses the other three by name instead of falling back to LRU, so declaring them would promise an admission the writer then denies. SchedStrategy_LPS is declared: the limit is exported as a single-node blocking region, not dropped. True for the JMVA algorithms that solve a CLOSED product-form network only.

RECAL, CoMoM, Chow, Bard-Schweitzer (both spellings), AQL, Linearizer and De Souza-Muntz Linearizer. Measured against JMT 1.2.x: each answers an open or a mixed model with jmt.common.exception.UnsupportedModelException: The selected solver cannot handle open classes, please choose another. and a load-dependent one with the same exception naming load-dependent stations, while the exact MVA engine behind 'jmva' and 'jmva.mva' serves both. The single-server half of the same restriction is a station COUNT and has no feature name, so it is refused structurally by jmt::jmt_method_refusal.

Definition at line 1427 of file solver_feature_sets.h.

References jmva_is_closed_only().

Referenced by jmt_feature_set(), line::jmt::jmt_method_refusal(), and jmva_is_closed_only().

◆ ldes_feature_set()

FeatureSet line::qn::ldes_feature_set ( const std::string & )
inline

SolverLDES.getFeatureSet, transcribed WHOLE.

THE ONE SET IN THIS FILE THAT IS NOT NARROWED, and for a reason that does not generalise: every other function here declares what the C++ code implements, because a feature declared and not implemented yields a wrong number. The LDES client implements NONE of these – it forwards the model.json document to the SSJ engine byte for byte and reads the result back – so the code that has to support a feature is the engine, the same engine MATLAB and native Python drive. Narrowing here would refuse models that the reference simulates with the very binary this port is about to run, which is the opposite of the usual danger.

SOURCE: matlab/src/solvers/wrappers/LDES/@@SolverLDES/SolverLDES.m:108-230, name for name, and every name there has a registry enumerator. BatchArrival IS one of them: the note that used to sit here called it a name no solver declares and no recorder sets, and both halves were false – SolverLDES.m:210 declares it and MNetwork.getUsedLangFeatures marks it, as used_lang_features has here since the Source arm learned arrival_batch. Left undeclared, this set refused every model built with Source.setArrivalBatch, which is the one engine that simulates the batch.

WHAT THE GATE STILL CANNOT SEE. The set is consulted against used_lang_features, which is built from a PARSED NetworkStruct; the LDES arm of the CLI never parses the document, so a model outside this port's reader reaches the engine without passing here at all. That is intended – forwarding losslessly is the whole point – and it means this set governs SolverAUTO's choice rather than the client's own admission.

Definition at line 1305 of file solver_feature_sets.h.

References ldes_feature_set(), and line::qn::FeatureSet::set().

Referenced by line::autosolver::auto_supports(), and ldes_feature_set().

◆ lld_factor()

template<class T>
T line::qn::lld_factor ( const NetworkStruct< T > & sn,
std::size_t ist,
double n )

The limited-load-dependent multiplier at population n, 1 when unset.

Definition at line 790 of file state_events.h.

References lld_factor().

Referenced by after_event_station_dep(), after_event_station_phase(), and lld_factor().

◆ mam_feature_set()

FeatureSet line::qn::mam_feature_set ( const std::string & method)
inline

SolverMAM.getFeatureSet, the union of its four setTrue calls: 55 MATLAB names, WIDENED for 'default'/'ldqbd' only, and NARROWED by one name no MAM path ever serves.

THE METHOD PARAMETER IS NOW READ, where it used to be discarded. Two consequences of discarding it were both the over-declaration feature_set.h:30-33 warns against:

+LoadDependence, method in {default, ldqbd} ONLY solver_mam_ldqbd.h:152 reads st.lldscaling, but only the 'ldqbd' method and 'default''s single-class closed Delay+Queue route (mam_dispatch.h's branch 2e) ever call it. Declaring it for every method let 'dec.source', 'dec.poisson' and 'mna' pass a load-dependent model straight to solver_mam_basic / solver_mna, neither of which reads the field, so those methods silently solved at nominal rates. The featset cannot see topology, so 'default' still needs the structural check in check_model_method (solver_mam_runner.h) that refuses a load-dependent model whose shape is not the one ldqbd can solve; 'ldqbd' itself is already self-checking (solver_mam_ldqbd.h:109-131). -SchedStrategy_FCFSPRPRIO, every method No MAM analyzer serves it: solve_fcfs_station in solver_mam_basic.h dispatches only FCFS and HOL (solver_mam_basic.h:1144), so an FCFSPRPRIO station always reaches the station ladder's unconditional throw at solver_mam_basic.h:1147-1154 regardless of this declaration. The enumerator itself DOES exist in C++ (lang_types.h:144); what is absent is a serving path, so the fix is here, not in SchedStrategy. Undeclaring lets the gate refuse first, by feature name, instead of reaching the deeper and less specific station-ladder message. DMAP, ME, RAP and SetupDelayOff stay declared and are inert: no ProcessType or NetworkStruct field can make used_lang_features emit them.

Definition at line 1140 of file solver_feature_sets.h.

References mam_feature_set(), line::qn::FeatureSet::set(), and line::qn::FeatureSet::unset().

Referenced by line::autosolver::auto_supports(), mam_feature_set(), line::mam::solver_mam_get_tran_avg(), and line::mam::solver_mam_solve().

◆ mva_base_method()

std::string line::qn::mva_base_method ( const std::string & method)
inline

SolverMVA.getFeatureSet, plus getMethodFeatureSet's per-method deltas.

SolverMVA.m:189-213 declares 59 names; this set is those 59, name for name. RQNA natively consumes non-renewal MAP/MMPP/RAP processes but is open-network only; QNA is a two-moment open-network method.

THE SIZE-BASED NAMES WERE REMOVED ONCE AND ARE BACK, AND THE REFERENCE IS WHY. SchedStrategy_SRPT, _PSJF, _FB, _LRPT and _SETF were dropped on 2026-07-29 on the ground that MATLAB's getFeatureSet declared none of them, making them a WIDENING of the reference envelope rather than a transcription of it.

That premise expired. MATLAB's SolverMVA.m now declares all five ("Listed only now that the analyzer runs"), and the JAR and native Python gained solver_mva_qsys_sizebased_analyzer and the same five names on 2026-08-16. Keeping them out made C++ NARROWER than the reference: branch 3 of mva_dispatch.h and the qsys_mg1_srpt/_psjf/_fb/_lrpt/_setf closed forms behind it were reachable code held behind a closed gate, and a size-based model the other three solve was refused here.

The lesson is about the shape of the note, not the names: a featset comment that records what the reference declared ON A DATE goes stale silently. When the reference moves, this file has to move with it.

Every OTHER declared name was checked against the code that consumes it, not assumed: Cache, CacheClassSwitcher mva_dispatch.h:754, :765 CacheRetrieval mva_dispatch.h:741 (open); the CLOSED variant is refused by name at :734-740, a shape restriction the boolean cannot express ReplacementStrategy_LRU, _HLRU solver_mva_cache.h:144-165 SchedStrategy_OI, _PAS mva_dispatch.h, branch 1, solver_mva_oi.h SchedStrategy_POLLING mva_dispatch.h, branch 5, solver_mva_polling.h SchedStrategy_SJF mva_dispatch.h, branch 0, solver_mva_sjn.h; the OPEN case is refused by name there, a shape restriction the boolean cannot express SchedStrategy_SRPT, _PSJF, _FB, mva_dispatch.h, branch 3, _LRPT, _SETF solver_mva_qsys_sizebased Fork, Forker, Join, Joiner solver_mva_runner.h:414-426, fj_mmt + fj_fixed_point LoadDependence solver_mva.h:543-561, :655-662, :1486-1487 ClassDependence solver_mva.h:553-560, :671-684 (pfqn_cdfun) Pareto, Weibull, Lognormal, Uniform, Det, Replayer, BMAP and MMAP carry no consumer of their own by design: there is no ProcessType:: reference anywhere under cpp/include/line/solvers/mva/, because MVA is a two-moment method that reads only rates and SCVs. That is exactly how MATLAB's MVA treats them, which is why it declares them. BMAP is the weakest of the eight: the batch structure is dropped to two moments rather than refused, in both codebases. The method name with any leading "amva." alias stripped.

The mva registry strips the prefix before it selects an algorithm, so every rule keyed on a method name has to see the canonical spelling or it would hold for "bs" and not for "amva.bs".

Definition at line 124 of file solver_feature_sets.h.

References mva_base_method().

Referenced by line::mva::list_valid_methods(), mva_base_method(), line::mva::mva_closed_population_reason(), mva_feature_set(), mva_feature_set(), mva_is_closed_population_method(), line::mva::mva_mapqn_reason(), line::mva::mva_mvac_reason(), line::mva::mva_schmidt_ext_reason(), and line::mva::mva_single_class_open_reason().

◆ mva_feature_set() [1/2]

◆ mva_feature_set() [2/2]

template<class T>
FeatureSet line::qn::mva_feature_set ( const std::string & raw_method,
const NetworkStruct< T > & sn )

mva_feature_set on a MODEL, i.e.

the whole of SolverMVA.getMethodFeatureSet.

The reference's last arm reads self.model (SolverMVA.m:396-399): every method but 'exact' is granted FiniteCapacity on a single-station M/M/1/K with tail drop, because mva_dispatch ORs sn_is_mm1k_loss into its single-station test and answers that shape whatever the caller named. A name cannot carry the grant, so a caller that HAS the struct asks this overload and one that does not gets the static table above.

Definition at line 364 of file solver_feature_sets.h.

References mva_base_method(), mva_feature_set(), and line::qn::FeatureSet::set().

◆ mva_is_closed_population_method()

bool line::qn::mva_is_closed_population_method ( const std::string & method)
inline

The AMVA algorithms whose recursion is over a CLOSED population vector.

Each approximates the arrival-instant queue length E[Q(N-1_r)] from E[Q(N)] and is handed (L, N, Z) alone, with no arrival rate and no rate function, so an open chain gives it nothing to recur on and the recursion falls out with every metric at zero. ONE list: mva_feature_set drops OpenClass for these, mva::mva_closed_population_reason refuses them by name at solve time, and mva::list_valid_methods withholds them where they cannot run.

Definition at line 138 of file solver_feature_sets.h.

References mva_base_method(), and mva_is_closed_population_method().

Referenced by line::mva::mva_closed_population_reason(), mva_feature_set(), and mva_is_closed_population_method().

◆ mva_unset_non_bcmp_sched()

void line::qn::mva_unset_non_bcmp_sched ( FeatureSet & f)
inline

Drops every scheduling name OUTSIDE the BCMP set {INF, PS, FCFS, SIRO, LCFS-PR} that the base MVA envelope declares.

The chain algorithms that walk the stations one by one – the summation method, MVAC and QNA – accept the BCMP set and refuse the rest, so each drops these from its own envelope rather than answering a station it has no arm for.

Definition at line 156 of file solver_feature_sets.h.

References mva_unset_non_bcmp_sched(), and line::qn::FeatureSet::unset().

Referenced by mva_feature_set(), and mva_unset_non_bcmp_sched().

◆ nc_feature_set()

FeatureSet line::qn::nc_feature_set ( const std::string & method)
inline

SolverNC.getFeatureSet, 48 names, transcribed unchanged.

Region is declared DELIBERATELY (SolverNC.m:185-190): NC solves the open single-Delay loss network exactly and a boolean cannot express that split, so the queueing-station case stays as the imperative refusal at solver_nc_runner.h:315-332. DPS, GPS and HOL appear under cpp/.../nc/ but are absent here because MATLAB's NC refuses them and MATLAB is ground truth.

Definition at line 380 of file solver_feature_sets.h.

References nc_feature_set(), line::qn::FeatureSet::set(), and line::qn::FeatureSet::unset().

Referenced by line::autosolver::auto_supports(), nc_feature_set(), and line::nc::solver_nc_solve().

◆ pad_tags()

template<typename T>
void line::qn::pad_tags ( EventOutcome< T > & out)
inline

Bring the tag vectors up to one entry per successor, so a caller can index them exactly like space.

Definition at line 88 of file state_events.h.

References pad_tags(), line::qn::EventOutcome< T >::preempt, line::qn::EventOutcome< T >::space, and line::qn::EventOutcome< T >::start.

Referenced by after_event_station_arv(), after_event_station_dep(), after_event_station_pas(), after_event_station_retry(), after_event_station_switch(), and pad_tags().

◆ pas_increments()

template<class T, class F>
std::vector< double > line::qn::pas_increments ( const F & mu_fun,
const std::vector< std::size_t > & c )
inline

Port of State.afterEventStationPAS: events at a pass-and-swap station.

The state here is NOT the [buffer | server] split every other discipline uses: it is the full ordered list of class indices, left-aligned and zero padded, with no server block at all. Service is governed by the rate function mu(c) rather than by a per-class rate, so the whole notion of "in service" is replaced by a token at each position. Per-position service rate increments Delta_mu(c1..cp) = mu(c1..cp) - mu(c1..c_{p-1}).

Definition at line 2380 of file state_events.h.

References pas_increments().

Referenced by pas_increments(), and pas_tag_started().

◆ pas_multiset_perms()

std::vector< std::vector< std::size_t > > line::qn::pas_multiset_perms ( const std::vector< std::size_t > & vec)
inline

Port of matlab/util/multiset_perms.m on an ASCENDING multiset, ROW ORDER INCLUDED.

(Until 2026-08-19 the reference was the vendored uniqueperms.m, removed for want of a license grant; the replacement reproduces its listing exactly, so this port is unchanged.)

The row order is not an aesthetic choice: row 0 is what default_init_state takes as the initial state, so it decides which communicating class a chain made reducible by the swap graph settles in. The reference's own ordering is inconsistent between its two branches and is mirrored here rather than normalised: an all-distinct multiset goes through perms, which is REVERSE lexicographic (descending first), while a multiset with a repeat recurses over its unique values in ASCENDING order. Both are reproduced.

The caller supplies vec sorted ascending, which is what the class-major build in the PAS arm of from_marginal_core produces; the recursion erases one element and preserves that order.

Definition at line 519 of file state.h.

References pas_multiset_perms().

Referenced by from_marginal_core(), and pas_multiset_perms().

◆ pas_tag_started()

template<class T, class F>
void line::qn::pas_tag_started ( EventOutcome< T > & out,
const F & mu_fun,
const std::vector< std::size_t > & cold,
const std::vector< std::size_t > & cnew )
inline

Tag the successor just appended to OUT with the PAS positions that started service on it: those of CNEW that are served (Delta_mu > 0) and were not served in COLD.

Under a swap the tag follows the POSITION rather than the job identity, since pass-and-swap redefines which job holds a position.

Definition at line 2399 of file state_events.h.

References pas_increments(), pas_tag_started(), line::qn::EventOutcome< T >::space, and tag_last().

Referenced by after_event_station_pas(), and pas_tag_started().

◆ pass_and_swap()

template<class T>
std::pair< std::vector< std::size_t >, std::size_t > line::qn::pass_and_swap ( const std::vector< std::size_t > & c,
std::size_t p,
const std::vector< std::vector< bool > > & G )

Port of State.passAndSwap: the transition a service completion triggers at a pass-and-swap station (Dorsman and Gardner 2024, Sect.

2.3).

The completing job scans FORWARD from its own position for the first job it may swap with per the graph G, takes that job's place and ejects it; the ejected job repeats the scan. The chain ends at a job with no swappable successor, and THAT job departs – which is why the departing class is in general not the class whose service completed.

Parameters
c0-based list of 1-based class indices, oldest first
p0-based position whose service token completed
Gclass-compatibility graph, G[a][b] true when a may swap with b
Returns
(the list after the transition, the 1-based departing class)

Definition at line 2338 of file state_events.h.

References line::InputError::InputError(), and pass_and_swap().

Referenced by after_event_station_pas(), and pass_and_swap().

◆ phase_rates()

template<class T>
std::pair< std::vector< T >, std::vector< T > > line::qn::phase_rates ( const NetworkStruct< T > & sn,
std::size_t ist,
std::size_t cls )

sn.mu and sn.phi for one (station, class), derived as MATLAB's Markovian.getMu / getPhi derive them from the (D0, D1) pair:

mu(k) = -D0(k,k) total exit rate of phase k phi(k) = sum_j D1(k,j) / -D0(k,k) probability the exit COMPLETES service

so mu*phi is the departure rate and mu*(1-phi) the phase-advance rate. An Immediate process has D0(1,1) = 0 and takes phi = 1, since every exit of a zero-duration service is a completion.

Definition at line 768 of file state_events.h.

References line::lang::Distrib< T >::D0, line::lang::Distrib< T >::D1, and phase_rates().

Referenced by after_event_station_dep(), and phase_rates().

◆ polling_blocks()

template<class T>
std::vector< std::vector< T > > line::qn::polling_blocks ( const PollingInfo< T > & pi,
std::size_t srvclass,
const std::vector< std::size_t > & nbuf )

Port of State.pollingBlocks + State.pollingProject: every controller configuration compatible with one (buffer, server) row.

ENUMERATING PER ROW rather than taking a blind cartesian product is what keeps the space tight and the chain irreducible. pos is PINNED to the class in service; a switchover excludes a busy facility; and a park excludes a non-empty station, because with only immediate switchovers the server would have reached the waiting work in zero time. A cartesian product would admit "serving buffer 1 while a class-2 job holds the server", which no transition can enter or leave consistently with the marginals.

Parameters
srvclass1-based class holding the single service facility, 0 if idle
nbufper-class waiting counts
pithe polling configuration of the station
Returns
one row per configuration, PROJECTED onto the columns pinfo materializes; the elided ones are reconstructible from the rest of the state (polling_get), so keeping them would split each state into copies no observation can tell apart

Definition at line 933 of file state.h.

References line::lang::DECREMENTING, line::lang::EXHAUSTIVE, line::lang::GATED, line::qn::PollingInfo< T >::has_sw, line::qn::PollingInfo< T >::ictr, line::qn::PollingInfo< T >::ipos, line::qn::PollingInfo< T >::iswk, line::lang::KLIMITED, line::qn::PollingInfo< T >::ksw, line::qn::PollingInfo< T >::pk, line::qn::PollingInfo< T >::polled, polling_blocks(), and line::qn::PollingInfo< T >::ptype.

Referenced by append_local_vars(), and polling_blocks().

◆ polling_budget()

template<class T>
long line::qn::polling_budget ( const PollingInfo< T > & pi,
long nbufq )

◆ polling_get()

template<class T>
void line::qn::polling_get ( const PollingInfo< T > & pi,
const std::vector< T > & var,
std::size_t srvclass,
std::size_t & pos,
std::size_t & swk,
long & ctr )

Defined below; the polling branches of ARV, DEP and SWITCH use these.

Read (pos, swk, ctr) out of the local-variable block.

Definition at line 2637 of file state_events.h.

References line::qn::PollingInfo< T >::ictr, line::qn::PollingInfo< T >::ipos, line::qn::PollingInfo< T >::iswk, line::qn::PollingInfo< T >::off, and polling_get().

Referenced by after_event_station_arv(), after_event_station_dep(), after_event_station_switch(), and polling_get().

◆ polling_info()

◆ polling_land()

template<class T>
void line::qn::polling_land ( const NetworkStruct< T > & sn,
std::size_t ist,
const PollingInfo< T > & pi,
std::size_t q,
int mode,
long budget,
const std::vector< T > & buf,
const std::vector< T > & srv,
const std::vector< T > & var,
const RowLayout< T > & L,
std::vector< std::vector< T > > & rows,
std::vector< T > & probs )

◆ polling_next()

template<class T>
void line::qn::polling_next ( const PollingInfo< T > & pi,
std::size_t pos,
const std::vector< long > & nbuf,
std::size_t R,
bool arrived,
std::size_t & q,
int & mode,
long & budget )

Port of State.pollingNext: where the server goes from buffer pos.

Returns mode 1 to open a visit at q, 2 to enter the switchover into q, and 0 to PARK. Parking is reachable only with every switchover immediate, where a server completing a full lap without finding work would otherwise cycle in zero time forever.

Definition at line 2684 of file state_events.h.

References line::qn::PollingInfo< T >::has_sw, line::qn::PollingInfo< T >::polled, polling_budget(), and polling_next().

Referenced by after_event_station_arv(), after_event_station_dep(), after_event_station_switch(), and polling_next().

◆ polling_set()

template<class T>
std::vector< T > line::qn::polling_set ( const PollingInfo< T > & pi,
std::vector< T > var,
std::size_t pos,
std::size_t swk,
long ctr )

◆ prio_pop()

template<class T>
PrioPop< T > line::qn::prio_pop ( const NetworkStruct< T > & sn,
std::size_t ist,
const Marginal< T > & m,
std::size_t cls,
double ni,
double S )

Compute the *PRIO effective population; a no-op for every other discipline.

Definition at line 854 of file state_events.h.

References line::qn::PrioPop< T >::masked, line::qn::PrioPop< T >::ni, line::qn::Marginal< T >::nir, line::qn::PrioPop< T >::nir, prio_pop(), and line::qn::PrioPop< T >::served.

Referenced by after_event_station_dep(), prio_pop(), and service_share().

◆ qns_feature_set()

FeatureSet line::qn::qns_feature_set ( const std::string & )
inline

SolverQNS.getFeatureSet, transcribed WHOLE.

THE SECOND SET IN THIS FILE THAT IS NOT NARROWED, for ldes_feature_set's reason and no other: SolverQNS implements no numerics. It writes the JMVA document qnsolver reads, or converts the model through qn2lqn and hands it to lqns – the same two routes, through the same two external binaries, that solver_qns.m drives. The code that has to support a declared feature is therefore the binary the reference also runs, so narrowing here would refuse models the reference answers with the very process this port is about to start.

WHERE THE REAL REFUSALS LIVE, all of them at solve time and none expressible as a boolean over feature names: qns::detail::check_supported a station that is not a Queue, a Delay or a Source, and class priorities, on the JMVA route only – the layered route legitimately carries Join nodes the document cannot encode qn::check_binding_capacity a finite buffer, which neither binary models the multiserver gate 'suri' and 'schmidt' reach LQNS and not qnsolver -m

SOURCE: matlab/src/solvers/wrappers/QNS/@@SolverQNS/SolverQNS.m, name for name. Normal is the one name dropped: it has a registry enumerator here, and write_jmva reduces every law to its mean, so a Normal service is written as its mean like any other – but a Normal law admits negative samples and the reference's own JMT writer refuses it (see jmt_feature_set), so declaring it on this route alone would be the only place in the port that accepts it.

Definition at line 1811 of file solver_feature_sets.h.

References qns_feature_set(), and line::qn::FeatureSet::set().

Referenced by qns_feature_set().

◆ refresh_global_sync()

template<class T>
std::vector< GlobalSync< T > > line::qn::refresh_global_sync ( const NetworkStruct< T > & sn)

Port of MNetwork.refreshGlobalSync: the ENABLE and FIRE synchronizations.

An inhibiting place enters as a LOCAL passive rather than a PRE, and only when it is not already an enabling or firing place: its marking is read for the inhibition test but no token crosses the arc.

Definition at line 3204 of file state_events.h.

References line::qn::GlobalSync< T >::active, line::Matrix< T >::cols(), line::qn::TransitionParam< T >::enabling, line::qn::TransitionParam< T >::firing, line::qn::TransitionParam< T >::inhibiting, line::qn::TransitionParam< T >::nmodes, line::qn::GlobalSync< T >::passive, refresh_global_sync(), and line::Matrix< T >::rows().

Referenced by refresh_global_sync(), line::ssa::solver_ssa_reachability(), and line::ssa::SsaSerialEngine< T >::SsaSerialEngine().

◆ refresh_sync()

template<class T>
std::vector< Sync< T > > line::qn::refresh_sync ( const NetworkStruct< T > & sn,
const std::vector< std::vector< bool > > & impatience_classes = std::vector<std::vector<bool>>(),
const std::vector< std::size_t > & breakdown_nodes = std::vector<std::size_t>() )

Port of MNetwork.refreshSync: the synchronization list.

The ORDER matters as much as the content: the generator adds rates in this order, and while addition is commutative in exact arithmetic it is not in floating point, so a reordered list perturbs the last digits of every reported metric.

Parameters
impatience_classes(station x class) true where reneging is declared
breakdown_nodes1-based node indices with a server breakdown
snthe refreshed network struct

Definition at line 3683 of file state_events.h.

References line::qn::Sync< T >::active, line::qn::PollingInfo< T >::has_sw, line::qn::NodeDef::nodetype, line::qn::Sync< T >::passive, polling_info(), refresh_sync(), line::qn::NodeDef::routing, line::qn::NodeDef::stateful, line::qn::NodeDef::station, and line::qn::PollingInfo< T >::valid.

Referenced by refresh_sync(), line::ssa::solver_ssa_reachability(), and line::ssa::SsaSerialEngine< T >::SsaSerialEngine().

◆ reply_block_info()

template<class T>
ReplyBlockInfo line::qn::reply_block_info ( const NetworkStruct< T > & sn,
std::size_t ind )

Defined below; the departure branch records a server held for a reply.

Port of State.replyBlockInfo: the layout of the reply block.

The block trails the modulation, routing and shared-node columns of nvars, occupying columns 2R+1+r. Appending is deliberate – every existing nvars reader keeps its indices, and the columns stay zero-width for models without reply signals, so no other model changes state width.

Definition at line 2511 of file state_events.h.

References line::qn::ReplyBlockInfo::classes, reply_block_info(), line::qn::ReplyBlockInfo::slot, and line::qn::ReplyBlockInfo::width.

Referenced by after_event_station(), after_event_station_dep(), after_event_station_reply(), reply_block_info(), reply_blocked(), and line::ctmc::solver_ctmc_avg_from_pi().

◆ reply_blocked()

template<class T>
double line::qn::reply_blocked ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & var )

Defined below; the reply block subtracts held servers in the ARV branch.

How many servers node ind is holding for pending replies, from its vars.

Definition at line 2530 of file state_events.h.

References line::qn::ReplyBlockInfo::classes, reply_block_info(), reply_blocked(), and line::qn::ReplyBlockInfo::slot.

Referenced by after_event_station_arv(), after_event_station_dep(), after_event_station_reply(), and reply_blocked().

◆ routing_to_text()

const char * line::lang::routing_to_text ( RoutingStrategy r)
inline

Definition at line 402 of file lang_types.h.

Referenced by line::qn::NetworkStruct< T >::refresh_routing().

◆ row_layout()

◆ rr_advance_row()

template<class T>
void line::qn::rr_advance_row ( const NetworkStruct< T > & sn,
std::size_t ind,
std::size_t cls,
std::vector< std::vector< T > > & rows )

Port of State.afterEventStation's dispatch: the successors of one event at one station.

Advance the round-robin dispatch pointer of (IND, CLS) in every successor row.

The event-specific rates that are not derivable from sn alone – patience, retrial and breakdown – are passed in, because the reference reads them from fields (impatienceMu, retrialMu, breakdownMu) that this port has not yet grown. Every rate that IS derivable is computed from the struct.

The local-variable block is the TAIL of a state row, so the pointer is located from the right; rr_var_slot gives its 1-based index inside that block. A no-op wherever the pair does not dispatch round-robin.

Definition at line 1779 of file state_events.h.

References rr_advance_row().

Referenced by after_event_router(), after_event_station(), and rr_advance_row().

◆ rt_state()

template<class T>
Matrix< T > line::qn::rt_state ( const NetworkStruct< T > & sn,
const std::vector< std::vector< T > > & local )

Port of sn.rtfun: the routing over the stateful nodes AT ONE STATE.

rt is a constant matrix because almost every routing strategy is; SDR is not, and eq. (10) of Krzesinski (1987) makes the split out of the entry centre a function of the branch and subnetwork populations. This rebuilds the node-level table with the SDR rows re-evaluated at local and eliminates the stateless nodes through the SAME stochastic complement rt is built with, so a model with a Router between the centres is complemented identically either way.

The residual mass returns the customer to the departure centre – the busy form of waiting of Sec. 2.5 – and a branch closed by its own population bound simply receives nothing, because pfqn_sdrprob returns zero there.

sub_sdr returns zero off the class diagonal: SDR does not switch class, so only the (r, r) block of the entry row carries mass.

Parameters
snthe refreshed network struct
localper-stateful-node state rows, the NetState::local of the state
Returns
the (nstateful * nclasses) square routing table at that state

Definition at line 375 of file state.h.

References line::InputError::InputError(), line::pfqn::pfqn_sdrcoeff(), line::pfqn::pfqn_sdrped(), line::pfqn::pfqn_sdrprob(), line::qn::NodeDef::routing, line::Matrix< T >::rows(), rt_state(), and station_populations().

Referenced by rt_state(), and line::ctmc::solver_ctmc().

◆ service_share()

template<class T>
T line::qn::service_share ( const NetworkStruct< T > & sn,
std::size_t ist,
const Marginal< T > & m,
std::size_t cls,
double ni,
double S )

Defined below; DEP and PHASE must share one definition of the share.

The fraction of the station's capacity a class-cls job in phase k receives, which is the only part of the rate the discipline decides.

PHASE and DEP share this factor exactly: an internal phase transition is driven by the same server share as a completion, which is why a job under PS advances through its phases more slowly when the station is busy. Only the MATRIX differs – D0(k,kdest) for a phase advance, D1 for a completion.

Definition at line 1342 of file state_events.h.

References line::qn::PrioPop< T >::ni, line::qn::PrioPop< T >::nir, prio_pop(), line::qn::PrioPop< T >::served, service_share(), and line::UnsupportedError::UnsupportedError().

Referenced by after_event_station_dep(), after_event_station_phase(), and service_share().

◆ signal_batch_pmf()

template<class T>
std::pair< std::vector< std::size_t >, std::vector< T > > line::qn::signal_batch_pmf ( const NetworkStruct< T > & sn,
std::size_t cls,
std::size_t ntot )

Port of State.signalBatchPMF: the batch size a negative signal removes.

The pmf is CLIPPED at the eligible population: an oversized batch empties the station rather than driving the queue negative, so the whole tail P(B >= n) lumps onto "remove all n". That is the same clipping LDES applies with min(B,n) and the tail term MAM uses.

Definition at line 2025 of file state_events.h.

References signal_batch_pmf().

Referenced by after_event_station_signal(), and signal_batch_pmf().

◆ sn_fj_supports()

template<class T>
std::string line::qn::sn_fj_supports ( const NetworkStruct< T > & sn)

Can the exact fork-join construction be asked for this model?

The fork-join model class sn_fj_validate admits, asked as a predicate rather than thrown, so that a REPORT can reach it: solver_ctmc_analyzer and the SSA runner reach the SAME rules through fj_tag, which calls the validator on its first line. The message the validator throws is about "the exact fork-join implementation", which both share, so this predicate belongs beside it rather than inside either solver.

IT WRAPS THE VALIDATOR RATHER THAN RESTATING IT, and that is the point: the rules are eight and they move (pairing, join strategy, tasks-per-link, branch probability, open classes through a fork), so a second copy would be a second thing to keep in step. There is exactly one body of rules and two ways in – one that throws, for the run, and this one, which answers.

WHAT IT REFUSES AND WHY THE ANALYZER IS RIGHT TO. The fork-join PAIRING is a declaration carried by the Join (Join(model, name, fork) in all four codebases), not a derivation from the routing: a nested model such as fj_basic_nesting has two forks and two joins whose pairing the routing alone does not determine. So a Join built without naming its fork leaves sn.fj empty, and "has no matched Join" is the honest answer to a model that declares none – not a topology test that failed to see one.

Parameters
snthe refreshed struct of the model
Returns
an empty string when the fork-join construction may run

Definition at line 282 of file fj_tag.h.

References sn_fj_supports(), and sn_fj_validate().

Referenced by line::autosolver::auto_family_refusal(), and sn_fj_supports().

◆ sn_fj_validate()

template<class T>
void line::qn::sn_fj_validate ( const NetworkStruct< T > & sn)

Port of sn_fj_validate: is this fork-join model inside the exact solver's reach?

The checks here are the STRUCTURAL ones that can be asked of the original struct; the branch-level ones (class switching on a branch, nesting, sibling traps) can only be asked during branch discovery and are raised there.

Definition at line 106 of file fj_tag.h.

References line::qn::ForkParam< T >::fan_out_dist, line::qn::ForkParam< T >::fan_out_link, line::qn::ForkParam< T >::fan_out_prob, line::qn::NodeDef::name, line::lang::PARTIAL, sn_fj_validate(), line::lang::STD, line::qn::NodeDef::tasks_per_link, and line::UnsupportedError::UnsupportedError().

Referenced by fj_tag(), sn_fj_supports(), and sn_fj_validate().

◆ space_capacity_c()

template<class T>
std::vector< std::vector< std::size_t > > line::qn::space_capacity_c ( const NetworkStruct< T > & sn,
const std::vector< std::size_t > & cutoff,
const std::vector< std::vector< std::size_t > > & cutoff_mat = std::vector<std::vector<std::size_t>>() )

Port of the capacityc table of State.spaceGeneratorNodes: the largest class-r marginal node ind may hold in the enumerated space.

WITHOUT THIS TABLE THE LATTICE IS PLACED BLIND. space_closed_multi_cs spreads a class's population over EVERY stateful node, including the ones the class never visits, so a mixed model enumerates open jobs at a closed-only station and closed jobs at an open-only one. Those states are unreachable, but they are not free: they enlarge the generator, and on mqn_multiserver_fcfs (1904 states against the reference's 1304) they moved the Source's departure rate from 0.24763 to 0.26040 – an arrival rate the model never offers.

The bound is the reference's, in its order: a class that does not visit the node is capped at its DECLARED initial occupancy (nonzero only for an SPN Place, which may hold tokens at time zero without ever being re-entered), a disabled service at 0, an open class at its cutoff and a closed one at its chain population, both cut down by the station's per-class buffer and then by any finite-capacity region the station belongs to.

Parameters
snthe network struct
cutoffper-class population bound for open classes
cutoff_matoptional (nstations x nclasses) bound, the reference's matrix options.cutoff; overrides cutoff per station
Returns
(nnodes x nclasses) capacities, 0-based in both indices

Definition at line 2190 of file state.h.

References line::qn::NetworkStruct< T >::Region::cap, line::qn::NodeDef::nodetype, space_capacity_c(), state_initial_occupancy(), line::qn::NodeDef::stateful, and line::qn::NodeDef::station.

Referenced by space_capacity_c(), and space_generator().

◆ space_closed_multi()

template<class T>
std::vector< std::vector< T > > line::qn::space_closed_multi ( std::size_t M,
const std::vector< std::size_t > & N,
const std::vector< std::vector< long > > & caps = std::vector<std::vector<long>>() )

Port of State.spaceClosedMulti: how N[r] class-r jobs distribute over M stateful nodes, for every class, as the cartesian fold of the per-class placements.

Column block r holds class r's counts, M columns wide.

Definition at line 2058 of file state.h.

References cartesian(), space_closed_multi(), space_closed_single(), and space_closed_single_capped().

Referenced by space_closed_multi(), and space_closed_multi_cs().

◆ space_closed_multi_cs()

template<class T>
std::vector< std::vector< T > > line::qn::space_closed_multi_cs ( std::size_t M,
const std::vector< std::size_t > & N,
const std::vector< std::vector< bool > > & chains,
const std::vector< std::vector< long > > & caps = std::vector<std::vector<long>>() )

Port of State.spaceClosedMultiCS: the same, but a CHAIN's population is shared among its classes, so the split between them is itself enumerated.

Class switching moves a job between classes of one chain, so only the CHAIN total is invariant. Enumerating over per-class populations alone would fix a split the model does not fix, and drop every state reachable by a switch.

Parameters
Mnumber of stateful nodes (sources excluded by the caller)
Nper-class populations
chainschains[c][r] true when class r belongs to chain c

Definition at line 2085 of file state.h.

References line::Matrix< T >::empty(), line::pfqn::multichoose_rows(), space_closed_multi(), and space_closed_multi_cs().

Referenced by space_closed_multi_cs(), and space_generator().

◆ space_closed_single()

template<class T>
std::vector< std::vector< T > > line::qn::space_closed_single ( std::size_t m,
std::size_t n )

Port of State.spaceClosedSingle: the ways to place n jobs over m phases.

m == 0 yields NO rows, not one empty row – a class with no service process contributes nothing, and returning an empty row instead would let it multiply the product by one and silently survive the fold.

Definition at line 437 of file state.h.

References line::pfqn::multichoose_rows(), and space_closed_single().

Referenced by from_marginal_core(), from_marginal_node(), from_marginal_node_first(), space_closed_multi(), and space_closed_single().

◆ space_closed_single_capped()

template<class T>
std::vector< std::vector< T > > line::qn::space_closed_single_capped ( std::size_t m,
std::size_t n,
const std::vector< long > & caps )

◆ space_closed_single_capped_rec()

template<class T>
void line::qn::space_closed_single_capped_rec ( std::size_t m,
long n,
const std::vector< long > & caps,
std::size_t off,
std::vector< T > & row,
std::vector< std::vector< T > > & out )

space_closed_single with a PER-SLOT bound, the reference's spaceClosedSingle(M, N, caps).

The bound is applied BEFORE recursing, which is the whole point: a slot of capacity 0 takes only the zero item, so a class that can occupy one node out of M enumerates M rows rather than binomial(n+M-1, M-1). The unbounded form generates the full lattice and leaves the caller to reject the impossible rows one at a time, at one from_marginal call each.

caps is one entry per slot; an entry of -1 means unbounded.

Definition at line 466 of file state.h.

References space_closed_single_capped_rec().

Referenced by space_closed_single_capped(), and space_closed_single_capped_rec().

◆ space_generator()

template<class T>
std::vector< NetState< T > > line::qn::space_generator ( const NetworkStruct< T > & sn,
const std::vector< std::size_t > & cutoff,
std::size_t maxst = 3000000,
const std::vector< std::vector< std::size_t > > & cutoff_mat = std::vector<std::vector<std::size_t>>() )

Port of State.spaceGenerator: every network state, reachable or not.

The population lattice is walked with space_closed_multi_cs, and each lattice row is expanded per node through from_marginal; the network states are the cartesian product of those local spaces. An open class has no finite population, so cutoff bounds it – WITHOUT a cutoff the lattice is infinite and the reference errors rather than truncating silently.

Parameters
snthe network struct
cutoffper-class population bound for open classes
maxstrefuse beyond this many states (the reference's ctmc_max_states)
cutoff_matoptional (nstations x nclasses) bound, the reference's matrix options.cutoff

Definition at line 2313 of file state.h.

References from_marginal_node(), line::InputError::InputError(), line::qn::NetState< T >::local, space_capacity_c(), space_closed_multi_cs(), space_generator(), and line::UnsupportedError::UnsupportedError().

Referenced by space_generator().

◆ ssa_feature_set()

FeatureSet line::qn::ssa_feature_set ( const std::string & )
inline

SolverSSA.getFeatureSet, 98 MATLAB names.

IT IS THE SOLVER'S REACH, NOT ONE ENGINE'S, and that is what makes it usable: solver_ssa under default runs the NRM when the NRM can run the model and the event-driven serial engine when it cannot, so a construct EITHER engine covers is a construct SolverSSA covers. AUTO chooses this solver on the strength of this set (solver_auto.h:453), so under-declaring costs a model the only solver that can answer it and over-declaring hands AUTO a refusal.

The serial engine applies the SAME event handlers state_events.h gives the CTMC generator, which is why the two sets are now close: a cache access, an SPN firing, a fork firing, a polling controller and the priority shares are all reached through handlers both solvers share. What is DECLARED here is what a test in test_ssa_fj_fcr.cpp or test_ssa_serial.cpp exercises end to end, never what a handler merely appears to support.

Still dropped, with the C++ refusal that proves each: RoutingStrategy_RROBIN, _WRROBIN, _JSQ, _SQ, _RL ssa_dispatch.h refuses them in the NRM and NetworkStruct::refresh_routing refuses the state-dependent ones when the struct is built, so no engine here can receive one SignalType_REPLY the REPLY signal is a LAYERED construct whose guard sits in the model layer; SolverCTMC declares it, this solver has no test for it ssa_check_phases (ssa_dispatch.h) stays imperative: non-exponential service AT a given discipline is a per-(station,class) join of two features and the boolean registry cannot state it. It gates the NRM only – the serial engine expands a phase-type process wherever the CTMC generator does – so a model it refuses is answered by the fallback rather than refused outright.

Definition at line 716 of file solver_feature_sets.h.

References line::qn::FeatureSet::set(), and ssa_feature_set().

Referenced by line::autosolver::auto_supports(), and ssa_feature_set().

◆ state_initial_occupancy()

template<class T>
std::size_t line::qn::state_initial_occupancy ( const NetworkStruct< T > & sn,
std::size_t ind,
std::size_t r )

Port of State.initialOccupancy: the class-r jobs node ind holds in the DECLARED initial state, or 0 when there is none.

Only a Place answers nonzero. Every other node type encodes its local state differently, so column r there is not an occupancy – and a station whose visit ratio is zero is genuinely never entered, while a Place with no input arc is a TRANSIENT state of the chain rather than an absent one.

Definition at line 2154 of file state.h.

References state_initial_occupancy().

Referenced by space_capacity_c(), and state_initial_occupancy().

◆ station_populations()

template<class T>
std::vector< double > line::qn::station_populations ( const NetworkStruct< T > & sn,
const std::vector< std::vector< T > > & local )

Total jobs held by every STATION at one network state, indexed by station.

A Source is an infinite reservoir whose to_marginal reports +Inf, which describes the encoding and not a queue length, so it is reported as zero here exactly as ctmc_state_space_aggr does. A station with no stateful node holds nothing.

Definition at line 330 of file state.h.

References line::qn::Marginal< T >::ni, station_populations(), and to_marginal().

Referenced by rt_state(), and station_populations().

◆ station_swap_graph()

template<class T>
Matrix< T > line::qn::station_swap_graph ( const NetworkStruct< T > & sn,
std::size_t ist )

The swap graph of a PAS / OI station, with the defaults refreshLocalVars.m installs applied.

MATLAB fills sn.nodeparam{ind}.swapGraph at refresh time and NEVER leaves it empty: an OI station always gets zeros(R,R), a PAS station with no explicit graph gets the complete compatibility graph ones(R,R) - eye(R), and an explicit graph is taken as given. The builder here stores the raw user graph, so the defaulting has to happen on read; doing it here rather than in the builder keeps it independent of whether the classes were added before or after set_service_rate_function.

Parameters
snthe struct
ist1-based station index

Definition at line 3732 of file network_struct.h.

References line::Matrix< T >::Matrix(), line::qn::Station< T >::sched, station_swap_graph(), and line::qn::Station< T >::swap_graph.

Referenced by line::nc::solver_nc_pas_is_analyzer(), station_swap_graph(), and station_swap_graph_is_zero().

◆ station_swap_graph_is_zero()

template<class T>
bool line::qn::station_swap_graph_is_zero ( const NetworkStruct< T > & sn,
std::size_t ist )

◆ tag_chain()

template<class T>
TaggedChain< T > line::qn::tag_chain ( const NetworkStruct< T > & sn,
std::size_t chain,
std::size_t jobclass,
const std::string & suffix = ".tagged" )

◆ tag_last()

template<typename T>
void line::qn::tag_last ( EventOutcome< T > & out,
std::size_t start_cls,
std::size_t preempt_cls )
inline

Tag the successor row just appended to OUT: START_CLS begins service on it and PREEMPT_CLS is displaced by it, either 0 for none.

The tag vectors are grown to match space, so only the arcs that carry a tag need to say anything and every other row is an empty list.

Definition at line 75 of file state_events.h.

References line::qn::EventOutcome< T >::preempt, line::qn::EventOutcome< T >::space, line::qn::EventOutcome< T >::start, and tag_last().

Referenced by after_event_station_arv(), after_event_station_dep(), after_event_station_retry(), after_event_station_switch(), pas_tag_started(), and tag_last().

◆ to_marginal()

template<class T>
Marginal< T > line::qn::to_marginal ( const NetworkStruct< T > & sn,
std::size_t ist,
const std::vector< T > & state_i,
const std::vector< std::size_t > & phasesz,
const std::vector< std::size_t > & phaseshift,
std::size_t nvar = 0 )

Port of State.toMarginal for a STATION, one state row at a time.

Parameters
snthe network struct
iststation index (1-based, as elsewhere in NetworkStruct)
state_ithe station's state row
phaseszper-class phase counts
phaseshiftper-class offset into the server block
nvarwidth of the trailing local-variable block, 0 when absent
Returns
the marginal counts; nir is +Inf for every class at a Source

Definition at line 130 of file state.h.

References line::InputError::InputError(), line::qn::Marginal< T >::kir, line::qn::GlobalConstants::MaxInt, line::qn::Marginal< T >::ni, line::qn::Marginal< T >::nir, line::qn::Marginal< T >::sir, and to_marginal().

Referenced by after_event_station_dep(), after_event_station_phase(), after_event_station_renege(), after_event_station_retry(), after_event_station_signal(), line::ctmc::ctmc_signal_busy(), line::ctmc::ctmc_state_space_aggr(), line::api::sn_is_state_valid(), line::ctmc::solver_ctmc_avg_from_pi(), station_populations(), and to_marginal().

◆ to_marginal_aggr()

template<class T>
std::pair< T, std::vector< T > > line::qn::to_marginal_aggr ( const NetworkStruct< T > & sn,
std::size_t ind,
const std::vector< T > & state_i )

Port of State.toMarginalAggr: the job counts of one node's state row, without the per-phase detail to_marginal also computes.

It is NOT simply a projection of to_marginal: it accepts stateful non-stations (whose row is a plain per-class count ahead of the local variables), and it leaves the preemptive families out of its buffer switch, so for those it reports only the jobs IN SERVICE. That asymmetry is the reference's, and it is load-bearing – the arrival branch uses this to test for room, where counting a preempted job twice would refuse a valid arrival.

Parameters
snthe network struct
indNODE index (1-based), as in the reference
state_ithe node's state row
Returns
(ni, nir): total jobs and jobs per class

Definition at line 110 of file state_events.h.

References line::InputError::InputError(), line::qn::GlobalConstants::MaxInt, line::qn::NodeDef::nodetype, line::qn::NodeDef::station, and to_marginal_aggr().

Referenced by after_event_station_arv(), after_fj_event(), after_global_event(), line::ctmc::ctmc_find_vanishing_states(), line::api::sn_declared_marginal(), line::api::sn_get_state_aggr(), and to_marginal_aggr().

◆ used_lang_features()