Fix inverse CDF tail refinement and Gamma regression - #174
Conversation
Retain the Chebyshev nodes bracketing tail cutoffs so refinement does not discard resolved probability mass. Replace the flaky Gamma sample-mean assertion with a deterministic conditional-CDF identity over an explicit probability grid. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
|
Investigation scratchpad for commit
No public API was added or changed; the explicit-probability hook is package-internal and drives the same inverse-CDF implementation used by |
Command-level verification appendixCommit and base
Clean-base stochastic reproduction julia --project=. --startup-file=no -e '
using PolyChaos, Random, Statistics, Test
Random.seed!(21)
samples = sampleMeasure(5000, GammaMeasure(2.0, 1.0); method = "inversecdf")
@test isapprox(mean(samples), 2.0; atol = 0.05)
'Observed Across 200 seeds:
An independent Deterministic regression before the fix After adding the explicit 999-point probability-grid identity but before changing the cutoff indices: julia --project=. --startup-file=no -e 'include("test/inverse_transform_sampling.jl")'Result: 15 passed, 1 failed. At requested probability Owner-public reference API evidence The regression uses only Distributions.jl's documented public reference interface:
Local ownership/export verification on the tested graph: (gamma_exported = true, gamma_owner = Distributions,
cdf_exported = true, cdf_owner = Distributions)No dependency internal or re-export-only name is used. After-fix commands and counts # focused
julia --project=. --startup-file=no -e 'include("test/inverse_transform_sampling.jl")'
# 16/16
# focused, repeated in one process
julia --project=. --startup-file=no -e '
for iteration in 1:10
include("test/inverse_transform_sampling.jl")
end
'
# 10 × 16/16
# package groups
GROUP=Core julia --project=. --startup-file=no -e 'using Pkg; Pkg.test()'
# 20,522/20,522
GROUP=QA julia --project=. --startup-file=no -e 'using Pkg; Pkg.test()'
# 17/17
# all repository Julia files
julia --project=/path/to/runic-env --startup-file=no \
-e 'using Runic; exit(Runic.main(ARGS))' -- --check --verbose .
# 43/43The focused suite also passed 16/16 in separate exact graphs with SpecialFunctions 1.8.8 and 2.8.0. The corrected 999-point grid's maximum conditional-CDF error is |
Summary
Root cause
The statistical failure and the numerical defect were related but distinct.
For
Gamma(2, 1)with 5,000 samples, the sample-mean standard error issqrt(2 / 5000) = 0.02. A 200-seed scan produced an empirical standard deviation of0.02159, and 4/200 means exceeded the test's fixedatol = 0.05. For example, seed 21 gives1.9366639977, so the existing assertion can fail under ordinary Monte Carlo variation.The deterministic CDF comparison also exposed a real refinement bug. The old lower boundary was
0.0547810463, which discards0.00144679235of the reference Gamma mass. The code selected the first Chebyshev node whose CDF was above the cutoff, rather than the preceding node that brackets it. The same off-by-one direction was present at the upper cutoff.After retaining the bracketing nodes, the explicit 999-point conditional-CDF grid has a maximum error of
1.67e-14with no custom tolerance.An isolated
git bisect runidentifiedb059b431e821bfdc57ceb9d69d5db3233abb6f81(Add inverse transform sampling using Chebyshev technology) as the first commit containing the failing behavior and assertion.Investigation workflow
upstream/masterat2f6205d.1.9784477486. The previously recorded2.052681result therefore depended on different ambient RNG consumption, not a Julia patch-level RNG boundary.Distributions.GammaandcdfAPIs, which revealed the dropped lower-tail mass.Verification
GROUP=Core Pkg.test(): 20,522/20,522GROUP=QA Pkg.test(): 17/17