![]() |
LINE Solver (C++)
Templated C++ port of the LINE queueing solver
|
The second-order fluid methods: fluid_moment_terms.m, fluid_lyapunov.m, fluid_drift_jacobian.m, fluid_refine_meanfield.m and solver_fluid_moments.m, which back options.method minnormal and refined. More...
#include "line/util/line_console.h"#include <algorithm>#include <cmath>#include <cstddef>#include <limits>#include <string>#include <vector>#include "line/lang/qn/network_struct.h"#include "line/solvers/fluid/fluid_closures.h"#include "line/solvers/fluid/fluid_nonhyperbolic.h"#include "line/solvers/fluid/fluid_odes.h"#include "line/solvers/fluid/solver_fluid.h"#include "line/util/eig.h"#include "line/util/error.h"#include "line/util/linalg.h"#include "line/util/matrix.h"#include "line/util/svd.h"#include "line/util/sylvester.h"Go to the source code of this file.
Classes | |
| struct | line::fluid::FluidLyapunovInfo |
| The reference's MException('LINE:FluidNonHyperbolic'), as a type. More... | |
| struct | line::fluid::FluidMomentTerms |
| Port of fluid_moment_terms.m: the event representation of the fluid population process, plus the drift, rate and Jacobian handles the covariance equation needs. More... | |
| struct | line::fluid::FluidRefineInfo |
| What fluid_refine_meanfield reports about the correction it computed. More... | |
Namespaces | |
| namespace | line |
| namespace | line::fluid |
Functions | |
| FluidClosure | line::fluid::fluid_blend_closure (const FluidClosure &a, const FluidClosure &b, double step) |
| a + step*(b - a) for a closure, entry by entry. | |
| Matrix< double > | line::fluid::fluid_lyapunov (const Matrix< double > &A, const Matrix< double > &Qdiff, const Matrix< double > &D, FluidLyapunovInfo &info, double tol=-1.0) |
| Port of fluid_lyapunov.m: the stationary covariance of the linear noise approximation. | |
| bool | line::fluid::fluid_coord_eliminated (const FluidMomentTerms &t, std::size_t s) |
| True when the immediate reduction folded coordinate s away, so the reduced drift holds no mass there and no event lands on it. | |
| template<class T> | |
| FluidMomentTerms | line::fluid::fluid_moment_terms (const qn::NetworkStruct< T > &sn, const FluidOptions &opt) |
| std::vector< double > | line::fluid::fluid_moment_factors (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl) |
| The rate factors g(x) under a closure: terms.factorFcn. | |
| std::vector< double > | line::fluid::fluid_moment_rates (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl) |
| The event rates r(x) under a closure: terms.ratesFcn. | |
| std::vector< double > | line::fluid::fluid_moment_drift (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl) |
| The drift F(x) = D r(x) under a closure: terms.driftFcn. | |
| Matrix< double > | line::fluid::fluid_drift_jacobian (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl) |
| Port of fluid_drift_jacobian.m: the analytic Jacobian of the fluid drift. | |
| std::vector< std::size_t > | line::fluid::fluid_kink_stations (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl) |
| Every station whose population sits ON the saturation kink n_i = c_i of the first-order rate factor, in increasing order, empty when none does. | |
| std::vector< double > | line::fluid::fluid_nudge_off_kink (const FluidMomentTerms &t, const std::vector< double > &x, const std::vector< std::size_t > &kink, double rel) |
| A copy of x with every station in kink moved to c_i*(1 + rel), i.e. | |
| Matrix< double > | line::fluid::fluid_moment_lyapunov (const FluidMomentTerms &t, const Matrix< double > &A, const std::vector< double > &r, const Matrix< double > *clampT=nullptr) |
| local_lyapunov of solver_fluid_moments.m: the covariance on the coordinates that carry a real population, scattered back to full size. | |
| std::vector< double > | line::fluid::fluid_refine_meanfield (const FluidMomentTerms &t, const std::vector< double > &x, const FluidClosure &cl, const Matrix< double > &Sigma, FluidRefineInfo &info, double epsrel=1e-4) |
| Port of fluid_refine_meanfield.m: the O(1/N) refined mean field correction of Gast (POMACS 2017). | |
| template<class T> | |
| FluidSolution | line::fluid::solver_fluid_moments (const qn::NetworkStruct< T > &sn, const FluidOptions &opt) |
| Port of solver_fluid_moments.m: the second-order fluid analysis backing minnormal and refined. | |
The second-order fluid methods: fluid_moment_terms.m, fluid_lyapunov.m, fluid_drift_jacobian.m, fluid_refine_meanfield.m and solver_fluid_moments.m, which back options.method minnormal and refined.
WHY THE PORT NEEDED THESE AT ALL, given that the first-order methods already answered every model. minnormal is what the REFERENCE'S default resolves to wherever it applies (fluid_resolve_default_method.m), so without it the port answered a different method than the reference under the same name – and answered it less accurately, since the first-order closure replaces E[min(X,c)] by min(E[X],c) and is worst exactly at rho ~ 1. On the reference's own sweep (Delay(Z=1) -> Queue(PS, c=2), N=6) the exact CTMC queue length is 1.95137, closing returns 2.00000 and minnormal 1.96063.
WHAT THE SECOND MOMENT IS, and why a fluid solver has one. The closing ODEs are a density-dependent Markov population process
dx/dt = F(x) = D r(x), r_e(x) = rateBase_e g_e(x)
whose fluctuation process Z = X - x* obeys, to leading order, dZ = A Z dt + sqrt(D diag(r) D') dW with A = dF/dx. That linear noise approximation has a stationary covariance, the solution of the Lyapunov equation A Sigma + Sigma A' + D diag(r) D' = 0, and THAT is the second moment reported through getMoments. solver_fluid_odes.m throws D and r away once it has composed F, which is why fluid_moment_terms rebuilds them: the diffusion matrix cannot be recovered from F alone.
THE TWO METHODS DIFFER IN WHICH FIXED POINT THEY EXPAND ABOUT, and mixing them would count the same term twice. minnormal solves mean and covariance self-consistently, so its fixed point already RESUMS the O(1/N) correction – expanding E[F(X)] to second order and setting it to zero reproduces the Gast correction equation exactly. refined therefore recomputes the base point with the FIRST-order closure and adds the correction to that.
Definition in file fluid_moments.h.