![]() |
LINE Solver (C++)
Templated C++ port of the LINE queueing solver
|
SolverSSA, the EXPLICIT STATE SPACE variant of the Next Reaction Method: a port of solver_ssa_nrm_space.m and of the else branch of solver_ssa_analyzer_nrm.m that consumes it, together with solver_ssa_findenabled.m. More...
#include <algorithm>#include <cmath>#include <cstddef>#include <limits>#include <map>#include <string>#include <type_traits>#include <vector>#include "line/lang/distribution.h"#include "line/lang/qn/network_struct.h"#include "line/lang/qn/state.h"#include "line/lang/qn/state_events.h"#include "line/solvers/ssa/ssa_types.h"#include "line/util/error.h"#include "line/util/matrix.h"Go to the source code of this file.
Classes | |
| struct | line::ssa::EnabledEvent< T > |
| One transition the enabled scan found: where it goes, and at what rate. More... | |
| struct | line::ssa::SsaNrmSpaceOptions |
| The knobs the space variant reads. More... | |
| struct | line::ssa::NrmSpaceState |
| One state of the aggregate chain: the (node, class) populations, and the ordered buffer contents of every buffered node. More... | |
| struct | line::ssa::SsaNrmSpaceRun< T > |
| What solver_ssa_nrm_space.m returns, plus what makes it a measurement. More... | |
| struct | line::ssa::SsaNrmSpaceSolution< T > |
| The metric table, the table it came from, and the stream that produced it. More... | |
| class | line::ssa::NrmSpaceEngine< T > |
| The aggregate NRM engine of solver_ssa_nrm_space.m. More... | |
Namespaces | |
| namespace | line |
| namespace | line::ssa |
Functions | |
| template<class T> | |
| std::vector< EnabledEvent< T > > | line::ssa::ssa_find_enabled (const qn::NetworkStruct< T > &sn, const std::vector< qn::Sync< T > > &sync, const std::vector< qn::GlobalSync< T > > &gsync, const qn::NetState< T > &state, std::vector< std::vector< double > > *arv=nullptr, std::vector< std::vector< double > > *dep=nullptr) |
| Port of solver_ssa_findenabled.m: every synchronization that can fire in state, with the arrival and departure rates each carries. | |
| template<class T> | |
| SsaNrmSpaceRun< T > | line::ssa::solver_ssa_nrm_space (const qn::NetworkStruct< T > &sn, const SsaNrmSpaceOptions &opt) |
| solver_ssa_nrm_space.m: run the tabulating engine. | |
| template<class T> | |
| SsaNrmSpaceSolution< T > | line::ssa::solver_ssa_nrm_space_analyzer (const qn::NetworkStruct< T > &sn, const SsaNrmSpaceOptions &opt) |
| Port of the else branch of solver_ssa_analyzer_nrm.m, the one state_space_gen selects: the means as pi * A over the tabulated states. | |
SolverSSA, the EXPLICIT STATE SPACE variant of the Next Reaction Method: a port of solver_ssa_nrm_space.m and of the else branch of solver_ssa_analyzer_nrm.m that consumes it, together with solver_ssa_findenabled.m.
HOW IT DIFFERS FROM THE PLAIN NRM. solver_ssa_nrm.m integrates the metrics along the path and never stores a state, so its cost is independent of how large the state space is. This variant instead TABULATES the path: it records every distinct state it visits, the time spent in each, and the whole propensity vector at each, and the analyzer then forms the means as pi * A rather than as a running time integral. That is the same answer by a different route – which is exactly what makes the two testable against each other, and what the reference's options.config.state_space_gen switch selects between (none and default take the plain engine, anything else takes this one).
WHAT THE TABLE BUYS. A propensity is a deterministic function of the state, so one observation of it IS its exact value and not a sample mean. The departure rates this variant reports are therefore exact per state, and all the Monte Carlo error left in the answer sits in pi. The plain engine cannot make that separation, because it never learns that two instants were the same state.
WHAT IT COSTS, AND WHY THIS PORT REFUSES OPEN MODELS. The table has one row per distinct state, so the variant is only viable when the reachable space is small enough to enumerate. In the AGGREGATE reaction network an open model has no such space: rtnodes gives a Sink no outgoing routing, so jobs accumulate in its slot forever, and a Source's slot is a fictitious token that every arrival decrements and nothing replenishes. Every firing therefore reaches a state never seen before, the table grows one row per sample, and pi becomes a uniform law over the trace. The reference does not guard this; here an open model is REFUSED BY NAME, as is any closed model whose space exceeds the declared cap, because a truncated table would report a normalized pi over whichever states happened to fit.
NO PHASE EXPANSION. The state is the (node, class) population vector, so a non-exponential service process is not represented: solver_ssa_nrm_space.m reads sn.rates alone and its propensity switch has five arms (EXT, INF, PS, FCFS/LCFS, and non-station). A phase-type process is refused by name rather than silently collapsed onto its mean rate, which would report the right throughput and the wrong queue length.
ONE DELIBERATE DIVERGENCE, and it is a reference defect that MATLAB has already fixed on the other side. solver_ssa_nrm_space.m line 295 draws the destination with 1+find(rand>=cdfVec{kfire},1). find(...,1) returns the FIRST true index and the predicate holds on a prefix, so the expression collapses to 2 for every draw above cdfVec(1): with three or more destinations the third onwards are never selected. solver_ssa_nrm.m line 1464 names this misuse in a comment and uses the inverse CDF instead, and NrmEngine is ported from the fixed form. This file uses the fixed form too, because reproducing the defect would silently misroute jobs and would make the two engines disagree on exactly the models they exist to cross-check.
DOUBLE ONLY, for the reason solver_ssa_nrm.h gives: the clocks are -log(u) of a uniform, there is no exact value to compute, and the answer's error is the Monte Carlo error rather than the rounding.
WHY ssa_find_enabled IS HERE. It is the standalone form of the scan the serial engine inlines (solver_ssa.m carries both and switches on use_inline), and it answers the same question this variant is built around: what can fire from a given state, tabulated rather than evaluated on the fly. It works at the STATE ENCODING level, not on the aggregate populations, so it does not interoperate with the engine below and is not used by it; the two are independent ports that share a file.
Definition in file solver_ssa_nrm_space.h.