Class FluidClosures
options.method='minnormal'
of SolverFluid. Java twin of the MATLAB fluid_lld_scaling,
fluid_min_closure, fluid_capacity_closure,
fluid_share_closure and fluid_gps_share.
The mean-field ODEs of SolverFluid close the moment hierarchy at first
order, replacing E[min(X,c)] by min(E[X],c) and the capacity
share w_j X_j / sum_m w_m X_m by that ratio at the mean. Both are
exact only where the map is locally linear, so their error peaks at the kink,
i.e. exactly where the two means meet (rho ~ 1 at a queueing station). The
functions here return instead the expectation under a normal marginal whose
variance is produced by the covariance (Lyapunov) equation, so mean and
covariance are solved self-consistently by SolverFluidMoments.
Every closure collapses to the first-order expression when its variance argument is zero, so callers share a single code path and the untouched methods are bit-identical.
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classA vector of capacity shares together with its Jacobian, and the joint-closure covariance Cov(S_j,N) and its Jacobian.static final classA closure value together with its first two derivatives with respect to the mean. -
Method Summary
Modifier and TypeMethodDescriptionstatic FluidClosures.ValueDerivcapacityClosure(double n, double c, double s2, double[] lldrow, boolean isInf) Moment closure of the station capacity term psi(X) and of its derivative, mirroring MATLABfluid_capacity_closure.static double[]expansionWeight(double ratio) How much of the second-order correction the series admits at this point, and d tau / d ratio, mirroring MATLABlocal_expansion_weight.static FluidClosures.ShareResultExpected capacity share of a GPS station under a normal marginal, mirroring MATLABfluid_gps_share.static FluidClosures.ValueDerivlldScaling(double[] lldrow, double n) Limited load-dependent rate scaling at a CONTINUOUS population, mirroring MATLABfluid_lld_scaling.static FluidClosures.ValueDerivminClosure(double n, double c, double s2) Specialisation ofminClosure(double, double, double, double, double)to a deterministic second argument.static FluidClosures.ValueDerivminClosure(double n, double c, double s2, double vc, double covNc) Min-normal moment closure ofE[min(X,Y)]for jointly normal X, Y, mirroring MATLABfluid_min_closure.static doublenormcdf(double z) Standard normal cumulative distribution function.static doublenormpdf(double z) Standard normal probability density function.static voidprojectRate(double[] r, double[] xb, boolean capped, double tot) Project a jointly closed per-coordinate service share onto the set it has to live in, mirroring MATLABlocal_project_rate:r >= 0,r <= xbwhere that bound applies, andsum(r) = tot.static FluidClosures.ShareResultshareClosure(Matrix x, Matrix wv, Matrix cov, boolean wantJac) The share closure without the joint-closure covariance.static FluidClosures.ShareResultshareClosure(Matrix x, Matrix wv, Matrix cov, boolean wantJac, boolean wantCov) Second-order closure of the capacity share of a sharing discipline, mirroring MATLABfluid_share_closure.
-
Method Details
-
normcdf
public static double normcdf(double z) Standard normal cumulative distribution function. -
normpdf
public static double normpdf(double z) Standard normal probability density function. -
lldScaling
Limited load-dependent rate scaling at a CONTINUOUS population, mirroring MATLABfluid_lld_scaling.sn.lldscaling(i,:)tabulates the station rate multiplier at integer populations 1..lldlimit, and the discrete solvers read it aslldscaling(i, min(n, lldlimit)). The fluid state is continuous, so the table is read here by linear interpolation between consecutive entries, clamped to the first entry below n=1 and to the last entry above the table end, matching the clamping the CTMC already applies.- Parameters:
lldrow- rate multipliers at populations 1..lldlimit; null or empty means no load dependence and returns a = 1, da = 0n- population, may be non-integer or negative- Returns:
- alpha(n) and d alpha / d n, the latter zero on the clamped tails
-
minClosure
public static FluidClosures.ValueDeriv minClosure(double n, double c, double s2, double vc, double covNc) Min-normal moment closure ofE[min(X,Y)]for jointly normal X, Y, mirroring MATLABfluid_min_closure.This is the closure of Guenther, Stefanek and Bradley (EPEW/UKPEW 2012, LNCS 7587:32-47, eq. 4), in their general two-population form
E[min(X,Y)] = E[X]*Phi((E[Y]-E[X])/th) + E[Y]*Phi((E[X]-E[Y])/th) - th*phi((E[Y]-E[X])/th) th = (Var[X] - 2*Cov[X,Y] + Var[Y])^(1/2)and the derivative with respect to E[X] is
Phi((E[Y]-E[X])/th), the probability that X is the smaller of the two. SolverFluid only ever needs the specialisation Y = c, the deterministic server count: vc = 0 and covNc = 0 give th = sqrt(s2) and the expression collapses to the truncated-normal form. The general arguments are kept so this IS the published closure rather than one instance of it, and so a future state-dependent capacity needs no new derivation.With th = 0 the expressions collapse to
min(n,c)and to the indicator1{n < c}, recovering the first-order closure exactly. The derivative at the kink is taken as 0, the right derivative of min(), which is the convention already implied by the strict inequality test in the closing rate factors.- Parameters:
n- mean of the first argumentc- mean of the second argument (server count when deterministic)s2- variance of the first argumentvc- variance of the second argument (0 when deterministic)covNc- covariance of the two arguments- Returns:
- E[min(X,Y)] and P(X < Y) under the normal marginal
-
minClosure
Specialisation ofminClosure(double, double, double, double, double)to a deterministic second argument. -
capacityClosure
public static FluidClosures.ValueDeriv capacityClosure(double n, double c, double s2, double[] lldrow, boolean isInf) Moment closure of the station capacity term psi(X) and of its derivative, mirroring MATLABfluid_capacity_closure.Every scheduling branch of the closing rate factors scales the coordinates of a station by psi(n_i)/n_i, where psi is how much work the station clears at population n_i:
psi(n) = min(n,c) * alpha(n) at a queueing station psi(n) = n * alpha(n) at an infinite server
and alpha is the limited load-dependent scaling (1 when the station has none). This returns E[psi(X)] for X ~ Normal(n, s2) together with d/dn E[psi(X)]. s2 = 0 gives psi(n) itself, so the first-order closure is the same code path.
Without load dependence the expectation is the closed form of
minClosure(double, double, double, double, double). With a tabulated alpha,lldScaling(double[], double)makes alpha piecewise linear on the integer lattice, so psi is piecewise QUADRATIC with breakpoints at the integers and at c, and the expectation is integrated segment by segment against the normal density using the truncated moments M0, M1, M2. The derivative is E[psi'(X)] by differentiation under the integral sign, valid because psi is Lipschitz.The integration must be exact, NOT a fixed quadrature rule. Gauss-Hermite with fixed nodes applied to a piecewise-linear integrand does not smooth its kinks, it relocates them: the resulting estimate of E[psi] is itself piecewise linear in n, so its second derivative is zero almost everywhere and the 1/N refinement silently returns a null correction. That is what the segment-wise closed form below avoids.
psi is extended by zero below n = 0, the only physically admissible continuation, since a station holding no jobs clears no work.
- Parameters:
n- mean population at the stationc- number of servers (ignored when isInf)s2- population variance, 0 for the first-order closurelldrow- load-dependent scaling, null or empty when absentisInf- true at an infinite-server station- Returns:
- E[psi(X)] and d/dn E[psi(X)]
-
expansionWeight
public static double[] expansionWeight(double ratio) How much of the second-order correction the series admits at this point, and d tau / d ratio, mirroring MATLABlocal_expansion_weight.Every second-order term of the share closure is a term of the series for E[1/v], whose successive terms are in the ratio
Var(v)/v^2, so the truncation is meaningful below 1 and the terms GROW above it. Nothing in the algebra notices: at a near-empty station the corrections come back larger than the quantity they correct, and the drift that follows is not integrable.One on [0,1], zero from 4 up, and the C^1 smoothstep between. Both ends matter. The lower one has to be EXACTLY one on the whole convergent region, so every model already inside it is bit-identical; the upper one has to be reached with a vanishing derivative, because the drift is integrated and a kink in it is what collapses the step size. The thresholds are the series, not a tuning: at ratio 1 successive terms stop shrinking, and at ratio 4 the standard deviation of v is twice its mean, where a non-negative v has essentially no mass near the point being expanded about.
- Parameters:
ratio- Var(v)/v^2 at the point being expanded about- Returns:
- {tau, d tau / d ratio}
-
projectRate
public static void projectRate(double[] r, double[] xb, boolean capped, double tot) Project a jointly closed per-coordinate service share onto the set it has to live in, mirroring MATLABlocal_project_rate:r >= 0,r <= xbwhere that bound applies, andsum(r) = tot.THE JOINT CLOSURE IS AN EXPANSION AND CAN LEAVE THAT SET.
r = s*psi + psi'*Cov(S,N)adds a term that sums to ZERO over the coordinates, so it moves mass between them and its entries can push one past either bound; the first-order sharex_j/n_i*psicannot, being x_j scaled bypsi/n_i <= 1. Either breach ends the same way, because the integrator holds every coordinate non-negative:r_j > x_jdrains coordinate j faster than it holds, the state goes negative and the clamp INJECTS mass.THE UPPER BOUND HOLDS ONLY WITHOUT LOAD DEPENDENCE, which is what CAPPED selects. r is an expected NUMBER in service so
r_j <= x_j, butpsi(n) = min(n,c)*alpha(n)folds the load-dependent scaling into the same variable, and with alpha > 1 the first-order share itself exceeds x_j.Clip, then move the residual onto the coordinates that still have slack in proportion to it, so
sum(r) = totsurvives and the station still clears what its capacity closure says it clears. It is a NO-OP whenever the expansion stayed inside the set, which is why models already inside it are bit-identical.- Parameters:
r- the jointly closed rates, projected in placexb- the coordinate means, the upper bound when cappedcapped- true without load dependence, where r_j <= x_j holdstot- what the capacity closure says the station clears
-