From b832fc3f67231e7f8e7256ef4021ebd94460566a Mon Sep 17 00:00:00 2001 From: tnagler Date: Sun, 23 Aug 2026 22:28:19 +0200 Subject: [PATCH 01/25] Use power transform for one-sided boundaries --- include/kde1d/kde1d.hpp | 62 ++++++++++++++++++++---------- test/test_numerical_invariants.cpp | 16 ++++++++ 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 22d4920..1f5c750 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -140,8 +140,10 @@ class Kde1d double prob0_{ 0.0 }; double loglik_{ NAN }; double edf_{ NAN }; - // Regularizes one-sided log transforms in the units of the fitted data. + // Regularizes one-sided power transforms in the units of the fitted data. double boundary_offset_{ NAN }; + // Makes one-sided transforms dimensionless and scale equivariant. + double boundary_scale_{ 1.0 }; static constexpr double K0_ = 0.3989425; // private methods @@ -363,16 +365,16 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) else distances = xx.array() - xmin_; if (w.size() == 0) { - boundary_offset_ = 1e-5 * stats::median(distances); + boundary_scale_ = stats::median(distances); } else { - boundary_offset_ = - 1e-5 * stats::quantile( - distances, Eigen::VectorXd::Constant(1, 0.5), w)(0); + boundary_scale_ = stats::quantile( + distances, Eigen::VectorXd::Constant(1, 0.5), w)(0); } - if (!(boundary_offset_ > 0.0)) - boundary_offset_ = 1e-5 * distances.maxCoeff(); - if (!(boundary_offset_ > 0.0)) - boundary_offset_ = 1e-5; + if (!(boundary_scale_ > 0.0)) + boundary_scale_ = distances.maxCoeff(); + if (!(boundary_scale_ > 0.0)) + boundary_scale_ = 1.0; + boundary_offset_ = 1e-5 * boundary_scale_; } xx = boundary_transform(xx); @@ -779,11 +781,17 @@ Kde1d::boundary_transform(const Eigen::VectorXd& x, bool inverse) x_new = (x.array() - xmin_ + 5e-5 * rng) / (1.0001 * rng); x_new = stats::qnorm(x_new); } else if (!std::isnan(xmin_)) { - // left boundary -> log transform - x_new = (boundary_offset_ + x.array() - xmin_).log(); + // left boundary -> power-3/4 transform + x_new = 4.0 * (((boundary_offset_ + x.array() - xmin_) / + boundary_scale_) + .pow(0.25) - + std::pow(boundary_offset_ / boundary_scale_, 0.25)); } else if (!std::isnan(xmax_)) { - // right boundary -> negative log transform - x_new = (boundary_offset_ + xmax_ - x.array()).log(); + // right boundary -> reflected power-3/4 transform + x_new = 4.0 * (((boundary_offset_ + xmax_ - x.array()) / + boundary_scale_) + .pow(0.25) - + std::pow(boundary_offset_ / boundary_scale_, 0.25)); } else { // no boundary -> no transform } @@ -793,11 +801,19 @@ Kde1d::boundary_transform(const Eigen::VectorXd& x, bool inverse) auto rng = xmax_ - xmin_; x_new = stats::pnorm(x).array() * 1.0001 * rng + xmin_ - 5e-5 * rng; } else if (!std::isnan(xmin_)) { - // left boundary -> log transform - x_new = x.array().exp() + xmin_ - boundary_offset_; + // left boundary -> inverse power-3/4 transform + x_new = boundary_scale_ * + (x.array() / 4.0 + + std::pow(boundary_offset_ / boundary_scale_, 0.25)) + .pow(4) + + xmin_ - boundary_offset_; } else if (!std::isnan(xmax_)) { - // right boundary -> negative log transform - x_new = -(x.array().exp() - xmax_ - boundary_offset_); + // right boundary -> inverse reflected power-3/4 transform + x_new = xmax_ + boundary_offset_ - + boundary_scale_ * + (x.array() / 4.0 + + std::pow(boundary_offset_ / boundary_scale_, 0.25)) + .pow(4); } else { // no boundary -> no transform } @@ -827,11 +843,15 @@ Kde1d::boundary_correct(const Eigen::VectorXd& x, const Eigen::VectorXd& fhat) corr_term /= (xmax_ - xmin_ + 1e-4 * rng); corr_term = 1.0 / corr_term.array(); } else if (!std::isnan(xmin_)) { - // left boundary -> log transform - corr_term = 1.0 / (boundary_offset_ + x.array() - xmin_); + // left boundary -> power-3/4 transform + corr_term = ((boundary_offset_ + x.array() - xmin_) / boundary_scale_) + .pow(-0.75) / + boundary_scale_; } else if (!std::isnan(xmax_)) { - // right boundary -> negative log transform - corr_term = 1.0 / (boundary_offset_ + xmax_ - x.array()); + // right boundary -> reflected power-3/4 transform + corr_term = ((boundary_offset_ + xmax_ - x.array()) / boundary_scale_) + .pow(-0.75) / + boundary_scale_; } else { // no boundary -> no transform corr_term.fill(1.0); diff --git a/test/test_numerical_invariants.cpp b/test/test_numerical_invariants.cpp index c726e9d..98e8c86 100644 --- a/test/test_numerical_invariants.cpp +++ b/test/test_numerical_invariants.cpp @@ -128,6 +128,22 @@ TEST_CASE("one-sided fits are scale equivariant", } } +TEST_CASE("one-sided power grids do not explode on exponential data", + "[numerical-invariants][boundary-grid]") +{ + Eigen::VectorXd probabilities = + Eigen::VectorXd::LinSpaced(500, 0.5 / 500.0, 1.0 - 0.5 / 500.0); + Eigen::VectorXd observations = (-(1.0 - probabilities.array()).log()); + kde1d::Kde1d fit(0.0, NAN, "continuous"); + fit.fit(observations); + + Eigen::VectorXd boundary_density = + fit.pdf(Eigen::VectorXd::Constant(1, 0.0)); + CHECK(fit.get_grid_points().maxCoeff() < 10.0 * observations.maxCoeff()); + CHECK(std::isfinite(boundary_density(0))); + CHECK(boundary_density(0) > 0.0); +} + TEST_CASE("interpolation preserves nonuniform-grid reference values", "[interpolation][parity]") { From ff52268ea87e3f37cc159cbb5a893b91ab51651d Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 13:15:26 +0200 Subject: [PATCH 02/25] Add two-sided boundary repair reference --- diagnostic/README.md | 4 + diagnostic/boundary-repair/HANDOFF.md | 50 +++ diagnostic/boundary-repair/NATIVE_CPP.md | 88 ++++ diagnostic/boundary-repair/README.md | 67 ++++ diagnostic/boundary-repair/RESULTS.md | 59 +++ .../plots/bounded-estimator-validation.pdf | Bin 0 -> 70646 bytes .../plots/endpoint-classifier-ablation.pdf | Bin 0 -> 77147 bytes .../results/bounded-estimator-validation.csv | 25 ++ .../results/endpoint-classifier-ablation.csv | 85 ++++ .../scripts/ablate_endpoint_classifier.R | 235 +++++++++++ .../scripts/bounded_estimator.R | 376 ++++++++++++++++++ .../plot_bounded_estimator_validation.R | 208 ++++++++++ .../plot_endpoint_classifier_ablation.R | 234 +++++++++++ .../scripts/validate_bounded_estimator.R | 195 +++++++++ 14 files changed, 1626 insertions(+) create mode 100644 diagnostic/boundary-repair/HANDOFF.md create mode 100644 diagnostic/boundary-repair/NATIVE_CPP.md create mode 100644 diagnostic/boundary-repair/README.md create mode 100644 diagnostic/boundary-repair/RESULTS.md create mode 100644 diagnostic/boundary-repair/plots/bounded-estimator-validation.pdf create mode 100644 diagnostic/boundary-repair/plots/endpoint-classifier-ablation.pdf create mode 100644 diagnostic/boundary-repair/results/bounded-estimator-validation.csv create mode 100644 diagnostic/boundary-repair/results/endpoint-classifier-ablation.csv create mode 100644 diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R create mode 100644 diagnostic/boundary-repair/scripts/bounded_estimator.R create mode 100644 diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R create mode 100644 diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R create mode 100644 diagnostic/boundary-repair/scripts/validate_bounded_estimator.R diff --git a/diagnostic/README.md b/diagnostic/README.md index d34d715..7466023 100644 --- a/diagnostic/README.md +++ b/diagnostic/README.md @@ -29,3 +29,7 @@ where the true density vanishes, while CDF error can remain small despite a severely unstable pointwise density. Candidate repairs should therefore be checked against both finite nonzero boundary densities and densities that tend to zero. + +The separate transformation-boundary investigation, its retained simulation +results, and its current recommendations live in +[`boundary-repair/`](boundary-repair/README.md). diff --git a/diagnostic/boundary-repair/HANDOFF.md b/diagnostic/boundary-repair/HANDOFF.md new file mode 100644 index 0000000..92a57ed --- /dev/null +++ b/diagnostic/boundary-repair/HANDOFF.md @@ -0,0 +1,50 @@ +# Two-boundary repair handoff + +## Current state + +The directory now contains one experimental estimator for continuous data +with two known finite bounds. It fits the current probit bulk estimator once, +adds an equal local-linear/local-quadratic expert for confidently finite +endpoints, and otherwise reuses bulk. Smooth CDF-scale gates shrink as +$n^{-1/2}$. The finite-endpoint classifier uses +$k=\min(n-1,\lceil2\sqrt n\rceil)$ order statistics and a 95% decision. + +There is no exploding-tail expert, power warp, transformation offset, or CV +selector. Superseded oversmoothing and offset code and outputs were removed. +The retained 100-replication validation and classifier ablation are summarized +in `RESULTS.md`. + +## Reproduce + +From the R-package root: + +```sh +Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R +Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R +Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R 100 +Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R +``` + +For a smoke test, pass a smaller replication count and temporary output path +as the first two arguments to either simulation script. + +## Known limitations + +- The R reference assumes support $[0,1]$; native code must apply an affine + map for arbitrary finite bounds. +- Weighted observations have not been specified or validated for the tail + index, weighted ranks, or shrinking gate. +- The finite-versus-bulk decision is hard, so between-sample endpoint behavior + can still change discretely. +- Before release, test affine support changes, weaker and stronger endpoint + singularities, interior modes, ties, and weighted data. + +## Next work + +The immediate next investigation is the analogous one-sided estimator. Keep +that work in a separate sibling diagnostic directory so this two-boundary +reference remains stable. Native implementation of this estimator should +follow `NATIVE_CPP.md` after the one-sided design has settled enough to assess +shared infrastructure. + +Unrelated top-level generated documentation changes were left untouched. diff --git a/diagnostic/boundary-repair/NATIVE_CPP.md b/diagnostic/boundary-repair/NATIVE_CPP.md new file mode 100644 index 0000000..1672e4a --- /dev/null +++ b/diagnostic/boundary-repair/NATIVE_CPP.md @@ -0,0 +1,88 @@ +# Native C++ implementation plan + +## Integration point + +The production estimator belongs in +`include/kde1d/kde1d.hpp`, where `Kde1d::fit()` currently handles bounded +continuous data through a single probit-transformed local-likelihood fit. The +new path should activate only when both bounds are finite and the variable is +continuous. One-sided, unbounded, discrete, and zero-inflated behavior should +remain unchanged. + +Avoid implementing the method through recursively constructed public +`Kde1d` objects: a nested bounded fit would activate the boundary selector +again. Extract the existing bounded-probit calculation into a private helper, +or introduce an internal mode that requests the legacy transformation fit +directly. + +## Components to implement + +1. Normalize observations and grid locations to $[0,1]$ using the supplied + finite support. Convert final density values back with the inverse support + length. This must preserve affine equivariance. +2. Fit the unweighted legacy probit bulk estimator once. Retain its PDF, CDF, + and final original-scale grid. +3. Compute $k=\min(n-1,\lceil2\sqrt n\rceil)$ and the two order-statistic tail + indices. Use a partial selection algorithm if convenient, although a full + sort is acceptable initially. Protect zero endpoint distances with the C++ + equivalent of `std::numeric_limits::epsilon()`. +4. Classify each endpoint as finite or bulk using the fixed finite-endpoint + rule in `README.md`. Exploding, vanishing, and ambiguous cases all use bulk. +5. Construct rank-based lower and upper bandwidth weights using average ranks + for ties and boundary fraction $\min(0.25,n^{-1/2})$. +6. Add a private Gaussian equivalent-kernel evaluator for boundary polynomial + degrees one and two. Select each bandwidth through + `bandwidth::PluginBandwidthSelector` with endpoint weights, impose the + corresponding full-sample unweighted bandwidth as its floor, but evaluate + density contributions with equal observation weights. Reflect data and + grid locations for the upper endpoint. +7. Average the degree-one and degree-two endpoint densities. Clamp negative + component values to zero before component normalization, matching the R + reference. +8. Obtain fusion probabilities from the bulk CDF and evaluate the smoothstep + gates. Substitute bulk or finite component values according to each + endpoint decision, fuse arithmetically, clamp at zero, and normalize on the + final grid. +9. Store the fused values in `interp::InterpolationGrid` so existing PDF, + CDF, quantile, and simulation methods continue to work without a new + public fitted-object representation. + +## API and metadata decisions + +The first implementation can keep the method automatic for two finite bounds, +but an internal feature switch is useful while validating. Decide whether the +selector threshold and gate constants remain private or become advanced API +parameters; the current recommendation is to keep them fixed until broader +validation justifies exposing them. + +`loglik_` can be recomputed from the final interpolated density. Effective +degrees of freedom do not combine trivially across selected and fused experts; +do not silently reuse the bulk value. Either derive the fused influence trace +or return `NaN` for `edf_` until a principled definition is implemented. + +The public API accepts case weights, while the retained experiment is +unweighted. Before enabling the new estimator for weighted fits, define: + +- weighted ranks and tie handling for endpoint bandwidth weights; +- an effective sample size for $k$ and the shrinking gate; +- a weighted order-statistic tail index; +- whether selector confidence adjustments use raw or effective sample size. + +Until those choices are validated, weighted bounded fits should remain on the +legacy path rather than pretending the unweighted selector applies. + +## Tests required + +- Golden PDF vectors against `scripts/bounded_estimator.R` for fixed Uniform, + Beta$(1,2)$, Beta$(0.75,2)$, and Beta$(0.75,0.75)$ samples. +- Explicit samples that select bulk and finite behavior at each endpoint, + including asymmetric lower/upper decisions. +- Nonnegativity, unit mass, monotone CDF, inverse-CDF consistency, and support + truncation. +- Affine-equivariance tests on intervals such as $[-3,7]$. +- Stability with ties, observations exactly at a bound, small samples, and + nearly degenerate samples. +- Regression tests proving that one-sided, unbounded, discrete, + zero-inflated, and weighted fits retain their existing behavior. +- A native rerun of the retained 100-replication validation before making the + new path the default. diff --git a/diagnostic/boundary-repair/README.md b/diagnostic/boundary-repair/README.md new file mode 100644 index 0000000..fb263e1 --- /dev/null +++ b/diagnostic/boundary-repair/README.md @@ -0,0 +1,67 @@ +# Two-sided boundary repair + +This directory contains the selected experimental estimator for continuous +densities on a known finite interval, its paired validation against the +current probit estimator, and the retained endpoint-classifier ablation. + +## Selected estimator + +The reference implementation assumes the support has been mapped affinely to +$[0,1]$. First fit the current unweighted probit estimator $\widehat f_B$ and +use its CDF to define sample-shrinking endpoint gates. With +$r_n=\min(0.25,n^{-1/2})$ and $s(t)=3t^2-2t^3$, + +$$ +w_L(x)=1-s\left(\min\left\{1,\frac{\widehat F_B(x)}{r_n}\right\}\right), +\qquad +w_U(x)=1-s\left(\min\left\{1,\frac{1-\widehat F_B(x)}{r_n}\right\}\right), +$$ + +and $w_B(x)=1-w_L(x)-w_U(x)$. The finite-boundary expert is the +equal average of Gaussian equivalent-kernel local-linear and local-quadratic +estimates. Rank-based endpoint weights select their bandwidths, but density +contributions remain unweighted, so the estimand does not change. Negative +component values are truncated during normalization. + +Finite endpoint behavior is identified from +$k=\min(n-1,\lceil2\sqrt n\rceil)$ order statistics. At the lower endpoint, + +$$ +\widehat\beta_L += +\frac{k}{\sum_{i=1}^k +\log\{X_{(k+1)}/X_{(i)}\}}, +$$ + +with the analogous calculation on $1-X$ at the upper endpoint. The finite +expert is used if +$\widehat\beta\geq0.9$ and +$\widehat\beta(1-1.645/\sqrt{k})\leq1$; otherwise the endpoint reuses the bulk +estimator. Thus exploding, vanishing, and ambiguous endpoints require no +additional fit. + +The finite or bulk endpoint components are fused with $w_L,w_B,w_U$, +truncated at zero, and normalized numerically. There is no power transform, +offset transform, oversmoothed tail expert, or cross-validation selector. + +## Retained files + +- `scripts/bounded_estimator.R`: self-contained R reference implementation. +- `scripts/validate_bounded_estimator.R`: paired validation against current. +- `scripts/plot_bounded_estimator_validation.R`: numerical and realization + report. +- `scripts/ablate_endpoint_classifier.R`: paired classifier ablation. +- `scripts/plot_endpoint_classifier_ablation.R`: classifier report. +- `results/` and `plots/`: corresponding 100-replication outputs. +- `RESULTS.md`: final numerical conclusions. +- `HANDOFF.md`: concise continuation state. +- `NATIVE_CPP.md`: native C++ implementation plan. + +Run from the R-package root: + +```sh +Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R +Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R +Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R 100 +Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R +``` diff --git a/diagnostic/boundary-repair/RESULTS.md b/diagnostic/boundary-repair/RESULTS.md new file mode 100644 index 0000000..128f69e --- /dev/null +++ b/diagnostic/boundary-repair/RESULTS.md @@ -0,0 +1,59 @@ +# Validation results + +## Final estimator + +The final two-boundary estimator combines the current probit bulk fit with an +equal local-linear/local-quadratic expert at endpoints classified as finite. +All other endpoint types reuse bulk. The validation uses 100 paired +replications for Uniform, Beta$(1,2)$, Beta$(0.75,2)$, and +Beta$(0.75,0.75)$ at $n=100,1000,2000$. The primary measure is integrated +squared error (ISE). + +Global ISE ratios to the current bounded estimator are: + +| density | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:| +| Uniform | 0.884 | 0.830 | 0.814 | +| Beta$(1,2)$ | 0.879 | 0.818 | 0.802 | +| Beta$(0.75,2)$ | 0.943 | 1.050 | 1.045 | +| Beta$(0.75,0.75)$ | 0.945 | 1.037 | 1.033 | + +Mean ratios across the four densities are 0.913, 0.934, and 0.923. The +finite-endpoint cases improve clearly. Losses for exploding densities are +small and accepted in exchange for keeping a generic, shape-agnostic finite +expert. + +All retained estimates are nonnegative and normalized numerically. The +maximum mass error in the validation is $2.2\times10^{-16}$. + +## Endpoint classifier + +The selected rule uses one tail-index estimate with +$k=\min(n-1,\lceil2\sqrt n\rceil)$ and a 95% finite-endpoint decision. It was +compared with single scales $\sqrt n$ and $1.5\sqrt n$, and multiscale median +and voting rules. Mean ISE ratios to current are: + +| $n$ | $\sqrt n$, 95% | $2\sqrt n$, 95% | multiscale vote, 90% | +|---:|---:|---:|---:| +| 100 | 0.885 | 0.912 | 0.919 | +| 1000 | 0.976 | 0.936 | 0.996 | +| 2000 | 0.994 | 0.921 | 0.981 | + +The smaller scale is slightly better at $n=100$, but $2\sqrt n$ is clearly +better at $n=1000,2000$ and substantially reduces the worst exploding-tail +loss. Multiscale classification adds complexity without improving ISE or the +representative fits. + +## Bulk decision for nonfinite endpoints + +A final focused comparison used asymmetric Beta$(a,2)$ and symmetric +Beta$(a,a)$ densities for $a=0.9,0.75,0.6$. An oversmoothed probit tail reduced +integrated variance by roughly one third, but its mean ISE ratios to simply +reusing bulk were 0.948, 1.079, and 1.095 at $n=100,1000,2000$. Bulk won all +six large-sample scenarios. The additional transformed fit, offset, bandwidth +multiplier, and fusion branch were therefore removed from the selected +estimator. + +The retained CSVs contain global and endpoint-local ISE, squared bias, +integrated variance, selection rates, minimum density, and mass error. The +PDFs add representative full-density and logarithmic-distance endpoint plots. diff --git a/diagnostic/boundary-repair/plots/bounded-estimator-validation.pdf b/diagnostic/boundary-repair/plots/bounded-estimator-validation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4cc2542177c80985f191f43a8d52acb5cdb2772c GIT binary patch literal 70646 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 literal 0 HcmV?d00001 diff --git a/diagnostic/boundary-repair/plots/endpoint-classifier-ablation.pdf b/diagnostic/boundary-repair/plots/endpoint-classifier-ablation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3a26b5f5df5054e02c34bae2be7271be24263b64 GIT binary patch literal 77147 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
3B95lS$8S)-dE*iAfbmqDABh24aHIAT`!kQ= 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 QVX-K@prWF&wTa;W0UT{W6951J literal 0 HcmV?d00001 diff --git a/diagnostic/boundary-repair/results/bounded-estimator-validation.csv b/diagnostic/boundary-repair/results/bounded-estimator-validation.csv new file mode 100644 index 0000000..2266312 --- /dev/null +++ b/diagnostic/boundary-repair/results/bounded-estimator-validation.csv @@ -0,0 +1,25 @@ +"distribution","sample_size","replications","method","global_ise","global_ise_median","global_squared_bias","global_variance","left_ise","left_squared_bias","left_variance","right_ise","right_squared_bias","right_variance","lower_finite_rate","upper_finite_rate","lower_bulk_rate","upper_bulk_rate","minimum_density","maximum_mass_error" +"uniform",100,100,"current",0.0394376359325329,0.0338111604704578,0.000617180948333801,0.0388204549841991,0.0143090894493515,0.000329356842577829,0.0139797326067737,0.0119951702383231,5.07569694759032e-05,0.0119444132688472,NA,NA,NA,NA,0,1.11022302462516e-16 +"uniform",100,100,"selected",0.0348777989524127,0.026772428104564,0.000732746013117419,0.0341450529392953,0.0113822372997225,0.000287103069134737,0.0110951342305877,0.0105132810395891,0.000250949704263428,0.0102623313353256,0.67,0.71,0.33,0.29,0,2.22044604925031e-16 +"uniform",1000,100,"current",0.00455374226860925,0.00377493251816298,0.000120426238243223,0.00443331603036602,0.00166512497918556,7.02679895893482e-05,0.00159485698959621,0.00156545415124511,1.10297242802776e-05,0.00155442442696484,NA,NA,NA,NA,6.32797475579434e-09,2.22044604925031e-16 +"uniform",1000,100,"selected",0.00377752447828285,0.00300211604552172,9.73413970320961e-05,0.00368018308125076,0.00130195385815075,3.46665195773036e-05,0.00126728733857345,0.00116196816839797,3.04849796492858e-05,0.00113148318874868,0.78,0.75,0.22,0.25,1.93936477529325e-05,2.22044604925031e-16 +"uniform",2000,100,"current",0.00219073406404686,0.00192055379535926,5.53558190218886e-05,0.00213537824502498,0.000783683950013612,3.33444879551106e-05,0.000750339462058502,0.000815932318097777,1.52965600524858e-05,0.000800635758045291,NA,NA,NA,NA,0.00041306652255468,1.11022302462516e-16 +"uniform",2000,100,"selected",0.00178253309691287,0.00151417624660391,2.00338606849405e-05,0.00176249923622793,0.00055128516716811,6.31058532121784e-06,0.000544974581846892,0.000642140498147629,7.02233285931979e-06,0.000635118165288309,0.88,0.82,0.12,0.18,0.000427940598708137,1.11022302462516e-16 +"beta-1-2",100,100,"current",0.0454039530333344,0.0378817494739727,0.000294496132934666,0.0451094569003997,0.0308242314704997,9.61419783217316e-05,0.0307280894921779,0.000619383994696991,7.68869882163405e-06,0.000611695295875357,NA,NA,NA,NA,0,1.11022302462516e-16 +"beta-1-2",100,100,"selected",0.0398899718020702,0.0284120449632399,0.000575661274437074,0.0393143105276331,0.0251426161241531,0.000399150610548051,0.0247434655136051,0.000761578605536506,9.98520133962911e-06,0.000751593404196877,0.59,0.13,0.41,0.87,0,1.11022302462516e-16 +"beta-1-2",1000,100,"current",0.00619849332649953,0.00538986832082836,8.06843343984859e-05,0.00611780899210105,0.0044487283767016,7.43173699097184e-05,0.00437441100679188,8.71119362452834e-05,7.00981152975579e-08,8.70418381299858e-05,NA,NA,NA,NA,0,1.11022302462516e-16 +"beta-1-2",1000,100,"selected",0.00507124781292705,0.0038351154993051,6.30407278622915e-05,0.00500820708506475,0.00332739234761219,5.50301044221794e-05,0.00327236224319001,8.69390062784019e-05,8.23561012186089e-08,8.68566501771833e-05,0.8,0,0.2,1,0,1.11022302462516e-16 +"beta-1-2",2000,100,"current",0.00269830501263795,0.00240268850898862,5.7379479881232e-05,0.00264092553275672,0.00188144723847374,4.60804519336171e-05,0.00183536678654012,3.44468945601477e-05,7.21472861216931e-07,3.37254216989307e-05,NA,NA,NA,NA,0,2.22044604925031e-16 +"beta-1-2",2000,100,"selected",0.00216467208617947,0.00176963180531096,3.74612394644642e-05,0.002127210846715,0.00135151630196739,2.58746584550445e-05,0.00132564164351235,3.44241145998833e-05,7.33286870140865e-07,3.36908277297425e-05,0.82,0,0.18,1,0,2.22044604925031e-16 +"beta-0.75-2",100,100,"current",0.104720547076617,0.078388069609558,0.0109053419453534,0.0938152051312638,0.092826145012719,0.010755039731205,0.082071105281514,0.000294257769639688,4.31895439320073e-07,0.000293825874200368,NA,NA,NA,NA,0,1.11022302462516e-16 +"beta-0.75-2",100,100,"selected",0.0987766159045782,0.0786622783748146,0.0100657362740795,0.0887108796304987,0.0868085593832687,0.00992193113189107,0.0768866282513777,0.000333570896186141,1.43319523306781e-06,0.000332137700953073,0.18,0.05,0.82,0.95,0,1.11022302462516e-16 +"beta-0.75-2",1000,100,"current",0.0191565263143446,0.0164151173872431,0.00755189921993969,0.0116046270944049,0.0178080933087401,0.00752360339569207,0.010284489913048,4.7184329064819e-05,4.95109523993255e-07,4.66892195408257e-05,NA,NA,NA,NA,0,2.22044604925031e-16 +"beta-0.75-2",1000,100,"selected",0.0201222594239744,0.0164151173872431,0.00773244033317598,0.0123898190907984,0.0187711681332489,0.00770407109713924,0.0110670970361096,4.72294630729243e-05,4.92309258282758e-07,4.67371538146415e-05,0.06,0,0.94,1,0,2.22044604925031e-16 +"beta-0.75-2",2000,100,"current",0.0148612960341197,0.0130187542490117,0.00855237291074781,0.00630892312337185,0.0141683912522109,0.00851857159113627,0.00564981966107461,2.40093648581477e-05,5.78564251466386e-08,2.39515084330011e-05,NA,NA,NA,NA,0,2.22044604925031e-16 +"beta-0.75-2",2000,100,"selected",0.0155261390665641,0.0130187542490117,0.0086390314906581,0.00688710757590605,0.014830894988867,0.00860545745293673,0.00622543753593024,2.40038076246844e-05,5.64761885801453e-08,2.39473314361043e-05,0.06,0,0.94,1,0,1.11022302462516e-16 +"beta-0.75-0.75",100,100,"current",0.0698084190975684,0.0581896383336078,0.00155949393231754,0.0682489251652509,0.02982964896149,0.000960676657862926,0.0288689723036271,0.0328385552456753,0.000592860451193691,0.0322456947944816,NA,NA,NA,NA,1.00337510605646e-53,1.11022302462516e-16 +"beta-0.75-0.75",100,100,"selected",0.0659995179633665,0.05319205202227,0.00163226917192385,0.0643672487914426,0.028467322042892,0.000940245360854324,0.0275270766820377,0.0304420977085639,0.000682184099958427,0.0297599136086055,0.25,0.23,0.75,0.77,2.70295283383755e-08,1.11022302462516e-16 +"beta-0.75-0.75",1000,100,"current",0.00989852286075191,0.0088598631051671,0.00274707166757628,0.00715145119317563,0.00455528025338978,0.00135139391358385,0.00320388633980593,0.00446910740708714,0.00138765866671413,0.00308144874037302,NA,NA,NA,NA,0.163655037117267,1.11022302462516e-16 +"beta-0.75-0.75",1000,100,"selected",0.0102687283458827,0.0088598631051671,0.00279848820038407,0.00747024014549865,0.0047423306796736,0.00138733024305387,0.00335500043661973,0.00464944672637947,0.00140255271122454,0.00324689401515493,0.09,0.06,0.91,0.94,0.639857430838072,1.11022302462516e-16 +"beta-0.75-0.75",2000,100,"current",0.0067112597444121,0.00593016483343542,0.00268017857954491,0.00403108116486719,0.00294324243876054,0.0013077911745055,0.00163545126425505,0.00329549979435017,0.00135110913373508,0.00194439066061508,NA,NA,NA,NA,0.37705599508214,2.22044604925031e-16 +"beta-0.75-0.75",2000,100,"selected",0.00693306659961766,0.00593016483343542,0.002711448599349,0.00422161800026865,0.00309305200309237,0.00133529603139543,0.00175775597169694,0.00336651740633136,0.00135459479260747,0.00201192261372389,0.05,0.04,0.95,0.96,0.37705599508214,1.11022302462516e-16 diff --git a/diagnostic/boundary-repair/results/endpoint-classifier-ablation.csv b/diagnostic/boundary-repair/results/endpoint-classifier-ablation.csv new file mode 100644 index 0000000..0ee71bb --- /dev/null +++ b/diagnostic/boundary-repair/results/endpoint-classifier-ablation.csv @@ -0,0 +1,85 @@ +"distribution","sample_size","replications","method","global_ise","global_squared_bias","global_variance","left_ise","left_squared_bias","left_variance","right_ise","right_squared_bias","right_variance","lower_accuracy","upper_accuracy","lower_finite_rate","upper_finite_rate","minimum_density","maximum_mass_error" +"uniform",100,100,"kde-current",0.0395679608211775,0.000660315183665581,0.0389076456375119,0.0147140524945475,0.000353115726237842,0.0143609367683097,0.0119536069470872,7.93565361068368e-05,0.0118742504109804,NA,NA,NA,NA,0,1.11022302462516e-16 +"uniform",100,100,"single-95",0.0349551478183599,0.00096855258259265,0.0339865952357673,0.0119457705109792,0.000482444078260364,0.0114633264327188,0.0102912035338974,0.000305160231532077,0.00998604330236527,0.65,0.7,0.65,0.7,0,1.11022302462516e-16 +"uniform",100,100,"single-1.5-95",0.0351633913177871,0.000761433247192275,0.0344019580705948,0.012279634075376,0.000348221453612649,0.0119314126217634,0.0101504943845229,0.000232186903384519,0.00991830748113841,0.65,0.7,0.65,0.7,0,1.11022302462516e-16 +"uniform",100,100,"single-2-95",0.0349793140593923,0.000738228342999683,0.0342410857163926,0.0118474696512444,0.000350856077199829,0.0114966135740446,0.0103898593304783,0.000205771048124749,0.0101840882823535,0.67,0.73,0.67,0.73,0,2.22044604925031e-16 +"uniform",100,100,"median-90",0.0338757899115898,0.000435282615478925,0.0334405072961109,0.011397903010171,0.000210110326641735,0.0111877926835293,0.00966537216799255,3.69414920130523e-05,0.0096284306759795,0.79,0.79,0.79,0.79,0,1.11022302462516e-16 +"uniform",100,100,"vote-90",0.0338757899115898,0.000435282615478925,0.0334405072961109,0.011397903010171,0.000210110326641735,0.0111877926835293,0.00966537216799255,3.69414920130523e-05,0.0096284306759795,0.79,0.79,0.79,0.79,0,1.11022302462516e-16 +"uniform",100,100,"vote-95",0.0318854637679857,0.000444412789471119,0.0314410509785145,0.010832802032572,0.000206756505177359,0.0106260455273946,0.00823194765557557,5.0710003529682e-05,0.00818123765204589,0.87,0.9,0.87,0.9,0,1.11022302462516e-16 +"uniform",1000,100,"kde-current",0.00458911943386039,0.000123195088823585,0.00446592434503681,0.00166683029146066,6.92227494859114e-05,0.00159760754197475,0.00159673304722858,9.62432316008856e-06,0.0015871087240685,NA,NA,NA,NA,6.32797475579434e-09,2.22044604925031e-16 +"uniform",1000,100,"single-95",0.00379607956960838,0.000130996098302809,0.00366508347130558,0.0012843866686856,4.22612830929953e-05,0.00124212538559261,0.00120052007613777,5.1345594302538e-05,0.00114917448183523,0.74,0.7,0.74,0.7,6.33057767207451e-09,2.22044604925031e-16 +"uniform",1000,100,"single-1.5-95",0.00381767885835155,0.00012084718079626,0.00369683167755529,0.00127592738886872,3.27515762536521e-05,0.00124317581261507,0.00122912103360067,5.05283620314296e-05,0.00117859267156924,0.82,0.69,0.82,0.69,1.93936477529325e-05,2.22044604925031e-16 +"uniform",1000,100,"single-2-95",0.00381184942018333,9.90963734823122e-05,0.00371275304670102,0.00130522324074235,3.29075871114687e-05,0.00127231565363089,0.00118972143822462,2.83245258226514e-05,0.00116139691240197,0.78,0.75,0.78,0.75,1.93936477529325e-05,2.22044604925031e-16 +"uniform",1000,100,"median-90",0.0037637571051833,7.23407522910959e-05,0.0036914163528922,0.00127012675606472,2.79819544724081e-05,0.00124214480159231,0.0011777664292238,4.68625980623549e-06,0.00117308016941756,0.84,0.84,0.84,0.84,6.33057767207451e-09,2.22044604925031e-16 +"uniform",1000,100,"vote-90",0.0037637571051833,7.23407522910959e-05,0.0036914163528922,0.00127012675606472,2.79819544724081e-05,0.00124214480159231,0.0011777664292238,4.68625980623549e-06,0.00117308016941756,0.84,0.84,0.84,0.84,6.33057767207451e-09,2.22044604925031e-16 +"uniform",1000,100,"vote-95",0.00362762827836124,7.16661316866633e-05,0.00355596214667458,0.00120149079406307,2.56391144121468e-05,0.00117585167965092,0.00110939276034633,6.92558501454552e-06,0.00110246717533179,0.91,0.9,0.91,0.9,6.33057767207451e-09,2.22044604925031e-16 +"uniform",2000,100,"kde-current",0.00222178056987251,6.21791105355296e-05,0.00215960145933698,0.000768223716127646,2.96354139538484e-05,0.000738588302173798,0.000849021464606157,2.40080442937546e-05,0.000825013420312402,NA,NA,NA,NA,0.00041306652255468,1.11022302462516e-16 +"uniform",2000,100,"single-95",0.00182951975894074,2.90388099639102e-05,0.00180048094897683,0.000562771588628805,1.08061577264253e-05,0.00055196543090238,0.000664099182943261,9.85263060748603e-06,0.000654246552335775,0.81,0.79,0.81,0.79,0.000427940598708137,1.11022302462516e-16 +"uniform",2000,100,"single-1.5-95",0.00187194506155839,1.90093424679686e-05,0.00185293571909043,0.000600490360408868,5.22292067570678e-06,0.000595267439733161,0.000669679998506429,5.52531321147942e-06,0.00066415468529495,0.83,0.84,0.83,0.84,0.000427940598708137,1.11022302462516e-16 +"uniform",2000,100,"single-2-95",0.00180757806700822,2.34784277748362e-05,0.00178409963923338,0.000541100385218893,8.4533907650244e-06,0.000532646994453868,0.000664183635669372,6.68871426274667e-06,0.000657494921406625,0.88,0.84,0.88,0.84,0.000427940598708137,1.11022302462516e-16 +"uniform",2000,100,"median-90",0.00187888201249991,1.88665212566633e-05,0.00186001549124325,0.000564349997872153,5.29231814880099e-06,0.000559057679723352,0.000710664021296797,5.35257580931804e-06,0.000705311445487479,0.91,0.8,0.91,0.8,0.000427940598708137,1.11022302462516e-16 +"uniform",2000,100,"vote-90",0.00187888201249991,1.88665212566633e-05,0.00186001549124325,0.000564349997872153,5.29231814880099e-06,0.000559057679723352,0.000710664021296797,5.35257580931804e-06,0.000705311445487479,0.91,0.8,0.91,0.8,0.000427940598708137,1.11022302462516e-16 +"uniform",2000,100,"vote-95",0.00175012124004211,1.88458399207556e-05,0.00173127540012135,0.000543857025510756,5.57575581703163e-06,0.000538281269693724,0.00060376351646917,5.03215654702641e-06,0.000598731359922143,0.93,0.92,0.93,0.92,0.000427940598708137,1.11022302462516e-16 +"beta-1-2",100,100,"kde-current",0.0452169408150938,0.000354970969907924,0.0448619698451858,0.0306893049739044,0.00014262362515346,0.0305466813487509,0.000611637781132187,6.38147426040877e-06,0.000605256306871778,NA,NA,NA,NA,0,1.11022302462516e-16 +"beta-1-2",100,100,"single-95",0.0381578421479701,0.000645417448081303,0.0375124246998888,0.02355364871879,0.000457175981001329,0.0230964727377887,0.000768062583551767,1.92362063564655e-05,0.000748826377195302,0.67,0.51,0.67,0.49,0,2.22044604925031e-16 +"beta-1-2",100,100,"single-1.5-95",0.0391447581497541,0.000761530465982772,0.0383832276837713,0.0245139853396121,0.000573167886424792,0.0239408174531873,0.000768694620224218,1.26444380310741e-05,0.000756050182193144,0.59,0.75,0.59,0.25,0,1.11022302462516e-16 +"beta-1-2",100,100,"single-2-95",0.0394500514824982,0.000571865397191171,0.038878186085307,0.0247654009525492,0.000381396460769478,0.0243840044917797,0.000753658240802613,8.76337172050094e-06,0.000744894869082112,0.59,0.87,0.59,0.13,0,1.11022302462516e-16 +"beta-1-2",100,100,"median-90",0.0389604014953733,0.000299480749325628,0.0386609207460477,0.0242918518204971,8.17788016543939e-05,0.0242100730188427,0.000702443494037229,8.07378453048265e-06,0.000694369709506746,0.77,0.94,0.77,0.06,0,1.11022302462516e-16 +"beta-1-2",100,100,"vote-90",0.0389604014953733,0.000299480749325628,0.0386609207460477,0.0242918518204971,8.17788016543939e-05,0.0242100730188427,0.000702443494037229,8.07378453048265e-06,0.000694369709506746,0.77,0.94,0.77,0.06,0,1.11022302462516e-16 +"beta-1-2",100,100,"vote-95",0.0356643678809153,0.000217751309885197,0.0354466165710301,0.0210358597203943,1.81187809165201e-05,0.0210177409394778,0.000741777849535933,8.91808306355962e-06,0.000732859766472373,0.89,0.84,0.89,0.16,0,1.11022302462516e-16 +"beta-1-2",1000,100,"kde-current",0.00622941335597601,0.000101587564273177,0.00612782579170284,0.00451672337826204,9.43554387791781e-05,0.00442236793948286,9.02072744846522e-05,1.55460319135784e-08,9.01917284527386e-05,NA,NA,NA,NA,0,1.11022302462516e-16 +"beta-1-2",1000,100,"single-95",0.00529124863096217,0.000110121698790694,0.00518112693217148,0.00357825537492738,0.000100014564090765,0.00347824081083661,8.97843633139735e-05,1.1840214358906e-08,8.97725230996146e-05,0.66,0.99,0.66,0.01,0,1.11022302462516e-16 +"beta-1-2",1000,100,"single-1.5-95",0.00525536506766485,0.000101544516058266,0.00515382055160659,0.00354473395881986,9.15539265449705e-05,0.00345318003227489,9.00401007445582e-05,1.17497403758797e-08,9.00283510041823e-05,0.74,1,0.74,0,0,1.11022302462516e-16 +"beta-1-2",1000,100,"single-2-95",0.00513761227662957,5.78945891361482e-05,0.00507971768749342,0.00342972281757982,4.87076055548851e-05,0.00338101521202494,9.00239701021473e-05,1.24358879462303e-08,9.00115342142011e-05,0.77,1,0.77,0,0,1.11022302462516e-16 +"beta-1-2",1000,100,"median-90",0.0049123689857565,4.93722850242422e-05,0.00486299670073226,0.00320691875823006,4.07493449194204e-05,0.00316616941331064,9.00442888497998e-05,1.30619411365843e-08,9.00312269086632e-05,0.85,1,0.85,0,0,1.11022302462516e-16 +"beta-1-2",1000,100,"vote-90",0.0049123689857565,4.93722850242422e-05,0.00486299670073226,0.00320691875823006,4.07493449194204e-05,0.00316616941331064,9.00442888497998e-05,1.30619411365843e-08,9.00312269086632e-05,0.85,1,0.85,0,0,1.11022302462516e-16 +"beta-1-2",1000,100,"vote-95",0.00479175426470969,4.91523689740518e-05,0.00474260189573564,0.00308282424744127,4.05622837487035e-05,0.00304226196369257,9.01045323537463e-05,1.31951660768547e-08,9.00913371876695e-05,0.9,1,0.9,0,0,1.11022302462516e-16 +"beta-1-2",2000,100,"kde-current",0.00272230305310735,5.59676809242751e-05,0.00266633537218308,0.0019056790375289,4.31831657209516e-05,0.00186249587180795,3.49019550540507e-05,5.12563386140297e-07,3.43893916679104e-05,NA,NA,NA,NA,0,2.22044604925031e-16 +"beta-1-2",2000,100,"single-95",0.00227842226439808,3.40702721838305e-05,0.00224435199221425,0.00146586980788403,2.1089106066304e-05,0.00144478070181773,3.4873876560525e-05,5.18956936090987e-07,3.4354919624434e-05,0.74,1,0.74,0,0,2.22044604925031e-16 +"beta-1-2",2000,100,"single-1.5-95",0.00217658515518833,3.81566931004108e-05,0.00213842846208792,0.00136388840900227,2.50752121402069e-05,0.00133881319686206,3.4835864163282e-05,5.21680567860125e-07,3.43141835954219e-05,0.8,1,0.8,0,0,2.22044604925031e-16 +"beta-1-2",2000,100,"single-2-95",0.00215978434563467,3.94198605827913e-05,0.00212036448505188,0.00134606968415594,2.63280331240295e-05,0.00131974165103191,3.48458558427712e-05,5.21477750032391e-07,3.43243780927388e-05,0.82,1,0.82,0,0,2.22044604925031e-16 +"beta-1-2",2000,100,"median-90",0.00217684309476441,2.91319321580093e-05,0.0021477111626064,0.00136459368425178,1.62432324012425e-05,0.00134835045185054,3.48334709044314e-05,5.16930699224826e-07,3.43165402052066e-05,0.88,1,0.88,0,0,2.22044604925031e-16 +"beta-1-2",2000,100,"vote-90",0.00217684309476441,2.91319321580093e-05,0.0021477111626064,0.00136459368425178,1.62432324012425e-05,0.00134835045185054,3.48334709044314e-05,5.16930699224826e-07,3.43165402052066e-05,0.88,1,0.88,0,0,2.22044604925031e-16 +"beta-1-2",2000,100,"vote-95",0.00207141291327238,2.9292340230164e-05,0.00204212057304222,0.00125919314973815,1.63959872555449e-05,0.0012427971624826,3.4846487209274e-05,5.17220111703576e-07,3.43292670975705e-05,0.95,1,0.95,0,0,2.22044604925031e-16 +"beta-0.75-2",100,100,"kde-current",0.10333078278857,0.0119855482130719,0.0913452345754977,0.0917400982146583,0.0118000473232489,0.0799400508914094,0.000303702741962194,7.78354490929604e-07,0.000302924387471264,NA,NA,NA,NA,0,1.11022302462516e-16 +"beta-0.75-2",100,100,"single-95",0.0941217388781045,0.011349458756582,0.0827722801215225,0.0822135251348918,0.0111930600083389,0.0710204651265529,0.000450939023734345,1.53201727591279e-05,0.000435618850975217,0.75,0.52,0.25,0.48,0,1.11022302462516e-16 +"beta-0.75-2",100,100,"single-1.5-95",0.0947974087167762,0.0107399481755028,0.0840574605412734,0.0829664350643179,0.0105821776101739,0.072384257454144,0.000418017455627756,7.39349579874081e-06,0.000410623959829015,0.78,0.78,0.22,0.22,0,1.11022302462516e-16 +"beta-0.75-2",100,100,"single-2-95",0.0973258478625205,0.0110919402209551,0.0862339076415654,0.0856409967361105,0.0109161650043089,0.0747248317318016,0.00034650333943378,2.17330109423369e-06,0.000344330038339546,0.82,0.94,0.18,0.06,0,1.11022302462516e-16 +"beta-0.75-2",100,100,"median-90",0.104073466961675,0.0174343600649418,0.0866391068967335,0.092400973768718,0.0171693962689645,0.0752315774997535,0.000336932160326384,1.85192848496392e-06,0.00033508023184142,0.47,0.97,0.53,0.03,0,1.11022302462516e-16 +"beta-0.75-2",100,100,"vote-90",0.104073466961675,0.0174343600649418,0.0866391068967335,0.092400973768718,0.0171693962689645,0.0752315774997535,0.000336932160326384,1.85192848496392e-06,0.00033508023184142,0.47,0.97,0.53,0.03,0,1.11022302462516e-16 +"beta-0.75-2",100,100,"vote-95",0.107767494152978,0.0259133115617868,0.081854182591191,0.0958601247621016,0.0255811216121714,0.0702790031499302,0.000376011903308601,3.97172603832936e-06,0.000372040177270272,0.28,0.91,0.72,0.09,0,1.11022302462516e-16 +"beta-0.75-2",1000,100,"kde-current",0.0190167719805673,0.00748364876693982,0.0115331232136275,0.0176652908776476,0.00746281474640339,0.0102024761312443,4.61718908311821e-05,4.11391362501522e-07,4.57604994686805e-05,NA,NA,NA,NA,0,2.22044604925031e-16 +"beta-0.75-2",1000,100,"single-95",0.0216750884821827,0.00822517975230909,0.0134499087298736,0.0203126662836491,0.00820358015740727,0.0121090861262418,4.98199501522167e-05,5.36008590649573e-07,4.92839415615672e-05,0.87,0.97,0.13,0.03,0,2.22044604925031e-16 +"beta-0.75-2",1000,100,"single-1.5-95",0.0202283486798806,0.00777517646021835,0.0124531722196622,0.0188772549433714,0.00775421341037295,0.0111230415329985,4.62140569238117e-05,4.09161767609483e-07,4.58048951562022e-05,0.92,1,0.08,0,0,2.22044604925031e-16 +"beta-0.75-2",1000,100,"single-2-95",0.0199825050901971,0.00766579347108848,0.0123167116191086,0.0186283657021565,0.00764487387625293,0.0109834918259035,4.62170248392874e-05,4.09703777269343e-07,4.5807321062018e-05,0.94,1,0.06,0,0,2.22044604925031e-16 +"beta-0.75-2",1000,100,"median-90",0.0233981416545154,0.0088848493319451,0.0145132923225703,0.0220381666775545,0.00886288556872924,0.0131752811088253,4.62377835826615e-05,4.02073096310369e-07,4.58357104863512e-05,0.78,1,0.22,0,0,2.22044604925031e-16 +"beta-0.75-2",1000,100,"vote-90",0.0233981416545154,0.0088848493319451,0.0145132923225703,0.0220381666775545,0.00886288556872924,0.0131752811088253,4.62377835826615e-05,4.02073096310369e-07,4.58357104863512e-05,0.78,1,0.22,0,0,2.22044604925031e-16 +"beta-0.75-2",1000,100,"vote-95",0.0257620203679631,0.00985650758645671,0.0159055127815063,0.0244022726252111,0.00983354998846533,0.0145687226367458,4.63290826975616e-05,3.98468524490173e-07,4.59306141730714e-05,0.68,1,0.32,0,0,2.22044604925031e-16 +"beta-0.75-2",2000,100,"kde-current",0.01508555489414,0.00850923175013998,0.00657632314399997,0.0143894041053101,0.0084756555891786,0.00591374851613146,2.29872314005426e-05,1.83641597051423e-07,2.28035898034912e-05,NA,NA,NA,NA,0,2.22044604925031e-16 +"beta-0.75-2",2000,100,"single-95",0.0178927623292423,0.00931447188432378,0.00857829044491854,0.0171909169521438,0.00928145051848341,0.00790946643366039,2.30109518469592e-05,1.73395168733203e-07,2.2837556678226e-05,0.81,1,0.19,0,0,1.11022302462516e-16 +"beta-0.75-2",2000,100,"single-1.5-95",0.0164612710663761,0.0087588645792512,0.00770240648712489,0.0157624921763759,0.00872563247402369,0.00703685970235222,2.29791810666458e-05,1.79354615629126e-07,2.27998264510167e-05,0.9,1,0.1,0,0,1.11022302462516e-16 +"beta-0.75-2",2000,100,"single-2-95",0.0157503979265844,0.0085827190900329,0.00716767883655155,0.0150519078419661,0.0085493769885552,0.00650253085341095,2.29816741670793e-05,1.81112470633985e-07,2.28005616964453e-05,0.94,1,0.06,0,0,1.11022302462516e-16 +"beta-0.75-2",2000,100,"median-90",0.017694420737506,0.00919636996660086,0.00849805077090512,0.0169936481569977,0.00916327791737292,0.00783037023962477,2.30001070652951e-05,1.74838196823934e-07,2.28252688684712e-05,0.83,1,0.17,0,0,1.11022302462516e-16 +"beta-0.75-2",2000,100,"vote-90",0.017694420737506,0.00919636996660086,0.00849805077090512,0.0169936481569977,0.00916327791737292,0.00783037023962477,2.30001070652951e-05,1.74838196823934e-07,2.28252688684712e-05,0.83,1,0.17,0,0,1.11022302462516e-16 +"beta-0.75-2",2000,100,"vote-95",0.0189734607854946,0.00967388755222815,0.00929957323326641,0.0182724507734024,0.00964087574067331,0.00863157503272911,2.30170026525439e-05,1.71432647905287e-07,2.28455700046386e-05,0.77,1,0.23,0,0,1.11022302462516e-16 +"beta-0.75-0.75",100,100,"kde-current",0.0701482728754187,0.00155813534598916,0.0685901375294296,0.0304626880324348,0.000949055694439168,0.0295136323379957,0.0325734665545723,0.000599057090266889,0.0319744094643054,NA,NA,NA,NA,1.00337510605646e-53,1.11022302462516e-16 +"beta-0.75-0.75",100,100,"single-95",0.0633027826564518,0.00155650647026388,0.0617462761861879,0.0265330555588591,0.000844633122721144,0.025688422436138,0.0297734339887635,0.000697285110476889,0.0290761488782866,0.71,0.7,0.29,0.3,2.70295283383755e-08,1.11022302462516e-16 +"beta-0.75-0.75",100,100,"single-1.5-95",0.0653837942836675,0.00156500048051562,0.0638187938031519,0.0279714803616632,0.000867686562138423,0.0271037937995248,0.0303574143960939,0.000683053509164122,0.0296743608869298,0.73,0.76,0.27,0.24,5.68124764878753e-08,1.11022302462516e-16 +"beta-0.75-0.75",100,100,"single-2-95",0.0664838619258033,0.00163330495450213,0.0648505569713012,0.0291088443155113,0.000933175566093991,0.0281756687494173,0.0303121944539524,0.000686289887512471,0.0296259045664399,0.75,0.79,0.25,0.21,2.70295283383755e-08,1.11022302462516e-16 +"beta-0.75-0.75",100,100,"median-90",0.0668447189934785,0.00213687174922969,0.0647078472442488,0.028657209378944,0.00148416979983781,0.0271730395791061,0.03112554574768,0.000642603244003097,0.0304829425036769,0.46,0.51,0.54,0.49,1.74518520713497e-07,1.11022302462516e-16 +"beta-0.75-0.75",100,100,"vote-90",0.0668447189934785,0.00213687174922969,0.0647078472442488,0.028657209378944,0.00148416979983781,0.0271730395791061,0.03112554574768,0.000642603244003097,0.0304829425036769,0.46,0.51,0.54,0.49,1.74518520713497e-07,1.11022302462516e-16 +"beta-0.75-0.75",100,100,"vote-95",0.0651942669000884,0.00390161803235702,0.0612926488677314,0.0280949089361279,0.00231658005540894,0.025778328880719,0.0300949288785869,0.00157248430593897,0.0285224445726479,0.34,0.31,0.66,0.69,7.59886136601248e-06,1.11022302462516e-16 +"beta-0.75-0.75",1000,100,"kde-current",0.00988648152079718,0.00273966149466241,0.00714682002613477,0.00460950574110299,0.00138524004010197,0.00322426570100101,0.00442155731559371,0.00134556387167816,0.00307599344391555,NA,NA,NA,NA,0.163655037117267,1.11022302462516e-16 +"beta-0.75-0.75",1000,100,"single-95",0.0107405089864702,0.00286916198635601,0.00787134700011416,0.00499918531901173,0.0014468169621687,0.00355236835684303,0.00487935167031932,0.00141164183742496,0.00346770983289435,0.87,0.88,0.13,0.12,0.7863851245034,1.11022302462516e-16 +"beta-0.75-0.75",1000,100,"single-1.5-95",0.0102870666247854,0.00278567543416402,0.00750139119062134,0.00471646598499695,0.00139127994492352,0.00332518604007342,0.00471221266704946,0.00138465804761353,0.00332755461943593,0.92,0.91,0.08,0.09,0.639857430838072,1.11022302462516e-16 +"beta-0.75-0.75",1000,100,"single-2-95",0.010256687005928,0.00279203515035173,0.00746465185557625,0.00479655616738681,0.0014232208918276,0.00337333527555921,0.00460189663488603,0.00135933149427092,0.00324256514061511,0.91,0.94,0.09,0.06,0.639857430838072,1.11022302462516e-16 +"beta-0.75-0.75",1000,100,"median-90",0.0113341946744834,0.00303692624943848,0.00829726842504488,0.00552601607198135,0.00161612956839203,0.00390988650358932,0.0049441561729981,0.00140943241263818,0.00353472376035992,0.77,0.85,0.23,0.15,0.639857430838072,1.11022302462516e-16 +"beta-0.75-0.75",1000,100,"vote-90",0.0113341946744834,0.00303692624943848,0.00829726842504488,0.00552601607198135,0.00161612956839203,0.00390988650358932,0.0049441561729981,0.00140943241263818,0.00353472376035992,0.77,0.85,0.23,0.15,0.639857430838072,1.11022302462516e-16 +"beta-0.75-0.75",1000,100,"vote-95",0.0127905333626411,0.00350784384396239,0.00928268951867866,0.00628801233826839,0.00189437702781669,0.00439363531045169,0.00563172873977056,0.00159931848395278,0.00403241025581779,0.66,0.74,0.34,0.26,0.7863851245034,1.11022302462516e-16 +"beta-0.75-0.75",2000,100,"kde-current",0.00684077886201357,0.00270665655031356,0.00413412231170002,0.00304691730201407,0.0013214906725532,0.00172542662946087,0.00332276610510772,0.00136989453476547,0.00195287157034225,NA,NA,NA,NA,0.37705599508214,2.22044604925031e-16 +"beta-0.75-0.75",2000,100,"single-95",0.00772900065720123,0.00299776559822408,0.00473123505897715,0.00352806248353887,0.00141371011658039,0.00211435236695848,0.0037271196112084,0.00156706684549027,0.00216005276571813,0.88,0.86,0.12,0.14,0.793775176927469,1.11022302462516e-16 +"beta-0.75-0.75",2000,100,"single-1.5-95",0.00713066662475509,0.0027464281638779,0.00438423846087719,0.00318155231896237,0.00133992409120143,0.00184162822776094,0.00347775798206784,0.00139074625748771,0.00208701172458013,0.94,0.93,0.06,0.07,0.793775176927469,1.11022302462516e-16 +"beta-0.75-0.75",2000,100,"single-2-95",0.00706075203244803,0.00273322696679824,0.00432752506564979,0.003194836709572,0.00134366972475958,0.00185116698481242,0.00339375219571971,0.00137397305064016,0.00201977914507954,0.94,0.96,0.06,0.04,0.37705599508214,1.11022302462516e-16 +"beta-0.75-0.75",2000,100,"median-90",0.0075581872325074,0.0028437896946846,0.0047143975378228,0.0034810219983618,0.00140846040120306,0.00207256159715873,0.00360446463231341,0.00141899086237187,0.00218547376994154,0.88,0.9,0.12,0.1,0.793775176927469,1.11022302462516e-16 +"beta-0.75-0.75",2000,100,"vote-90",0.00756867245068476,0.00285026956433839,0.00471840288634637,0.00348103301206084,0.00140849467309012,0.00207253833897071,0.00361509248622447,0.00142545271887366,0.00218963976735082,0.88,0.91,0.12,0.09,0.37705599508214,1.11022302462516e-16 +"beta-0.75-0.75",2000,100,"vote-95",0.00871945752096456,0.00320121654235764,0.00551824097860691,0.00416036224794122,0.00162157367055352,0.0025387885773877,0.00408287571203191,0.0015617130318416,0.00252116268019031,0.77,0.82,0.23,0.18,0.793775176927469,1.11022302462516e-16 diff --git a/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R b/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R new file mode 100644 index 0000000..65cf569 --- /dev/null +++ b/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R @@ -0,0 +1,235 @@ +# Paired ablation of order-statistic endpoint classifiers. +# Run from the root of the kde1d R package. + +if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { + stop("run from the kde1d package root with pkgload installed") +} +pkgload::load_all(".", quiet = TRUE) +source(paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/", + "bounded_estimator.R" +)) + +arguments <- commandArgs(trailingOnly = TRUE) +replication_count <- if (length(arguments) >= 1L) { + as.integer(arguments[[1L]]) +} else { + 100L +} +output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/results/", + "endpoint-classifier-ablation.csv" +) +if (length(arguments) > 2L || !is.finite(replication_count) || + replication_count < 2L) { + stop("usage: ablate_endpoint_classifier.R [replications] [output.csv]") +} + +make_beta_distribution <- function(shape1, shape2, endpoint_truth) { + list( + random = function(sample_size) rbeta(sample_size, shape1, shape2), + density = function(values) dbeta(values, shape1, shape2), + endpoint_truth = endpoint_truth + ) +} +validation_distributions <- list( + uniform = list( + random = runif, + density = dunif, + endpoint_truth = c(lower = "finite", upper = "finite") + ), + `beta-1-2` = make_beta_distribution( + 1, 2, c(lower = "finite", upper = "bulk") + ), + `beta-0.75-2` = make_beta_distribution( + 0.75, 2, c(lower = "bulk", upper = "bulk") + ), + `beta-0.75-0.75` = make_beta_distribution( + 0.75, 0.75, c(lower = "bulk", upper = "bulk") + ) +) +sample_sizes <- c(100L, 1000L, 2000L) +classifier_methods <- c( + "single-95", "single-1.5-95", "single-2-95", + "median-90", "vote-90", "vote-95" +) +methods <- c("kde-current", classifier_methods) +evaluation_points <- sort(unique(c( + 10^seq(-10, -2, length.out = 101L), + seq(0.01, 0.99, length.out = 301L), + 1 - 10^seq(-2, -10, length.out = 101L) +))) +left_points <- evaluation_points <= 0.1 +right_points <- evaluation_points >= 0.9 +result_rows <- list() + +make_classifier_selections <- function(observations) { + list( + `single-95` = select_bounded_endpoint_experts_single_scale(observations), + `single-1.5-95` = select_bounded_endpoint_experts_single_scale( + observations, + tail_multiplier = 1.5 + ), + `single-2-95` = select_bounded_endpoint_experts_single_scale( + observations, + tail_multiplier = 2 + ), + `median-90` = select_bounded_endpoint_experts_multiscale( + observations, + evidence_threshold = qnorm(0.90), + rule = "median" + ), + `vote-90` = select_bounded_endpoint_experts_multiscale( + observations, + evidence_threshold = qnorm(0.90), + rule = "vote" + ), + `vote-95` = select_bounded_endpoint_experts_multiscale( + observations, + evidence_threshold = qnorm(0.95), + rule = "vote" + ) + ) +} + +summarize_estimates <- function(estimates, true_density, region_points) { + mean_density <- rowMeans(estimates) + integrated_errors <- vapply( + seq_len(ncol(estimates)), + function(replication) { + trapezoid_integral( + evaluation_points[region_points], + (estimates[region_points, replication] - + true_density[region_points])^2 + ) + }, + numeric(1L) + ) + c( + ise = mean(integrated_errors), + squared_bias = trapezoid_integral( + evaluation_points[region_points], + (mean_density[region_points] - true_density[region_points])^2 + ), + variance = trapezoid_integral( + evaluation_points[region_points], + rowMeans((estimates[region_points, , drop = FALSE] - + mean_density[region_points])^2) + ) + ) +} + +for (distribution_index in seq_along(validation_distributions)) { + true_density <- validation_distributions[[distribution_index]]$density( + evaluation_points + ) + for (sample_size in sample_sizes) { + estimates <- setNames( + lapply(methods, function(method) { + matrix(NA_real_, length(evaluation_points), replication_count) + }), + methods + ) + choices <- setNames( + lapply(classifier_methods, function(method) { + matrix( + NA_character_, replication_count, 2L, + dimnames = list(NULL, c("lower", "upper")) + ) + }), + classifier_methods + ) + for (replication in seq_len(replication_count)) { + set.seed( + 20260909L + 100000L * distribution_index + + 1000L * match(sample_size, sample_sizes) + replication + ) + observations <- validation_distributions[[distribution_index]]$random( + sample_size + ) + estimates$`kde-current`[, replication] <- normalize_density( + evaluation_points, + dkde1d( + evaluation_points, + kde1d(observations, xmin = 0, xmax = 1) + ) + ) + estimator_components <- fit_bounded_estimator_components( + observations, + evaluation_points + ) + classifier_selections <- make_classifier_selections(observations) + for (method in classifier_methods) { + estimator_components$selection <- classifier_selections[[method]] + estimates[[method]][, replication] <- + fuse_bounded_estimator_components( + evaluation_points, + estimator_components + )$density + choices[[method]][replication, ] <- + classifier_selections[[method]]$expert_choices + } + } + for (method in methods) { + global_summary <- summarize_estimates( + estimates[[method]], true_density, rep(TRUE, length(evaluation_points)) + ) + left_summary <- summarize_estimates( + estimates[[method]], true_density, left_points + ) + right_summary <- summarize_estimates( + estimates[[method]], true_density, right_points + ) + endpoint_truth <- validation_distributions[[distribution_index]]$endpoint_truth + result_rows[[length(result_rows) + 1L]] <- data.frame( + distribution = names(validation_distributions)[[distribution_index]], + sample_size = sample_size, + replications = replication_count, + method = method, + global_ise = global_summary[["ise"]], + global_squared_bias = global_summary[["squared_bias"]], + global_variance = global_summary[["variance"]], + left_ise = left_summary[["ise"]], + left_squared_bias = left_summary[["squared_bias"]], + left_variance = left_summary[["variance"]], + right_ise = right_summary[["ise"]], + right_squared_bias = right_summary[["squared_bias"]], + right_variance = right_summary[["variance"]], + lower_accuracy = if (method == "kde-current") { + NA_real_ + } else { + mean(choices[[method]][, "lower"] == endpoint_truth[["lower"]]) + }, + upper_accuracy = if (method == "kde-current") { + NA_real_ + } else { + mean(choices[[method]][, "upper"] == endpoint_truth[["upper"]]) + }, + lower_finite_rate = if (method == "kde-current") NA_real_ else + mean(choices[[method]][, "lower"] == "finite"), + upper_finite_rate = if (method == "kde-current") NA_real_ else + mean(choices[[method]][, "upper"] == "finite"), + minimum_density = min(estimates[[method]]), + maximum_mass_error = max(abs(vapply( + seq_len(replication_count), + function(replication) { + trapezoid_integral( + evaluation_points, + estimates[[method]][, replication] + ) - 1 + }, + numeric(1L) + ))) + ) + } + message( + names(validation_distributions)[[distribution_index]], + ", n = ", sample_size + ) + } +} + +results <- do.call(rbind, result_rows) +dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) +write.csv(results, output_file, row.names = FALSE) +message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/boundary-repair/scripts/bounded_estimator.R b/diagnostic/boundary-repair/scripts/bounded_estimator.R new file mode 100644 index 0000000..7ef12c0 --- /dev/null +++ b/diagnostic/boundary-repair/scripts/bounded_estimator.R @@ -0,0 +1,376 @@ +# Reference R implementation of the selected two-sided boundary estimator. + +trapezoid_integral <- function(evaluation_points, values) { + sum(diff(evaluation_points) * + (values[-length(values)] + values[-1L]) / 2) +} + +normalize_density <- function(evaluation_points, density) { + density <- pmax(0, density) + density_mass <- trapezoid_integral(evaluation_points, density) + if (!is.finite(density_mass) || density_mass <= 0) { + stop("density cannot be normalized") + } + density / density_mass +} + +smoothstep <- function(normalized_distance) { + 3 * normalized_distance^2 - 2 * normalized_distance^3 +} + +make_bounded_expert_weights <- function(probabilities, sample_size, + concentration = 1, + shrinkage_exponent = 0.5) { + boundary_fraction <- min( + 0.25, + concentration / sample_size^shrinkage_exponent + ) + lower_weights <- 1 - smoothstep(pmin(1, probabilities / boundary_fraction)) + upper_weights <- 1 - smoothstep(pmin( + 1, + (1 - probabilities) / boundary_fraction + )) + cbind( + lower = lower_weights, + bulk = pmax(0, 1 - lower_weights - upper_weights), + upper = upper_weights + ) +} + +fit_local_polynomial_boundary <- function( + observations, + evaluation_points, + bandwidth_weights, + minimum_bandwidth, + degree) { + if (!degree %in% c(1, 2)) { + stop("local boundary degree must be 1 or 2") + } + selected_bandwidth <- kde1d( + observations, + weights = bandwidth_weights, + deg = degree + )$bw + bandwidth <- max(selected_bandwidth, minimum_bandwidth) + standardized_boundary <- evaluation_points / bandwidth + truncated_moment_0 <- pnorm(standardized_boundary) + truncated_moment_1 <- -dnorm(standardized_boundary) + truncated_moment_2 <- truncated_moment_0 - + standardized_boundary * dnorm(standardized_boundary) + if (degree == 1) { + moment_determinant <- truncated_moment_0 * truncated_moment_2 - + truncated_moment_1^2 + equivalent_kernel_coefficients <- cbind( + truncated_moment_2 / moment_determinant, + -truncated_moment_1 / moment_determinant + ) + } else { + truncated_moment_3 <- -( + standardized_boundary^2 + 2 + ) * dnorm(standardized_boundary) + truncated_moment_4 <- 3 * truncated_moment_0 - ( + standardized_boundary^3 + 3 * standardized_boundary + ) * dnorm(standardized_boundary) + moment_determinant <- + truncated_moment_0 * ( + truncated_moment_2 * truncated_moment_4 - truncated_moment_3^2 + ) - + truncated_moment_1 * ( + truncated_moment_1 * truncated_moment_4 - + truncated_moment_2 * truncated_moment_3 + ) + + truncated_moment_2 * ( + truncated_moment_1 * truncated_moment_3 - truncated_moment_2^2 + ) + equivalent_kernel_coefficients <- cbind( + ( + truncated_moment_2 * truncated_moment_4 - truncated_moment_3^2 + ) / moment_determinant, + ( + truncated_moment_2 * truncated_moment_3 - + truncated_moment_1 * truncated_moment_4 + ) / moment_determinant, + ( + truncated_moment_1 * truncated_moment_3 - truncated_moment_2^2 + ) / moment_determinant + ) + } + density <- numeric(length(evaluation_points)) + for (chunk_start in seq(1L, length(evaluation_points), by = 128L)) { + chunk_indices <- chunk_start:min( + chunk_start + 127L, + length(evaluation_points) + ) + kernel_arguments <- outer( + evaluation_points[chunk_indices], + observations, + "-" + ) / bandwidth + base_kernels <- dnorm(kernel_arguments) + corrected_kernels <- base_kernels * + equivalent_kernel_coefficients[chunk_indices, 1L] + for (polynomial_order in seq_len(degree)) { + corrected_kernels <- corrected_kernels + + base_kernels * + equivalent_kernel_coefficients[ + chunk_indices, + polynomial_order + 1L + ] * kernel_arguments^polynomial_order + } + density[chunk_indices] <- rowMeans(corrected_kernels) / bandwidth + } + list( + density = normalize_density(evaluation_points, density), + bandwidth = bandwidth, + selected_bandwidth = selected_bandwidth + ) +} + +fit_bounded_finite_expert <- function(observations, evaluation_points, + concentration = 1, + shrinkage_exponent = 0.5) { + probability_ranks <- (rank(observations, ties.method = "average") - 0.5) / + length(observations) + bandwidth_weights <- make_bounded_expert_weights( + probability_ranks, + length(observations), + concentration, + shrinkage_exponent + ) + bulk_model <- kde1d(observations, xmin = 0, xmax = 1) + bulk_density <- normalize_density( + evaluation_points, + dkde1d(evaluation_points, bulk_model) + ) + endpoint_densities <- lapply(c(1L, 2L), function(degree) { + minimum_bandwidth <- kde1d(observations, deg = degree)$bw + lower_density <- fit_local_polynomial_boundary( + observations, + evaluation_points, + bandwidth_weights[, "lower"], + minimum_bandwidth, + degree + )$density + upper_density <- rev(fit_local_polynomial_boundary( + 1 - observations, + rev(1 - evaluation_points), + bandwidth_weights[, "upper"], + minimum_bandwidth, + degree + )$density) + cbind(lower = lower_density, bulk = bulk_density, upper = upper_density) + }) + component_densities <- ( + endpoint_densities[[1L]] + endpoint_densities[[2L]] + ) / 2 + evaluation_weights <- make_bounded_expert_weights( + pkde1d(evaluation_points, bulk_model), + length(observations), + concentration, + shrinkage_exponent + ) + list( + density = normalize_density( + evaluation_points, + rowSums(evaluation_weights * component_densities) + ), + component_densities = component_densities, + evaluation_weights = evaluation_weights, + boundary_fraction = min( + 0.25, + concentration / length(observations)^shrinkage_exponent + ) + ) +} + +estimate_bounded_tail_indices <- function(observations, tail_counts) { + if (any(tail_counts < 1L) || any(tail_counts >= length(observations))) { + stop("tail_counts must be between one and sample size minus one") + } + ordered_observations <- sort(observations) + upper_distances <- sort(1 - observations) + tail_indices <- vapply(tail_counts, function(tail_count) { + c( + lower = tail_count / sum(log( + ordered_observations[[tail_count + 1L]] / + pmax( + .Machine$double.eps, + ordered_observations[seq_len(tail_count)] + ) + )), + upper = tail_count / sum(log( + upper_distances[[tail_count + 1L]] / + pmax(.Machine$double.eps, upper_distances[seq_len(tail_count)]) + )) + ) + }, numeric(2L)) + if (length(tail_counts) == 1L) { + tail_indices <- matrix( + tail_indices, + nrow = 2L, + dimnames = list(c("lower", "upper"), NULL) + ) + } + rownames(tail_indices) <- c("lower", "upper") + colnames(tail_indices) <- as.character(tail_counts) + tail_indices +} + +select_bounded_endpoint_experts_single_scale <- function( + observations, + tail_multiplier = 1, + evidence_threshold = qnorm(0.95), + minimum_finite_index = 0.9) { + if (!is.finite(tail_multiplier) || tail_multiplier <= 0) { + stop("tail_multiplier must be finite and positive") + } + tail_count <- min( + length(observations) - 1L, + ceiling(tail_multiplier * sqrt(length(observations))) + ) + tail_indices <- estimate_bounded_tail_indices( + observations, + tail_count + )[, 1L] + expert_choices <- rep("bulk", length(tail_indices)) + names(expert_choices) <- names(tail_indices) + expert_choices[ + tail_indices >= minimum_finite_index & + tail_indices * (1 - evidence_threshold / sqrt(tail_count)) <= 1 + ] <- "finite" + list( + expert_choices = expert_choices, + tail_indices = tail_indices, + tail_count = tail_count, + evidence_threshold = evidence_threshold, + minimum_finite_index = minimum_finite_index + ) +} + +select_bounded_endpoint_experts_multiscale <- function( + observations, + evidence_threshold = qnorm(0.90), + tail_multipliers = c(1, 1.5, 2), + maximum_tail_fraction = 0.15, + rule = c("vote", "median")) { + rule <- match.arg(rule) + tail_counts <- pmin( + floor(maximum_tail_fraction * length(observations)), + ceiling(tail_multipliers * sqrt(length(observations))) + ) + tail_counts <- pmax(1L, pmin(length(observations) - 1L, tail_counts)) + tail_indices <- estimate_bounded_tail_indices(observations, tail_counts) + standardized_indices <- sweep( + log(tail_indices), + 2L, + sqrt(tail_counts), + "*" + ) + expert_choices <- apply(standardized_indices, 1L, function(scores) { + if (rule == "median") { + median_score <- median(scores) + if (abs(median_score) <= evidence_threshold) { + "finite" + } else { + "bulk" + } + } else { + required_votes <- floor(length(scores) / 2) + 1L + if (sum(abs(scores) <= evidence_threshold) >= required_votes) { + "finite" + } else { + "bulk" + } + } + }) + list( + expert_choices = expert_choices, + tail_indices = tail_indices, + standardized_indices = standardized_indices, + tail_counts = tail_counts, + evidence_threshold = evidence_threshold, + tail_multipliers = tail_multipliers, + maximum_tail_fraction = maximum_tail_fraction, + rule = rule + ) +} + +select_bounded_endpoint_experts <- function( + observations, + evidence_threshold = qnorm(0.95), + minimum_finite_index = 0.9) { + select_bounded_endpoint_experts_single_scale( + observations, + tail_multiplier = 2, + evidence_threshold, + minimum_finite_index + ) +} + +fit_bounded_estimator_components <- function( + observations, + evaluation_points, + concentration = 1, + shrinkage_exponent = 0.5) { + if (length(observations) < 4L || any(!is.finite(observations)) || + any(observations < 0 | observations > 1)) { + stop("observations must contain at least four finite values in [0, 1]") + } + if (any(!is.finite(evaluation_points)) || + is.unsorted(evaluation_points, strictly = TRUE) || + any(evaluation_points < 0 | evaluation_points > 1)) { + stop("evaluation_points must be strictly increasing in [0, 1]") + } + finite_fit <- fit_bounded_finite_expert( + observations, + evaluation_points, + concentration, + shrinkage_exponent + ) + selection <- select_bounded_endpoint_experts(observations) + list( + finite_fit = finite_fit, + selection = selection + ) +} + +fuse_bounded_estimator_components <- function( + evaluation_points, + estimator_components) { + finite_fit <- estimator_components$finite_fit + selection <- estimator_components$selection + component_densities <- finite_fit$component_densities + for (boundary in c("lower", "upper")) { + if (selection$expert_choices[[boundary]] != "finite") { + component_densities[, boundary] <- component_densities[, "bulk"] + } + } + list( + density = normalize_density( + evaluation_points, + rowSums(finite_fit$evaluation_weights * component_densities) + ), + component_densities = component_densities, + evaluation_weights = finite_fit$evaluation_weights, + expert_choices = selection$expert_choices, + tail_indices = selection$tail_indices, + tail_count = selection$tail_count, + boundary_fraction = finite_fit$boundary_fraction + ) +} + +fit_bounded_selected_estimator <- function( + observations, + evaluation_points, + concentration = 1, + shrinkage_exponent = 0.5) { + fuse_bounded_estimator_components( + evaluation_points, + fit_bounded_estimator_components( + observations, + evaluation_points, + concentration, + shrinkage_exponent + ) + ) +} diff --git a/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R b/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R new file mode 100644 index 0000000..ddb2597 --- /dev/null +++ b/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R @@ -0,0 +1,208 @@ +# Plot the paired validation of the selected bounded estimator. +# Run from the root of the kde1d R package. + +if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { + stop("run from the kde1d package root with pkgload installed") +} +pkgload::load_all(".", quiet = TRUE) +source(paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/", + "bounded_estimator.R" +)) + +arguments <- commandArgs(trailingOnly = TRUE) +input_file <- if (length(arguments) >= 1L) arguments[[1L]] else paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/results/", + "bounded-estimator-validation.csv" +) +output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/plots/", + "bounded-estimator-validation.pdf" +) +if (length(arguments) > 2L) { + stop("usage: plot_bounded_estimator_validation.R [input.csv] [output.pdf]") +} + +results <- read.csv(input_file) +replication_count <- unique(results$replications) +if (length(replication_count) != 1L) { + stop("input must contain a single replication count") +} +method_colors <- c(current = "grey45", selected = "#009E73") +validation_distributions <- list( + uniform = list(random = runif, density = dunif), + `beta-1-2` = list( + random = function(sample_size) rbeta(sample_size, 1, 2), + density = function(values) dbeta(values, 1, 2) + ), + `beta-0.75-2` = list( + random = function(sample_size) rbeta(sample_size, 0.75, 2), + density = function(values) dbeta(values, 0.75, 2) + ), + `beta-0.75-0.75` = list( + random = function(sample_size) rbeta(sample_size, 0.75, 0.75), + density = function(values) dbeta(values, 0.75, 0.75) + ) +) +evaluation_points <- sort(unique(c( + 10^seq(-10, -2, length.out = 101L), + seq(0.01, 0.99, length.out = 301L), + 1 - 10^seq(-2, -10, length.out = 101L) +))) + +pdf(output_file, width = 12, height = 8) +par(mfrow = c(3, 4), mar = c(4.5, 4.2, 2.4, 0.5), oma = c(0, 0, 3.5, 0)) +for (sample_size in sort(unique(results$sample_size))) { + for (distribution in names(validation_distributions)) { + scenario_results <- results[ + results$sample_size == sample_size & + results$distribution == distribution, + ] + current_result <- scenario_results[scenario_results$method == "current", ] + selected_result <- scenario_results[scenario_results$method == "selected", ] + ratios <- c( + ISE = selected_result$global_ise / current_result$global_ise, + bias = selected_result$global_squared_bias / + current_result$global_squared_bias, + variance = selected_result$global_variance / + current_result$global_variance + ) + barplot( + ratios, col = c("grey45", "#E69F00", "#56B4E9"), + ylim = range(c(0, 1, ratios)), ylab = "selected / current", + main = sprintf("%s, n = %d", distribution, sample_size) + ) + abline(h = 1, lty = 2) + } +} +mtext( + sprintf("Selected estimator: %d paired replications", replication_count), + outer = TRUE, font = 2, cex = 1.1 +) + +par(mfrow = c(3, 4), mar = c(4.5, 4.2, 2.4, 0.5), oma = c(0, 0, 3.5, 0)) +for (sample_size in sort(unique(results$sample_size))) { + for (distribution in names(validation_distributions)) { + selected_result <- results[ + results$sample_size == sample_size & + results$distribution == distribution & + results$method == "selected", + ] + barplot( + rbind( + bulk = c(selected_result$lower_bulk_rate, selected_result$upper_bulk_rate), + finite = c( + selected_result$lower_finite_rate, + selected_result$upper_finite_rate + ) + ), + names.arg = c("lower", "upper"), col = c("grey60", "#0072B2"), + ylim = c(0, 1), ylab = "selection rate", + main = sprintf("%s, n = %d", distribution, sample_size) + ) + if (sample_size == min(results$sample_size) && + distribution == names(validation_distributions)[[1L]]) { + legend( + "topright", c("bulk", "finite"), + fill = c("grey60", "#0072B2"), bty = "n", cex = 0.75 + ) + } + } +} +mtext("Effective endpoint components", outer = TRUE, font = 2, cex = 1.1) + +sample_size <- 1000L +for (distribution_index in seq_along(validation_distributions)) { + true_density <- validation_distributions[[distribution_index]]$density( + evaluation_points + ) + par(mfrow = c(2, 3), mar = c(4, 4.2, 2.3, 0.6), oma = c(0, 0, 3, 0)) + for (replication in 1:2) { + set.seed( + 20260906L + 100000L * distribution_index + 1000L * 2L + replication + ) + observations <- validation_distributions[[distribution_index]]$random( + sample_size + ) + selected_fit <- fit_bounded_selected_estimator( + observations, + evaluation_points + ) + estimates <- list( + current = normalize_density( + evaluation_points, + dkde1d( + evaluation_points, + kde1d(observations, xmin = 0, xmax = 1) + ) + ), + selected = selected_fit$density + ) + plot( + evaluation_points, true_density, type = "l", lwd = 3, col = "black", + ylim = c(0, quantile(c(true_density, unlist(estimates)), 0.98)), + xlab = "x", ylab = "density", + main = sprintf( + "realization %d: L=%s, U=%s", + replication, + selected_fit$expert_choices[["lower"]], + selected_fit$expert_choices[["upper"]] + ) + ) + for (method in names(estimates)) { + lines( + evaluation_points, estimates[[method]], col = method_colors[[method]], + lwd = if (method == "selected") 2.5 else 1.5, + lty = match(method, names(estimates)) + ) + } + if (replication == 1L) { + legend( + "topright", c("truth", "current", "selected"), + col = c("black", method_colors), lty = c(1, 1, 2), + lwd = c(3, 1.5, 2.5), bty = "n", cex = 0.75 + ) + } + for (boundary in c("left", "right")) { + boundary_points <- if (boundary == "left") { + evaluation_points >= 1e-6 & evaluation_points <= 0.1 + } else { + evaluation_points >= 0.9 & evaluation_points <= 1 - 1e-6 + } + boundary_distances <- if (boundary == "left") { + evaluation_points[boundary_points] + } else { + 1 - evaluation_points[boundary_points] + } + boundary_order <- order(boundary_distances) + plot( + boundary_distances[boundary_order], + true_density[boundary_points][boundary_order], + type = "l", log = "x", lwd = 3, col = "black", + ylim = c(0, quantile(c( + true_density[boundary_points], + unlist(lapply(estimates, function(density) density[boundary_points])) + ), 0.99)), + xlab = "distance from boundary", ylab = "density", main = boundary + ) + for (method in names(estimates)) { + lines( + boundary_distances[boundary_order], + estimates[[method]][boundary_points][boundary_order], + col = method_colors[[method]], + lwd = if (method == "selected") 2.5 else 1.5, + lty = match(method, names(estimates)) + ) + } + } + } + mtext( + sprintf( + "%s, n = %d; effective choices shown in panel titles", + names(validation_distributions)[[distribution_index]], sample_size + ), + outer = TRUE, font = 2, cex = 1.1 + ) +} +dev.off() +message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R b/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R new file mode 100644 index 0000000..89b6a40 --- /dev/null +++ b/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R @@ -0,0 +1,234 @@ +# Plot the paired endpoint-classifier ablation and representative fits. +# Run from the root of the kde1d R package. + +if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { + stop("run from the kde1d package root with pkgload installed") +} +pkgload::load_all(".", quiet = TRUE) +source(paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/", + "bounded_estimator.R" +)) + +arguments <- commandArgs(trailingOnly = TRUE) +input_file <- if (length(arguments) >= 1L) arguments[[1L]] else paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/results/", + "endpoint-classifier-ablation.csv" +) +output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/plots/", + "endpoint-classifier-ablation.pdf" +) +if (length(arguments) > 2L) { + stop("usage: plot_endpoint_classifier_ablation.R [input.csv] [output.pdf]") +} + +results <- read.csv(input_file) +classifier_methods <- c( + "single-95", "single-1.5-95", "single-2-95", + "median-90", "vote-90", "vote-95" +) +method_labels <- c( + `single-95` = "1x", `single-1.5-95` = "1.5x", `single-2-95` = "2x", + `median-90` = "median", `vote-90` = "vote 90", `vote-95` = "vote 95" +) +method_colors <- c( + `single-95` = "#009E73", `single-1.5-95` = "#56B4E9", + `single-2-95` = "#E69F00", `median-90` = "#CC79A7", + `vote-90` = "#7B3294", `vote-95` = "#D55E00" +) +validation_distributions <- list( + uniform = list(random = runif, density = dunif), + `beta-1-2` = list( + random = function(sample_size) rbeta(sample_size, 1, 2), + density = function(values) dbeta(values, 1, 2) + ), + `beta-0.75-2` = list( + random = function(sample_size) rbeta(sample_size, 0.75, 2), + density = function(values) dbeta(values, 0.75, 2) + ), + `beta-0.75-0.75` = list( + random = function(sample_size) rbeta(sample_size, 0.75, 0.75), + density = function(values) dbeta(values, 0.75, 0.75) + ) +) +evaluation_points <- sort(unique(c( + 10^seq(-10, -2, length.out = 101L), + seq(0.01, 0.99, length.out = 301L), + 1 - 10^seq(-2, -10, length.out = 101L) +))) + +dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) +pdf(output_file, width = 12, height = 8) + +par(mfrow = c(3, 4), mar = c(4.5, 4.2, 2.4, 0.5), oma = c(0, 0, 3.5, 0)) +for (sample_size in sort(unique(results$sample_size))) { + for (distribution in names(validation_distributions)) { + scenario_results <- results[ + results$sample_size == sample_size & + results$distribution == distribution, + ] + current_ise <- scenario_results$global_ise[ + scenario_results$method == "kde-current" + ] + scenario_results <- scenario_results[ + match(classifier_methods, scenario_results$method), + ] + ratios <- scenario_results$global_ise / current_ise + barplot( + ratios, + names.arg = method_labels[classifier_methods], + col = method_colors[classifier_methods], las = 2, cex.names = 0.7, + ylim = range(c(0, 1, ratios)), ylab = "global ISE / current", + main = sprintf("%s, n = %d", distribution, sample_size) + ) + abline(h = 1, lty = 2) + } +} +mtext( + sprintf( + "Classifier ISE: %d paired replications", + unique(results$replications) + ), + outer = TRUE, font = 2, cex = 1.1 +) + +par(mfrow = c(3, 4), mar = c(4.5, 4.2, 2.4, 0.5), oma = c(0, 0, 3.5, 0)) +for (sample_size in sort(unique(results$sample_size))) { + for (distribution in names(validation_distributions)) { + scenario_results <- results[ + results$sample_size == sample_size & + results$distribution == distribution & + results$method %in% classifier_methods, + ] + scenario_results <- scenario_results[ + match(classifier_methods, scenario_results$method), + ] + barplot( + rowMeans(scenario_results[, c("lower_accuracy", "upper_accuracy")]), + names.arg = method_labels[classifier_methods], + col = method_colors[classifier_methods], las = 2, cex.names = 0.7, + ylim = c(0, 1), ylab = "mean endpoint accuracy", + main = sprintf("%s, n = %d", distribution, sample_size) + ) + } +} +mtext( + "Classification accuracy (finite versus bulk endpoint component)", + outer = TRUE, font = 2, cex = 1.1 +) + +visual_methods <- c("single-95", "single-2-95", "vote-90") +sample_size <- 1000L +for (distribution_index in seq_along(validation_distributions)) { + true_density <- validation_distributions[[distribution_index]]$density( + evaluation_points + ) + par(mfrow = c(2, 3), mar = c(4, 4.2, 2.4, 0.6), oma = c(0, 0, 3, 0)) + for (replication in 1:2) { + set.seed( + 20260909L + 100000L * distribution_index + 1000L * 2L + replication + ) + observations <- validation_distributions[[distribution_index]]$random( + sample_size + ) + estimator_components <- fit_bounded_estimator_components( + observations, + evaluation_points + ) + selections <- list( + `single-95` = select_bounded_endpoint_experts_single_scale(observations), + `single-2-95` = select_bounded_endpoint_experts_single_scale( + observations, + tail_multiplier = 2 + ), + `vote-90` = select_bounded_endpoint_experts_multiscale( + observations, + evidence_threshold = qnorm(0.90), + rule = "vote" + ) + ) + estimates <- list( + current = normalize_density( + evaluation_points, + dkde1d( + evaluation_points, + kde1d(observations, xmin = 0, xmax = 1) + ) + ) + ) + for (method in visual_methods) { + estimator_components$selection <- selections[[method]] + estimates[[method]] <- fuse_bounded_estimator_components( + evaluation_points, + estimator_components + )$density + } + plot( + evaluation_points, true_density, type = "l", lwd = 3, col = "black", + ylim = c(0, quantile(c(true_density, unlist(estimates)), 0.98)), + xlab = "x", ylab = "density", + main = sprintf("realization %d", replication) + ) + lines(evaluation_points, estimates$current, col = "grey45", lwd = 1.5) + for (method in visual_methods) { + lines( + evaluation_points, estimates[[method]], col = method_colors[[method]], + lwd = if (method == "single-2-95") 2.5 else 1.5, + lty = match(method, visual_methods) + ) + } + if (replication == 1L) { + legend( + "topright", c("truth", "current", method_labels[visual_methods]), + col = c("black", "grey45", method_colors[visual_methods]), + lty = c(1, 1, seq_along(visual_methods)), + lwd = c(3, 1.5, 1.5, 2.5, 1.5), bty = "n", cex = 0.72 + ) + } + for (boundary in c("left", "right")) { + boundary_points <- if (boundary == "left") { + evaluation_points >= 1e-6 & evaluation_points <= 0.1 + } else { + evaluation_points >= 0.9 & evaluation_points <= 1 - 1e-6 + } + boundary_distances <- if (boundary == "left") { + evaluation_points[boundary_points] + } else { + 1 - evaluation_points[boundary_points] + } + boundary_order <- order(boundary_distances) + plot( + boundary_distances[boundary_order], + true_density[boundary_points][boundary_order], + type = "l", log = "x", lwd = 3, col = "black", + ylim = c(0, quantile(c( + true_density[boundary_points], + unlist(lapply(estimates, function(density) density[boundary_points])) + ), 0.98)), + xlab = "distance from boundary", ylab = "density", main = boundary + ) + lines( + boundary_distances[boundary_order], + estimates$current[boundary_points][boundary_order], + col = "grey45", lwd = 1.5 + ) + for (method in visual_methods) { + lines( + boundary_distances[boundary_order], + estimates[[method]][boundary_points][boundary_order], + col = method_colors[[method]], + lwd = if (method == "single-2-95") 2.5 else 1.5, + lty = match(method, visual_methods) + ) + } + } + } + mtext( + sprintf("%s, n = %d", names(validation_distributions)[distribution_index], sample_size), + outer = TRUE, font = 2, cex = 1.1 + ) +} + +dev.off() +message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R b/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R new file mode 100644 index 0000000..32cddd6 --- /dev/null +++ b/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R @@ -0,0 +1,195 @@ +# Paired validation of the selected bounded estimator against current kde1d. +# Run from the root of the kde1d R package. + +if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { + stop("run from the kde1d package root with pkgload installed") +} +pkgload::load_all(".", quiet = TRUE) +source(paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/", + "bounded_estimator.R" +)) + +arguments <- commandArgs(trailingOnly = TRUE) +replication_count <- if (length(arguments) >= 1L) { + as.integer(arguments[[1L]]) +} else { + 100L +} +output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( + "inst/include/kde1d-cpp/diagnostic/boundary-repair/results/", + "bounded-estimator-validation.csv" +) +if (length(arguments) > 2L || !is.finite(replication_count) || + replication_count < 2L) { + stop("usage: validate_bounded_estimator.R [replications] [output.csv]") +} + +make_beta_distribution <- function(shape1, shape2) { + list( + random = function(sample_size) rbeta(sample_size, shape1, shape2), + density = function(values) dbeta(values, shape1, shape2) + ) +} +validation_distributions <- list( + uniform = list(random = runif, density = dunif), + `beta-1-2` = make_beta_distribution(1, 2), + `beta-0.75-2` = make_beta_distribution(0.75, 2), + `beta-0.75-0.75` = make_beta_distribution(0.75, 0.75) +) +sample_sizes <- c(100L, 1000L, 2000L) +methods <- c("current", "selected") +evaluation_points <- sort(unique(c( + 10^seq(-10, -2, length.out = 101L), + seq(0.01, 0.99, length.out = 301L), + 1 - 10^seq(-2, -10, length.out = 101L) +))) +left_points <- evaluation_points <= 0.1 +right_points <- evaluation_points >= 0.9 +result_rows <- list() + +summarize_estimates <- function(estimates, true_density, region_points) { + mean_density <- rowMeans(estimates) + integrated_errors <- vapply( + seq_len(ncol(estimates)), + function(replication) { + trapezoid_integral( + evaluation_points[region_points], + (estimates[region_points, replication] - + true_density[region_points])^2 + ) + }, + numeric(1L) + ) + c( + ise = mean(integrated_errors), + ise_median = median(integrated_errors), + squared_bias = trapezoid_integral( + evaluation_points[region_points], + (mean_density[region_points] - true_density[region_points])^2 + ), + variance = trapezoid_integral( + evaluation_points[region_points], + rowMeans((estimates[region_points, , drop = FALSE] - + mean_density[region_points])^2) + ) + ) +} + +for (distribution_index in seq_along(validation_distributions)) { + true_density <- validation_distributions[[distribution_index]]$density( + evaluation_points + ) + for (sample_size in sample_sizes) { + estimates <- setNames( + lapply(methods, function(method) { + matrix(NA_real_, length(evaluation_points), replication_count) + }), + methods + ) + expert_choices <- array( + NA_character_, + dim = c(replication_count, 2L), + dimnames = list(NULL, c("lower", "upper")) + ) + for (replication in seq_len(replication_count)) { + set.seed( + 20260906L + 100000L * distribution_index + + 1000L * match(sample_size, sample_sizes) + replication + ) + observations <- validation_distributions[[distribution_index]]$random( + sample_size + ) + estimates$current[, replication] <- normalize_density( + evaluation_points, + dkde1d( + evaluation_points, + kde1d(observations, xmin = 0, xmax = 1) + ) + ) + estimator_components <- fit_bounded_estimator_components( + observations, + evaluation_points + ) + selected_fit <- fuse_bounded_estimator_components( + evaluation_points, + estimator_components + ) + estimates$selected[, replication] <- selected_fit$density + expert_choices[replication, ] <- selected_fit$expert_choices + } + for (method in methods) { + global_summary <- summarize_estimates( + estimates[[method]], + true_density, + rep(TRUE, length(evaluation_points)) + ) + left_summary <- summarize_estimates( + estimates[[method]], + true_density, + left_points + ) + right_summary <- summarize_estimates( + estimates[[method]], + true_density, + right_points + ) + result_rows[[length(result_rows) + 1L]] <- data.frame( + distribution = names(validation_distributions)[[distribution_index]], + sample_size = sample_size, + replications = replication_count, + method = method, + global_ise = global_summary[["ise"]], + global_ise_median = global_summary[["ise_median"]], + global_squared_bias = global_summary[["squared_bias"]], + global_variance = global_summary[["variance"]], + left_ise = left_summary[["ise"]], + left_squared_bias = left_summary[["squared_bias"]], + left_variance = left_summary[["variance"]], + right_ise = right_summary[["ise"]], + right_squared_bias = right_summary[["squared_bias"]], + right_variance = right_summary[["variance"]], + lower_finite_rate = if (method == "selected") { + mean(expert_choices[, "lower"] == "finite") + } else { + NA_real_ + }, + upper_finite_rate = if (method == "selected") { + mean(expert_choices[, "upper"] == "finite") + } else { + NA_real_ + }, + lower_bulk_rate = if (method == "selected") { + mean(expert_choices[, "lower"] == "bulk") + } else { + NA_real_ + }, + upper_bulk_rate = if (method == "selected") { + mean(expert_choices[, "upper"] == "bulk") + } else { + NA_real_ + }, + minimum_density = min(estimates[[method]]), + maximum_mass_error = max(abs(vapply( + seq_len(replication_count), + function(replication) { + trapezoid_integral( + evaluation_points, + estimates[[method]][, replication] + ) - 1 + }, + numeric(1L) + ))) + ) + } + message( + names(validation_distributions)[[distribution_index]], + ", n = ", sample_size + ) + } +} + +results <- do.call(rbind, result_rows) +dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) +write.csv(results, output_file, row.names = FALSE) +message("wrote ", normalizePath(output_file)) From a3968256b5d2bfd6c1fbf43e4b940be3cead8b33 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 13:52:57 +0200 Subject: [PATCH 03/25] Add one-sided boundary expert diagnostics --- diagnostic/README.md | 3 + diagnostic/one-sided-repair/HANDOFF.md | 33 ++ diagnostic/one-sided-repair/README.md | 44 +++ diagnostic/one-sided-repair/RESULTS.md | 59 +++ .../plots/local-floor-fraction-ablation.pdf | Bin 0 -> 77662 bytes .../results/local-floor-fraction-ablation.csv | 111 ++++++ .../scripts/ablate_local_floor_fraction.R | 212 +++++++++++ .../scripts/one_sided_estimator.R | 360 ++++++++++++++++++ .../plot_local_floor_fraction_ablation.R | 163 ++++++++ 9 files changed, 985 insertions(+) create mode 100644 diagnostic/one-sided-repair/HANDOFF.md create mode 100644 diagnostic/one-sided-repair/README.md create mode 100644 diagnostic/one-sided-repair/RESULTS.md create mode 100644 diagnostic/one-sided-repair/plots/local-floor-fraction-ablation.pdf create mode 100644 diagnostic/one-sided-repair/results/local-floor-fraction-ablation.csv create mode 100644 diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R create mode 100644 diagnostic/one-sided-repair/scripts/one_sided_estimator.R create mode 100644 diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R diff --git a/diagnostic/README.md b/diagnostic/README.md index 7466023..9624814 100644 --- a/diagnostic/README.md +++ b/diagnostic/README.md @@ -33,3 +33,6 @@ to zero. The separate transformation-boundary investigation, its retained simulation results, and its current recommendations live in [`boundary-repair/`](boundary-repair/README.md). + +The follow-up for supports with exactly one finite endpoint lives in +[`one-sided-repair/`](one-sided-repair/README.md). diff --git a/diagnostic/one-sided-repair/HANDOFF.md b/diagnostic/one-sided-repair/HANDOFF.md new file mode 100644 index 0000000..edf56af --- /dev/null +++ b/diagnostic/one-sided-repair/HANDOFF.md @@ -0,0 +1,33 @@ +# One-sided repair handoff + +The production branch already uses a scale-equivariant power-$3/4$ transform +for one-sided supports. The diagnostic candidate keeps that estimator as the +unweighted bulk and adds the selected two-boundary method's finite expert: +equal local-linear/local-quadratic estimates, a shrinking CDF gate, and a +$2\sqrt n$ order-statistic finite-versus-bulk decision. + +The bandwidth floor is the unweighted bandwidth fitted to the lowest 75% of +boundary distances. A 30-replication ablation compared fixed fractions from +15% through 100% and a $\sqrt n$ shrinking subset. Performance improved up to +75%; using all observations reversed the long-tail gains because remote Lomax +observations again controlled the floor. The 75% choice has mean global ISE +ratios to current of 0.902 at $n=100$ and 0.889 at $n=1000$, with corresponding +boundary ratios 0.854 and 0.834. + +The representative plots confirm that 75% removes most residual finite-endpoint +spiking. It is visually close to the full-sample floor for Exponential and +half-normal cases, but remains stable for Lomax. The main remaining loss is a +small-sample false finite classification for Gamma$(2)$: global ISE is 1.026 +and boundary ISE is 1.083 relative to current at $n=100$. At $n=1000$ the +classifier always chooses bulk for both Gamma examples, so the result is +exactly current. + +The log transform was rejected and removed. The working diagnostic now contains +only the current power-transform candidate and the floor-fraction validation. + +Before native C++ implementation, expand the scenario suite around the selected +75% value and classifier edge cases. In particular, add finite-boundary shapes +with steep nonzero slopes, heavier remote tails, upper-bounded reflections, and +sample sizes between 100 and 1000. Keep paired global/boundary ISE, bias, +variance, normalization, nonnegativity, reflection, scale, and realization +checks. diff --git a/diagnostic/one-sided-repair/README.md b/diagnostic/one-sided-repair/README.md new file mode 100644 index 0000000..66f7a1d --- /dev/null +++ b/diagnostic/one-sided-repair/README.md @@ -0,0 +1,44 @@ +# One-sided boundary repair + +This workspace applies the selected two-boundary idea to continuous densities +with exactly one known finite endpoint. It is deliberately separate from +`boundary-repair/`, which is stable. + +## Current candidate + +The power-$3/4$ transformation estimator is the unweighted bulk fit. A single +order-statistic tail index classifies the finite endpoint using +$k=\min(n-1,\lceil2\sqrt n\rceil)$ and the same 95% rule as in the +two-boundary estimator. A confidently finite endpoint receives the equal +local-linear/local-quadratic expert; exploding, vanishing, and ambiguous +endpoints reuse bulk. + +The boundary expert is blended with bulk through a smooth gate based on the +bulk CDF, with boundary probability $\min(0.25,n^{-1/2})$. Its local-polynomial +bandwidth is floored at the unweighted bandwidth fitted to the lowest 75% of +boundary distances. This preserves the stabilizing information in most of the +sample without allowing the most remote observations to dominate the floor. +The construction is reflection- and scale-equivariant. + +The validation suite uses 30 paired replications at $n=100,1000$ for +Exponential, half-normal, Gamma$(2)$, Gamma$(0.75)$, and Lomax$(2)$ densities. +The log transform was rejected and its experimental implementation and outputs +have been removed. + +## Files + +- `scripts/one_sided_estimator.R`: current R reference implementation. +- `scripts/ablate_local_floor_fraction.R`: selected floor-fraction ablation. +- `scripts/plot_local_floor_fraction_ablation.R`: tuning curves and example + estimates. +- `results/local-floor-fraction-ablation.csv` and + `plots/local-floor-fraction-ablation.pdf`: current tuning evidence. +- `RESULTS.md`: numerical conclusions. +- `HANDOFF.md`: implementation state and next steps. + +Run from the R-package root: + +```sh +Rscript inst/include/kde1d-cpp/diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R 30 +Rscript inst/include/kde1d-cpp/diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R +``` diff --git a/diagnostic/one-sided-repair/RESULTS.md b/diagnostic/one-sided-repair/RESULTS.md new file mode 100644 index 0000000..b302222 --- /dev/null +++ b/diagnostic/one-sided-repair/RESULTS.md @@ -0,0 +1,59 @@ +# One-sided boundary-repair results + +## Estimator held fixed during the ablation + +The candidate uses the power-$3/4$ estimator as unweighted bulk. If the +order-statistic classifier identifies a finite nonzero endpoint, equal +local-linear and local-quadratic estimates are blended into the shrinking +boundary region. Only the bandwidth-floor sample fraction changes. + +The experiment uses 30 paired replications for five densities at $n=100$ and +$n=1000$. It compares the lowest 15%, 20%, 25%, 30%, 35%, 40%, 50%, 75%, and +100% of boundary distances, plus a shrinking subset of $\lceil\sqrt n\rceil$ +distances. All values below are candidate/current ratios, so smaller is better. + +## Aggregate result + +| $n$ | floor subset | global ISE | boundary ISE | squared bias | variance | +|---:|---:|---:|---:|---:|---:| +| 100 | 25% | 0.989 | 0.986 | 0.895 | 1.007 | +| 100 | 50% | 0.933 | 0.899 | 0.860 | 0.949 | +| 100 | 75% | **0.902** | **0.854** | **0.829** | **0.917** | +| 100 | 100% | 0.941 | 0.911 | 1.004 | 0.923 | +| 100 | $\sqrt n$ | 1.073 | 1.127 | 0.905 | 1.102 | +| 1000 | 25% | 0.933 | 0.896 | 0.801 | 0.976 | +| 1000 | 50% | 0.909 | 0.863 | 0.797 | 0.946 | +| 1000 | 75% | **0.889** | **0.834** | **0.789** | **0.924** | +| 1000 | 100% | 0.983 | 0.959 | 0.963 | 0.986 | +| 1000 | $\sqrt n$ | 1.043 | 1.064 | 0.806 | 1.112 | + +The old 25% floor is too local. Increasing the subset through 75% reduces both +bias and variance. A shrinking $\sqrt n$ subset is clearly too small and +reintroduces instability. Using the full sample overshoots the optimum because +remote tail observations again inflate the floor. + +## Selected 75% floor by density + +| density | $n$ | global ISE | boundary ISE | squared bias | variance | +|---|---:|---:|---:|---:|---:| +| Exponential | 100 | 0.808 | 0.709 | 0.575 | 0.841 | +| Exponential | 1000 | 0.805 | 0.722 | 0.455 | 0.890 | +| half-normal | 100 | 0.869 | 0.744 | 0.817 | 0.878 | +| half-normal | 1000 | 0.808 | 0.672 | 0.868 | 0.801 | +| Gamma$(2)$ | 100 | 1.026 | 1.083 | 1.174 | 1.019 | +| Gamma$(2)$ | 1000 | 1.000 | 1.000 | 1.000 | 1.000 | +| Gamma$(0.75)$ | 100 | 0.985 | 0.983 | 0.913 | 0.992 | +| Gamma$(0.75)$ | 1000 | 1.000 | 1.000 | 1.000 | 1.000 | +| Lomax$(2)$ | 100 | 0.819 | 0.752 | 0.670 | 0.857 | +| Lomax$(2)$ | 1000 | 0.833 | 0.774 | 0.622 | 0.926 | + +The full-sample floor would improve the finite light-tail cases further, but it +raises Lomax global ISE to 1.075 at $n=100$ and 1.392 at $n=1000$. The 75% +floor retains large improvements for both light and long remote tails and is +therefore the selected default. + +The realization plots show the same trade-off. Relative to 25%, the selected +floor substantially calms the near-endpoint estimates. Relative to 100%, it +avoids the flattened Lomax boundary while remaining visually smooth for +Exponential data. All simulated estimates are nonnegative and normalized to +numerical precision. diff --git a/diagnostic/one-sided-repair/plots/local-floor-fraction-ablation.pdf b/diagnostic/one-sided-repair/plots/local-floor-fraction-ablation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1fafa4a0116d914812a2ef0062d64719a4959a6a GIT binary patch literal 77662 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 SvU4buHcSVktZZsy2KpbMJ4BcO literal 0 HcmV?d00001 diff --git a/diagnostic/one-sided-repair/results/local-floor-fraction-ablation.csv b/diagnostic/one-sided-repair/results/local-floor-fraction-ablation.csv new file mode 100644 index 0000000..9aebb6c --- /dev/null +++ b/diagnostic/one-sided-repair/results/local-floor-fraction-ablation.csv @@ -0,0 +1,111 @@ +"distribution","sample_size","replications","method","global_ise","global_squared_bias","global_variance","boundary_ise","boundary_squared_bias","boundary_variance","finite_rate","mean_floor_ratio","minimum_density","maximum_mass_error" +"exponential",100,30,"current",0.0165472389855547,0.00205016560497188,0.0144970733805828,0.0106234994208158,0.00126599700538637,0.00935750241542941,NA,NA,1.87620764495024e-15,1.11022302462516e-16 +"exponential",100,30,"fixed-15pct",0.0164068280322217,0.00176173524182124,0.0146450927904004,0.0104884088522769,0.000969273783595678,0.00951913506868119,0.666666666666667,2.26138933228023,0,1.11022302462516e-16 +"exponential",100,30,"fixed-20pct",0.0157245002505956,0.00165925024528034,0.0140652500053152,0.00977827871653413,0.000871272403187169,0.00890700631334696,0.666666666666667,2.72230964287038,1.8683320459021e-15,1.11022302462516e-16 +"exponential",100,30,"fixed-25pct",0.0154464207902959,0.00159454865963953,0.0138518721306564,0.0094772157298769,0.00081402806341869,0.00866318766645821,0.666666666666667,3.3746911588894,1.86756569172953e-15,1.11022302462516e-16 +"exponential",100,30,"fixed-30pct",0.0152787565880896,0.00159907933870905,0.0136796772493806,0.00929504572248738,0.000818405451515906,0.00847664027097147,0.666666666666667,4.09079193231902,1.87053078117119e-15,1.11022302462516e-16 +"exponential",100,30,"fixed-35pct",0.0150985550244765,0.00157889875105775,0.0135196562734187,0.00910619553077884,0.00080019644459805,0.00830599908618079,0.666666666666667,4.74814780644128,1.87467719387415e-15,1.11022302462516e-16 +"exponential",100,30,"fixed-40pct",0.0148474205746887,0.00152076471560491,0.0133266558590838,0.00886082377495489,0.000749827554669101,0.00811099622028579,0.666666666666667,5.28142581925347,1.87508377257283e-15,2.22044604925031e-16 +"exponential",100,30,"fixed-50pct",0.0144525145480613,0.00140802584850766,0.0130444886995537,0.00850068136672482,0.000655265975954673,0.00784541539077015,0.666666666666667,6.6658845934232,1.87677765384802e-15,1.11022302462516e-16 +"exponential",100,30,"fixed-75pct",0.013372535861314,0.0011785272962235,0.0121940085650905,0.00753230138812056,0.000480751354051795,0.00705155003406876,0.666666666666667,11.0333560732554,1.8732244279489e-15,1.11022302462516e-16 +"exponential",100,30,"fixed-100pct",0.0122027604558946,0.00112660422901432,0.0110761562268802,0.00650597734670406,0.000461015912509725,0.00604496143419433,0.666666666666667,25.0263770275047,1.87799591395489e-15,1.11022302462516e-16 +"exponential",100,30,"shrinking",0.017856701300014,0.00171894251195662,0.0161377587880574,0.0119985964464945,0.000950185514962622,0.0110484109315318,0.666666666666667,1.53936144201145,0,1.11022302462516e-16 +"exponential",1000,30,"current",0.00240917299788813,0.000470619160762849,0.00193855383712528,0.00165537707098662,0.000403802822230112,0.00125157424875651,NA,NA,1.84245192195729e-08,1.11022302462516e-16 +"exponential",1000,30,"fixed-15pct",0.00226862893387558,0.000267541194142079,0.0020010877397335,0.00151319998629151,0.000204448971019676,0.00130875101527183,0.8,4.74481059084514,1.84460227396814e-08,1.11022302462516e-16 +"exponential",1000,30,"fixed-20pct",0.00225442266571058,0.000262749740050737,0.00199167292565984,0.00149821118453056,0.000200035780791981,0.00129817540373858,0.8,5.98252748718848,1.84548529261594e-08,1.11022302462516e-16 +"exponential",1000,30,"fixed-25pct",0.00223163792088978,0.000257242065644417,0.00197439585524536,0.0014751821032443,0.000194947305987805,0.00128023479725649,0.8,7.22495317992321,1.84584351924974e-08,2.22044604925031e-16 +"exponential",1000,30,"fixed-30pct",0.00221870029017855,0.000252826191135576,0.00196587409904297,0.00146218422878417,0.000190827664872001,0.00127135656391217,0.8,8.52165916461346,1.84604292036413e-08,1.11022302462516e-16 +"exponential",1000,30,"fixed-35pct",0.00219384531132905,0.000247241712589002,0.00194660359874005,0.00143795550079077,0.000185653506736015,0.00125230199405476,0.8,9.8649716598902,1.84610565220666e-08,1.11022302462516e-16 +"exponential",1000,30,"fixed-40pct",0.00217145301439129,0.000242349204881074,0.00192910380951022,0.00141640854005911,0.000181158632597437,0.00123524990746168,0.8,11.0937383479702,1.84608070901668e-08,2.22044604925031e-16 +"exponential",1000,30,"fixed-50pct",0.00211986240298299,0.000235244426606243,0.00188461797637675,0.00136696335158836,0.00017465441086855,0.00119230894071981,0.8,14.2235753638748,1.84549854155193e-08,1.11022302462516e-16 +"exponential",1000,30,"fixed-75pct",0.00193955914179103,0.000214004486169561,0.00172555465562147,0.00119551447318874,0.000155328617762214,0.00104018585542653,0.8,23.6847920686692,1.84070208807465e-08,1.11022302462516e-16 +"exponential",1000,30,"fixed-100pct",0.00179827087563706,0.000210590735373438,0.00158768014026362,0.0010637085141229,0.000152188847628034,0.00091151966649487,0.8,59.0059636907067,1.83724706743234e-08,1.11022302462516e-16 +"exponential",1000,30,"shrinking",0.00273822412309522,0.00028350698150981,0.00245471714158541,0.00198144991484761,0.000219256056318021,0.00176219385852959,0.8,1.39713095946284,0,1.11022302462516e-16 +"half_normal",100,30,"current",0.0219941368244042,0.0030219174956199,0.0189722193287843,0.0110161925675509,0.000849741178896194,0.0101664513886547,NA,NA,0,2.22044604925031e-16 +"half_normal",100,30,"fixed-15pct",0.0227249965243955,0.00273111590377345,0.019993880620622,0.0117287333016139,0.000600066952616288,0.0111286663489976,0.8,2.37019396388901,0,1.11022302462516e-16 +"half_normal",100,30,"fixed-20pct",0.0224219661004901,0.00271727802633407,0.0197046880741561,0.011438676091904,0.000586237600351728,0.0108524384915523,0.8,2.71464262028137,0,1.11022302462516e-16 +"half_normal",100,30,"fixed-25pct",0.0219269324508956,0.00269041598616543,0.0192365164647302,0.0109498342362696,0.000558589786947187,0.0103912444493225,0.8,3.14072469187916,0,1.11022302462516e-16 +"half_normal",100,30,"fixed-30pct",0.0215633488241571,0.00267166572203566,0.0188916831021214,0.0105948753978839,0.000542078086840766,0.0100527973110432,0.8,3.60955830997078,0,1.11022302462516e-16 +"half_normal",100,30,"fixed-35pct",0.0210312218425393,0.00266532168736644,0.0183659001551728,0.0100696160284695,0.000533729203646682,0.00953588682482281,0.8,4.16410671809387,0,1.11022302462516e-16 +"half_normal",100,30,"fixed-40pct",0.0206204333336116,0.0026483827572441,0.0179720505763675,0.00965859372516434,0.000516888221053642,0.0091417055041107,0.8,4.81231426826691,0,1.11022302462516e-16 +"half_normal",100,30,"fixed-50pct",0.0200327113370716,0.00263109300195777,0.0174016183351138,0.00906277994189698,0.000497753785072715,0.00856502615682426,0.8,5.9807411308278,3.06939566084117e-10,1.11022302462516e-16 +"half_normal",100,30,"fixed-75pct",0.0191219774632953,0.00246802725978619,0.0166539502035091,0.00820055137292614,0.000374255974420255,0.00782629539850588,0.8,9.15049092595185,3.07494413352088e-10,1.11022302462516e-16 +"half_normal",100,30,"fixed-100pct",0.0177911170386674,0.00223295181803002,0.0155581652206374,0.00704315204661345,0.000232650073862045,0.0068105019727514,0.8,14.7602804283356,3.06779576076905e-10,1.11022302462516e-16 +"half_normal",100,30,"shrinking",0.0237532831195187,0.00267081247804823,0.0210824706414705,0.0127376215859904,0.000545114336237087,0.0121925072497533,0.8,1.70499785686247,0,1.11022302462516e-16 +"half_normal",1000,30,"current",0.00274341237242215,0.000280571449502999,0.00246284092291915,0.00156264121910904,8.45358254246363e-05,0.00147810539368441,NA,NA,4.07601257168278e-10,2.22044604925031e-16 +"half_normal",1000,30,"fixed-15pct",0.00239860475791024,0.00023031830376732,0.00216828645414292,0.00122490802991675,4.12353743580945e-05,0.00118367265555866,0.7,4.34564987912544,1.13038952589692e-05,2.22044604925031e-16 +"half_normal",1000,30,"fixed-20pct",0.00234511782877151,0.000233818969557785,0.00211129885921373,0.00117410137914751,4.61022224571394e-05,0.00112799915669037,0.7,5.32984658897953,1.13034006367537e-05,2.22044604925031e-16 +"half_normal",1000,30,"fixed-25pct",0.00232711352945201,0.000237367111878006,0.00208974641757401,0.00115726236610121,5.02670537112527e-05,0.00110699531238995,0.7,6.43401199260486,1.13040847624379e-05,2.22044604925031e-16 +"half_normal",1000,30,"fixed-30pct",0.00231117000000692,0.000240171907376736,0.00207099809263018,0.00114228501393874,5.35257957790126e-05,0.00108875921815973,0.7,7.48910434944926,1.13047763103815e-05,2.22044604925031e-16 +"half_normal",1000,30,"fixed-35pct",0.00229686297939699,0.000242642686529828,0.00205422029286716,0.00112882622241208,5.63660204190984e-05,0.00107246020199298,0.7,8.43677378168733,1.13050274090261e-05,2.22044604925031e-16 +"half_normal",1000,30,"fixed-40pct",0.00228944963338305,0.000242831116619971,0.00204661851676308,0.00112179246612444,5.655341339539e-05,0.00106523905272905,0.7,9.34145379661723,1.13047290481858e-05,2.22044604925031e-16 +"half_normal",1000,30,"fixed-50pct",0.00227344588313635,0.000243474537140234,0.00202997134599611,0.00110571228344061,5.71353280387194e-05,0.00104857695540189,0.7,11.3280875827355,1.13029900215361e-05,2.22044604925031e-16 +"half_normal",1000,30,"fixed-75pct",0.00221714034673766,0.000243482061837878,0.00197365828489979,0.00104976938408884,5.78750403428966e-05,0.000991894343745948,0.7,16.7479465148207,1.1293032196771e-05,2.22044604925031e-16 +"half_normal",1000,30,"fixed-100pct",0.0021329497805297,0.000243836210442882,0.00188911357008682,0.000968433716153227,6.06661299234941e-05,0.000907767586229733,0.7,27.3251884944149,1.12679030054272e-05,2.22044604925031e-16 +"half_normal",1000,30,"shrinking",0.00284213353017322,0.000230931420125264,0.00261120211004796,0.00166941156763807,4.14921749166945e-05,0.00162791939272138,0.7,1.35077773725852,0,2.22044604925031e-16 +"gamma_2",100,30,"current",0.00448352076124264,0.000201561828895339,0.00428195893234731,0.00146327990980918,0.000135018357992683,0.0013282615518165,NA,NA,0,2.22044604925031e-16 +"gamma_2",100,30,"fixed-15pct",0.00459371029079864,0.000201207501479278,0.00439250278931936,0.00158037848320732,0.000136949605033015,0.00144342887817431,0.333333333333333,1.91525005228117,0,1.11022302462516e-16 +"gamma_2",100,30,"fixed-20pct",0.00455634729915098,0.000208004490920689,0.00434834280823029,0.00154236062875898,0.000142810162262304,0.00139955046649668,0.333333333333333,2.29761042217586,0,1.11022302462516e-16 +"gamma_2",100,30,"fixed-25pct",0.00455623114841961,0.000214821631304367,0.00434140951711525,0.00154202356205872,0.000149333840245232,0.00139268972181349,0.333333333333333,2.77544275831225,0,1.11022302462516e-16 +"gamma_2",100,30,"fixed-30pct",0.00455120479869776,0.000215698390397887,0.00433550640829987,0.00153831983882578,0.000150238994097621,0.00138808084472816,0.333333333333333,2.90797508198628,0,1.11022302462516e-16 +"gamma_2",100,30,"fixed-35pct",0.0045471326651577,0.000217952041254612,0.00432918062390309,0.00153459820934171,0.00015244906752056,0.00138214914182115,0.333333333333333,2.99786682361582,0,1.11022302462516e-16 +"gamma_2",100,30,"fixed-40pct",0.00454576337060127,0.000220363954783064,0.0043253994158182,0.00153287357090786,0.000154975717175496,0.00137789785373237,0.333333333333333,3.23371893266245,0,1.11022302462516e-16 +"gamma_2",100,30,"fixed-50pct",0.00455160765603087,0.000226965756163114,0.00432464189986776,0.00153792876544311,0.000162076200268522,0.00137585256517459,0.333333333333333,3.75543047296855,0,1.11022302462516e-16 +"gamma_2",100,30,"fixed-75pct",0.00460136779113603,0.000236565440002761,0.00436480235113327,0.00158461737904955,0.000173807172003612,0.00141081020704594,0.333333333333333,5.25961330940397,0,1.11022302462516e-16 +"gamma_2",100,30,"fixed-100pct",0.00474861631473468,0.00023424922057421,0.00451436709416047,0.00171685956647603,0.000174884739131384,0.00154197482734464,0.333333333333333,8.06494615215408,0,1.11022302462516e-16 +"gamma_2",100,30,"shrinking",0.0046866663853133,0.000191314677613302,0.00449535170769999,0.00167153051624082,0.000128138743162736,0.00154339177307808,0.333333333333333,1.46249077481671,0,1.11022302462516e-16 +"gamma_2",1000,30,"current",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,NA,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"fixed-15pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"fixed-20pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"fixed-25pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"fixed-30pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"fixed-35pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"fixed-40pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"fixed-50pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"fixed-75pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"fixed-100pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_2",1000,30,"shrinking",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 +"gamma_0.75",100,30,"current",0.0662130479543093,0.00603847252934643,0.0601745754249629,0.0596204629596765,0.00509342274353279,0.0545270402161437,NA,NA,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"fixed-15pct",0.0688437108923025,0.00596993002684055,0.062873780865462,0.0622764116383608,0.00502879344888837,0.0572476181894724,0.233333333333333,2.51217988508221,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"fixed-20pct",0.0681154550739925,0.00587067138602011,0.0622447836879724,0.0615411348528898,0.00493451100349295,0.0566066238493968,0.233333333333333,3.00451108242131,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"fixed-25pct",0.0669550767706018,0.00570743403616402,0.0612476427344378,0.0603956774670474,0.00477713459093501,0.0556185428761124,0.233333333333333,3.60367826811898,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"fixed-30pct",0.0658758521149039,0.00556660841555187,0.060309243699352,0.0593383501020204,0.004642953742049,0.0546953963599714,0.233333333333333,5.02363090385764,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"fixed-35pct",0.0654203316851601,0.00548660007863664,0.0599337316065235,0.0588890777872092,0.00456762074901735,0.0543214570381918,0.233333333333333,6.27557902395686,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"fixed-40pct",0.0650860242835899,0.00542694184924156,0.0596590824343483,0.0585561390714141,0.00451209769209147,0.0540440413793226,0.233333333333333,7.16425287464413,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"fixed-50pct",0.0647090006418789,0.00533834478367925,0.0593706558581996,0.0581738553795754,0.00442938224035204,0.0537444731392233,0.233333333333333,10.0698415841485,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"fixed-75pct",0.0651901055934623,0.00551032830221601,0.0596797772912463,0.0586057654421702,0.0045791668266887,0.0540265986154815,0.233333333333333,19.660134936497,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"fixed-100pct",0.0676880390463463,0.0060496287625182,0.0616384102838281,0.0609849876154783,0.00506658758002695,0.0559184000354514,0.233333333333333,51.1114722569795,2.97020597181301e-32,2.22044604925031e-16 +"gamma_0.75",100,30,"shrinking",0.0708120152547144,0.00622858341689876,0.0645834318378157,0.0642682642137913,0.0052944469595103,0.058973817254281,0.233333333333333,1.56444490537761,0,2.22044604925031e-16 +"gamma_0.75",1000,30,"current",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,NA,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"fixed-15pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"fixed-20pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"fixed-25pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"fixed-30pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"fixed-35pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"fixed-40pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"fixed-50pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"fixed-75pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"fixed-100pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"gamma_0.75",1000,30,"shrinking",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 +"lomax_2",100,30,"current",0.0320268987246898,0.00648388858700561,0.0255430101376842,0.022571498829797,0.00539273643819479,0.0171787623916022,NA,NA,0,1.11022302462516e-16 +"lomax_2",100,30,"fixed-15pct",0.0341784289040103,0.00545431820112166,0.0287241107028886,0.0246692629391396,0.00437317194694695,0.0202960909921927,0.7,1.74298292023704,0,1.11022302462516e-16 +"lomax_2",100,30,"fixed-20pct",0.0329364272846334,0.00531565631751246,0.0276207709671209,0.0234373427192617,0.00422860716891606,0.0192087355503456,0.7,2.25345608974253,0,1.11022302462516e-16 +"lomax_2",100,30,"fixed-25pct",0.0315504362882948,0.00516885482754763,0.0263815814607472,0.022037140835904,0.00407275491685668,0.0179643859190473,0.7,2.77239130253995,0,1.11022302462516e-16 +"lomax_2",100,30,"fixed-30pct",0.0302487831990908,0.00501418054191126,0.0252346026571795,0.0207106798807081,0.00390287366269442,0.0168078062180136,0.7,3.42851685390775,0,1.11022302462516e-16 +"lomax_2",100,30,"fixed-35pct",0.0299454664033389,0.00498769968054349,0.0249577667227954,0.0204190781644711,0.00387799504835325,0.0165410831161179,0.7,4.08323232164168,0,1.11022302462516e-16 +"lomax_2",100,30,"fixed-40pct",0.0294528981772044,0.00493738819233153,0.0245155099848729,0.0199445389599459,0.00382085750427208,0.0161236814556738,0.7,4.72644379724695,0,1.11022302462516e-16 +"lomax_2",100,30,"fixed-50pct",0.0285189100946901,0.00474155087942755,0.0237773592152626,0.0190556289633984,0.00360673315380207,0.0154488958095963,0.7,6.18958080513734,0,1.11022302462516e-16 +"lomax_2",100,30,"fixed-75pct",0.0262364414943695,0.00434160891191695,0.0218948325824526,0.0169627470963472,0.00315960086719081,0.0138031462291564,0.7,11.9477658059949,0,1.11022302462516e-16 +"lomax_2",100,30,"fixed-100pct",0.0344264830854107,0.0101608357551471,0.0242656473302637,0.0250325446664152,0.00909821530212285,0.0159343293642923,0.7,92.7046182399041,0,1.11022302462516e-16 +"lomax_2",100,30,"shrinking",0.0349986902781772,0.0053166941988258,0.0296819960793514,0.0255221859554241,0.00423518037423045,0.0212870055811936,0.7,1.33704272336928,0,1.11022302462516e-16 +"lomax_2",1000,30,"current",0.00466466138729923,0.00143513707469976,0.00322952431259947,0.00350149716851033,0.00112671300315472,0.00237478416535561,NA,NA,0,1.11022302462516e-16 +"lomax_2",1000,30,"fixed-15pct",0.00436099990888606,0.000878121257830974,0.00348287865105509,0.00320092795758196,0.000564160869336452,0.00263676708824551,0.666666666666667,4.4932550558715,0,1.11022302462516e-16 +"lomax_2",1000,30,"fixed-20pct",0.00423966119040754,0.000876618726807714,0.00336304246359983,0.00307622311705505,0.000560854659297538,0.00251536845775752,0.666666666666667,5.81675470465849,0,1.11022302462516e-16 +"lomax_2",1000,30,"fixed-25pct",0.0041430445540767,0.000876082849395204,0.0032669617046815,0.00297729161922663,0.00055846411536554,0.00241882750386109,0.666666666666667,7.11933483971629,0,2.22044604925031e-16 +"lomax_2",1000,30,"fixed-30pct",0.0040731577359026,0.000877330147025215,0.00319582758887738,0.00290481115181225,0.00055813996746545,0.0023466711843468,0.666666666666667,8.52294235352961,0,1.11022302462516e-16 +"lomax_2",1000,30,"fixed-35pct",0.00401937859112426,0.000878730832829979,0.00314064775829428,0.00284942159321027,0.000558245311673399,0.00229117628153687,0.666666666666667,9.97469592167928,0,1.11022302462516e-16 +"lomax_2",1000,30,"fixed-40pct",0.00397052028672156,0.000880354759175136,0.00309016552754642,0.0027996394210534,0.00055854532208646,0.00224109409896694,0.666666666666667,11.5527001556363,0,1.11022302462516e-16 +"lomax_2",1000,30,"fixed-50pct",0.00390556519468693,0.000885414325502173,0.00302015086918476,0.00273302688240551,0.000561236325944702,0.0021717905564608,0.666666666666667,15.168288605388,0,1.11022302462516e-16 +"lomax_2",1000,30,"fixed-75pct",0.00388389723608418,0.000892559922975234,0.00299133731310895,0.00271109831571414,0.000567744771275972,0.00214335354443817,0.666666666666667,28.0685793643946,0,1.11022302462516e-16 +"lomax_2",1000,30,"fixed-100pct",0.00649334812218761,0.00215366087792471,0.0043396872442629,0.00536551738685692,0.00189185791667889,0.00347365947017803,0.666666666666667,316.351208853879,0,1.11022302462516e-16 +"lomax_2",1000,30,"shrinking",0.00485525856366109,0.000865000667250043,0.00399025789641104,0.00369570145755347,0.000550680684486621,0.00314502077306685,0.666666666666667,1.32912073570791,0,1.11022302462516e-16 diff --git a/diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R b/diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R new file mode 100644 index 0000000..ec0bd78 --- /dev/null +++ b/diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R @@ -0,0 +1,212 @@ +# Paired ablation of the local probability mass used for the bandwidth floor. +# Run from the root of the kde1d R package. + +if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { + stop("run from the kde1d package root with pkgload installed") +} +pkgload::load_all(".", quiet = TRUE) +source(paste0( + "inst/include/kde1d-cpp/diagnostic/one-sided-repair/scripts/", + "one_sided_estimator.R" +)) + +arguments <- commandArgs(trailingOnly = TRUE) +replication_count <- if (length(arguments) >= 1L) { + as.integer(arguments[[1L]]) +} else { + 30L +} +output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( + "inst/include/kde1d-cpp/diagnostic/one-sided-repair/results/", + "local-floor-fraction-ablation.csv" +) +if (length(arguments) > 2L || !is.finite(replication_count) || + replication_count < 2L) { + stop("usage: ablate_local_floor_fraction.R [replications] [output.csv]") +} + +validation_distributions <- list( + exponential = list(random = rexp, density = dexp, quantile = qexp), + half_normal = list( + random = function(sample_size) abs(rnorm(sample_size)), + density = function(values) 2 * dnorm(values), + quantile = function(probabilities) qnorm((probabilities + 1) / 2) + ), + gamma_2 = list( + random = function(sample_size) rgamma(sample_size, 2), + density = function(values) dgamma(values, 2), + quantile = function(probabilities) qgamma(probabilities, 2) + ), + gamma_0.75 = list( + random = function(sample_size) rgamma(sample_size, 0.75), + density = function(values) dgamma(values, 0.75), + quantile = function(probabilities) qgamma(probabilities, 0.75) + ), + lomax_2 = list( + random = function(sample_size) (1 - runif(sample_size))^(-0.5) - 1, + density = function(values) 2 / (1 + values)^3, + quantile = function(probabilities) (1 - probabilities)^(-0.5) - 1 + ) +) +sample_sizes <- c(100L, 1000L) +local_floor_fractions <- c( + 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.50, 0.75, 1 +) +fraction_methods <- paste0( + "fixed-", + format(100 * local_floor_fractions, trim = TRUE), + "pct" +) +candidate_methods <- c(fraction_methods, "shrinking") +methods <- c("current", candidate_methods) +evaluation_probabilities <- sort(unique(c( + 10^seq(-10, -2, length.out = 101L), + seq(0.01, 0.999, length.out = 401L), + 0.9999, 0.99999 +))) +result_rows <- list() + +summarize_fraction_estimates <- function( + evaluation_points, + estimates, + true_density, + region_points) { + mean_density <- rowMeans(estimates) + integrated_errors <- vapply(seq_len(ncol(estimates)), function(replication) { + one_sided_trapezoid_integral( + evaluation_points[region_points], + (estimates[region_points, replication] - true_density[region_points])^2 + ) + }, numeric(1L)) + c( + ise = mean(integrated_errors), + squared_bias = one_sided_trapezoid_integral( + evaluation_points[region_points], + (mean_density[region_points] - true_density[region_points])^2 + ), + variance = one_sided_trapezoid_integral( + evaluation_points[region_points], + rowMeans((estimates[region_points, , drop = FALSE] - + mean_density[region_points])^2) + ) + ) +} + +for (distribution_index in seq_along(validation_distributions)) { + evaluation_points <- validation_distributions[[distribution_index]]$quantile( + evaluation_probabilities + ) + true_density <- validation_distributions[[distribution_index]]$density( + evaluation_points + ) + boundary_points <- evaluation_probabilities <= 0.1 + for (sample_size in sample_sizes) { + estimates <- setNames(lapply(methods, function(method) { + matrix(NA_real_, length(evaluation_points), replication_count) + }), methods) + finite_choices <- logical(replication_count) + floor_ratios <- setNames(lapply(candidate_methods, function(method) { + rep(NA_real_, replication_count) + }), candidate_methods) + for (replication in seq_len(replication_count)) { + set.seed( + 20260914L + 100000L * distribution_index + + 1000L * match(sample_size, sample_sizes) + replication + ) + observations <- validation_distributions[[distribution_index]]$random( + sample_size + ) + estimates$current[, replication] <- normalize_one_sided_density( + evaluation_points, + dkde1d(evaluation_points, kde1d(observations, xmin = 0)) + ) + for (fraction_index in seq_along(local_floor_fractions)) { + method <- fraction_methods[[fraction_index]] + candidate_fit <- fit_one_sided_candidate( + observations, + evaluation_points, + bandwidth_floor = "local", + local_floor_fraction = local_floor_fractions[[fraction_index]] + ) + estimates[[method]][, replication] <- candidate_fit$density + floor_ratios[[method]][[replication]] <- mean( + candidate_fit$boundary_bandwidths / + candidate_fit$selected_boundary_bandwidths + ) + if (fraction_index == 1L) { + finite_choices[[replication]] <- + candidate_fit$expert_choice == "finite" + } + } + shrinking_fit <- fit_one_sided_candidate( + observations, + evaluation_points, + bandwidth_floor = "shrinking" + ) + estimates$shrinking[, replication] <- shrinking_fit$density + floor_ratios$shrinking[[replication]] <- mean( + shrinking_fit$boundary_bandwidths / + shrinking_fit$selected_boundary_bandwidths + ) + } + for (method in methods) { + global_summary <- summarize_fraction_estimates( + evaluation_points, + estimates[[method]], + true_density, + rep(TRUE, length(evaluation_points)) + ) + boundary_summary <- summarize_fraction_estimates( + evaluation_points, + estimates[[method]], + true_density, + boundary_points + ) + result_rows[[length(result_rows) + 1L]] <- data.frame( + distribution = names(validation_distributions)[[distribution_index]], + sample_size = sample_size, + replications = replication_count, + method = method, + global_ise = global_summary[["ise"]], + global_squared_bias = global_summary[["squared_bias"]], + global_variance = global_summary[["variance"]], + boundary_ise = boundary_summary[["ise"]], + boundary_squared_bias = boundary_summary[["squared_bias"]], + boundary_variance = boundary_summary[["variance"]], + finite_rate = if (method %in% candidate_methods) { + mean(finite_choices) + } else { + NA_real_ + }, + mean_floor_ratio = if ( + method %in% candidate_methods && + any(is.finite(floor_ratios[[method]])) + ) { + mean(floor_ratios[[method]], na.rm = TRUE) + } else { + NA_real_ + }, + minimum_density = min(estimates[[method]]), + maximum_mass_error = max(abs(vapply( + seq_len(replication_count), + function(replication) { + one_sided_trapezoid_integral( + evaluation_points, + estimates[[method]][, replication] + ) - 1 + }, + numeric(1L) + ))) + ) + } + message( + names(validation_distributions)[[distribution_index]], + ", n = ", sample_size + ) + } +} + +results <- do.call(rbind, result_rows) +dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) +write.csv(results, output_file, row.names = FALSE) +message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/one-sided-repair/scripts/one_sided_estimator.R b/diagnostic/one-sided-repair/scripts/one_sided_estimator.R new file mode 100644 index 0000000..8a9ec0b --- /dev/null +++ b/diagnostic/one-sided-repair/scripts/one_sided_estimator.R @@ -0,0 +1,360 @@ +# Reference R implementation of the one-sided finite-boundary candidate. + +one_sided_trapezoid_integral <- function(evaluation_points, values) { + sum(diff(evaluation_points) * + (values[-length(values)] + values[-1L]) / 2) +} + +normalize_one_sided_density <- function(evaluation_points, density) { + density <- pmax(0, density) + density_mass <- one_sided_trapezoid_integral(evaluation_points, density) + if (!is.finite(density_mass) || density_mass <= 0) { + stop("density cannot be normalized") + } + density / density_mass +} + +one_sided_smoothstep <- function(normalized_distance) { + 3 * normalized_distance^2 - 2 * normalized_distance^3 +} + +make_one_sided_expert_weights <- function(probabilities, sample_size, + concentration = 1, + shrinkage_exponent = 0.5) { + boundary_fraction <- min( + 0.25, + concentration / sample_size^shrinkage_exponent + ) + boundary_weights <- 1 - one_sided_smoothstep(pmin( + 1, + probabilities / boundary_fraction + )) + cbind(boundary = boundary_weights, bulk = 1 - boundary_weights) +} + +one_sided_weighted_quantile <- function(values, weights, probability) { + value_order <- order(values) + ordered_weights <- weights[value_order] + values[value_order][which( + cumsum(ordered_weights) / sum(ordered_weights) >= probability + )[[1L]]] +} + +select_one_sided_bandwidth_floor <- function( + boundary_distances, + bandwidth_weights, + degree, + bandwidth_floor = c("local", "shrinking", "global", "none", "robust"), + local_floor_fraction = 0.75) { + bandwidth_floor <- match.arg(bandwidth_floor) + if (bandwidth_floor == "none") { + return(0) + } + if (bandwidth_floor == "global") { + return(kde1d(boundary_distances, deg = degree)$bw) + } + if (bandwidth_floor == "local" || bandwidth_floor == "shrinking") { + if (!is.finite(local_floor_fraction) || local_floor_fraction <= 0 || + local_floor_fraction > 1) { + stop("local_floor_fraction must lie in (0, 1]") + } + local_count <- if (bandwidth_floor == "shrinking") { + max(4L, ceiling(sqrt(length(boundary_distances)))) + } else { + max(4L, ceiling(local_floor_fraction * length(boundary_distances))) + } + return(kde1d(sort(boundary_distances)[seq_len(local_count)], deg = degree)$bw) + } + weighted_median <- one_sided_weighted_quantile( + boundary_distances, + bandwidth_weights, + 0.5 + ) + weighted_mad <- one_sided_weighted_quantile( + abs(boundary_distances - weighted_median), + bandwidth_weights, + 0.5 + ) + if (!(weighted_mad > 0)) { + weighted_mad <- one_sided_weighted_quantile( + boundary_distances, + bandwidth_weights, + 0.75 + ) - weighted_median + } + if (!(weighted_mad > 0)) { + weighted_mad <- max(boundary_distances) * .Machine$double.eps + } + winsorized_distances <- pmin( + boundary_distances, + weighted_median + 6 * weighted_mad + ) + kde1d(winsorized_distances, deg = degree)$bw +} + +fit_one_sided_bulk <- function( + observations, + evaluation_points, + lower_bound, + upper_bound) { + lower_bounded <- !is.na(lower_bound) + bulk_model <- if (lower_bounded) { + kde1d(observations, xmin = lower_bound) + } else { + kde1d(observations, xmax = upper_bound) + } + list( + density = normalize_one_sided_density( + evaluation_points, + dkde1d(evaluation_points, bulk_model) + ), + boundary_probabilities = if (lower_bounded) { + pkde1d(evaluation_points, bulk_model) + } else { + 1 - pkde1d(evaluation_points, bulk_model) + } + ) +} + +fit_one_sided_local_polynomial <- function( + boundary_distances, + evaluation_distances, + bandwidth_weights, + minimum_bandwidth, + degree) { + if (!degree %in% c(1, 2)) { + stop("local boundary degree must be 1 or 2") + } + selected_bandwidth <- kde1d( + boundary_distances, + weights = bandwidth_weights, + deg = degree + )$bw + bandwidth <- max(selected_bandwidth, minimum_bandwidth) + standardized_boundary <- evaluation_distances / bandwidth + truncated_moment_0 <- pnorm(standardized_boundary) + truncated_moment_1 <- -dnorm(standardized_boundary) + truncated_moment_2 <- truncated_moment_0 - + standardized_boundary * dnorm(standardized_boundary) + if (degree == 1) { + moment_determinant <- truncated_moment_0 * truncated_moment_2 - + truncated_moment_1^2 + equivalent_kernel_coefficients <- cbind( + truncated_moment_2 / moment_determinant, + -truncated_moment_1 / moment_determinant + ) + } else { + truncated_moment_3 <- -( + standardized_boundary^2 + 2 + ) * dnorm(standardized_boundary) + truncated_moment_4 <- 3 * truncated_moment_0 - ( + standardized_boundary^3 + 3 * standardized_boundary + ) * dnorm(standardized_boundary) + moment_determinant <- + truncated_moment_0 * ( + truncated_moment_2 * truncated_moment_4 - truncated_moment_3^2 + ) - + truncated_moment_1 * ( + truncated_moment_1 * truncated_moment_4 - + truncated_moment_2 * truncated_moment_3 + ) + + truncated_moment_2 * ( + truncated_moment_1 * truncated_moment_3 - truncated_moment_2^2 + ) + equivalent_kernel_coefficients <- cbind( + ( + truncated_moment_2 * truncated_moment_4 - truncated_moment_3^2 + ) / moment_determinant, + ( + truncated_moment_2 * truncated_moment_3 - + truncated_moment_1 * truncated_moment_4 + ) / moment_determinant, + ( + truncated_moment_1 * truncated_moment_3 - truncated_moment_2^2 + ) / moment_determinant + ) + } + density <- numeric(length(evaluation_distances)) + for (chunk_start in seq(1L, length(evaluation_distances), by = 128L)) { + chunk_indices <- chunk_start:min( + chunk_start + 127L, + length(evaluation_distances) + ) + kernel_arguments <- outer( + evaluation_distances[chunk_indices], + boundary_distances, + "-" + ) / bandwidth + base_kernels <- dnorm(kernel_arguments) + corrected_kernels <- base_kernels * + equivalent_kernel_coefficients[chunk_indices, 1L] + for (polynomial_order in seq_len(degree)) { + corrected_kernels <- corrected_kernels + + base_kernels * + equivalent_kernel_coefficients[ + chunk_indices, + polynomial_order + 1L + ] * kernel_arguments^polynomial_order + } + density[chunk_indices] <- rowMeans(corrected_kernels) / bandwidth + } + list( + density = normalize_one_sided_density(evaluation_distances, density), + bandwidth = bandwidth, + selected_bandwidth = selected_bandwidth + ) +} + +select_one_sided_endpoint_expert <- function( + boundary_distances, + tail_multiplier = 2, + evidence_threshold = qnorm(0.95), + minimum_finite_index = 0.9) { + tail_count <- min( + length(boundary_distances) - 1L, + ceiling(tail_multiplier * sqrt(length(boundary_distances))) + ) + ordered_distances <- sort(boundary_distances) + tail_index <- tail_count / sum(log( + ordered_distances[[tail_count + 1L]] / + pmax(.Machine$double.eps, ordered_distances[seq_len(tail_count)]) + )) + list( + expert_choice = if ( + tail_index >= minimum_finite_index && + tail_index * (1 - evidence_threshold / sqrt(tail_count)) <= 1 + ) { + "finite" + } else { + "bulk" + }, + tail_index = tail_index, + tail_count = tail_count + ) +} + +fit_one_sided_candidate <- function( + observations, + evaluation_points, + lower_bound = 0, + upper_bound = NA_real_, + concentration = 1, + shrinkage_exponent = 0.5, + bandwidth_floor = c("local", "shrinking", "global", "none", "robust"), + local_floor_fraction = 0.75) { + bandwidth_floor <- match.arg(bandwidth_floor) + if (is.na(lower_bound) == is.na(upper_bound)) { + stop("exactly one finite boundary must be supplied") + } + if (length(observations) < 4L || any(!is.finite(observations)) || + any(!is.finite(evaluation_points)) || + is.unsorted(evaluation_points, strictly = TRUE)) { + stop("observations and evaluation_points must be finite and ordered") + } + lower_bounded <- !is.na(lower_bound) + boundary_distances <- if (lower_bounded) { + observations - lower_bound + } else { + upper_bound - observations + } + if (any(boundary_distances < 0)) { + stop("observations must lie inside the supplied support") + } + evaluation_distances <- if (lower_bounded) { + evaluation_points - lower_bound + } else { + rev(upper_bound - evaluation_points) + } + bulk_fit <- fit_one_sided_bulk( + observations, + evaluation_points, + lower_bound, + upper_bound + ) + selection <- select_one_sided_endpoint_expert(boundary_distances) + if (selection$expert_choice == "bulk") { + return(list( + density = bulk_fit$density, + expert_choice = "bulk", + tail_index = selection$tail_index, + tail_count = selection$tail_count, + boundary_bandwidths = c(linear = NA_real_, quadratic = NA_real_), + selected_boundary_bandwidths = c( + linear = NA_real_, quadratic = NA_real_ + ), + bandwidth_floor = bandwidth_floor, + local_floor_fraction = local_floor_fraction, + boundary_fraction = min( + 0.25, + concentration / length(observations)^shrinkage_exponent + ) + )) + } + probability_ranks <- (rank( + boundary_distances, + ties.method = "average" + ) - 0.5) / length(observations) + bandwidth_weights <- make_one_sided_expert_weights( + probability_ranks, + length(observations), + concentration, + shrinkage_exponent + )[, "boundary"] + local_fits <- lapply(c(1L, 2L), function(degree) { + fit_one_sided_local_polynomial( + boundary_distances, + evaluation_distances, + bandwidth_weights, + select_one_sided_bandwidth_floor( + boundary_distances, + bandwidth_weights, + degree, + bandwidth_floor, + local_floor_fraction + ), + degree + ) + }) + boundary_density <- rowMeans(vapply( + local_fits, + function(local_fit) local_fit$density, + numeric(length(evaluation_distances)) + )) + if (!lower_bounded) { + boundary_density <- rev(boundary_density) + } + evaluation_weights <- make_one_sided_expert_weights( + bulk_fit$boundary_probabilities, + length(observations), + concentration, + shrinkage_exponent + ) + list( + density = normalize_one_sided_density( + evaluation_points, + evaluation_weights[, "boundary"] * boundary_density + + evaluation_weights[, "bulk"] * bulk_fit$density + ), + expert_choice = "finite", + tail_index = selection$tail_index, + tail_count = selection$tail_count, + boundary_bandwidths = setNames( + vapply(local_fits, function(local_fit) local_fit$bandwidth, numeric(1L)), + c("linear", "quadratic") + ), + selected_boundary_bandwidths = setNames( + vapply( + local_fits, + function(local_fit) local_fit$selected_bandwidth, + numeric(1L) + ), + c("linear", "quadratic") + ), + bandwidth_floor = bandwidth_floor, + local_floor_fraction = local_floor_fraction, + boundary_fraction = min( + 0.25, + concentration / length(observations)^shrinkage_exponent + ) + ) +} diff --git a/diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R b/diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R new file mode 100644 index 0000000..ce84da5 --- /dev/null +++ b/diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R @@ -0,0 +1,163 @@ +# Plot the local bandwidth-floor fraction ablation. +# Run from the root of the kde1d R package. + +if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { + stop("run from the kde1d package root with pkgload installed") +} +pkgload::load_all(".", quiet = TRUE) +source(paste0( + "inst/include/kde1d-cpp/diagnostic/one-sided-repair/scripts/", + "one_sided_estimator.R" +)) + +input_file <- paste0( + "inst/include/kde1d-cpp/diagnostic/one-sided-repair/results/", + "local-floor-fraction-ablation.csv" +) +output_file <- paste0( + "inst/include/kde1d-cpp/diagnostic/one-sided-repair/plots/", + "local-floor-fraction-ablation.pdf" +) +results <- read.csv(input_file) +fractions <- as.numeric(sub( + "pct$", "", sub("fixed-", "", results$method[grepl("^fixed", results$method)]), + fixed = FALSE +)) +fractions <- sort(unique(fractions)) +comparison_distributions <- list( + exponential = list(random = rexp, density = dexp, quantile = qexp), + gamma_2 = list( + random = function(sample_size) rgamma(sample_size, 2), + density = function(values) dgamma(values, 2), + quantile = function(probabilities) qgamma(probabilities, 2) + ), + lomax_2 = list( + random = function(sample_size) (1 - runif(sample_size))^(-0.5) - 1, + density = function(values) 2 / (1 + values)^3, + quantile = function(probabilities) (1 - probabilities)^(-0.5) - 1 + ) +) +evaluation_probabilities <- sort(unique(c( + 10^seq(-10, -2, length.out = 101L), + seq(0.01, 0.999, length.out = 401L), + 0.9999, 0.99999 +))) +method_colors <- c( + current = "grey45", `25%` = "#0072B2", `75%` = "#009E73", + `100%` = "#D55E00" +) + +dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) +pdf(output_file, width = 11, height = 7.5) +par(mfrow = c(2, 2), mar = c(4.3, 4.5, 2.3, 0.8), oma = c(0, 0, 3, 0)) +for (sample_size in sort(unique(results$sample_size))) { + current_results <- results[ + results$sample_size == sample_size & results$method == "current", + ] + fixed_results <- results[ + results$sample_size == sample_size & grepl("^fixed", results$method), + ] + fixed_results <- merge( + fixed_results, + current_results[, c("distribution", "global_ise", "boundary_ise")], + by = "distribution", suffixes = c("", "_current") + ) + for (metric in c("global", "boundary")) { + ratio_matrix <- vapply(fractions, function(fraction) { + selected_results <- fixed_results[ + fixed_results$method == paste0("fixed-", fraction, "pct"), + ] + selected_results[[paste0(metric, "_ise")]] / + selected_results[[paste0(metric, "_ise_current")]] + }, numeric(nrow(current_results))) + matplot( + fractions, t(ratio_matrix), type = "l", lty = 1, lwd = 1.4, + col = adjustcolor("grey40", 0.45), ylim = range(c(0.7, 1.1, ratio_matrix)), + xlab = "lowest sample fraction used for floor (%)", + ylab = "candidate / current ISE", + main = sprintf("%s ISE, n=%d", metric, sample_size) + ) + lines(fractions, colMeans(ratio_matrix), lwd = 3, col = "#009E73") + abline(h = 1, lty = 2) + } +} +mtext("Bandwidth-floor fraction: density-specific curves and mean", outer = TRUE, + font = 2, cex = 1.1) + +for (boundary_zoom in c(FALSE, TRUE)) { + par(mfrow = c(2, 3), mar = c(4.2, 4.2, 2.5, 0.5), oma = c(0, 0, 3, 0)) + for (sample_size in c(100L, 1000L)) { + for (distribution_index in seq_along(comparison_distributions)) { + evaluation_points <- comparison_distributions[[distribution_index]]$quantile( + evaluation_probabilities + ) + true_density <- comparison_distributions[[distribution_index]]$density( + evaluation_points + ) + set.seed( + 20260914L + 100000L * match( + names(comparison_distributions)[[distribution_index]], + c("exponential", "half_normal", "gamma_2", "gamma_0.75", "lomax_2") + ) + 1000L * match(sample_size, c(100L, 1000L)) + 1L + ) + observations <- comparison_distributions[[distribution_index]]$random( + sample_size + ) + estimates <- list( + current = normalize_one_sided_density( + evaluation_points, + dkde1d(evaluation_points, kde1d(observations, xmin = 0)) + ), + `25%` = fit_one_sided_candidate( + observations, evaluation_points, local_floor_fraction = 0.25 + )$density, + `75%` = fit_one_sided_candidate( + observations, evaluation_points, local_floor_fraction = 0.75 + )$density, + `100%` = fit_one_sided_candidate( + observations, evaluation_points, local_floor_fraction = 1 + )$density + ) + plotted_points <- if (boundary_zoom) { + evaluation_probabilities <= 0.2 + } else { + evaluation_probabilities <= 0.999 + } + plot( + evaluation_points[plotted_points], true_density[plotted_points], + type = "l", lwd = 3, col = "black", log = if (boundary_zoom) "x" else "", + ylim = c(0, quantile(c( + true_density[plotted_points], + unlist(lapply(estimates, function(density) density[plotted_points])) + ), 0.995)), + xlab = if (boundary_zoom) "distance from boundary" else "x", + ylab = "density", + main = sprintf( + "%s, n=%d", names(comparison_distributions)[[distribution_index]], + sample_size + ) + ) + for (method in names(estimates)) { + lines( + evaluation_points[plotted_points], estimates[[method]][plotted_points], + col = method_colors[[method]], lwd = if (method == "75%") 2.5 else 1.5, + lty = match(method, names(estimates)) + ) + } + if (sample_size == 100L && distribution_index == 1L) { + legend( + "topright", c("truth", names(estimates)), + col = c("black", method_colors), lty = c(1, seq_along(estimates)), + lwd = c(3, 1.5, 1.5, 2.5, 1.5), bty = "n", cex = 0.72 + ) + } + } + } + mtext( + if (boundary_zoom) "Representative boundary views" else + "Representative full-density views", + outer = TRUE, font = 2, cex = 1.1 + ) +} +dev.off() +message("wrote ", normalizePath(output_file)) From d6b78339121bb7ccf18c7b6073161a15b195362e Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 14:48:28 +0200 Subject: [PATCH 04/25] Document native boundary expert roadmap --- diagnostic/boundary-repair/NATIVE_CPP.md | 89 +---- diagnostic/boundary-repair/README.md | 2 +- diagnostic/one-sided-repair/NATIVE_CPP.md | 425 ++++++++++++++++++++++ diagnostic/one-sided-repair/README.md | 1 + 4 files changed, 430 insertions(+), 87 deletions(-) create mode 100644 diagnostic/one-sided-repair/NATIVE_CPP.md diff --git a/diagnostic/boundary-repair/NATIVE_CPP.md b/diagnostic/boundary-repair/NATIVE_CPP.md index 1672e4a..45608d8 100644 --- a/diagnostic/boundary-repair/NATIVE_CPP.md +++ b/diagnostic/boundary-repair/NATIVE_CPP.md @@ -1,88 +1,5 @@ # Native C++ implementation plan -## Integration point - -The production estimator belongs in -`include/kde1d/kde1d.hpp`, where `Kde1d::fit()` currently handles bounded -continuous data through a single probit-transformed local-likelihood fit. The -new path should activate only when both bounds are finite and the variable is -continuous. One-sided, unbounded, discrete, and zero-inflated behavior should -remain unchanged. - -Avoid implementing the method through recursively constructed public -`Kde1d` objects: a nested bounded fit would activate the boundary selector -again. Extract the existing bounded-probit calculation into a private helper, -or introduce an internal mode that requests the legacy transformation fit -directly. - -## Components to implement - -1. Normalize observations and grid locations to $[0,1]$ using the supplied - finite support. Convert final density values back with the inverse support - length. This must preserve affine equivariance. -2. Fit the unweighted legacy probit bulk estimator once. Retain its PDF, CDF, - and final original-scale grid. -3. Compute $k=\min(n-1,\lceil2\sqrt n\rceil)$ and the two order-statistic tail - indices. Use a partial selection algorithm if convenient, although a full - sort is acceptable initially. Protect zero endpoint distances with the C++ - equivalent of `std::numeric_limits::epsilon()`. -4. Classify each endpoint as finite or bulk using the fixed finite-endpoint - rule in `README.md`. Exploding, vanishing, and ambiguous cases all use bulk. -5. Construct rank-based lower and upper bandwidth weights using average ranks - for ties and boundary fraction $\min(0.25,n^{-1/2})$. -6. Add a private Gaussian equivalent-kernel evaluator for boundary polynomial - degrees one and two. Select each bandwidth through - `bandwidth::PluginBandwidthSelector` with endpoint weights, impose the - corresponding full-sample unweighted bandwidth as its floor, but evaluate - density contributions with equal observation weights. Reflect data and - grid locations for the upper endpoint. -7. Average the degree-one and degree-two endpoint densities. Clamp negative - component values to zero before component normalization, matching the R - reference. -8. Obtain fusion probabilities from the bulk CDF and evaluate the smoothstep - gates. Substitute bulk or finite component values according to each - endpoint decision, fuse arithmetically, clamp at zero, and normalize on the - final grid. -9. Store the fused values in `interp::InterpolationGrid` so existing PDF, - CDF, quantile, and simulation methods continue to work without a new - public fitted-object representation. - -## API and metadata decisions - -The first implementation can keep the method automatic for two finite bounds, -but an internal feature switch is useful while validating. Decide whether the -selector threshold and gate constants remain private or become advanced API -parameters; the current recommendation is to keep them fixed until broader -validation justifies exposing them. - -`loglik_` can be recomputed from the final interpolated density. Effective -degrees of freedom do not combine trivially across selected and fused experts; -do not silently reuse the bulk value. Either derive the fused influence trace -or return `NaN` for `edf_` until a principled definition is implemented. - -The public API accepts case weights, while the retained experiment is -unweighted. Before enabling the new estimator for weighted fits, define: - -- weighted ranks and tie handling for endpoint bandwidth weights; -- an effective sample size for $k$ and the shrinking gate; -- a weighted order-statistic tail index; -- whether selector confidence adjustments use raw or effective sample size. - -Until those choices are validated, weighted bounded fits should remain on the -legacy path rather than pretending the unweighted selector applies. - -## Tests required - -- Golden PDF vectors against `scripts/bounded_estimator.R` for fixed Uniform, - Beta$(1,2)$, Beta$(0.75,2)$, and Beta$(0.75,0.75)$ samples. -- Explicit samples that select bulk and finite behavior at each endpoint, - including asymmetric lower/upper decisions. -- Nonnegativity, unit mass, monotone CDF, inverse-CDF consistency, and support - truncation. -- Affine-equivariance tests on intervals such as $[-3,7]$. -- Stability with ties, observations exactly at a bound, small samples, and - nearly degenerate samples. -- Regression tests proving that one-sided, unbounded, discrete, - zero-inflated, and weighted fits retain their existing behavior. -- A native rerun of the retained 100-replication validation before making the - new path the default. +The canonical native roadmap now covers the shared one- and two-sided +boundary-expert implementation. See +[`../one-sided-repair/NATIVE_CPP.md`](../one-sided-repair/NATIVE_CPP.md). diff --git a/diagnostic/boundary-repair/README.md b/diagnostic/boundary-repair/README.md index fb263e1..ee49a6c 100644 --- a/diagnostic/boundary-repair/README.md +++ b/diagnostic/boundary-repair/README.md @@ -55,7 +55,7 @@ offset transform, oversmoothed tail expert, or cross-validation selector. - `results/` and `plots/`: corresponding 100-replication outputs. - `RESULTS.md`: final numerical conclusions. - `HANDOFF.md`: concise continuation state. -- `NATIVE_CPP.md`: native C++ implementation plan. +- `NATIVE_CPP.md`: pointer to the shared one- and two-sided native roadmap. Run from the R-package root: diff --git a/diagnostic/one-sided-repair/NATIVE_CPP.md b/diagnostic/one-sided-repair/NATIVE_CPP.md new file mode 100644 index 0000000..62c2b53 --- /dev/null +++ b/diagnostic/one-sided-repair/NATIVE_CPP.md @@ -0,0 +1,425 @@ +# Native boundary-expert implementation roadmap + +## Scope + +Implement both selected finite-boundary repairs through one concise internal +path: + +| support | unchanged bulk estimator | candidate endpoints | bandwidth floor | +|---|---|---|---| +| exactly one finite endpoint | power-$3/4$ transform | the finite endpoint | closest 75% of boundary distances | +| two finite endpoints | probit transform | lower and upper, classified independently | all boundary distances | + +The existing transformed estimator remains the bulk component in both cases. +Unbounded continuous, discrete, and zero-inflated behavior remains unchanged. + +The first native version should activate only for unweighted fits with an +automatically selected bandwidth and the default degree two. Weighted fits, +explicit bandwidths, and nondefault degrees retain the current estimator until +their expert semantics have been specified and validated. This is the first +implementation milestone, not the intended final support boundary: experiments +and subsequent activation for weighted and manual-bandwidth fits are important +follow-up work. Keep the bandwidth multiplier supported immediately by +applying it to every expert bandwidth after selection and flooring. + +Do not add a public method switch or another fitted-object representation. + +## Minimal integration point + +Call the repair coordinator only when `type_ == VarType::continuous`, at least +one support bound is finite, `weights` is empty, `bandwidth_spec_` is `NaN`, +and `degree_ == 2`. This makes every initial fallback condition explicit at a +single call site. + +Keep the current body of `Kde1d::fit()` through construction of the normalized +bulk `InterpolationGrid`. Preserve the cleaned observations on their original +scale before applying `boundary_transform()`. Immediately after constructing +the bulk grid: + +1. classify every finite endpoint from original-scale boundary distances; +2. return to the unchanged bulk path if no endpoint is confidently finite; +3. fit a boundary component only for each selected endpoint, using the existing + original-scale grid; +4. form gate probabilities from the normalized bulk CDF; +5. fuse bulk and selected endpoint values and replace `grid_` with the + normalized fused grid. + +The existing PDF, CDF, quantile, simulation, support truncation, and +log-likelihood code then operates on the fused grid. `bandwidth_` continues to +report the bulk bandwidth. + +Boundary distances and local densities can stay in the original units. Every +classifier ratio is dimensionless, and both selected and floor bandwidths +scale with the data, so this is equivalent to the R reference's affine map to +$[0,1]$ without adding a second normalization path. + +No changes should be required in `boundary_transform()`, `boundary_correct()`, +`construct_grid_points()`, `InterpolationGrid`, `PluginBandwidthSelector`, or +the public constructors. + +## Shared private helpers in `kde1d.hpp` + +Keep the implementation in the existing header and add three focused helpers. + +### 1. Endpoint classifier + +Given ascending distances from one endpoint, use +$k=\min(n-1,\lceil2\sqrt n\rceil)$ and + +$$ +\widehat\beta= +\frac{k}{\sum_{i=1}^k +\log\{d_{(k+1)}/\max(d_{(i)},\epsilon d_{(k+1)})\}}}. +$$ + +The scale-relative numerical floor preserves scale equivariance. Select the +finite expert when + +$$ +\widehat\beta\geq0.9, +\qquad +\widehat\beta\left\{1- +\frac{\Phi^{-1}(0.95)}{\sqrt{k}}\right\}\leq1. +$$ + +Run this helper once for the one-sided finite endpoint and independently on +lower and upper distances for two-sided support. Exploding, vanishing, and +ambiguous endpoints all select bulk. A nonpositive $(k+1)$st distance or a +nonfinite/nonpositive logarithmic denominator is a degenerate classifier input +and must also select bulk. + +### 2. Local-polynomial boundary component + +The helper takes boundary distances, ascending evaluation distances, rank +weights, a floor fraction, and degree one or two. + +- Select the weighted bandwidth with `PluginBandwidthSelector`. +- Select the unweighted floor bandwidth from the closest + $\max(4,\lceil q n\rceil)$ distances, where $q=0.75$ for one-sided support + and $q=1$ for two-sided support. +- Use the maximum of the selected and floor bandwidths, then apply the public + multiplier. +- Use rank weights only for bandwidth selection. Evaluate density + contributions with equal observation weights so the estimand remains the + original density. + +Construct the equivalent-kernel coefficients as the first row of the inverse +truncated-normal moment matrix. Generate the moments with + +$$ +\mu_0(a)=\Phi(a),\qquad +\mu_1(a)=-\phi(a),\qquad +\mu_j(a)=(j-1)\mu_{j-2}(a)-a^{j-1}\phi(a). +$$ + +This calculation covers degrees one and two more concisely than separate +determinant formulas. Clamp each component at zero, normalize it on the +distance grid, and average the degree-one and degree-two components. Return +both that density and its diagonal density response for the EDF calculation +described below; the response uses the same clamp mask and normalization as +the density. + +Start with direct $O(nm)$ Gaussian evaluation on the existing grid of +$m\approx401$ points. It follows the retained R references closely and avoids +a second interpolation grid or FFT-specific derivation. Benchmark before +considering an optimized implementation. + +### 3. Boundary-repair coordinator + +This helper owns endpoint distances, average ranks for ties, classification, +local component calls, CDF gates, reflection, and fusion. Use +`tools::get_order()` locally; do not add a general ranking API unless another +production caller needs it. + +For an upper endpoint, compute on ascending reflected distances and reverse the +component once. The floor fraction is the only local-component policy that +differs between one- and two-sided support. + +The helper should return an empty result when every endpoint selects bulk. +`Kde1d::fit()` can then leave the already constructed bulk grid untouched. + +## Gate and fusion + +Let $F_B(x)$ be the bulk CDF and + +$$ +q_n=\min(0.25,n^{-1/2}), +\qquad +s(r)=3r^2-2r^3. +$$ + +For a lower endpoint use + +$$ +w_L(x)=1-s\left(\min\{1,F_B(x)/q_n\}\right), +$$ + +and for an upper endpoint use + +$$ +w_U(x)=1-s\left(\min\{1,(1-F_B(x))/q_n\}\right). +$$ + +Set the gate of every bulk-classified endpoint to zero. The final values are + +$$ +\widehat f(x)= +w_L(x)\widehat f_L(x) ++\{1-w_L(x)-w_U(x)\}\widehat f_B(x) ++w_U(x)\widehat f_U(x). +$$ + +With $q_n\leq0.25$, the endpoint gates do not overlap. The same expression +covers one-sided support by setting the absent endpoint weight to zero. Clamp +the fused values at zero and construct a normalized `InterpolationGrid` on the +existing original-scale grid. + +## Conditional EDF approximation + +The current EDF is already a conditional influence-trace approximation: it +holds the selected bandwidth and final grid normalization fixed. Extend the +same convention to expert selection and fusion rather than returning `NaN`. + +For a degree-$p$ boundary component, let $M_p(a)$ be the truncated-normal +moment matrix above, let $h_p$ be its final bandwidth, let $Z_p$ be the mass +used to normalize its nonnegative density, and let $\widetilde f_p$ denote its +value before clamping and normalization. Its diagonal density response is + +$$ +r_p(x)= +\frac{\mathbf 1\{\widetilde f_p(x)>0\}}{Z_p} +\frac{\phi(0)}{n h_p} +\left[M_p\{d(x)/h_p\}^{-1}\right]_{00}. +$$ + +Only the constant equivalent-kernel coefficient remains because a +self-contribution has kernel argument zero. For the equal linear/quadratic +expert, use + +$$ +f_E(x)=\frac{f_1(x)+f_2(x)}{2}, +\qquad +r_E(x)=\frac{r_1(x)+r_2(x)}{2}. +$$ + +For the bulk component, the existing influence column is its log-density +leverage $\ell_B(x)$, so its diagonal density response is +$r_B(x)=f_B(x)\ell_B(x)$. Fuse the responses with exactly the same gates as the +densities: + +$$ +\begin{aligned} +g(x)&=w_L(x)f_L(x) + +\{1-w_L(x)-w_U(x)\}f_B(x)+w_U(x)f_U(x),\\ +r(x)&=w_L(x)r_L(x) + +\{1-w_L(x)-w_U(x)\}r_B(x)+w_U(x)r_U(x),\\ +\ell(x)&=\frac{r(x)}{g(x)}. +\end{aligned} +$$ + +Thus the mixture leverage is weighted by local density shares, not just by +the gate values. Estimate + +$$ +\operatorname{edf}=\sum_{i=1}^n +\min\{3,\max(0,\ell(X_i))\}, +$$ + +retaining the current per-observation cap. The final common normalization of +$g$ and $r$ cancels in their ratio when its derivative is ignored. + +This approximation conditions on bandwidths, endpoint classifications, CDF +gates, clamp states, and normalization constants. It deliberately omits the +derivatives of those data-adaptive choices. That keeps it consistent with the +existing EDF convention and costs only additional grid-vector arithmetic; no +refits or per-observation matrices are needed. Validate it diagnostically +against the corresponding leave-one-out approximation + +$$ +1+\sum_{i=1}^n +\{\log \widehat f(X_i)-\log \widehat f_{-i}(X_i)\}. +$$ + +First confirm that this diagnostic reproduces the existing bulk EDF to the +expected approximation error. A gate-derivative correction is worth +considering only if the active-expert comparison then shows an additional +systematic discrepancy. + +## Weights and remaining fit metadata + +The experts' rank weights affect bandwidth selection only; density +contributions remain equally weighted, matching the validated estimand. The +first native implementation falls back to bulk when public case weights are +supplied because those weights genuinely change the estimand. Defining +weighted ranks, effective sample size, weighted tail indices, and weighted +confidence adjustments is a separate statistical task. + +Recompute `loglik_` from the final grid using the existing code. Use the +conditional mixture trace above for `edf_` whenever a finite expert is active, +and retain the current calculation unchanged for pure-bulk fits. + +No classifier choice, tail index, boundary bandwidth, or gate state needs to +persist in the fitted object for the first implementation. Diagnostic values +belong in tests and validation scripts rather than the public class layout. + +## Exact production changes + +The intended implementation footprint is: + +1. `include/kde1d/kde1d.hpp` + - preserve original-scale cleaned observations; + - add the three private helpers; + - call the coordinator after bulk-grid construction; + - carry the bulk and expert diagonal responses through fusion for EDF. +2. `test/test.cpp` + - deterministic golden results and fallback behavior. +3. `test/test_numerical_invariants.cpp` + - active-expert normalization, reflection, scale, support, and quantile + invariants. +4. `diagnostic/one-sided-repair/` and `diagnostic/boundary-repair/` + - thin R evaluators and final baseline-versus-native reports. + +Avoid modifying `interpolation.hpp`, `dpik.hpp`, `stats.hpp`, constructors, or +public getters unless implementation evidence shows that it is necessary. + +## Implementation sequence + +1. Synchronize this branch with the isolated PR #34 fix so + `boundary_offset_` is `NaN` before fitting. Record the current production + head and run the native R evaluators once to create one- and two-sided + baseline outputs before changing estimator behavior. +2. Add the eligibility check and preserve original-scale observations. With + the coordinator returning bulk, verify tight numerical parity for every + existing support type. +3. Implement the shared endpoint classifier and deterministic finite/bulk + tests for lower and upper endpoints. +4. Implement the shared degree-one/two equivalent-kernel evaluator. Validate + both bandwidth-floor policies against the retained R references. +5. Activate one-sided fusion with the 75% floor and verify the selected + one-sided scenarios. +6. Activate two-sided fusion with the full-sample floor and verify independent + lower/upper decisions, including asymmetric densities. +7. Complete log-likelihood and conditional-EDF handling, numerical regression + tests, and fit-time benchmarks. +8. Run the larger R validation against the recorded native baselines, retain + only final comparison artifacts, and prepare the PR report. + +Each step should be a separately testable commit. Avoid refactoring unrelated +fit logic while implementing the method. + +## Important follow-up: weights and manual bandwidths + +Do not close the estimator work after the initial unweighted, automatic- +bandwidth activation. Keep the following experiments and production activation +as explicit roadmap items, preferably in follow-up commits or a follow-up PR so +the initial implementation remains reviewable. + +### Public case weights + +Public case weights change the target density, unlike the endpoint-targeting +weights used only to select expert bandwidths. A weighted expert should +therefore use public case weights for density contributions and use the product +of public and endpoint-targeting weights for bandwidth selection. Before +activation, compare and validate choices for: + +- weighted average ranks and endpoint distances; +- effective sample size in $k$, $q_n$, and the classifier confidence term; +- a weighted order-statistic tail index; +- defining the closest 75% floor by cumulative public weight rather than row + count; +- weighted diagonal responses and EDF validation. + +Experiments should include highly unequal weights, weights concentrated near +and far from the boundary, zero weights, global rescaling of all weights, and +integer weights compared with explicitly replicated observations. Require +weight-scale invariance, approximate replication equivalence, stable endpoint +classification, and acceptable global/boundary ISE before removing the +weighted fallback. + +### Manually specified bandwidths + +A manual bulk bandwidth is expressed on the transformed scale, whereas local +boundary bandwidths are expressed in original data units. Reusing the same +number for both is therefore invalid. The leading candidate is to compute the +automatic bulk reference bandwidth $h_{B,0}$ and interpret the manual choice +$h_B$ through the dimensionless ratio + +$$ +\rho=\frac{h_B}{h_{B,0}}, +$$ + +then multiply every automatically selected and floored expert bandwidth by +$\rho$. This preserves the requested bulk bandwidth while treating it as a +global smoothing adjustment. Compare this with leaving expert bandwidths +automatic when only the bulk bandwidth is manual; reject direct numerical +reuse across scales. + +Run the comparison over manual-to-automatic ratios such as $0.5$, $0.75$, $1$, +$1.5$, and $2$, several support rescalings, both support types, finite and +exploding endpoint shapes, and representative visual fits. Include the extra +cost of computing $h_{B,0}$ in the manual case. Activate manual-bandwidth fits +only after selecting and documenting one interpretation that preserves affine +equivariance and behaves predictably with `multiplier_`. + +Finally test weighted and manual bandwidths together after each has been +validated separately. Nondefault local-likelihood degrees remain a lower- +priority extension because the selected boundary expert deliberately averages +degrees one and two. + +## Native tests + +Add compact tests to the existing executables. + +Shared coverage: + +- nonnegativity, unit mass, monotone CDF, quantile round trips, finite + log-likelihood and EDF, and support truncation; +- exact EDF parity with the current path when no expert is active, plus + diagnostic comparison with leave-one-out log-likelihood optimism when an + expert is active; +- scaling over several orders of magnitude; +- ties, observations exactly at an endpoint, small samples, and nearly + degenerate samples; +- regression coverage proving that unbounded, discrete, zero-inflated, + weighted, fixed-bandwidth, and nondefault-degree fits retain the current + path; +- fit-time benchmarks at representative $n$ values. + +One-sided coverage: + +- deterministic Exponential, half-normal, Gamma$(2)$, Gamma$(0.75)$, and + Lomax samples; +- lower/upper reflection while the expert is active; +- finite and bulk classifier outcomes; +- golden grid or PDF values against `one_sided_estimator.R`. + +Two-sided coverage: + +- deterministic Uniform, Beta$(1,2)$, Beta$(0.75,2)$, and + Beta$(0.75,0.75)$ samples; +- lower and upper finite/bulk outcomes, including asymmetric decisions; +- affine equivariance on non-unit intervals; +- golden grid or PDF values against `bounded_estimator.R`. + +If direct local evaluation is materially expensive, optimize only after a +profile identifies it as the relevant fit cost. + +## R validation without C++ experiment bloat + +Keep Monte Carlo comparisons in R. Use small native-evaluator scripts that run +the installed estimator for deterministic scenario seeds and write +replication-level global and boundary ISE plus aggregate squared bias and +variance. Run them once at the recorded baseline commit and once at the +candidate commit, then join the outputs in reporting scripts. + +This avoids a legacy-mode switch in the public C++ API and avoids maintaining +two production estimator paths solely for benchmarking. + +The final one-sided suite should expand the retained scenarios with +intermediate sample sizes, steeper finite-endpoint slopes, heavier remote +tails, upper-bounded reflections, and visual realizations. The final two-sided +suite should retain varied symmetric and asymmetric finite, vanishing, and +exploding endpoint shapes plus local boundary plots. Report paired ISE ratios +with Monte Carlo uncertainty, global and local bias/variance, classifier rates +computed by matching R code, visual examples, and fit time relative to the +current transformed baselines. diff --git a/diagnostic/one-sided-repair/README.md b/diagnostic/one-sided-repair/README.md index 66f7a1d..1fa174d 100644 --- a/diagnostic/one-sided-repair/README.md +++ b/diagnostic/one-sided-repair/README.md @@ -35,6 +35,7 @@ have been removed. `plots/local-floor-fraction-ablation.pdf`: current tuning evidence. - `RESULTS.md`: numerical conclusions. - `HANDOFF.md`: implementation state and next steps. +- `NATIVE_CPP.md`: shared one- and two-sided native implementation roadmap. Run from the R-package root: From bacade544290a52d574941a74e34e10d6954e961 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 15:00:12 +0200 Subject: [PATCH 05/25] Implement one-sided boundary expert --- diagnostic/one-sided-repair/NATIVE_CPP.md | 13 +- include/kde1d/kde1d.hpp | 268 +++++++++++++++++++++- test/test.cpp | 48 ++++ 3 files changed, 320 insertions(+), 9 deletions(-) diff --git a/diagnostic/one-sided-repair/NATIVE_CPP.md b/diagnostic/one-sided-repair/NATIVE_CPP.md index 62c2b53..1983ec9 100644 --- a/diagnostic/one-sided-repair/NATIVE_CPP.md +++ b/diagnostic/one-sided-repair/NATIVE_CPP.md @@ -13,9 +13,10 @@ path: The existing transformed estimator remains the bulk component in both cases. Unbounded continuous, discrete, and zero-inflated behavior remains unchanged. -The first native version should activate only for unweighted fits with an -automatically selected bandwidth and the default degree two. Weighted fits, -explicit bandwidths, and nondefault degrees retain the current estimator until +The first native version should activate only for samples of at least 16 +observations, unweighted or constant-weight fits, an automatically selected +bandwidth, and the default degree two. Nonconstant weighted fits, explicit +bandwidths, and nondefault degrees retain the current estimator until their expert semantics have been specified and validated. This is the first implementation milestone, not the intended final support boundary: experiments and subsequent activation for weighted and manual-bandwidth fits are important @@ -27,9 +28,9 @@ Do not add a public method switch or another fitted-object representation. ## Minimal integration point Call the repair coordinator only when `type_ == VarType::continuous`, at least -one support bound is finite, `weights` is empty, `bandwidth_spec_` is `NaN`, -and `degree_ == 2`. This makes every initial fallback condition explicit at a -single call site. +one support bound is finite, at least 16 cleaned observations remain, case +weights are absent or constant, `bandwidth_spec_` is `NaN`, and `degree_ == 2`. +This makes every initial fallback condition explicit at a single call site. Keep the current body of `Kde1d::fit()` through construction of the normalized bulk `InterpolationGrid`. Preserve the cleaned observations on their original diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 1f5c750..f83b864 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -121,6 +121,12 @@ class Kde1d void set_interpolation_grid(const interp::InterpolationGrid& grid); private: + struct BoundaryComponent + { + Eigen::VectorXd density; + Eigen::VectorXd response; + }; + // data members interp::InterpolationGrid grid_; double xmin_; @@ -185,6 +191,16 @@ class Kde1d double multiplier, size_t degree, const Eigen::VectorXd& weights) const; + bool is_finite_endpoint(Eigen::VectorXd distances) const; + BoundaryComponent fit_boundary_component( + const Eigen::VectorXd& distances, + const Eigen::VectorXd& evaluation_distances, + const Eigen::VectorXd& bandwidth_weights, + double floor_fraction, + size_t degree) const; + void repair_boundaries(const Eigen::VectorXd& observations, + const Eigen::VectorXd& grid_points, + Eigen::VectorXd& influences); std::string as_str(VarType type) const; VarType as_enum(std::string type) const; @@ -329,6 +345,17 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) Eigen::VectorXd w = weights; tools::remove_nans(xx, w); + // Nonconstant case weights and manual bandwidths need separate expert + // semantics; constant weights are equivalent to an unweighted sample. + const bool unweighted = w.size() == 0 || w.minCoeff() == w.maxCoeff(); + const bool repair_one_sided = type_ == VarType::continuous && + xx.size() >= 16 && unweighted && + std::isnan(bandwidth_spec_) && degree_ == 2 && + (std::isnan(xmin_) != std::isnan(xmax_)); + Eigen::VectorXd boundary_observations; + if (repair_one_sided) + boundary_observations = xx; + if (w.size() > 0) { w /= w.mean(); } @@ -392,9 +419,15 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) // order grid points from left to right grid_points = finalize_grid(grid_points); + Eigen::VectorXd influences = fitted.col(1); + if (std::isnan(xmin_) && !std::isnan(xmax_)) + influences.reverseInPlace(); + // construct interpolation grid // (3 iterations for normalization to a proper density) grid_ = interp::InterpolationGrid(grid_points, values, 3); + if (repair_one_sided) + repair_boundaries(boundary_observations, grid_points, influences); // calculate log-likelihood of final estimate xx = boundary_transform(xx, true); @@ -415,9 +448,7 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) } // calculate effective degrees of freedom - Eigen::VectorXd influences = fitted.col(1).cwiseMin(3.0).cwiseMax(0); - if (std::isnan(xmin_) && !std::isnan(xmax_)) - influences.reverseInPlace(); + influences = influences.cwiseMin(3.0).cwiseMax(0); interp::InterpolationGrid infl_grid(grid_points, influences, 0); influences = infl_grid.interpolate(xx).array(); edf_ = influences.sum() + static_cast(prob0_ > 0); @@ -917,6 +948,237 @@ Kde1d::finalize_grid(Eigen::VectorXd& grid_points) return grid_points; } +//! Classifies a support endpoint from the power law of its closest order +//! statistics. Ambiguous and numerically degenerate cases retain the bulk fit. +inline bool +Kde1d::is_finite_endpoint(Eigen::VectorXd distances) const +{ + std::sort(distances.data(), distances.data() + distances.size()); + const size_t tail_count = + std::min(static_cast(distances.size() - 1), + static_cast(std::ceil(2.0 * std::sqrt(distances.size())))); + const double threshold = distances(tail_count); + if (!(threshold > 0.0) || !std::isfinite(threshold)) + return false; + + double log_sum = 0.0; + const double distance_floor = + std::numeric_limits::epsilon() * threshold; + for (size_t index = 0; index < tail_count; ++index) { + log_sum += std::log(threshold / std::max(distances(index), distance_floor)); + } + if (!(log_sum > 0.0) || !std::isfinite(log_sum)) + return false; + + const double tail_index = static_cast(tail_count) / log_sum; + // 1.64485 is the 95% standard-normal quantile used by the R selector. + return tail_index >= 0.9 && + tail_index * (1.0 - 1.6448536269514722 / std::sqrt(tail_count)) <= 1.0; +} + +//! Fits one Gaussian local-polynomial endpoint component. Targeting weights +//! select its bandwidth only; equal observation contributions preserve the +//! original density estimand. +inline Kde1d::BoundaryComponent +Kde1d::fit_boundary_component(const Eigen::VectorXd& distances, + const Eigen::VectorXd& evaluation_distances, + const Eigen::VectorXd& bandwidth_weights, + double floor_fraction, + size_t degree) const +{ + bandwidth::PluginBandwidthSelector selector(distances, bandwidth_weights); + double bandwidth = selector.select_bandwidth(degree); + + Eigen::VectorXd ordered_distances = distances; + std::sort(ordered_distances.data(), + ordered_distances.data() + ordered_distances.size()); + const Eigen::Index floor_count = std::min( + distances.size(), + std::max( + 4, + static_cast(std::ceil(floor_fraction * distances.size())))); + bandwidth::PluginBandwidthSelector floor_selector( + ordered_distances.head(floor_count)); + bandwidth = + std::max(bandwidth, floor_selector.select_bandwidth(degree)) * multiplier_; + if (!(bandwidth > 0.0) || !std::isfinite(bandwidth)) + return {}; + + BoundaryComponent component{ Eigen::VectorXd(evaluation_distances.size()), + Eigen::VectorXd(evaluation_distances.size()) }; + for (Eigen::Index row = 0; row < evaluation_distances.size(); ++row) { + const double boundary_position = evaluation_distances(row) / bandwidth; + const double normal_density = + K0_ * std::exp(-0.5 * boundary_position * boundary_position); + Eigen::VectorXd moments(2 * degree + 1); + moments(0) = + stats::pnorm(Eigen::VectorXd::Constant(1, boundary_position))(0); + moments(1) = -normal_density; + for (size_t order = 2; order < static_cast(moments.size()); + ++order) { + moments(order) = (order - 1.0) * moments(order - 2) - + std::pow(boundary_position, order - 1) * normal_density; + } + + Eigen::MatrixXd moment_matrix(degree + 1, degree + 1); + for (size_t column = 0; column <= degree; ++column) { + for (size_t matrix_row = 0; matrix_row <= degree; ++matrix_row) + moment_matrix(matrix_row, column) = moments(matrix_row + column); + } + const Eigen::VectorXd coefficients = moment_matrix.inverse().row(0); + + double density = 0.0; + for (Eigen::Index observation = 0; observation < distances.size(); + ++observation) { + const double kernel_argument = + (evaluation_distances(row) - distances(observation)) / bandwidth; + double polynomial = coefficients(degree); + for (size_t order = degree; order > 0; --order) + polynomial = polynomial * kernel_argument + coefficients(order - 1); + density += + K0_ * std::exp(-0.5 * kernel_argument * kernel_argument) * polynomial; + } + component.density(row) = + density / (static_cast(distances.size()) * bandwidth); + component.response(row) = + K0_ * coefficients(0) / + (static_cast(distances.size()) * bandwidth); + } + + for (Eigen::Index row = 0; row < component.density.size(); ++row) { + if (!(component.density(row) > 0.0) || + !std::isfinite(component.density(row)) || + !std::isfinite(component.response(row))) { + component.density(row) = 0.0; + component.response(row) = 0.0; + } + } + double mass = 0.0; + for (Eigen::Index row = 0; row < component.density.size() - 1; ++row) { + mass += (evaluation_distances(row + 1) - evaluation_distances(row)) * + (component.density(row) + component.density(row + 1)) / 2.0; + } + if (!(mass > 0.0) || !std::isfinite(mass)) + return {}; + component.density /= mass; + component.response /= mass; + return component; +} + +//! Replaces the transformed bulk density near confidently finite endpoints +//! and carries the same local mixture through the diagonal EDF response. +inline void +Kde1d::repair_boundaries(const Eigen::VectorXd& observations, + const Eigen::VectorXd& grid_points, + Eigen::VectorXd& influences) +{ + Eigen::VectorXd lower_distances; + Eigen::VectorXd upper_distances; + bool repair_lower = !std::isnan(xmin_); + bool repair_upper = !std::isnan(xmax_); + if (repair_lower) { + lower_distances = observations.array() - xmin_; + repair_lower = is_finite_endpoint(lower_distances); + } + if (repair_upper) { + upper_distances = xmax_ - observations.array(); + repair_upper = is_finite_endpoint(upper_distances); + } + if (!repair_lower && !repair_upper) + return; + + const double boundary_fraction = + std::min(0.25, 1.0 / std::sqrt(observations.size())); + auto endpoint_weight = [&](double probability) { + const double position = std::min(1.0, probability / boundary_fraction); + return 1.0 - + (3.0 * position * position - 2.0 * position * position * position); + }; + auto targeting_weights = [&](const Eigen::VectorXd& distances) { + Eigen::VectorXd weights(distances.size()); + const Eigen::VectorXi order = tools::get_order(distances); + Eigen::Index first = 0; + while (first < order.size()) { + Eigen::Index last = first; + while (last + 1 < order.size() && + distances(order(last + 1)) == distances(order(first))) + ++last; + const double probability = static_cast(first + last + 1) / + (2.0 * static_cast(distances.size())); + for (Eigen::Index index = first; index <= last; ++index) + weights(order(index)) = endpoint_weight(probability); + first = last + 1; + } + return weights; + }; + + const double floor_fraction = + (!std::isnan(xmin_) && !std::isnan(xmax_)) ? 1.0 : 0.75; + auto fit_endpoint = [&](const Eigen::VectorXd& distances, + const Eigen::VectorXd& evaluation_distances) { + const Eigen::VectorXd weights = targeting_weights(distances); + BoundaryComponent linear = fit_boundary_component( + distances, evaluation_distances, weights, floor_fraction, 1); + BoundaryComponent quadratic = fit_boundary_component( + distances, evaluation_distances, weights, floor_fraction, 2); + if (linear.density.size() == 0 || quadratic.density.size() == 0) + return BoundaryComponent{}; + linear.density = (linear.density + quadratic.density) / 2.0; + linear.response = (linear.response + quadratic.response) / 2.0; + return linear; + }; + + BoundaryComponent lower; + BoundaryComponent upper; + if (repair_lower) { + lower = fit_endpoint(lower_distances, grid_points.array() - xmin_); + repair_lower = lower.density.size() > 0; + } + if (repair_upper) { + Eigen::VectorXd evaluation_distances = + (xmax_ - grid_points.array()).reverse(); + upper = fit_endpoint(upper_distances, evaluation_distances); + repair_upper = upper.density.size() > 0; + if (repair_upper) { + upper.density.reverseInPlace(); + upper.response.reverseInPlace(); + } + } + if (!repair_lower && !repair_upper) + return; + + const Eigen::VectorXd bulk_density = grid_.get_values(); + const Eigen::VectorXd probabilities = grid_.integrate(grid_points, true); + Eigen::VectorXd lower_weights = Eigen::VectorXd::Zero(grid_points.size()); + Eigen::VectorXd upper_weights = Eigen::VectorXd::Zero(grid_points.size()); + for (Eigen::Index row = 0; row < grid_points.size(); ++row) { + if (repair_lower) { + lower_weights(row) = endpoint_weight(probabilities(row)); + } + if (repair_upper) { + upper_weights(row) = endpoint_weight(1.0 - probabilities(row)); + } + } + + Eigen::VectorXd density(grid_points.size()); + Eigen::VectorXd response(grid_points.size()); + for (Eigen::Index row = 0; row < grid_points.size(); ++row) { + const double bulk_weight = 1.0 - lower_weights(row) - upper_weights(row); + density(row) = bulk_weight * bulk_density(row); + response(row) = bulk_weight * bulk_density(row) * influences(row); + if (repair_lower) { + density(row) += lower_weights(row) * lower.density(row); + response(row) += lower_weights(row) * lower.response(row); + } + if (repair_upper) { + density(row) += upper_weights(row) * upper.density(row); + response(row) += upper_weights(row) * upper.response(row); + } + influences(row) = density(row) > 0.0 ? response(row) / density(row) : 0.0; + } + grid_ = interp::InterpolationGrid(grid_points, density.cwiseMax(0.0), 3); +} + // Bandwidth for Kernel Density Estimation //' @param x vector of observations //' @param bandwidth bandwidth parameter, NA for automatic selection. diff --git a/test/test.cpp b/test/test.cpp index a3c76e2..5e426e7 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -133,6 +133,54 @@ TEST_CASE("one-boundary fits are reflection equivariant", "[boundary-reflection] CHECK(left_bounded.get_edf() == Approx(right_bounded.get_edf())); } +TEST_CASE("one-sided finite endpoints use the boundary expert", + "[boundary-expert]") +{ + const Eigen::VectorXd probabilities = + Eigen::VectorXd::LinSpaced(200, 0.5 / 200.0, 1.0 - 0.5 / 200.0); + const Eigen::VectorXd observations = (-(1.0 - probabilities.array()).log()); + Kde1d fit(0.0, NAN, "continuous"); + fit.fit(observations); + + // A manual fit with the selected bulk bandwidth bypasses boundary repair. + Kde1d bulk(0.0, NAN, "continuous", 1.0, fit.get_bandwidth()); + bulk.fit(observations); + CHECK((fit.get_values() - bulk.get_values()).cwiseAbs().maxCoeff() > 0.01); + + Eigen::VectorXd expected_density(6); + expected_density << 0.9905722, 0.9905911, 0.9885084, 0.9473293, 0.7314338, + 0.0077356; + Eigen::VectorXd selected_density(6); + selected_density << fit.get_values()(0), fit.get_values()(4), + fit.get_values()(24), fit.get_values()(49), fit.get_values()(99), + fit.get_values()(199); + CHECK(selected_density.isApprox(expected_density, 2e-4)); + CHECK(std::isfinite(fit.get_edf())); + + Kde1d reflected(NAN, 0.0, "continuous"); + reflected.fit(-observations); + CHECK(fit.get_grid_points().isApprox(-reflected.get_grid_points().reverse(), + 1e-12)); + CHECK(fit.get_values().isApprox(reflected.get_values().reverse(), 1e-12)); + CHECK(fit.get_edf() == Approx(reflected.get_edf()).epsilon(1e-12)); +} + +TEST_CASE("one-sided vanishing endpoints retain the bulk fit", + "[boundary-expert]") +{ + const Eigen::VectorXd probabilities = + Eigen::VectorXd::LinSpaced(200, 0.5 / 200.0, 1.0 - 0.5 / 200.0); + const Eigen::VectorXd observations = probabilities.array().sqrt(); + Kde1d fit(0.0, NAN, "continuous"); + fit.fit(observations); + + Kde1d bulk(0.0, NAN, "continuous", 1.0, fit.get_bandwidth()); + bulk.fit(observations); + CHECK(fit.get_grid_points().isApprox(bulk.get_grid_points(), 1e-12)); + CHECK(fit.get_values().isApprox(bulk.get_values(), 1e-12)); + CHECK(fit.get_edf() == Approx(bulk.get_edf()).epsilon(1e-12)); +} + TEST_CASE("finite support truncates density", "[finite-support]") { Eigen::VectorXd observations = Eigen::VectorXd::LinSpaced(200, 0.0, 1.0); From e6e7e00c855ff9441e8b2d80150d70e9f5dd8625 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 15:03:14 +0200 Subject: [PATCH 06/25] Activate two-sided boundary experts --- include/kde1d/kde1d.hpp | 12 +++---- test/test.cpp | 72 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index f83b864..823c7b3 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -348,12 +348,12 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) // Nonconstant case weights and manual bandwidths need separate expert // semantics; constant weights are equivalent to an unweighted sample. const bool unweighted = w.size() == 0 || w.minCoeff() == w.maxCoeff(); - const bool repair_one_sided = type_ == VarType::continuous && - xx.size() >= 16 && unweighted && - std::isnan(bandwidth_spec_) && degree_ == 2 && - (std::isnan(xmin_) != std::isnan(xmax_)); + const bool use_boundary_repair = + type_ == VarType::continuous && xx.size() >= 16 && unweighted && + std::isnan(bandwidth_spec_) && degree_ == 2 && + (!std::isnan(xmin_) || !std::isnan(xmax_)); Eigen::VectorXd boundary_observations; - if (repair_one_sided) + if (use_boundary_repair) boundary_observations = xx; if (w.size() > 0) { @@ -426,7 +426,7 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) // construct interpolation grid // (3 iterations for normalization to a proper density) grid_ = interp::InterpolationGrid(grid_points, values, 3); - if (repair_one_sided) + if (use_boundary_repair) repair_boundaries(boundary_observations, grid_points, influences); // calculate log-likelihood of final estimate diff --git a/test/test.cpp b/test/test.cpp index 5e426e7..75acbb8 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -181,6 +181,78 @@ TEST_CASE("one-sided vanishing endpoints retain the bulk fit", CHECK(fit.get_edf() == Approx(bulk.get_edf()).epsilon(1e-12)); } +TEST_CASE("two-sided finite endpoints use the boundary experts", + "[boundary-expert]") +{ + const Eigen::VectorXd observations = + Eigen::VectorXd::LinSpaced(200, 0.5 / 200.0, 1.0 - 0.5 / 200.0); + Kde1d fit(0.0, 1.0, "continuous"); + fit.fit(observations); + + Kde1d bulk(0.0, 1.0, "continuous", 1.0, fit.get_bandwidth()); + bulk.fit(observations); + CHECK((fit.get_values() - bulk.get_values()).cwiseAbs().maxCoeff() > 0.01); + + Eigen::VectorXd expected_density(6); + expected_density << 1.0368661, 1.0367788, 1.0250191, 0.9972352, 1.0231640, + 1.0368661; + Eigen::VectorXd selected_density(6); + selected_density << fit.get_values()(0), fit.get_values()(49), + fit.get_values()(99), fit.get_values()(199), fit.get_values()(299), + fit.get_values()(400); + CHECK(selected_density.isApprox(expected_density, 2e-4)); + CHECK(std::isfinite(fit.get_edf())); + + Kde1d scaled(-3.0, 7.0, "continuous"); + scaled.fit(-3.0 + 10.0 * observations.array()); + CHECK(((scaled.get_grid_points().array() + 3.0) / 10.0) + .matrix() + .isApprox(fit.get_grid_points(), 1e-12)); + CHECK((10.0 * scaled.get_values()).isApprox(fit.get_values(), 1e-10)); + CHECK(scaled.get_edf() == Approx(fit.get_edf()).epsilon(1e-10)); +} + +TEST_CASE("two-sided endpoints are classified independently", + "[boundary-expert]") +{ + const Eigen::VectorXd probabilities = + Eigen::VectorXd::LinSpaced(200, 0.5 / 200.0, 1.0 - 0.5 / 200.0); + const Eigen::VectorXd observations = + 1.0 - (1.0 - probabilities.array()).sqrt(); + Kde1d fit(0.0, 1.0, "continuous"); + fit.fit(observations); + + Eigen::VectorXd expected_density(6); + expected_density << 1.9952890, 1.9913280, 1.9839701, 0.9946680, 0.0562144, + 0.0000020; + Eigen::VectorXd selected_density(6); + selected_density << fit.get_values()(0), fit.get_values()(49), + fit.get_values()(99), fit.get_values()(199), fit.get_values()(299), + fit.get_values()(400); + CHECK(selected_density.isApprox(expected_density, 2e-4)); + + Kde1d reflected(0.0, 1.0, "continuous"); + reflected.fit(1.0 - observations.array()); + CHECK(fit.get_values().isApprox(reflected.get_values().reverse(), 1e-12)); + CHECK(fit.get_edf() == Approx(reflected.get_edf()).epsilon(1e-12)); +} + +TEST_CASE("two-sided exploding endpoints retain the bulk fit", + "[boundary-expert]") +{ + const Eigen::VectorXd probabilities = + Eigen::VectorXd::LinSpaced(200, 0.5 / 200.0, 1.0 - 0.5 / 200.0); + const Eigen::VectorXd observations = + (0.5 * std::acos(-1.0) * probabilities.array()).sin().square(); + Kde1d fit(0.0, 1.0, "continuous"); + fit.fit(observations); + + Kde1d bulk(0.0, 1.0, "continuous", 1.0, fit.get_bandwidth()); + bulk.fit(observations); + CHECK(fit.get_values().isApprox(bulk.get_values(), 1e-12)); + CHECK(fit.get_edf() == Approx(bulk.get_edf()).epsilon(1e-12)); +} + TEST_CASE("finite support truncates density", "[finite-support]") { Eigen::VectorXd observations = Eigen::VectorXd::LinSpaced(200, 0.0, 1.0); From df1b0623c6c7653431911574f414a29d4dc89417 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 15:15:54 +0200 Subject: [PATCH 07/25] Validate native boundary experts --- benchmark/benchmark.cpp | 17 ++ diagnostic/NATIVE_RESULTS.md | 79 ++++++++ diagnostic/README.md | 4 + diagnostic/validate_native_boundary_experts.R | 184 ++++++++++++++++++ 4 files changed, 284 insertions(+) create mode 100644 diagnostic/NATIVE_RESULTS.md create mode 100644 diagnostic/validate_native_boundary_experts.R diff --git a/benchmark/benchmark.cpp b/benchmark/benchmark.cpp index 281983d..a1251b4 100644 --- a/benchmark/benchmark.cpp +++ b/benchmark/benchmark.cpp @@ -10,6 +10,9 @@ TEST_CASE("continuous KDE performance", "[!benchmark]") unbounded.array() += 0.35 * (4.0 * unbounded.array()).sin(); Eigen::VectorXd bounded = (1.0 / (1.0 + (-unbounded.array()).exp())).matrix(); + Eigen::VectorXd probabilities = Eigen::VectorXd::LinSpaced( + unbounded.size(), 0.5 / unbounded.size(), 1.0 - 0.5 / unbounded.size()); + Eigen::VectorXd one_sided = (-(1.0 - probabilities.array()).log()); Eigen::VectorXd weights = Eigen::VectorXd::LinSpaced(10000, 0.5, 1.5); BENCHMARK("fit/end-to-end/bounded/tll/n=10000") @@ -19,6 +22,20 @@ TEST_CASE("continuous KDE performance", "[!benchmark]") return fit.get_loglik(); }; + BENCHMARK("fit/end-to-end/one-sided-finite-expert/tll/n=10000") + { + kde1d::Kde1d fit(0.0, NAN, "continuous", 1.0, NAN, 2, 400); + fit.fit(one_sided); + return fit.get_loglik(); + }; + + BENCHMARK("fit/end-to-end/two-sided-finite-experts/tll/n=10000") + { + kde1d::Kde1d fit(0.0, 1.0, "continuous", 1.0, NAN, 2, 400); + fit.fit(probabilities); + return fit.get_loglik(); + }; + BENCHMARK("fit/fixed-bandwidth/unbounded/tll/n=10000") { kde1d::Kde1d fit(NAN, NAN, "continuous", 1.0, 0.3, 2, 400); diff --git a/diagnostic/NATIVE_RESULTS.md b/diagnostic/NATIVE_RESULTS.md new file mode 100644 index 0000000..8067ea6 --- /dev/null +++ b/diagnostic/NATIVE_RESULTS.md @@ -0,0 +1,79 @@ +# Native boundary-expert validation + +## Statistical validation + +The native candidate was compared with commit `4f3d148`, immediately before +the expert implementation. The paired experiment used 100 replications at +$n=25,100,1000,2000$. One-sided scenarios were Exponential, half-normal, +Gamma$(2)$, Gamma$(0.75)$, and Lomax$(2)$; two-sided scenarios were Uniform and +six symmetric or asymmetric beta densities. Ratios below average the +scenario-specific ratios of mean ISE. Parentheses contain paired Monte Carlo +standard errors. + +| support | $n$ | global ISE ratio | boundary ISE ratio | +|---|---:|---:|---:| +| one-sided | 25 | 0.932 (0.008) | 0.896 (0.016) | +| one-sided | 100 | 0.929 (0.009) | 0.903 (0.016) | +| one-sided | 1000 | 0.907 (0.012) | 0.857 (0.017) | +| one-sided | 2000 | 0.881 (0.015) | 0.824 (0.020) | +| two-sided | 25 | 0.874 (0.021) | 0.862 (0.020) | +| two-sided | 100 | 0.911 (0.008) | 0.917 (0.007) | +| two-sided | 1000 | 0.939 (0.007) | 0.954 (0.006) | +| two-sided | 2000 | 0.944 (0.007) | 0.955 (0.006) | + +Average integrated variance ratios range from 0.93 to 0.94 one-sided and from +0.87 to 0.96 two-sided. Boundary variance ratios range from 0.88 to 0.90 and +from 0.86 to 0.97, respectively. The extra small-sample bias is the intended +price for smoother boundary realizations; at $n=1000,2000$, average integrated +squared bias is also lower than baseline. + +The main accepted losses remain the difficult shapes identified by the R +experiments. At $n=2000$, Gamma$(0.75)$ has global/boundary ratios +1.085/1.098, Beta$(0.75,2)$ has 1.075/1.072, and the reflected +Beta$(2,0.75)$ has 1.027/1.026. Gamma$(2)$ and Beta$(2,2)$ select bulk in every +large-sample replication and are exactly unchanged. Uniform, Beta$(1,2)$, and +Beta$(2,1)$ have $n=2000$ global ratios 0.844, 0.817, and 0.830. + +The deterministic native tests agree with the retained R reference values to +within $2\times10^{-4}$ relative tolerance and cover lower/upper reflection, +independent two-sided endpoint decisions, exploding/vanishing fallback, and +affine support changes. + +## EDF check + +The conditional mixture EDF was compared with + +$$ +1+\sum_i\{\log\widehat f(X_i)-\log\widehat f_{-i}(X_i)\}. +$$ + +For deterministic finite-endpoint samples at $n=25,50,100$, the discrepancy +was 0.08--0.30 EDF units for Uniform and Exponential examples. The asymmetric +Beta$(1,2)$ discrepancy was 0.27--0.33 at $n=50,100$ and 0.84 at $n=25$. +This is adequate for the existing asymptotic EDF convention and does not +justify a gate-derivative correction. Pure-bulk fits retain the old EDF +exactly. + +## Fit time + +Release builds were timed against `4f3d148`. Bulk-classified fits incur only +sorting and remained within about 3% of baseline for $n=100$--$2000$. Active +experts cost more because the concise implementation directly evaluates the +Gaussian kernels on the 401-point grid: + +| active endpoints | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:| +| one | 1.70 ms (4.4x) | 5.93 ms (12.4x) | 10.67 ms (18.5x) | +| two | 2.90 ms (7.5x) | 10.41 ms (23.5x) | 18.84 ms (36.7x) | + +The absolute cost remains below 20 ms at $n=2000$. Keep the direct evaluator +for the first PR; optimize only if downstream profiling shows fit time is +material. + +## Reproduction + +Install the package with a clean native rebuild at each revision and run +`validate_native_boundary_experts.R`, giving each run a distinct method label +and output file. The script writes replication-level ISE/EDF/log-likelihood and +a companion bias/variance summary. Join the two raw files by support, +scenario, sample size, and replication for paired ratios and uncertainty. diff --git a/diagnostic/README.md b/diagnostic/README.md index 9624814..85687d3 100644 --- a/diagnostic/README.md +++ b/diagnostic/README.md @@ -36,3 +36,7 @@ results, and its current recommendations live in The follow-up for supports with exactly one finite endpoint lives in [`one-sided-repair/`](one-sided-repair/README.md). + +The shared native implementation is evaluated by +[`validate_native_boundary_experts.R`](validate_native_boundary_experts.R), +with current results summarized in [`NATIVE_RESULTS.md`](NATIVE_RESULTS.md). diff --git a/diagnostic/validate_native_boundary_experts.R b/diagnostic/validate_native_boundary_experts.R new file mode 100644 index 0000000..2a0a79f --- /dev/null +++ b/diagnostic/validate_native_boundary_experts.R @@ -0,0 +1,184 @@ +# Evaluate one native kde1d revision. Run once at the baseline commit and once +# at the candidate commit, then compare rows by scenario, size, and replication. + +arguments <- commandArgs(trailingOnly = TRUE) +if (length(arguments) < 2L || length(arguments) > 4L) { + stop("usage: script method output.csv [replications] [library-path]") +} +if (length(arguments) == 4L) { + .libPaths(c(arguments[[4L]], .libPaths())) +} +library(kde1d) + +method <- arguments[[1L]] +output_file <- arguments[[2L]] +replications <- if (length(arguments) >= 3L) { + as.integer(arguments[[3L]]) +} else { + 100L +} +if (!is.finite(replications) || replications < 2L) { + stop("replications must be at least two") +} + +integrate_values <- function(points, values) { + sum(diff(points) * (values[-length(values)] + values[-1L]) / 2) +} + +one_sided <- list( + exponential = list( + random = function(n) rexp(n), + density = dexp, + quantile = qexp + ), + half_normal = list( + random = function(n) abs(rnorm(n)), + density = function(x) 2 * dnorm(x), + quantile = function(p) qnorm((p + 1) / 2) + ), + gamma_2 = list( + random = function(n) rgamma(n, 2), + density = function(x) dgamma(x, 2), + quantile = function(p) qgamma(p, 2) + ), + gamma_075 = list( + random = function(n) rgamma(n, 0.75), + density = function(x) dgamma(x, 0.75), + quantile = function(p) qgamma(p, 0.75) + ), + lomax_2 = list( + random = function(n) (1 - runif(n))^(-0.5) - 1, + density = function(x) 2 / (1 + x)^3, + quantile = function(p) (1 - p)^(-0.5) - 1 + ) +) +two_sided <- list( + uniform = c(1, 1), + beta_1_2 = c(1, 2), + beta_2_1 = c(2, 1), + beta_075_2 = c(0.75, 2), + beta_2_075 = c(2, 0.75), + beta_075_075 = c(0.75, 0.75), + beta_2_2 = c(2, 2) +) +sample_sizes <- c(25L, 100L, 1000L, 2000L) +result_rows <- list() +summary_rows <- list() + +summarize_estimates <- function(points, estimates, truth, boundary) { + mean_density <- rowMeans(estimates) + c( + global_squared_bias = integrate_values( + points, (mean_density - truth)^2 + ), + global_variance = integrate_values( + points, rowMeans((estimates - mean_density)^2) + ), + boundary_squared_bias = integrate_values( + points[boundary], (mean_density[boundary] - truth[boundary])^2 + ), + boundary_variance = integrate_values( + points[boundary], + rowMeans((estimates[boundary, , drop = FALSE] - + mean_density[boundary])^2) + ) + ) +} + +for (scenario_index in seq_along(one_sided)) { + scenario <- one_sided[[scenario_index]] + points <- sort(unique(c( + 1e-10, + scenario$quantile(10^seq(-8, -1, length.out = 100L)), + scenario$quantile(seq(0.1, 0.9999, length.out = 401L)) + ))) + truth <- scenario$density(points) + boundary <- points <= scenario$quantile(0.1) + for (sample_size in sample_sizes) { + estimates <- matrix(NA_real_, length(points), replications) + for (replication in seq_len(replications)) { + set.seed(20260824L + 100000L * scenario_index + + 1000L * match(sample_size, sample_sizes) + replication) + fit <- kde1d(scenario$random(sample_size), xmin = 0) + estimates[, replication] <- dkde1d(points, fit) + result_rows[[length(result_rows) + 1L]] <- data.frame( + support = "one-sided", + scenario = names(one_sided)[[scenario_index]], + sample_size = sample_size, + replication = replication, + method = method, + global_ise = integrate_values( + points, (estimates[, replication] - truth)^2 + ), + boundary_ise = integrate_values( + points[boundary], + (estimates[boundary, replication] - truth[boundary])^2 + ), + edf = fit$edf, + loglik = fit$loglik + ) + } + summary_rows[[length(summary_rows) + 1L]] <- data.frame( + support = "one-sided", + scenario = names(one_sided)[[scenario_index]], + sample_size = sample_size, + method = method, + as.list(summarize_estimates(points, estimates, truth, boundary)) + ) + } +} + +points <- sort(unique(c( + 10^seq(-10, -2, length.out = 101L), + seq(0.01, 0.99, length.out = 301L), + 1 - 10^seq(-2, -10, length.out = 101L) +))) +boundary <- points <= 0.1 | points >= 0.9 +for (scenario_index in seq_along(two_sided)) { + shapes <- two_sided[[scenario_index]] + truth <- dbeta(points, shapes[[1L]], shapes[[2L]]) + for (sample_size in sample_sizes) { + estimates <- matrix(NA_real_, length(points), replications) + for (replication in seq_len(replications)) { + set.seed(20260825L + 100000L * scenario_index + + 1000L * match(sample_size, sample_sizes) + replication) + fit <- kde1d( + rbeta(sample_size, shapes[[1L]], shapes[[2L]]), + xmin = 0, + xmax = 1 + ) + estimates[, replication] <- dkde1d(points, fit) + result_rows[[length(result_rows) + 1L]] <- data.frame( + support = "two-sided", + scenario = names(two_sided)[[scenario_index]], + sample_size = sample_size, + replication = replication, + method = method, + global_ise = integrate_values( + points, (estimates[, replication] - truth)^2 + ), + boundary_ise = integrate_values( + points[boundary], + (estimates[boundary, replication] - truth[boundary])^2 + ), + edf = fit$edf, + loglik = fit$loglik + ) + } + summary_rows[[length(summary_rows) + 1L]] <- data.frame( + support = "two-sided", + scenario = names(two_sided)[[scenario_index]], + sample_size = sample_size, + method = method, + as.list(summarize_estimates(points, estimates, truth, boundary)) + ) + } +} + +dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) +write.csv(do.call(rbind, result_rows), output_file, row.names = FALSE) +write.csv( + do.call(rbind, summary_rows), + sub("\\.csv$", "-summary.csv", output_file), + row.names = FALSE +) From 0fcd5ccdf166adf488eaf7edc9555489d057dd07 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 15:19:37 +0200 Subject: [PATCH 08/25] Test boundary expert fallbacks --- test/test.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/test.cpp b/test/test.cpp index 75acbb8..2a8e47d 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -253,6 +253,37 @@ TEST_CASE("two-sided exploding endpoints retain the bulk fit", CHECK(fit.get_edf() == Approx(bulk.get_edf()).epsilon(1e-12)); } +TEST_CASE("unsupported expert options retain the transformed bulk fit", + "[boundary-expert]") +{ + const Eigen::VectorXd probabilities = + Eigen::VectorXd::LinSpaced(200, 0.5 / 200.0, 1.0 - 0.5 / 200.0); + const Eigen::VectorXd observations = (-(1.0 - probabilities.array()).log()); + const Eigen::VectorXd weights = + Eigen::VectorXd::LinSpaced(observations.size(), 0.5, 1.5); + + Kde1d weighted(0.0, NAN, "continuous"); + weighted.fit(observations, weights); + Kde1d weighted_bulk(0.0, NAN, "continuous", 1.0, weighted.get_bandwidth()); + weighted_bulk.fit(observations, weights); + CHECK(weighted.get_values().isApprox(weighted_bulk.get_values(), 1e-12)); + CHECK(weighted.get_edf() == Approx(weighted_bulk.get_edf()).epsilon(1e-12)); + + Kde1d linear(0.0, NAN, "continuous", 1.0, NAN, 1); + linear.fit(observations); + Kde1d linear_bulk(0.0, NAN, "continuous", 1.0, linear.get_bandwidth(), 1); + linear_bulk.fit(observations); + CHECK(linear.get_values().isApprox(linear_bulk.get_values(), 1e-12)); + CHECK(linear.get_edf() == Approx(linear_bulk.get_edf()).epsilon(1e-12)); + + Kde1d small(0.0, NAN, "continuous"); + small.fit(observations.head(15)); + Kde1d small_bulk(0.0, NAN, "continuous", 1.0, small.get_bandwidth()); + small_bulk.fit(observations.head(15)); + CHECK(small.get_values().isApprox(small_bulk.get_values(), 1e-12)); + CHECK(small.get_edf() == Approx(small_bulk.get_edf()).epsilon(1e-12)); +} + TEST_CASE("finite support truncates density", "[finite-support]") { Eigen::VectorXd observations = Eigen::VectorXd::LinSpaced(200, 0.0, 1.0); From 61faced13c4b42e3b89962ed732673b6c85cc582 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 17:22:13 +0200 Subject: [PATCH 09/25] Simplify boundary expert implementation --- include/kde1d/kde1d.hpp | 351 +++++++++++++++++++++++----------------- 1 file changed, 199 insertions(+), 152 deletions(-) diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 823c7b3..36fe127 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -124,7 +124,7 @@ class Kde1d struct BoundaryComponent { Eigen::VectorXd density; - Eigen::VectorXd response; + Eigen::VectorXd influence_num; }; // data members @@ -191,15 +191,14 @@ class Kde1d double multiplier, size_t degree, const Eigen::VectorXd& weights) const; - bool is_finite_endpoint(Eigen::VectorXd distances) const; - BoundaryComponent fit_boundary_component( - const Eigen::VectorXd& distances, - const Eigen::VectorXd& evaluation_distances, - const Eigen::VectorXd& bandwidth_weights, - double floor_fraction, - size_t degree) const; - void repair_boundaries(const Eigen::VectorXd& observations, - const Eigen::VectorXd& grid_points, + bool is_finite_endpoint(Eigen::VectorXd dist) const; + BoundaryComponent fit_boundary_component(const Eigen::VectorXd& dist, + const Eigen::VectorXd& eval_dist, + const Eigen::VectorXd& bw_weights, + double floor_fraction, + size_t degree) const; + void repair_boundaries(const Eigen::VectorXd& x, + const Eigen::VectorXd& grid, Eigen::VectorXd& influences); std::string as_str(VarType type) const; @@ -948,235 +947,283 @@ Kde1d::finalize_grid(Eigen::VectorXd& grid_points) return grid_points; } -//! Classifies a support endpoint from the power law of its closest order -//! statistics. Ambiguous and numerically degenerate cases retain the bulk fit. +//! Classifies a support endpoint from its ordered distances @f$d@f$ to the +//! endpoint. For @f$k = \min(n-1, \lceil 2\sqrt n \rceil)@f$, the lower-tail +//! index is +//! @f[ +//! \widehat\beta = \frac{k}{\sum_{i=1}^k +//! \log\{d_{(k+1)} / d_{(i)}\}}. +//! @f] +//! It is treated as finite when @f$\widehat\beta \geq 0.9@f$ and its +//! one-sided 95% lower confidence bound does not exceed one. Ambiguous and +//! numerically degenerate cases retain the bulk fit. +//! @param dist distances of the observations from the support endpoint; copied +//! because the classifier sorts them. +//! @return whether the endpoint is confidently classified as finite. inline bool -Kde1d::is_finite_endpoint(Eigen::VectorXd distances) const +Kde1d::is_finite_endpoint(Eigen::VectorXd dist) const { - std::sort(distances.data(), distances.data() + distances.size()); - const size_t tail_count = - std::min(static_cast(distances.size() - 1), - static_cast(std::ceil(2.0 * std::sqrt(distances.size())))); - const double threshold = distances(tail_count); - if (!(threshold > 0.0) || !std::isfinite(threshold)) + std::sort(dist.data(), dist.data() + dist.size()); + + // k is the number of lower order statistics; dist_k1 is d_(k+1). + const size_t k = + std::min(static_cast(dist.size() - 1), + static_cast(std::ceil(2.0 * std::sqrt(dist.size())))); + const double dist_k1 = dist(k); + if (!(dist_k1 > 0.0) || !std::isfinite(dist_k1)) return false; - double log_sum = 0.0; - const double distance_floor = - std::numeric_limits::epsilon() * threshold; - for (size_t index = 0; index < tail_count; ++index) { - log_sum += std::log(threshold / std::max(distances(index), distance_floor)); + // denom is the denominator of the lower-tail index beta = k / denom. + double denom = 0.0; + const double dist_min = std::numeric_limits::epsilon() * dist_k1; + for (size_t i = 0; i < k; ++i) { + denom += std::log(dist_k1 / std::max(dist(i), dist_min)); } - if (!(log_sum > 0.0) || !std::isfinite(log_sum)) + if (!(denom > 0.0) || !std::isfinite(denom)) return false; - const double tail_index = static_cast(tail_count) / log_sum; + const double beta = static_cast(k) / denom; // 1.64485 is the 95% standard-normal quantile used by the R selector. - return tail_index >= 0.9 && - tail_index * (1.0 - 1.6448536269514722 / std::sqrt(tail_count)) <= 1.0; + return beta >= 0.9 && beta * (1.0 - 1.6448536269514722 / std::sqrt(k)) <= 1.0; } -//! Fits one Gaussian local-polynomial endpoint component. Targeting weights -//! select its bandwidth only; equal observation contributions preserve the -//! original density estimand. +//! Fits a degree-@f$p@f$ Gaussian local-polynomial component from sample +//! distances @f$d@f$ to endpoint-distance grid @f$t@f$. With bandwidth +//! @f$h@f$, truncated Gaussian moments @f$\mu_r(a)@f$, and +//! @f$M_p(a) = [\mu_{j+k}(a)]_{j,k=0}^p@f$, the equivalent-kernel estimate is +//! @f[ +//! \begin{align*} +//! a &= t/h, & u_i &= (t-d_i)/h, \\[2pt] +//! \widehat f_p(t) +//! &= \frac{1}{nh}\sum_{i=1}^n \phi(u_i)\, +//! e_0^\mathsf{T} M_p(a)^{-1}(1,u_i,\ldots,u_i^p)^\mathsf{T}, \\[2pt] +//! \nu_p(t) &= \frac{\phi(0)}{nh} +//! e_0^\mathsf{T}M_p(a)^{-1}e_0. +//! \end{align*} +//! @f] +//! Targeting weights select @f$h@f$ only, so observations contribute equally +//! and the density estimand is unchanged. The influence numerator +//! @f$\nu_p(t)@f$ is the diagonal kernel contribution; dividing it by +//! @f$\widehat f_p(t)@f$ gives the pointwise influence used for EDF. +//! @param dist distances of the observations from the support endpoint. +//! @param eval_dist endpoint distances at which to evaluate the component. +//! @param bw_weights targeting weights used only for bandwidth selection. +//! @param floor_fraction fraction of the closest observations used to select +//! the bandwidth floor. +//! @param degree local-polynomial degree. +//! @return the normalized density and influence numerator on `eval_dist`; an +//! empty component indicates numerical failure. inline Kde1d::BoundaryComponent -Kde1d::fit_boundary_component(const Eigen::VectorXd& distances, - const Eigen::VectorXd& evaluation_distances, - const Eigen::VectorXd& bandwidth_weights, +Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, + const Eigen::VectorXd& eval_dist, + const Eigen::VectorXd& bw_weights, double floor_fraction, size_t degree) const { - bandwidth::PluginBandwidthSelector selector(distances, bandwidth_weights); - double bandwidth = selector.select_bandwidth(degree); - - Eigen::VectorXd ordered_distances = distances; - std::sort(ordered_distances.data(), - ordered_distances.data() + ordered_distances.size()); - const Eigen::Index floor_count = std::min( - distances.size(), + bandwidth::PluginBandwidthSelector selector(dist, bw_weights); + double h = selector.select_bandwidth(degree); + + // Floor h with a selector on the closest observations to stabilize the fit. + Eigen::VectorXd dist_sorted = dist; + std::sort(dist_sorted.data(), dist_sorted.data() + dist_sorted.size()); + const Eigen::Index n_floor = std::min( + dist.size(), std::max( - 4, - static_cast(std::ceil(floor_fraction * distances.size())))); - bandwidth::PluginBandwidthSelector floor_selector( - ordered_distances.head(floor_count)); - bandwidth = - std::max(bandwidth, floor_selector.select_bandwidth(degree)) * multiplier_; - if (!(bandwidth > 0.0) || !std::isfinite(bandwidth)) + 4, static_cast(std::ceil(floor_fraction * dist.size())))); + bandwidth::PluginBandwidthSelector floor_selector(dist_sorted.head(n_floor)); + h = std::max(h, floor_selector.select_bandwidth(degree)) * multiplier_; + if (!(h > 0.0) || !std::isfinite(h)) return {}; - BoundaryComponent component{ Eigen::VectorXd(evaluation_distances.size()), - Eigen::VectorXd(evaluation_distances.size()) }; - for (Eigen::Index row = 0; row < evaluation_distances.size(); ++row) { - const double boundary_position = evaluation_distances(row) / bandwidth; - const double normal_density = - K0_ * std::exp(-0.5 * boundary_position * boundary_position); - Eigen::VectorXd moments(2 * degree + 1); - moments(0) = - stats::pnorm(Eigen::VectorXd::Constant(1, boundary_position))(0); - moments(1) = -normal_density; - for (size_t order = 2; order < static_cast(moments.size()); - ++order) { - moments(order) = (order - 1.0) * moments(order - 2) - - std::pow(boundary_position, order - 1) * normal_density; + BoundaryComponent fit{ Eigen::VectorXd(eval_dist.size()), + Eigen::VectorXd(eval_dist.size()) }; + for (Eigen::Index j = 0; j < eval_dist.size(); ++j) { + // a = t/h truncates the kernel; mu stores its moments up to order 2p. + const double a = eval_dist(j) / h; + const double phi_a = K0_ * std::exp(-0.5 * a * a); + Eigen::VectorXd mu(2 * degree + 1); + mu(0) = stats::pnorm(Eigen::VectorXd::Constant(1, a))(0); + mu(1) = -phi_a; + for (size_t order = 2; order < static_cast(mu.size()); ++order) { + mu(order) = + (order - 1.0) * mu(order - 2) - std::pow(a, order - 1) * phi_a; } - Eigen::MatrixXd moment_matrix(degree + 1, degree + 1); + // M is the moment matrix; c, its first inverse row, gives the kernel. + Eigen::MatrixXd M(degree + 1, degree + 1); for (size_t column = 0; column <= degree; ++column) { - for (size_t matrix_row = 0; matrix_row <= degree; ++matrix_row) - moment_matrix(matrix_row, column) = moments(matrix_row + column); + for (size_t row = 0; row <= degree; ++row) + M(row, column) = mu(row + column); } - const Eigen::VectorXd coefficients = moment_matrix.inverse().row(0); - - double density = 0.0; - for (Eigen::Index observation = 0; observation < distances.size(); - ++observation) { - const double kernel_argument = - (evaluation_distances(row) - distances(observation)) / bandwidth; - double polynomial = coefficients(degree); + const Eigen::VectorXd c = M.inverse().row(0); + + double f = 0.0; + for (Eigen::Index i = 0; i < dist.size(); ++i) { + const double u = (eval_dist(j) - dist(i)) / h; + double p_u = c(degree); for (size_t order = degree; order > 0; --order) - polynomial = polynomial * kernel_argument + coefficients(order - 1); - density += - K0_ * std::exp(-0.5 * kernel_argument * kernel_argument) * polynomial; + p_u = p_u * u + c(order - 1); + f += K0_ * std::exp(-0.5 * u * u) * p_u; } - component.density(row) = - density / (static_cast(distances.size()) * bandwidth); - component.response(row) = - K0_ * coefficients(0) / - (static_cast(distances.size()) * bandwidth); + fit.density(j) = f / (static_cast(dist.size()) * h); + fit.influence_num(j) = K0_ * c(0) / (static_cast(dist.size()) * h); } - for (Eigen::Index row = 0; row < component.density.size(); ++row) { - if (!(component.density(row) > 0.0) || - !std::isfinite(component.density(row)) || - !std::isfinite(component.response(row))) { - component.density(row) = 0.0; - component.response(row) = 0.0; + // Remove unstable local-polynomial values, then normalize on the grid. + for (Eigen::Index j = 0; j < fit.density.size(); ++j) { + if (!(fit.density(j) > 0.0) || !std::isfinite(fit.density(j)) || + !std::isfinite(fit.influence_num(j))) { + fit.density(j) = 0.0; + fit.influence_num(j) = 0.0; } } double mass = 0.0; - for (Eigen::Index row = 0; row < component.density.size() - 1; ++row) { - mass += (evaluation_distances(row + 1) - evaluation_distances(row)) * - (component.density(row) + component.density(row + 1)) / 2.0; + for (Eigen::Index j = 0; j < fit.density.size() - 1; ++j) { + mass += (eval_dist(j + 1) - eval_dist(j)) * + (fit.density(j) + fit.density(j + 1)) / 2.0; } if (!(mass > 0.0) || !std::isfinite(mass)) return {}; - component.density /= mass; - component.response /= mass; - return component; + fit.density /= mass; + fit.influence_num /= mass; + return fit; } -//! Replaces the transformed bulk density near confidently finite endpoints -//! and carries the same local mixture through the diagonal EDF response. +//! Fuses the transformed bulk density @f$\widehat f_B@f$ with endpoint +//! densities @f$\widehat f_L@f$ and @f$\widehat f_U@f$. Each endpoint density +//! is the average of a local-linear and a local-quadratic estimate. Smooth +//! weights @f$w_L@f$ and @f$w_U@f$ are functions of the bulk CDF and shrink at +//! rate @f$\min(1/4,n^{-1/2})@f$: +//! @f[ +//! \begin{align*} +//! q &= \min(1/4,n^{-1/2}), & z(p) &= \min(1,p/q), \\[2pt] +//! g(p) &= 1-3z(p)^2+2z(p)^3, \\[2pt] +//! w_L &= g(F_B), & w_U &= g(1-F_B), \\[2pt] +//! \widehat f +//! &= w_L\widehat f_L+(1-w_L-w_U)\widehat f_B+w_U\widehat f_U, \\[2pt] +//! \nu &= w_L\nu_L+(1-w_L-w_U)\nu_B+w_U\nu_U, \\[2pt] +//! \mathrm{influence} &= \nu/\widehat f. +//! \end{align*} +//! @f] +//! Here @f$\nu@f$ is the influence numerator, i.e., the diagonal kernel +//! contribution on the density scale. Only endpoints classified as finite are +//! repaired. +//! @param x observations on the original scale. +//! @param grid increasing evaluation grid on the original scale. +//! @param influences on input, bulk-fit influences on `grid`; on output, +//! influences of the fused estimate. inline void -Kde1d::repair_boundaries(const Eigen::VectorXd& observations, - const Eigen::VectorXd& grid_points, +Kde1d::repair_boundaries(const Eigen::VectorXd& x, + const Eigen::VectorXd& grid, Eigen::VectorXd& influences) { - Eigen::VectorXd lower_distances; - Eigen::VectorXd upper_distances; + Eigen::VectorXd dist_lower; + Eigen::VectorXd dist_upper; bool repair_lower = !std::isnan(xmin_); bool repair_upper = !std::isnan(xmax_); if (repair_lower) { - lower_distances = observations.array() - xmin_; - repair_lower = is_finite_endpoint(lower_distances); + dist_lower = x.array() - xmin_; + repair_lower = is_finite_endpoint(dist_lower); } if (repair_upper) { - upper_distances = xmax_ - observations.array(); - repair_upper = is_finite_endpoint(upper_distances); + dist_upper = xmax_ - x.array(); + repair_upper = is_finite_endpoint(dist_upper); } if (!repair_lower && !repair_upper) return; - const double boundary_fraction = - std::min(0.25, 1.0 / std::sqrt(observations.size())); + // q is the shrinking probability width of each endpoint weight. + const double q = std::min(0.25, 1.0 / std::sqrt(x.size())); auto endpoint_weight = [&](double probability) { - const double position = std::min(1.0, probability / boundary_fraction); - return 1.0 - - (3.0 * position * position - 2.0 * position * position * position); + const double z = std::min(1.0, probability / q); + return 1.0 - (3.0 * z * z - 2.0 * z * z * z); }; - auto targeting_weights = [&](const Eigen::VectorXd& distances) { - Eigen::VectorXd weights(distances.size()); - const Eigen::VectorXi order = tools::get_order(distances); + // Mid-rank weights target endpoint observations during bandwidth selection. + auto targeting_weights = [&](const Eigen::VectorXd& dist) { + Eigen::VectorXd weights(dist.size()); + const Eigen::VectorXi order = tools::get_order(dist); Eigen::Index first = 0; while (first < order.size()) { Eigen::Index last = first; while (last + 1 < order.size() && - distances(order(last + 1)) == distances(order(first))) + dist(order(last + 1)) == dist(order(first))) ++last; const double probability = static_cast(first + last + 1) / - (2.0 * static_cast(distances.size())); - for (Eigen::Index index = first; index <= last; ++index) - weights(order(index)) = endpoint_weight(probability); + (2.0 * static_cast(dist.size())); + for (Eigen::Index i = first; i <= last; ++i) + weights(order(i)) = endpoint_weight(probability); first = last + 1; } return weights; }; + // The bandwidth floor uses all data on bounded support and 75% otherwise. const double floor_fraction = (!std::isnan(xmin_) && !std::isnan(xmax_)) ? 1.0 : 0.75; - auto fit_endpoint = [&](const Eigen::VectorXd& distances, - const Eigen::VectorXd& evaluation_distances) { - const Eigen::VectorXd weights = targeting_weights(distances); - BoundaryComponent linear = fit_boundary_component( - distances, evaluation_distances, weights, floor_fraction, 1); - BoundaryComponent quadratic = fit_boundary_component( - distances, evaluation_distances, weights, floor_fraction, 2); + auto fit_endpoint = [&](const Eigen::VectorXd& dist, + const Eigen::VectorXd& eval_dist) { + const Eigen::VectorXd bw_weights = targeting_weights(dist); + // Averaging orders one and two gives a smoother, more stable endpoint. + BoundaryComponent linear = + fit_boundary_component(dist, eval_dist, bw_weights, floor_fraction, 1); + BoundaryComponent quadratic = + fit_boundary_component(dist, eval_dist, bw_weights, floor_fraction, 2); if (linear.density.size() == 0 || quadratic.density.size() == 0) return BoundaryComponent{}; linear.density = (linear.density + quadratic.density) / 2.0; - linear.response = (linear.response + quadratic.response) / 2.0; + linear.influence_num = + (linear.influence_num + quadratic.influence_num) / 2.0; return linear; }; BoundaryComponent lower; BoundaryComponent upper; if (repair_lower) { - lower = fit_endpoint(lower_distances, grid_points.array() - xmin_); + lower = fit_endpoint(dist_lower, grid.array() - xmin_); repair_lower = lower.density.size() > 0; } if (repair_upper) { - Eigen::VectorXd evaluation_distances = - (xmax_ - grid_points.array()).reverse(); - upper = fit_endpoint(upper_distances, evaluation_distances); + Eigen::VectorXd upper_eval_dist = (xmax_ - grid.array()).reverse(); + upper = fit_endpoint(dist_upper, upper_eval_dist); repair_upper = upper.density.size() > 0; if (repair_upper) { upper.density.reverseInPlace(); - upper.response.reverseInPlace(); + upper.influence_num.reverseInPlace(); } } if (!repair_lower && !repair_upper) return; - const Eigen::VectorXd bulk_density = grid_.get_values(); - const Eigen::VectorXd probabilities = grid_.integrate(grid_points, true); - Eigen::VectorXd lower_weights = Eigen::VectorXd::Zero(grid_points.size()); - Eigen::VectorXd upper_weights = Eigen::VectorXd::Zero(grid_points.size()); - for (Eigen::Index row = 0; row < grid_points.size(); ++row) { - if (repair_lower) { - lower_weights(row) = endpoint_weight(probabilities(row)); - } - if (repair_upper) { - upper_weights(row) = endpoint_weight(1.0 - probabilities(row)); - } + // f_bulk and bulk_cdf determine the fused density and endpoint weights. + const Eigen::VectorXd f_bulk = grid_.get_values(); + const Eigen::VectorXd bulk_cdf = grid_.integrate(grid, true); + Eigen::VectorXd w_l = Eigen::VectorXd::Zero(grid.size()); + Eigen::VectorXd w_u = Eigen::VectorXd::Zero(grid.size()); + for (Eigen::Index j = 0; j < grid.size(); ++j) { + if (repair_lower) + w_l(j) = endpoint_weight(bulk_cdf(j)); + if (repair_upper) + w_u(j) = endpoint_weight(1.0 - bulk_cdf(j)); } - Eigen::VectorXd density(grid_points.size()); - Eigen::VectorXd response(grid_points.size()); - for (Eigen::Index row = 0; row < grid_points.size(); ++row) { - const double bulk_weight = 1.0 - lower_weights(row) - upper_weights(row); - density(row) = bulk_weight * bulk_density(row); - response(row) = bulk_weight * bulk_density(row) * influences(row); + // Fuse densities and influence numerators with the same weights. + Eigen::VectorXd f(grid.size()); + Eigen::VectorXd infl_num(grid.size()); + for (Eigen::Index j = 0; j < grid.size(); ++j) { + const double w_b = 1.0 - w_l(j) - w_u(j); + f(j) = w_b * f_bulk(j); + infl_num(j) = w_b * f_bulk(j) * influences(j); if (repair_lower) { - density(row) += lower_weights(row) * lower.density(row); - response(row) += lower_weights(row) * lower.response(row); + f(j) += w_l(j) * lower.density(j); + infl_num(j) += w_l(j) * lower.influence_num(j); } if (repair_upper) { - density(row) += upper_weights(row) * upper.density(row); - response(row) += upper_weights(row) * upper.response(row); + f(j) += w_u(j) * upper.density(j); + infl_num(j) += w_u(j) * upper.influence_num(j); } - influences(row) = density(row) > 0.0 ? response(row) / density(row) : 0.0; + influences(j) = f(j) > 0.0 ? infl_num(j) / f(j) : 0.0; } - grid_ = interp::InterpolationGrid(grid_points, density.cwiseMax(0.0), 3); + grid_ = interp::InterpolationGrid(grid, f.cwiseMax(0.0), 3); } // Bandwidth for Kernel Density Estimation From d957013ef4118242a0b5a00a071a5149a11d1da3 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 17:59:30 +0200 Subject: [PATCH 10/25] Speed up boundary expert evaluation --- diagnostic/NATIVE_RESULTS.md | 56 ++++-- diagnostic/boundary-repair/HANDOFF.md | 9 +- diagnostic/boundary-repair/README.md | 15 +- diagnostic/one-sided-repair/HANDOFF.md | 4 +- diagnostic/one-sided-repair/NATIVE_CPP.md | 107 +++++------ diagnostic/one-sided-repair/README.md | 17 +- include/kde1d/kde1d.hpp | 218 +++++++++------------- test/test.cpp | 10 +- 8 files changed, 210 insertions(+), 226 deletions(-) diff --git a/diagnostic/NATIVE_RESULTS.md b/diagnostic/NATIVE_RESULTS.md index 8067ea6..18cd011 100644 --- a/diagnostic/NATIVE_RESULTS.md +++ b/diagnostic/NATIVE_RESULTS.md @@ -34,10 +34,41 @@ Beta$(2,0.75)$ has 1.027/1.026. Gamma$(2)$ and Beta$(2,2)$ select bulk in every large-sample replication and are exactly unchanged. Uniform, Beta$(1,2)$, and Beta$(2,1)$ have $n=2000$ global ratios 0.844, 0.817, and 0.830. -The deterministic native tests agree with the retained R reference values to -within $2\times10^{-4}$ relative tolerance and cover lower/upper reflection, -independent two-sided endpoint decisions, exploding/vanishing fallback, and -affine support changes. +The deterministic native tests cover lower/upper reflection, independent +two-sided endpoint decisions, exploding/vanishing fallback, and affine support +changes. Their golden values were refreshed for the simplified evaluator. + +## Runtime simplification ablation + +The direct native evaluator was simplified after the main validation. The +local-linear and local-quadratic equivalent kernels now share the degree-2 +bandwidth and are averaged in one observation loop. On bounded support this +bandwidth uses all endpoint distances; on one-sided support it uses the closest +75%. Endpoint kernels are evaluated only where their smooth fusion weights are +nonzero, Gaussian terms beyond six bandwidths are omitted, and the fused grid +is normalized once at the end. + +A paired 100-replication check compared this implementation with commit +`cbde530` over Exponential, half-normal, Gamma$(2)$, Gamma$(0.75)$, Lomax$(2)$, +Uniform, Beta$(1,2)$, Beta$(0.75,2)$, Beta$(0.75,0.75)$, and Beta$(2,2)$. +Ratios compare the simplified evaluator with `cbde530`; parentheses contain +paired Monte Carlo standard errors: + +| support | $n$ | global ISE ratio | boundary ISE ratio | +|---|---:|---:|---:| +| one-sided | 25 | 0.996 (0.002) | 0.999 (0.004) | +| one-sided | 100 | 0.983 (0.003) | 0.982 (0.003) | +| one-sided | 1000 | 0.993 (0.003) | 0.992 (0.003) | +| one-sided | 2000 | 0.992 (0.003) | 0.991 (0.003) | +| two-sided | 25 | 1.010 (0.003) | 1.014 (0.006) | +| two-sided | 100 | 0.999 (0.002) | 1.002 (0.004) | +| two-sided | 1000 | 0.999 (0.003) | 0.992 (0.004) | +| two-sided | 2000 | 0.994 (0.003) | 0.986 (0.004) | + +The largest scenario-level increases were about 3.5% for Gamma$(0.75)$ and +3.9% for Beta$(0.75,0.75)$; Uniform, Beta$(1,2)$, Exponential, half-normal, +and Lomax generally improved. This supports the simpler shared-bandwidth +kernel average without a material aggregate accuracy cost. ## EDF check @@ -51,24 +82,23 @@ For deterministic finite-endpoint samples at $n=25,50,100$, the discrepancy was 0.08--0.30 EDF units for Uniform and Exponential examples. The asymmetric Beta$(1,2)$ discrepancy was 0.27--0.33 at $n=50,100$ and 0.84 at $n=25$. This is adequate for the existing asymptotic EDF convention and does not -justify a gate-derivative correction. Pure-bulk fits retain the old EDF +justify a weight-derivative correction. Pure-bulk fits retain the old EDF exactly. ## Fit time Release builds were timed against `4f3d148`. Bulk-classified fits incur only -sorting and remained within about 3% of baseline for $n=100$--$2000$. Active -experts cost more because the concise implementation directly evaluates the -Gaussian kernels on the 401-point grid: +sorting and remain close to baseline. With a 401-point output grid, the +simplified active-expert timings are: | active endpoints | $n=100$ | $n=1000$ | $n=2000$ | |---|---:|---:|---:| -| one | 1.70 ms (4.4x) | 5.93 ms (12.4x) | 10.67 ms (18.5x) | -| two | 2.90 ms (7.5x) | 10.41 ms (23.5x) | 18.84 ms (36.7x) | +| one | 0.65 ms (1.7x) | 0.94 ms (2.0x) | 1.22 ms (2.1x) | +| two | 0.78 ms (2.0x) | 1.63 ms (3.7x) | 2.26 ms (4.4x) | -The absolute cost remains below 20 ms at $n=2000$. Keep the direct evaluator -for the first PR; optimize only if downstream profiling shows fit time is -material. +Relative to `cbde530`, this is a speedup of 2.6--8.7x for one active endpoint +and 3.7--8.3x for two. Absolute expert-fit cost remains below 2.3 ms at +$n=2000$ in this benchmark. ## Reproduction diff --git a/diagnostic/boundary-repair/HANDOFF.md b/diagnostic/boundary-repair/HANDOFF.md index 92a57ed..3d66ef0 100644 --- a/diagnostic/boundary-repair/HANDOFF.md +++ b/diagnostic/boundary-repair/HANDOFF.md @@ -4,9 +4,10 @@ The directory now contains one experimental estimator for continuous data with two known finite bounds. It fits the current probit bulk estimator once, -adds an equal local-linear/local-quadratic expert for confidently finite -endpoints, and otherwise reuses bulk. Smooth CDF-scale gates shrink as -$n^{-1/2}$. The finite-endpoint classifier uses +adds an averaged local-linear/local-quadratic kernel expert for confidently +finite endpoints, and otherwise reuses bulk. The kernels share one degree-2 +bandwidth and smooth CDF-scale weights shrink as $n^{-1/2}$. The +finite-endpoint classifier uses $k=\min(n-1,\lceil2\sqrt n\rceil)$ order statistics and a 95% decision. There is no exploding-tail expert, power warp, transformation offset, or CV @@ -33,7 +34,7 @@ as the first two arguments to either simulation script. - The R reference assumes support $[0,1]$; native code must apply an affine map for arbitrary finite bounds. - Weighted observations have not been specified or validated for the tail - index, weighted ranks, or shrinking gate. + index or shrinking weights. - The finite-versus-bulk decision is hard, so between-sample endpoint behavior can still change discretely. - Before release, test affine support changes, weaker and stronger endpoint diff --git a/diagnostic/boundary-repair/README.md b/diagnostic/boundary-repair/README.md index ee49a6c..0fbb4e6 100644 --- a/diagnostic/boundary-repair/README.md +++ b/diagnostic/boundary-repair/README.md @@ -8,7 +8,7 @@ current probit estimator, and the retained endpoint-classifier ablation. The reference implementation assumes the support has been mapped affinely to $[0,1]$. First fit the current unweighted probit estimator $\widehat f_B$ and -use its CDF to define sample-shrinking endpoint gates. With +use its CDF to define sample-shrinking endpoint weights. With $r_n=\min(0.25,n^{-1/2})$ and $s(t)=3t^2-2t^3$, $$ @@ -17,11 +17,12 @@ w_L(x)=1-s\left(\min\left\{1,\frac{\widehat F_B(x)}{r_n}\right\}\right), w_U(x)=1-s\left(\min\left\{1,\frac{1-\widehat F_B(x)}{r_n}\right\}\right), $$ -and $w_B(x)=1-w_L(x)-w_U(x)$. The finite-boundary expert is the -equal average of Gaussian equivalent-kernel local-linear and local-quadratic -estimates. Rank-based endpoint weights select their bandwidths, but density -contributions remain unweighted, so the estimand does not change. Negative -component values are truncated during normalization. +and $w_B(x)=1-w_L(x)-w_U(x)$. The finite-boundary expert averages Gaussian +equivalent-kernel local-linear and local-quadratic kernels using one degree-2 +bandwidth selected from all endpoint distances. Density contributions remain +unweighted, so the estimand does not change. The native evaluator computes the +expert only where its fusion weight is nonzero, truncates negative values, and +normalizes once after fusion. Finite endpoint behavior is identified from $k=\min(n-1,\lceil2\sqrt n\rceil)$ order statistics. At the lower endpoint, @@ -46,7 +47,7 @@ offset transform, oversmoothed tail expert, or cross-validation selector. ## Retained files -- `scripts/bounded_estimator.R`: self-contained R reference implementation. +- `scripts/bounded_estimator.R`: pre-native tuning implementation. - `scripts/validate_bounded_estimator.R`: paired validation against current. - `scripts/plot_bounded_estimator_validation.R`: numerical and realization report. diff --git a/diagnostic/one-sided-repair/HANDOFF.md b/diagnostic/one-sided-repair/HANDOFF.md index edf56af..be19ba3 100644 --- a/diagnostic/one-sided-repair/HANDOFF.md +++ b/diagnostic/one-sided-repair/HANDOFF.md @@ -3,10 +3,10 @@ The production branch already uses a scale-equivariant power-$3/4$ transform for one-sided supports. The diagnostic candidate keeps that estimator as the unweighted bulk and adds the selected two-boundary method's finite expert: -equal local-linear/local-quadratic estimates, a shrinking CDF gate, and a +an averaged local-linear/local-quadratic kernel, a shrinking CDF weight, and a $2\sqrt n$ order-statistic finite-versus-bulk decision. -The bandwidth floor is the unweighted bandwidth fitted to the lowest 75% of +The native kernels share the degree-2 bandwidth fitted to the lowest 75% of boundary distances. A 30-replication ablation compared fixed fractions from 15% through 100% and a $\sqrt n$ shrinking subset. Performance improved up to 75%; using all observations reversed the long-tail gains because remote Lomax diff --git a/diagnostic/one-sided-repair/NATIVE_CPP.md b/diagnostic/one-sided-repair/NATIVE_CPP.md index 1983ec9..745f051 100644 --- a/diagnostic/one-sided-repair/NATIVE_CPP.md +++ b/diagnostic/one-sided-repair/NATIVE_CPP.md @@ -41,7 +41,7 @@ the bulk grid: 2. return to the unchanged bulk path if no endpoint is confidently finite; 3. fit a boundary component only for each selected endpoint, using the existing original-scale grid; -4. form gate probabilities from the normalized bulk CDF; +4. form endpoint weights from the normalized bulk CDF; 5. fuse bulk and selected endpoint values and replace `grid_` with the normalized fused grid. @@ -50,7 +50,7 @@ log-likelihood code then operates on the fused grid. `bandwidth_` continues to report the bulk bandwidth. Boundary distances and local densities can stay in the original units. Every -classifier ratio is dimensionless, and both selected and floor bandwidths +classifier ratio is dimensionless, and the boundary bandwidths scale with the data, so this is equivalent to the R reference's affine map to $[0,1]$ without adding a second normalization path. @@ -95,14 +95,12 @@ The helper takes boundary distances, ascending evaluation distances, rank weights, a floor fraction, and degree one or two. - Select the weighted bandwidth with `PluginBandwidthSelector`. -- Select the unweighted floor bandwidth from the closest +- Select one unweighted degree-2 bandwidth from the closest $\max(4,\lceil q n\rceil)$ distances, where $q=0.75$ for one-sided support and $q=1$ for two-sided support. -- Use the maximum of the selected and floor bandwidths, then apply the public - multiplier. -- Use rank weights only for bandwidth selection. Evaluate density - contributions with equal observation weights so the estimand remains the - original density. +- Share it between the degree-one and degree-two kernels, then apply the public + multiplier. Evaluate density contributions with equal observation weights + so the estimand remains the original density. Construct the equivalent-kernel coefficients as the first row of the inverse truncated-normal moment matrix. Generate the moments with @@ -113,24 +111,20 @@ $$ \mu_j(a)=(j-1)\mu_{j-2}(a)-a^{j-1}\phi(a). $$ -This calculation covers degrees one and two more concisely than separate -determinant formulas. Clamp each component at zero, normalize it on the -distance grid, and average the degree-one and degree-two components. Return -both that density and its diagonal density response for the EDF calculation -described below; the response uses the same clamp mask and normalization as -the density. +Use the explicit degree-one and degree-two determinants to avoid a dynamic +matrix inverse at every evaluation point. Average the two kernels before +fusion, clamp negative values, and return both the density and its influence +numerator for the EDF calculation described below. -Start with direct $O(nm)$ Gaussian evaluation on the existing grid of -$m\approx401$ points. It follows the retained R references closely and avoids -a second interpolation grid or FFT-specific derivation. Benchmark before -considering an optimized implementation. +Evaluate directly only where the endpoint weight is nonzero. With ordered +distances, omit observations more than six bandwidths from an evaluation +point; the omitted Gaussian tail mass is below $2\times10^{-9}$. Normalize the +fused grid once at the end. ### 3. Boundary-repair coordinator -This helper owns endpoint distances, average ranks for ties, classification, -local component calls, CDF gates, reflection, and fusion. Use -`tools::get_order()` locally; do not add a general ranking API unless another -production caller needs it. +This helper owns endpoint distances, classification, local component calls, +CDF weights, reflection, and fusion. For an upper endpoint, compute on ascending reflected distances and reverse the component once. The floor fraction is the only local-component policy that @@ -139,7 +133,7 @@ differs between one- and two-sided support. The helper should return an empty result when every endpoint selects bulk. `Kde1d::fit()` can then leave the already constructed bulk grid untouched. -## Gate and fusion +## Weights and fusion Let $F_B(x)$ be the bulk CDF and @@ -161,7 +155,7 @@ $$ w_U(x)=1-s\left(\min\{1,(1-F_B(x))/q_n\}\right). $$ -Set the gate of every bulk-classified endpoint to zero. The final values are +Set the weight of every bulk-classified endpoint to zero. The final values are $$ \widehat f(x)= @@ -170,7 +164,7 @@ w_L(x)\widehat f_L(x) +w_U(x)\widehat f_U(x). $$ -With $q_n\leq0.25$, the endpoint gates do not overlap. The same expression +With $q_n\leq0.25$, the endpoint weights do not overlap. The same expression covers one-sided support by setting the absent endpoint weight to zero. Clamp the fused values at zero and construct a normalized `InterpolationGrid` on the existing original-scale grid. @@ -182,15 +176,14 @@ holds the selected bandwidth and final grid normalization fixed. Extend the same convention to expert selection and fusion rather than returning `NaN`. For a degree-$p$ boundary component, let $M_p(a)$ be the truncated-normal -moment matrix above, let $h_p$ be its final bandwidth, let $Z_p$ be the mass -used to normalize its nonnegative density, and let $\widetilde f_p$ denote its -value before clamping and normalization. Its diagonal density response is +moment matrix above, let $h$ be the shared bandwidth, and let +$\widetilde f_p$ denote its value before clamping. Its influence numerator is $$ -r_p(x)= -\frac{\mathbf 1\{\widetilde f_p(x)>0\}}{Z_p} -\frac{\phi(0)}{n h_p} -\left[M_p\{d(x)/h_p\}^{-1}\right]_{00}. +\nu_p(x)= +\mathbf 1\{\widetilde f_p(x)>0\} +\frac{\phi(0)}{n h} +\left[M_p\{d(x)/h\}^{-1}\right]_{00}. $$ Only the constant equivalent-kernel coefficient remains because a @@ -200,26 +193,26 @@ expert, use $$ f_E(x)=\frac{f_1(x)+f_2(x)}{2}, \qquad -r_E(x)=\frac{r_1(x)+r_2(x)}{2}. +\nu_E(x)=\frac{\nu_1(x)+\nu_2(x)}{2}. $$ For the bulk component, the existing influence column is its log-density -leverage $\ell_B(x)$, so its diagonal density response is -$r_B(x)=f_B(x)\ell_B(x)$. Fuse the responses with exactly the same gates as the -densities: +leverage $\ell_B(x)$, so its influence numerator is +$\nu_B(x)=f_B(x)\ell_B(x)$. Fuse the numerators with exactly the same weights +as the densities: $$ \begin{aligned} g(x)&=w_L(x)f_L(x) +\{1-w_L(x)-w_U(x)\}f_B(x)+w_U(x)f_U(x),\\ -r(x)&=w_L(x)r_L(x) - +\{1-w_L(x)-w_U(x)\}r_B(x)+w_U(x)r_U(x),\\ -\ell(x)&=\frac{r(x)}{g(x)}. +\nu(x)&=w_L(x)\nu_L(x) + +\{1-w_L(x)-w_U(x)\}\nu_B(x)+w_U(x)\nu_U(x),\\ +\ell(x)&=\frac{\nu(x)}{g(x)}. \end{aligned} $$ Thus the mixture leverage is weighted by local density shares, not just by -the gate values. Estimate +the fusion weights. Estimate $$ \operatorname{edf}=\sum_{i=1}^n @@ -227,10 +220,10 @@ $$ $$ retaining the current per-observation cap. The final common normalization of -$g$ and $r$ cancels in their ratio when its derivative is ignored. +$g$ and $\nu$ cancels in their ratio when its derivative is ignored. This approximation conditions on bandwidths, endpoint classifications, CDF -gates, clamp states, and normalization constants. It deliberately omits the +weights, clamp states, and normalization constants. It deliberately omits the derivatives of those data-adaptive choices. That keeps it consistent with the existing EDF convention and costs only additional grid-vector arithmetic; no refits or per-observation matrices are needed. Validate it diagnostically @@ -242,24 +235,23 @@ $$ $$ First confirm that this diagnostic reproduces the existing bulk EDF to the -expected approximation error. A gate-derivative correction is worth +expected approximation error. A weight-derivative correction is worth considering only if the active-expert comparison then shows an additional systematic discrepancy. ## Weights and remaining fit metadata -The experts' rank weights affect bandwidth selection only; density -contributions remain equally weighted, matching the validated estimand. The -first native implementation falls back to bulk when public case weights are -supplied because those weights genuinely change the estimand. Defining -weighted ranks, effective sample size, weighted tail indices, and weighted -confidence adjustments is a separate statistical task. +Expert density contributions remain equally weighted, matching the validated +estimand. The native implementation falls back to bulk when public case +weights are supplied because those weights genuinely change the estimand. +Defining effective sample size, weighted tail indices, and weighted confidence +adjustments is a separate statistical task. Recompute `loglik_` from the final grid using the existing code. Use the conditional mixture trace above for `edf_` whenever a finite expert is active, and retain the current calculation unchanged for pure-bulk fits. -No classifier choice, tail index, boundary bandwidth, or gate state needs to +No classifier choice, tail index, boundary bandwidth, or weight state needs to persist in the fitted object for the first implementation. Diagnostic values belong in tests and validation scripts rather than the public class layout. @@ -271,7 +263,7 @@ The intended implementation footprint is: - preserve original-scale cleaned observations; - add the three private helpers; - call the coordinator after bulk-grid construction; - - carry the bulk and expert diagonal responses through fusion for EDF. + - carry the bulk and expert influence numerators through fusion for EDF. 2. `test/test.cpp` - deterministic golden results and fallback behavior. 3. `test/test_numerical_invariants.cpp` @@ -317,18 +309,17 @@ the initial implementation remains reviewable. ### Public case weights -Public case weights change the target density, unlike the endpoint-targeting -weights used only to select expert bandwidths. A weighted expert should -therefore use public case weights for density contributions and use the product -of public and endpoint-targeting weights for bandwidth selection. Before -activation, compare and validate choices for: +Public case weights change the target density. A weighted expert should +therefore use public case weights for density contributions and define the +bandwidth subset by cumulative public weight. Before activation, compare and +validate choices for: -- weighted average ranks and endpoint distances; +- weighted endpoint distances; - effective sample size in $k$, $q_n$, and the classifier confidence term; - a weighted order-statistic tail index; - defining the closest 75% floor by cumulative public weight rather than row count; -- weighted diagonal responses and EDF validation. +- weighted influence numerators and EDF validation. Experiments should include highly unequal weights, weights concentrated near and far from the boundary, zero weights, global rescaling of all weights, and diff --git a/diagnostic/one-sided-repair/README.md b/diagnostic/one-sided-repair/README.md index 1fa174d..41b2b56 100644 --- a/diagnostic/one-sided-repair/README.md +++ b/diagnostic/one-sided-repair/README.md @@ -9,15 +9,16 @@ with exactly one known finite endpoint. It is deliberately separate from The power-$3/4$ transformation estimator is the unweighted bulk fit. A single order-statistic tail index classifies the finite endpoint using $k=\min(n-1,\lceil2\sqrt n\rceil)$ and the same 95% rule as in the -two-boundary estimator. A confidently finite endpoint receives the equal -local-linear/local-quadratic expert; exploding, vanishing, and ambiguous +two-boundary estimator. A confidently finite endpoint receives the averaged +local-linear/local-quadratic kernel expert; exploding, vanishing, and ambiguous endpoints reuse bulk. -The boundary expert is blended with bulk through a smooth gate based on the -bulk CDF, with boundary probability $\min(0.25,n^{-1/2})$. Its local-polynomial -bandwidth is floored at the unweighted bandwidth fitted to the lowest 75% of -boundary distances. This preserves the stabilizing information in most of the -sample without allowing the most remote observations to dominate the floor. +The boundary expert is blended with bulk through a smooth weight based on the +bulk CDF, with boundary probability $\min(0.25,n^{-1/2})$. Both kernels share +the degree-2 bandwidth fitted to the closest 75% of boundary distances. The +native evaluator only computes expert values where this weight is nonzero and +normalizes once after fusion. This preserves the stabilizing information in +most of the sample without allowing the most remote observations to dominate. The construction is reflection- and scale-equivariant. The validation suite uses 30 paired replications at $n=100,1000$ for @@ -27,7 +28,7 @@ have been removed. ## Files -- `scripts/one_sided_estimator.R`: current R reference implementation. +- `scripts/one_sided_estimator.R`: pre-native tuning implementation. - `scripts/ablate_local_floor_fraction.R`: selected floor-fraction ablation. - `scripts/plot_local_floor_fraction_ablation.R`: tuning curves and example estimates. diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 36fe127..f979a77 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -194,9 +194,7 @@ class Kde1d bool is_finite_endpoint(Eigen::VectorXd dist) const; BoundaryComponent fit_boundary_component(const Eigen::VectorXd& dist, const Eigen::VectorXd& eval_dist, - const Eigen::VectorXd& bw_weights, - double floor_fraction, - size_t degree) const; + double bandwidth) const; void repair_boundaries(const Eigen::VectorXd& x, const Eigen::VectorXd& grid, Eigen::VectorXd& influences); @@ -987,89 +985,75 @@ Kde1d::is_finite_endpoint(Eigen::VectorXd dist) const return beta >= 0.9 && beta * (1.0 - 1.6448536269514722 / std::sqrt(k)) <= 1.0; } -//! Fits a degree-@f$p@f$ Gaussian local-polynomial component from sample -//! distances @f$d@f$ to endpoint-distance grid @f$t@f$. With bandwidth -//! @f$h@f$, truncated Gaussian moments @f$\mu_r(a)@f$, and -//! @f$M_p(a) = [\mu_{j+k}(a)]_{j,k=0}^p@f$, the equivalent-kernel estimate is +//! Fits the average of Gaussian local-linear and local-quadratic equivalent +//! kernels from sample distances @f$d@f$ to endpoint-distance grid @f$t@f$. +//! For degree @f$p@f$, shared bandwidth @f$h@f$, truncated Gaussian moments +//! @f$\mu_r(a)@f$, and @f$M_p(a)=[\mu_{j+k}(a)]_{j,k=0}^p@f$, //! @f[ //! \begin{align*} //! a &= t/h, & u_i &= (t-d_i)/h, \\[2pt] -//! \widehat f_p(t) +//! \widehat f_p(t;h) //! &= \frac{1}{nh}\sum_{i=1}^n \phi(u_i)\, -//! e_0^\mathsf{T} M_p(a)^{-1}(1,u_i,\ldots,u_i^p)^\mathsf{T}, \\[2pt] -//! \nu_p(t) &= \frac{\phi(0)}{nh} -//! e_0^\mathsf{T}M_p(a)^{-1}e_0. +//! e_0^\mathsf{T}M_p(a)^{-1} +//! (1,u_i,\ldots,u_i^p)^\mathsf{T}, \\[2pt] +//! \widehat f_\partial(t) +//! &= \{\widehat f_1(t;h)+\widehat f_2(t;h)\}/2. //! \end{align*} //! @f] -//! Targeting weights select @f$h@f$ only, so observations contribute equally -//! and the density estimand is unchanged. The influence numerator -//! @f$\nu_p(t)@f$ is the diagonal kernel contribution; dividing it by -//! @f$\widehat f_p(t)@f$ gives the pointwise influence used for EDF. -//! @param dist distances of the observations from the support endpoint. +//! Observations contribute equally to both kernels. The returned influence +//! numerator is the corresponding average diagonal kernel contribution. +//! @param dist ordered distances of the observations from the support endpoint. //! @param eval_dist endpoint distances at which to evaluate the component. -//! @param bw_weights targeting weights used only for bandwidth selection. -//! @param floor_fraction fraction of the closest observations used to select -//! the bandwidth floor. -//! @param degree local-polynomial degree. -//! @return the normalized density and influence numerator on `eval_dist`; an -//! empty component indicates numerical failure. +//! @param bandwidth shared bandwidth of both equivalent kernels. +//! @return the density and influence numerator on `eval_dist`. inline Kde1d::BoundaryComponent Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, const Eigen::VectorXd& eval_dist, - const Eigen::VectorXd& bw_weights, - double floor_fraction, - size_t degree) const + double bandwidth) const { - bandwidth::PluginBandwidthSelector selector(dist, bw_weights); - double h = selector.select_bandwidth(degree); - - // Floor h with a selector on the closest observations to stabilize the fit. - Eigen::VectorXd dist_sorted = dist; - std::sort(dist_sorted.data(), dist_sorted.data() + dist_sorted.size()); - const Eigen::Index n_floor = std::min( - dist.size(), - std::max( - 4, static_cast(std::ceil(floor_fraction * dist.size())))); - bandwidth::PluginBandwidthSelector floor_selector(dist_sorted.head(n_floor)); - h = std::max(h, floor_selector.select_bandwidth(degree)) * multiplier_; + const double h = bandwidth; if (!(h > 0.0) || !std::isfinite(h)) return {}; BoundaryComponent fit{ Eigen::VectorXd(eval_dist.size()), Eigen::VectorXd(eval_dist.size()) }; for (Eigen::Index j = 0; j < eval_dist.size(); ++j) { - // a = t/h truncates the kernel; mu stores its moments up to order 2p. + // c1 and c2 are the first inverse-moment rows for degrees 1 and 2. const double a = eval_dist(j) / h; - const double phi_a = K0_ * std::exp(-0.5 * a * a); - Eigen::VectorXd mu(2 * degree + 1); - mu(0) = stats::pnorm(Eigen::VectorXd::Constant(1, a))(0); - mu(1) = -phi_a; - for (size_t order = 2; order < static_cast(mu.size()); ++order) { - mu(order) = - (order - 1.0) * mu(order - 2) - std::pow(a, order - 1) * phi_a; - } - - // M is the moment matrix; c, its first inverse row, gives the kernel. - Eigen::MatrixXd M(degree + 1, degree + 1); - for (size_t column = 0; column <= degree; ++column) { - for (size_t row = 0; row <= degree; ++row) - M(row, column) = mu(row + column); - } - const Eigen::VectorXd c = M.inverse().row(0); + const double phi = K0_ * std::exp(-0.5 * a * a); + const double mu0 = 0.5 * std::erfc(-a * 0.7071067811865475); + const double mu1 = -phi; + const double mu2 = mu0 - a * phi; + const double mu3 = -(a * a + 2.0) * phi; + const double mu4 = 3.0 * mu0 - (a * a * a + 3.0 * a) * phi; + const double det1 = mu0 * mu2 - mu1 * mu1; + const double c10 = mu2 / det1; + const double c11 = -mu1 / det1; + const double det2 = mu0 * (mu2 * mu4 - mu3 * mu3) - + mu1 * (mu1 * mu4 - mu2 * mu3) + + mu2 * (mu1 * mu3 - mu2 * mu2); + const double c20 = (mu2 * mu4 - mu3 * mu3) / det2; + const double c21 = (mu2 * mu3 - mu1 * mu4) / det2; + const double c22 = (mu1 * mu3 - mu2 * mu2) / det2; double f = 0.0; - for (Eigen::Index i = 0; i < dist.size(); ++i) { - const double u = (eval_dist(j) - dist(i)) / h; - double p_u = c(degree); - for (size_t order = degree; order > 0; --order) - p_u = p_u * u + c(order - 1); - f += K0_ * std::exp(-0.5 * u * u) * p_u; + // Six Gaussian standard deviations leave less than 2e-9 tail mass. + const double radius = 6.0 * h; + const double* first = std::lower_bound( + dist.data(), dist.data() + dist.size(), eval_dist(j) - radius); + const double* last = std::upper_bound( + dist.data(), dist.data() + dist.size(), eval_dist(j) + radius); + for (const double* value = first; value != last; ++value) { + const double u = (eval_dist(j) - *value) / h; + f += K0_ * std::exp(-0.5 * u * u) * + (c10 + c11 * u + c20 + (c21 + c22 * u) * u) / h; } - fit.density(j) = f / (static_cast(dist.size()) * h); - fit.influence_num(j) = K0_ * c(0) / (static_cast(dist.size()) * h); + fit.density(j) = f / (2.0 * static_cast(dist.size())); + fit.influence_num(j) = + K0_ * (c10 + c20) / (2.0 * static_cast(dist.size()) * h); } - // Remove unstable local-polynomial values, then normalize on the grid. + // Remove unstable local-polynomial values. for (Eigen::Index j = 0; j < fit.density.size(); ++j) { if (!(fit.density(j) > 0.0) || !std::isfinite(fit.density(j)) || !std::isfinite(fit.influence_num(j))) { @@ -1077,23 +1061,15 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, fit.influence_num(j) = 0.0; } } - double mass = 0.0; - for (Eigen::Index j = 0; j < fit.density.size() - 1; ++j) { - mass += (eval_dist(j + 1) - eval_dist(j)) * - (fit.density(j) + fit.density(j + 1)) / 2.0; - } - if (!(mass > 0.0) || !std::isfinite(mass)) - return {}; - fit.density /= mass; - fit.influence_num /= mass; return fit; } //! Fuses the transformed bulk density @f$\widehat f_B@f$ with endpoint //! densities @f$\widehat f_L@f$ and @f$\widehat f_U@f$. Each endpoint density -//! is the average of a local-linear and a local-quadratic estimate. Smooth -//! weights @f$w_L@f$ and @f$w_U@f$ are functions of the bulk CDF and shrink at -//! rate @f$\min(1/4,n^{-1/2})@f$: +//! averages local-linear and local-quadratic kernels using one degree-2 +//! bandwidth, selected from all distances on bounded support and the closest +//! 75% on one-sided support. Smooth weights @f$w_L@f$ and @f$w_U@f$ are +//! functions of the bulk CDF and shrink at rate @f$\min(1/4,n^{-1/2})@f$: //! @f[ //! \begin{align*} //! q &= \min(1/4,n^{-1/2}), & z(p) &= \min(1,p/q), \\[2pt] @@ -1138,74 +1114,57 @@ Kde1d::repair_boundaries(const Eigen::VectorXd& x, const double z = std::min(1.0, probability / q); return 1.0 - (3.0 * z * z - 2.0 * z * z * z); }; - // Mid-rank weights target endpoint observations during bandwidth selection. - auto targeting_weights = [&](const Eigen::VectorXd& dist) { - Eigen::VectorXd weights(dist.size()); - const Eigen::VectorXi order = tools::get_order(dist); - Eigen::Index first = 0; - while (first < order.size()) { - Eigen::Index last = first; - while (last + 1 < order.size() && - dist(order(last + 1)) == dist(order(first))) - ++last; - const double probability = static_cast(first + last + 1) / - (2.0 * static_cast(dist.size())); - for (Eigen::Index i = first; i <= last; ++i) - weights(order(i)) = endpoint_weight(probability); - first = last + 1; - } - return weights; - }; - // The bandwidth floor uses all data on bounded support and 75% otherwise. - const double floor_fraction = + // Only evaluate endpoint fits where their fusion weights are nonzero. + const Eigen::VectorXd f_bulk = grid_.get_values(); + const Eigen::VectorXd bulk_cdf = grid_.integrate(grid, true); + Eigen::VectorXd w_l = Eigen::VectorXd::Zero(grid.size()); + Eigen::VectorXd w_u = Eigen::VectorXd::Zero(grid.size()); + for (Eigen::Index j = 0; j < grid.size(); ++j) { + if (repair_lower) + w_l(j) = endpoint_weight(bulk_cdf(j)); + if (repair_upper) + w_u(j) = endpoint_weight(1.0 - bulk_cdf(j)); + } + const Eigen::Index n_lower = (w_l.array() > 0.0).count(); + const Eigen::Index n_upper = (w_u.array() > 0.0).count(); + + // Select one shared degree-2 bandwidth, using the local 75% one-sided rule. + const double bw_fraction = (!std::isnan(xmin_) && !std::isnan(xmax_)) ? 1.0 : 0.75; + Eigen::VectorXd bw_dist = repair_lower ? dist_lower : dist_upper; + std::sort(bw_dist.data(), bw_dist.data() + bw_dist.size()); + const Eigen::Index n_bw = std::min( + bw_dist.size(), + std::max( + 4, static_cast(std::ceil(bw_fraction * bw_dist.size())))); + bandwidth::PluginBandwidthSelector selector(bw_dist.head(n_bw)); + const double h = selector.select_bandwidth(2) * multiplier_; + auto fit_endpoint = [&](const Eigen::VectorXd& dist, const Eigen::VectorXd& eval_dist) { - const Eigen::VectorXd bw_weights = targeting_weights(dist); - // Averaging orders one and two gives a smoother, more stable endpoint. - BoundaryComponent linear = - fit_boundary_component(dist, eval_dist, bw_weights, floor_fraction, 1); - BoundaryComponent quadratic = - fit_boundary_component(dist, eval_dist, bw_weights, floor_fraction, 2); - if (linear.density.size() == 0 || quadratic.density.size() == 0) - return BoundaryComponent{}; - linear.density = (linear.density + quadratic.density) / 2.0; - linear.influence_num = - (linear.influence_num + quadratic.influence_num) / 2.0; - return linear; + Eigen::VectorXd dist_sorted = dist; + std::sort(dist_sorted.data(), dist_sorted.data() + dist_sorted.size()); + return fit_boundary_component(dist_sorted, eval_dist, h); }; BoundaryComponent lower; BoundaryComponent upper; + repair_lower = repair_lower && n_lower > 0; + repair_upper = repair_upper && n_upper > 0; if (repair_lower) { - lower = fit_endpoint(dist_lower, grid.array() - xmin_); + lower = fit_endpoint(dist_lower, grid.head(n_lower).array() - xmin_); repair_lower = lower.density.size() > 0; } if (repair_upper) { - Eigen::VectorXd upper_eval_dist = (xmax_ - grid.array()).reverse(); + Eigen::VectorXd upper_eval_dist = + (xmax_ - grid.tail(n_upper).array()).reverse(); upper = fit_endpoint(dist_upper, upper_eval_dist); repair_upper = upper.density.size() > 0; - if (repair_upper) { - upper.density.reverseInPlace(); - upper.influence_num.reverseInPlace(); - } } if (!repair_lower && !repair_upper) return; - // f_bulk and bulk_cdf determine the fused density and endpoint weights. - const Eigen::VectorXd f_bulk = grid_.get_values(); - const Eigen::VectorXd bulk_cdf = grid_.integrate(grid, true); - Eigen::VectorXd w_l = Eigen::VectorXd::Zero(grid.size()); - Eigen::VectorXd w_u = Eigen::VectorXd::Zero(grid.size()); - for (Eigen::Index j = 0; j < grid.size(); ++j) { - if (repair_lower) - w_l(j) = endpoint_weight(bulk_cdf(j)); - if (repair_upper) - w_u(j) = endpoint_weight(1.0 - bulk_cdf(j)); - } - // Fuse densities and influence numerators with the same weights. Eigen::VectorXd f(grid.size()); Eigen::VectorXd infl_num(grid.size()); @@ -1213,13 +1172,14 @@ Kde1d::repair_boundaries(const Eigen::VectorXd& x, const double w_b = 1.0 - w_l(j) - w_u(j); f(j) = w_b * f_bulk(j); infl_num(j) = w_b * f_bulk(j) * influences(j); - if (repair_lower) { + if (w_l(j) > 0.0) { f(j) += w_l(j) * lower.density(j); infl_num(j) += w_l(j) * lower.influence_num(j); } - if (repair_upper) { - f(j) += w_u(j) * upper.density(j); - infl_num(j) += w_u(j) * upper.influence_num(j); + if (w_u(j) > 0.0) { + const Eigen::Index upper_j = grid.size() - 1 - j; + f(j) += w_u(j) * upper.density(upper_j); + infl_num(j) += w_u(j) * upper.influence_num(upper_j); } influences(j) = f(j) > 0.0 ? infl_num(j) / f(j) : 0.0; } diff --git a/test/test.cpp b/test/test.cpp index 2a8e47d..a61d7f5 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -148,8 +148,8 @@ TEST_CASE("one-sided finite endpoints use the boundary expert", CHECK((fit.get_values() - bulk.get_values()).cwiseAbs().maxCoeff() > 0.01); Eigen::VectorXd expected_density(6); - expected_density << 0.9905722, 0.9905911, 0.9885084, 0.9473293, 0.7314338, - 0.0077356; + expected_density << 0.9884817, 0.9885018, 0.9865198, 0.9465577, 0.7315411, + 0.0077367; Eigen::VectorXd selected_density(6); selected_density << fit.get_values()(0), fit.get_values()(4), fit.get_values()(24), fit.get_values()(49), fit.get_values()(99), @@ -194,8 +194,8 @@ TEST_CASE("two-sided finite endpoints use the boundary experts", CHECK((fit.get_values() - bulk.get_values()).cwiseAbs().maxCoeff() > 0.01); Eigen::VectorXd expected_density(6); - expected_density << 1.0368661, 1.0367788, 1.0250191, 0.9972352, 1.0231640, - 1.0368661; + expected_density << 0.9993158, 0.9992803, 0.9985546, 1.0001208, 0.9985473, + 0.9993158; Eigen::VectorXd selected_density(6); selected_density << fit.get_values()(0), fit.get_values()(49), fit.get_values()(99), fit.get_values()(199), fit.get_values()(299), @@ -223,7 +223,7 @@ TEST_CASE("two-sided endpoints are classified independently", fit.fit(observations); Eigen::VectorXd expected_density(6); - expected_density << 1.9952890, 1.9913280, 1.9839701, 0.9946680, 0.0562144, + expected_density << 1.9984196, 1.9944352, 1.9846050, 0.9946111, 0.0562112, 0.0000020; Eigen::VectorXd selected_density(6); selected_density << fit.get_values()(0), fit.get_values()(49), From 75409b92c97b0d3a4916fba55c7bea512ef5a277 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 18:18:07 +0200 Subject: [PATCH 11/25] Speed up boundary kernels with FFT --- diagnostic/NATIVE_RESULTS.md | 26 ++++++++++++++++ include/kde1d/kde1d.hpp | 58 ++++++++++++++++++++++++++---------- test/test.cpp | 8 +++-- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/diagnostic/NATIVE_RESULTS.md b/diagnostic/NATIVE_RESULTS.md index 18cd011..f39455f 100644 --- a/diagnostic/NATIVE_RESULTS.md +++ b/diagnostic/NATIVE_RESULTS.md @@ -100,6 +100,32 @@ Relative to `cbde530`, this is a speedup of 2.6--8.7x for one active endpoint and 3.7--8.3x for two. Absolute expert-fit cost remains below 2.3 ms at $n=2000$ in this benchmark. +### FFT evaluation + +The endpoint kernel can be written as a pointwise combination of an ordinary +Gaussian KDE and its first two derivatives. The implementation now evaluates +these three translation-invariant convolutions on a regular 256-bin grid and +interpolates them to the endpoint grid. + +Against the direct endpoint evaluator, total fit times with the default +401-point grid were: + +| active endpoints | $n$ | direct | FFT | speedup | +|---|---:|---:|---:|---:| +| one | 1000 | 0.93 ms | 0.78 ms | 1.19x | +| one | 2000 | 1.21 ms | 0.92 ms | 1.32x | +| two | 1000 | 1.62 ms | 0.84 ms | 1.93x | +| two | 2000 | 2.25 ms | 0.96 ms | 2.35x | + +The direct-kernel fallback was removed after a separate $n=25,100$ benchmark. +Across 51--401 grid points, the worst total-fit slowdown from always using FFT +was 1.25x. With the default grid at $n=100$, one endpoint slowed from 0.64 to +0.67 ms while two endpoints improved slightly from 0.77 to 0.74 ms. In the +100-replication validation suite, the mean relative ISE perturbation from FFT +binning was at most 0.011% for every support/sample-size group. Among fits +whose endpoint expert was active, the median absolute paired ISE change was +0.023%, the 99th percentile was 0.18%, and the maximum was 0.66%. + ## Reproduction Install the package with a clean native rebuild at each revision and run diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index f979a77..2f3e7e5 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -1000,6 +1000,17 @@ Kde1d::is_finite_endpoint(Eigen::VectorXd dist) const //! &= \{\widehat f_1(t;h)+\widehat f_2(t;h)\}/2. //! \end{align*} //! @f] +//! Writing @f$f^{(r)}@f$ for the @f$r@f$th derivative of the ordinary +//! Gaussian KDE and @f$c_{pj}@f$ for the entries of the first row of +//! @f$M_p(a)^{-1}@f$, the same estimator is +//! @f[ +//! \begin{align*} +//! \widehat f_\partial(t) +//! &= \frac{1}{2}\{(c_{10}+c_{20}+c_{22})f(t) +//! -h(c_{11}+c_{21})f^{(1)}(t)+h^2c_{22}f^{(2)}(t)\}. +//! \end{align*} +//! @f] +//! This identity evaluates the three convolutions by FFT. //! Observations contribute equally to both kernels. The returned influence //! numerator is the corresponding average diagonal kernel contribution. //! @param dist ordered distances of the observations from the support endpoint. @@ -1015,8 +1026,29 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, if (!(h > 0.0) || !std::isfinite(h)) return {}; - BoundaryComponent fit{ Eigen::VectorXd(eval_dist.size()), - Eigen::VectorXd(eval_dist.size()) }; + BoundaryComponent fit{ Eigen::VectorXd::Zero(eval_dist.size()), + Eigen::VectorXd::Zero(eval_dist.size()) }; + if (eval_dist.size() == 0) + return fit; + + // Compute the ordinary Gaussian KDE and its first two derivatives on a + // regular grid, then interpolate them to the endpoint grid. + const double fft_upper = eval_dist(eval_dist.size() - 1) + 6.0 * h; + const double* last = + std::upper_bound(dist.data(), dist.data() + dist.size(), fft_upper); + const Eigen::Index n_fft = last - dist.data(); + if (n_fft == 0) + return fit; + + // This resolution kept the worst paired ISE perturbation below 0.7%. + const size_t num_bins = 256; + fft::KdeFFT kde_fft( + dist.head(n_fft), h, 0.0, fft_upper, Eigen::VectorXd(), num_bins); + const double scale = + static_cast(n_fft) / static_cast(dist.size()); + const Eigen::VectorXd f0 = scale * kde_fft.kde_drv(0); + const Eigen::VectorXd f1 = scale * kde_fft.kde_drv(1); + const Eigen::VectorXd f2 = scale * kde_fft.kde_drv(2); for (Eigen::Index j = 0; j < eval_dist.size(); ++j) { // c1 and c2 are the first inverse-moment rows for degrees 1 and 2. const double a = eval_dist(j) / h; @@ -1036,19 +1068,15 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, const double c21 = (mu2 * mu3 - mu1 * mu4) / det2; const double c22 = (mu1 * mu3 - mu2 * mu2) / det2; - double f = 0.0; - // Six Gaussian standard deviations leave less than 2e-9 tail mass. - const double radius = 6.0 * h; - const double* first = std::lower_bound( - dist.data(), dist.data() + dist.size(), eval_dist(j) - radius); - const double* last = std::upper_bound( - dist.data(), dist.data() + dist.size(), eval_dist(j) + radius); - for (const double* value = first; value != last; ++value) { - const double u = (eval_dist(j) - *value) / h; - f += K0_ * std::exp(-0.5 * u * u) * - (c10 + c11 * u + c20 + (c21 + c22 * u) * u) / h; - } - fit.density(j) = f / (2.0 * static_cast(dist.size())); + const double position = eval_dist(j) * num_bins / fft_upper; + const size_t bin = std::min(static_cast(position), num_bins - 1); + const double fraction = position - static_cast(bin); + auto interpolate = [&](const Eigen::VectorXd& values) { + return (1.0 - fraction) * values(bin) + fraction * values(bin + 1); + }; + fit.density(j) = + 0.5 * ((c10 + c20 + c22) * interpolate(f0) - + h * (c11 + c21) * interpolate(f1) + h * h * c22 * interpolate(f2)); fit.influence_num(j) = K0_ * (c10 + c20) / (2.0 * static_cast(dist.size()) * h); } diff --git a/test/test.cpp b/test/test.cpp index a61d7f5..75c684e 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -119,10 +119,14 @@ TEST_CASE("boundary grids resolve the transformed support", "[boundary-grid]") TEST_CASE("one-boundary fits are reflection equivariant", "[boundary-reflection]") { Eigen::VectorXd observations = Eigen::VectorXd::LinSpaced(500, 0.01, 5.0); - Kde1d left_bounded(0.0, NAN, "continuous", 1.0, 0.5); + Kde1d left_bounded(0.0, NAN, "continuous"); left_bounded.fit(observations); + Kde1d bulk(0.0, NAN, "continuous", 1.0, left_bounded.get_bandwidth()); + bulk.fit(observations); + CHECK((left_bounded.get_values() - bulk.get_values()).cwiseAbs().maxCoeff() > + 0.01); - Kde1d right_bounded(NAN, 0.0, "continuous", 1.0, 0.5); + Kde1d right_bounded(NAN, 0.0, "continuous"); right_bounded.fit(-observations); CHECK(left_bounded.get_grid_points().isApprox( From 8c49a1f247d1b11043258b254049525c720ee2ad Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 19:31:51 +0200 Subject: [PATCH 12/25] Support manual bandwidth boundary repair --- include/kde1d/kde1d.hpp | 7 +++---- test/test.cpp | 20 +++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 2f3e7e5..e3794cb 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -342,13 +342,12 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) Eigen::VectorXd w = weights; tools::remove_nans(xx, w); - // Nonconstant case weights and manual bandwidths need separate expert - // semantics; constant weights are equivalent to an unweighted sample. + // Nonconstant case weights need separate expert semantics; constant weights + // are equivalent to an unweighted sample. const bool unweighted = w.size() == 0 || w.minCoeff() == w.maxCoeff(); const bool use_boundary_repair = type_ == VarType::continuous && xx.size() >= 16 && unweighted && - std::isnan(bandwidth_spec_) && degree_ == 2 && - (!std::isnan(xmin_) || !std::isnan(xmax_)); + degree_ == 2 && (!std::isnan(xmin_) || !std::isnan(xmax_)); Eigen::VectorXd boundary_observations; if (use_boundary_repair) boundary_observations = xx; diff --git a/test/test.cpp b/test/test.cpp index 75c684e..fa574ff 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -121,10 +121,9 @@ TEST_CASE("one-boundary fits are reflection equivariant", "[boundary-reflection] Eigen::VectorXd observations = Eigen::VectorXd::LinSpaced(500, 0.01, 5.0); Kde1d left_bounded(0.0, NAN, "continuous"); left_bounded.fit(observations); - Kde1d bulk(0.0, NAN, "continuous", 1.0, left_bounded.get_bandwidth()); - bulk.fit(observations); - CHECK((left_bounded.get_values() - bulk.get_values()).cwiseAbs().maxCoeff() > - 0.01); + Kde1d manual(0.0, NAN, "continuous", 1.0, left_bounded.get_bandwidth()); + manual.fit(observations); + CHECK(left_bounded.get_values().isApprox(manual.get_values(), 1e-12)); Kde1d right_bounded(NAN, 0.0, "continuous"); right_bounded.fit(-observations); @@ -146,10 +145,9 @@ TEST_CASE("one-sided finite endpoints use the boundary expert", Kde1d fit(0.0, NAN, "continuous"); fit.fit(observations); - // A manual fit with the selected bulk bandwidth bypasses boundary repair. - Kde1d bulk(0.0, NAN, "continuous", 1.0, fit.get_bandwidth()); - bulk.fit(observations); - CHECK((fit.get_values() - bulk.get_values()).cwiseAbs().maxCoeff() > 0.01); + Kde1d manual(0.0, NAN, "continuous", 1.0, fit.get_bandwidth()); + manual.fit(observations); + CHECK(fit.get_values().isApprox(manual.get_values(), 1e-12)); Eigen::VectorXd expected_density(6); expected_density << 0.9884817, 0.9885018, 0.9865198, 0.9465577, 0.7315411, @@ -193,9 +191,9 @@ TEST_CASE("two-sided finite endpoints use the boundary experts", Kde1d fit(0.0, 1.0, "continuous"); fit.fit(observations); - Kde1d bulk(0.0, 1.0, "continuous", 1.0, fit.get_bandwidth()); - bulk.fit(observations); - CHECK((fit.get_values() - bulk.get_values()).cwiseAbs().maxCoeff() > 0.01); + Kde1d manual(0.0, 1.0, "continuous", 1.0, fit.get_bandwidth()); + manual.fit(observations); + CHECK(fit.get_values().isApprox(manual.get_values(), 1e-12)); Eigen::VectorXd expected_density(6); expected_density << 0.9993158, 0.9992803, 0.9985546, 1.0001208, 0.9985473, From 7c51bfcd05b3292e645b020146f19497d2e8a3f7 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 19:34:36 +0200 Subject: [PATCH 13/25] Support weighted boundary repair --- diagnostic/one-sided-repair/NATIVE_CPP.md | 126 +++++++--------- include/kde1d/kde1d.hpp | 174 +++++++++++++++------- test/test.cpp | 43 +++++- 3 files changed, 209 insertions(+), 134 deletions(-) diff --git a/diagnostic/one-sided-repair/NATIVE_CPP.md b/diagnostic/one-sided-repair/NATIVE_CPP.md index 745f051..76a351c 100644 --- a/diagnostic/one-sided-repair/NATIVE_CPP.md +++ b/diagnostic/one-sided-repair/NATIVE_CPP.md @@ -13,24 +13,20 @@ path: The existing transformed estimator remains the bulk component in both cases. Unbounded continuous, discrete, and zero-inflated behavior remains unchanged. -The first native version should activate only for samples of at least 16 -observations, unweighted or constant-weight fits, an automatically selected -bandwidth, and the default degree two. Nonconstant weighted fits, explicit -bandwidths, and nondefault degrees retain the current estimator until -their expert semantics have been specified and validated. This is the first -implementation milestone, not the intended final support boundary: experiments -and subsequent activation for weighted and manual-bandwidth fits are important -follow-up work. Keep the bandwidth multiplier supported immediately by -applying it to every expert bandwidth after selection and flooring. +The production estimator activates for degree-two continuous fits with at least +16 observations and effective sample size at least 16. Public case weights and +manual bandwidths are supported. Nondefault degrees retain the transformed +bulk estimator pending separate evaluation. Apply the bandwidth multiplier to +every expert bandwidth after selection and flooring. Do not add a public method switch or another fitted-object representation. ## Minimal integration point Call the repair coordinator only when `type_ == VarType::continuous`, at least -one support bound is finite, at least 16 cleaned observations remain, case -weights are absent or constant, `bandwidth_spec_` is `NaN`, and `degree_ == 2`. -This makes every initial fallback condition explicit at a single call site. +one support bound is finite, at least 16 cleaned observations remain, and +`degree_ == 2`. The coordinator additionally retains the bulk fit when the +effective sample size is below 16. Keep the current body of `Kde1d::fit()` through construction of the normalized bulk `InterpolationGrid`. Preserve the cleaned observations on their original @@ -241,11 +237,13 @@ systematic discrepancy. ## Weights and remaining fit metadata -Expert density contributions remain equally weighted, matching the validated -estimand. The native implementation falls back to bulk when public case -weights are supplied because those weights genuinely change the estimand. -Defining effective sample size, weighted tail indices, and weighted confidence -adjustments is a separate statistical task. +Expert density contributions use the normalized public case weights, matching +the weighted bulk estimand. Effective sample size determines the minimum sample +check, fusion width, tail order, and classifier confidence. The weighted +classifier uses a conservative lower threshold of 0.975. The one-sided +bandwidth uses the closest 75% of positive-weight observations by row count and +passes their case weights to the plug-in selector. The influence numerator uses +the local average case weight on the FFT grid. Recompute `loglik_` from the final grid using the existing code. Use the conditional mixture trace above for `edf_` whenever a finite expert is active, @@ -300,63 +298,43 @@ public getters unless implementation evidence shows that it is necessary. Each step should be a separately testable commit. Avoid refactoring unrelated fit logic while implementing the method. -## Important follow-up: weights and manual bandwidths - -Do not close the estimator work after the initial unweighted, automatic- -bandwidth activation. Keep the following experiments and production activation -as explicit roadmap items, preferably in follow-up commits or a follow-up PR so -the initial implementation remains reviewable. - -### Public case weights - -Public case weights change the target density. A weighted expert should -therefore use public case weights for density contributions and define the -bandwidth subset by cumulative public weight. Before activation, compare and -validate choices for: - -- weighted endpoint distances; -- effective sample size in $k$, $q_n$, and the classifier confidence term; -- a weighted order-statistic tail index; -- defining the closest 75% floor by cumulative public weight rather than row - count; -- weighted influence numerators and EDF validation. - -Experiments should include highly unequal weights, weights concentrated near -and far from the boundary, zero weights, global rescaling of all weights, and -integer weights compared with explicitly replicated observations. Require -weight-scale invariance, approximate replication equivalence, stable endpoint -classification, and acceptable global/boundary ISE before removing the -weighted fallback. - -### Manually specified bandwidths - -A manual bulk bandwidth is expressed on the transformed scale, whereas local -boundary bandwidths are expressed in original data units. Reusing the same -number for both is therefore invalid. The leading candidate is to compute the -automatic bulk reference bandwidth $h_{B,0}$ and interpret the manual choice -$h_B$ through the dimensionless ratio - -$$ -\rho=\frac{h_B}{h_{B,0}}, -$$ - -then multiply every automatically selected and floored expert bandwidth by -$\rho$. This preserves the requested bulk bandwidth while treating it as a -global smoothing adjustment. Compare this with leaving expert bandwidths -automatic when only the bulk bandwidth is manual; reject direct numerical -reuse across scales. - -Run the comparison over manual-to-automatic ratios such as $0.5$, $0.75$, $1$, -$1.5$, and $2$, several support rescalings, both support types, finite and -exploding endpoint shapes, and representative visual fits. Include the extra -cost of computing $h_{B,0}$ in the manual case. Activate manual-bandwidth fits -only after selecting and documenting one interpretation that preserves affine -equivariance and behaves predictably with `multiplier_`. - -Finally test weighted and manual bandwidths together after each has been -validated separately. Nondefault local-likelihood degrees remain a lower- -priority extension because the selected boundary expert deliberately averages -degrees one and two. +## Weighted and manual-bandwidth resolution + +Manual bandwidths control only the transformed bulk fit. Boundary bandwidths +remain independently selected in original data units, exactly as when the bulk +bandwidth is automatic. The public multiplier remains the common smoothing +control and scales both bulk and expert bandwidths. + +Weighted experiments rejected defining the one-sided 75% bandwidth subset by +cumulative weight: concentrated weights made that subset too narrow and +unstable. Counting positive-weight observations was both simpler and more +accurate. Effective sample size gave a small but consistent improvement for the +fusion width under concentrated weights. A weighted classifier threshold of +0.975 avoided most false repair of exploding targets while retaining the +finite-boundary gains. Global weight rescaling and insertion or removal of +zero-weight observations are numerically invariant. + +Integer-weight replication equivalence is not required here because the +existing bulk bandwidth selector interprets public weights through effective +sample size rather than as frequency counts. Supporting frequency weights +would require a separate change to the bulk estimator's weight semantics. + +### Required follow-up: degrees zero and one + +Keep boundary-expert activation for `degree_ < 2` as an important open task. +The current estimator must continue to retain the transformed bulk fit for +these degrees until this is evaluated. Compare at least: + +- retaining the averaged local-linear/local-quadratic boundary expert for all + bulk degrees; +- matching the endpoint expert to the requested bulk degree; +- using local linear at the endpoint for both degree-zero and degree-one bulk + fits. + +Evaluate global and boundary ISE, bias and variance, visual boundary stability, +EDF behavior, and runtime for both support types, including weighted and manual- +bandwidth fits. Do not activate degrees zero or one based only on API symmetry; +the selected degree-two expert deliberately averages degrees one and two. ## Native tests diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index e3794cb..b29afd3 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -191,13 +191,17 @@ class Kde1d double multiplier, size_t degree, const Eigen::VectorXd& weights) const; - bool is_finite_endpoint(Eigen::VectorXd dist) const; - BoundaryComponent fit_boundary_component(const Eigen::VectorXd& dist, - const Eigen::VectorXd& eval_dist, - double bandwidth) const; + bool is_finite_endpoint(const Eigen::VectorXd& dist, + const Eigen::VectorXd& weights) const; + BoundaryComponent fit_boundary_component( + const Eigen::VectorXd& dist, + const Eigen::VectorXd& eval_dist, + double bandwidth, + const Eigen::VectorXd& weights) const; void repair_boundaries(const Eigen::VectorXd& x, const Eigen::VectorXd& grid, - Eigen::VectorXd& influences); + Eigen::VectorXd& influences, + const Eigen::VectorXd& weights); std::string as_str(VarType type) const; VarType as_enum(std::string type) const; @@ -342,12 +346,9 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) Eigen::VectorXd w = weights; tools::remove_nans(xx, w); - // Nonconstant case weights need separate expert semantics; constant weights - // are equivalent to an unweighted sample. - const bool unweighted = w.size() == 0 || w.minCoeff() == w.maxCoeff(); - const bool use_boundary_repair = - type_ == VarType::continuous && xx.size() >= 16 && unweighted && - degree_ == 2 && (!std::isnan(xmin_) || !std::isnan(xmax_)); + const bool use_boundary_repair = type_ == VarType::continuous && + xx.size() >= 16 && degree_ == 2 && + (!std::isnan(xmin_) || !std::isnan(xmax_)); Eigen::VectorXd boundary_observations; if (use_boundary_repair) boundary_observations = xx; @@ -423,7 +424,7 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) // (3 iterations for normalization to a proper density) grid_ = interp::InterpolationGrid(grid_points, values, 3); if (use_boundary_repair) - repair_boundaries(boundary_observations, grid_points, influences); + repair_boundaries(boundary_observations, grid_points, influences, w); // calculate log-likelihood of final estimate xx = boundary_transform(xx, true); @@ -951,37 +952,53 @@ Kde1d::finalize_grid(Eigen::VectorXd& grid_points) //! \widehat\beta = \frac{k}{\sum_{i=1}^k //! \log\{d_{(k+1)} / d_{(i)}\}}. //! @f] -//! It is treated as finite when @f$\widehat\beta \geq 0.9@f$ and its -//! one-sided 95% lower confidence bound does not exceed one. Ambiguous and +//! It is treated as finite when @f$\widehat\beta \geq 0.9@f$ and its one-sided +//! 95% lower confidence bound does not exceed one. The weighted threshold is +//! 0.975 to avoid unstable repair of exploding targets. Ambiguous and //! numerically degenerate cases retain the bulk fit. -//! @param dist distances of the observations from the support endpoint; copied -//! because the classifier sorts them. +//! With nonconstant case weights, their effective sample size replaces @f$n@f$ +//! and the lower tail is defined by cumulative normalized weight. +//! @param dist ordered distances of the observations from the support endpoint. +//! @param weights correspondingly ordered case weights with mean one. //! @return whether the endpoint is confidently classified as finite. inline bool -Kde1d::is_finite_endpoint(Eigen::VectorXd dist) const +Kde1d::is_finite_endpoint(const Eigen::VectorXd& dist, + const Eigen::VectorXd& weights) const { - std::sort(dist.data(), dist.data() + dist.size()); + const double n_eff = weights.sum() * weights.sum() / weights.squaredNorm(); + if (!(n_eff > 1.0) || !std::isfinite(n_eff)) + return false; - // k is the number of lower order statistics; dist_k1 is d_(k+1). - const size_t k = - std::min(static_cast(dist.size() - 1), - static_cast(std::ceil(2.0 * std::sqrt(dist.size())))); - const double dist_k1 = dist(k); + // Scale weights to effective counts and locate the (k+1)th weighted order + // statistic, where k = min(n_eff, ceil(2 sqrt(n_eff))). + const Eigen::VectorXd counts = weights * n_eff / weights.sum(); + const double target = + std::min(std::nextafter(n_eff, 0.0), std::ceil(2.0 * std::sqrt(n_eff))); + Eigen::Index k1 = 0; + double cumulative = counts(0); + while (cumulative <= target && k1 + 1 < dist.size()) + cumulative += counts(++k1); + const double dist_k1 = dist(k1); if (!(dist_k1 > 0.0) || !std::isfinite(dist_k1)) return false; - // denom is the denominator of the lower-tail index beta = k / denom. + // tail_mass and denom define the weighted lower-tail index beta. + double tail_mass = 0.0; double denom = 0.0; const double dist_min = std::numeric_limits::epsilon() * dist_k1; - for (size_t i = 0; i < k; ++i) { - denom += std::log(dist_k1 / std::max(dist(i), dist_min)); + for (Eigen::Index i = 0; i < k1; ++i) { + tail_mass += counts(i); + denom += counts(i) * std::log(dist_k1 / std::max(dist(i), dist_min)); } - if (!(denom > 0.0) || !std::isfinite(denom)) + if (!(tail_mass > 0.0) || !(denom > 0.0) || !std::isfinite(denom)) return false; - const double beta = static_cast(k) / denom; + const double beta = tail_mass / denom; // 1.64485 is the 95% standard-normal quantile used by the R selector. - return beta >= 0.9 && beta * (1.0 - 1.6448536269514722 / std::sqrt(k)) <= 1.0; + const double beta_min = + weights.minCoeff() == weights.maxCoeff() ? 0.9 : 0.975; + return beta >= beta_min && + beta * (1.0 - 1.6448536269514722 / std::sqrt(tail_mass)) <= 1.0; } //! Fits the average of Gaussian local-linear and local-quadratic equivalent @@ -992,7 +1009,7 @@ Kde1d::is_finite_endpoint(Eigen::VectorXd dist) const //! \begin{align*} //! a &= t/h, & u_i &= (t-d_i)/h, \\[2pt] //! \widehat f_p(t;h) -//! &= \frac{1}{nh}\sum_{i=1}^n \phi(u_i)\, +//! &= \frac{1}{nh}\sum_{i=1}^n w_i\phi(u_i)\, //! e_0^\mathsf{T}M_p(a)^{-1} //! (1,u_i,\ldots,u_i^p)^\mathsf{T}, \\[2pt] //! \widehat f_\partial(t) @@ -1010,16 +1027,18 @@ Kde1d::is_finite_endpoint(Eigen::VectorXd dist) const //! \end{align*} //! @f] //! This identity evaluates the three convolutions by FFT. -//! Observations contribute equally to both kernels. The returned influence -//! numerator is the corresponding average diagonal kernel contribution. +//! Both kernels use the same normalized case weights @f$w_i@f$. The returned +//! influence numerator is the corresponding average diagonal contribution. //! @param dist ordered distances of the observations from the support endpoint. //! @param eval_dist endpoint distances at which to evaluate the component. //! @param bandwidth shared bandwidth of both equivalent kernels. +//! @param weights correspondingly ordered case weights with mean one. //! @return the density and influence numerator on `eval_dist`. inline Kde1d::BoundaryComponent Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, const Eigen::VectorXd& eval_dist, - double bandwidth) const + double bandwidth, + const Eigen::VectorXd& weights) const { const double h = bandwidth; if (!(h > 0.0) || !std::isfinite(h)) @@ -1036,18 +1055,27 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, const double* last = std::upper_bound(dist.data(), dist.data() + dist.size(), fft_upper); const Eigen::Index n_fft = last - dist.data(); - if (n_fft == 0) + const double fft_weight = weights.head(n_fft).sum(); + if (n_fft == 0 || !(fft_weight > 0.0)) return fit; // This resolution kept the worst paired ISE perturbation below 0.7%. const size_t num_bins = 256; fft::KdeFFT kde_fft( - dist.head(n_fft), h, 0.0, fft_upper, Eigen::VectorXd(), num_bins); - const double scale = - static_cast(n_fft) / static_cast(dist.size()); + dist.head(n_fft), h, 0.0, fft_upper, weights.head(n_fft), num_bins); + const double scale = fft_weight / weights.sum(); const Eigen::VectorXd f0 = scale * kde_fft.kde_drv(0); const Eigen::VectorXd f1 = scale * kde_fft.kde_drv(1); const Eigen::VectorXd f2 = scale * kde_fft.kde_drv(2); + Eigen::VectorXd local_weight = Eigen::VectorXd::Ones(num_bins + 1); + if (weights.minCoeff() != weights.maxCoeff()) { + const Eigen::VectorXd count = tools::linbin( + dist.head(n_fft), 0.0, fft_upper, num_bins, Eigen::VectorXd::Ones(n_fft)); + local_weight = (count.array() == 0.0) + .select(Eigen::VectorXd::Zero(count.size()), + weights.head(n_fft).mean() * + kde_fft.get_bin_counts().cwiseQuotient(count)); + } for (Eigen::Index j = 0; j < eval_dist.size(); ++j) { // c1 and c2 are the first inverse-moment rows for degrees 1 and 2. const double a = eval_dist(j) / h; @@ -1076,8 +1104,8 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, fit.density(j) = 0.5 * ((c10 + c20 + c22) * interpolate(f0) - h * (c11 + c21) * interpolate(f1) + h * h * c22 * interpolate(f2)); - fit.influence_num(j) = - K0_ * (c10 + c20) / (2.0 * static_cast(dist.size()) * h); + fit.influence_num(j) = K0_ * (c10 + c20) * interpolate(local_weight) / + (2.0 * static_cast(dist.size()) * h); } // Remove unstable local-polynomial values. @@ -1095,11 +1123,12 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, //! densities @f$\widehat f_L@f$ and @f$\widehat f_U@f$. Each endpoint density //! averages local-linear and local-quadratic kernels using one degree-2 //! bandwidth, selected from all distances on bounded support and the closest -//! 75% on one-sided support. Smooth weights @f$w_L@f$ and @f$w_U@f$ are -//! functions of the bulk CDF and shrink at rate @f$\min(1/4,n^{-1/2})@f$: +//! 75% of positive-weight observations on one-sided support. Smooth weights +//! @f$w_L@f$ and @f$w_U@f$ are functions of the weighted bulk CDF and shrink +//! with effective sample size @f$n_e@f$: //! @f[ //! \begin{align*} -//! q &= \min(1/4,n^{-1/2}), & z(p) &= \min(1,p/q), \\[2pt] +//! q &= \min(1/4,n_e^{-1/2}), & z(p) &= \min(1,p/q), \\[2pt] //! g(p) &= 1-3z(p)^2+2z(p)^3, \\[2pt] //! w_L &= g(F_B), & w_U &= g(1-F_B), \\[2pt] //! \widehat f @@ -1115,28 +1144,51 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, //! @param grid increasing evaluation grid on the original scale. //! @param influences on input, bulk-fit influences on `grid`; on output, //! influences of the fused estimate. +//! @param weights normalized case weights; empty means equal weights. inline void Kde1d::repair_boundaries(const Eigen::VectorXd& x, const Eigen::VectorXd& grid, - Eigen::VectorXd& influences) + Eigen::VectorXd& influences, + const Eigen::VectorXd& weights) { Eigen::VectorXd dist_lower; Eigen::VectorXd dist_upper; + Eigen::VectorXd weights_lower; + Eigen::VectorXd weights_upper; + const Eigen::VectorXd case_weights = + weights.size() > 0 ? weights : Eigen::VectorXd::Ones(x.size()); + const double n_eff = + case_weights.sum() * case_weights.sum() / case_weights.squaredNorm(); + if (n_eff < 16.0) + return; + auto sort_endpoint = [&](Eigen::VectorXd& dist, + Eigen::VectorXd& sorted_weights) { + const Eigen::VectorXi order = tools::get_order(dist); + const Eigen::VectorXd unsorted_dist = dist; + for (Eigen::Index i = 0; i < dist.size(); ++i) { + dist(i) = unsorted_dist(order(i)); + sorted_weights(i) = case_weights(order(i)); + } + }; bool repair_lower = !std::isnan(xmin_); bool repair_upper = !std::isnan(xmax_); if (repair_lower) { dist_lower = x.array() - xmin_; - repair_lower = is_finite_endpoint(dist_lower); + weights_lower.resize(x.size()); + sort_endpoint(dist_lower, weights_lower); + repair_lower = is_finite_endpoint(dist_lower, weights_lower); } if (repair_upper) { dist_upper = xmax_ - x.array(); - repair_upper = is_finite_endpoint(dist_upper); + weights_upper.resize(x.size()); + sort_endpoint(dist_upper, weights_upper); + repair_upper = is_finite_endpoint(dist_upper, weights_upper); } if (!repair_lower && !repair_upper) return; // q is the shrinking probability width of each endpoint weight. - const double q = std::min(0.25, 1.0 / std::sqrt(x.size())); + const double q = std::min(0.25, 1.0 / std::sqrt(n_eff)); auto endpoint_weight = [&](double probability) { const double z = std::min(1.0, probability / q); return 1.0 - (3.0 * z * z - 2.0 * z * z * z); @@ -1159,20 +1211,31 @@ Kde1d::repair_boundaries(const Eigen::VectorXd& x, // Select one shared degree-2 bandwidth, using the local 75% one-sided rule. const double bw_fraction = (!std::isnan(xmin_) && !std::isnan(xmax_)) ? 1.0 : 0.75; - Eigen::VectorXd bw_dist = repair_lower ? dist_lower : dist_upper; - std::sort(bw_dist.data(), bw_dist.data() + bw_dist.size()); + const Eigen::VectorXd endpoint_dist = repair_lower ? dist_lower : dist_upper; + const Eigen::VectorXd endpoint_weights = + repair_lower ? weights_lower : weights_upper; + const Eigen::Index n_positive = (endpoint_weights.array() > 0.0).count(); + Eigen::VectorXd bw_dist(n_positive); + Eigen::VectorXd bw_weights(n_positive); + Eigen::Index positive_index = 0; + for (Eigen::Index i = 0; i < endpoint_dist.size(); ++i) { + if (endpoint_weights(i) > 0.0) { + bw_dist(positive_index) = endpoint_dist(i); + bw_weights(positive_index++) = endpoint_weights(i); + } + } const Eigen::Index n_bw = std::min( bw_dist.size(), std::max( 4, static_cast(std::ceil(bw_fraction * bw_dist.size())))); - bandwidth::PluginBandwidthSelector selector(bw_dist.head(n_bw)); + bandwidth::PluginBandwidthSelector selector(bw_dist.head(n_bw), + bw_weights.head(n_bw)); const double h = selector.select_bandwidth(2) * multiplier_; auto fit_endpoint = [&](const Eigen::VectorXd& dist, - const Eigen::VectorXd& eval_dist) { - Eigen::VectorXd dist_sorted = dist; - std::sort(dist_sorted.data(), dist_sorted.data() + dist_sorted.size()); - return fit_boundary_component(dist_sorted, eval_dist, h); + const Eigen::VectorXd& eval_dist, + const Eigen::VectorXd& endpoint_weights) { + return fit_boundary_component(dist, eval_dist, h, endpoint_weights); }; BoundaryComponent lower; @@ -1180,13 +1243,14 @@ Kde1d::repair_boundaries(const Eigen::VectorXd& x, repair_lower = repair_lower && n_lower > 0; repair_upper = repair_upper && n_upper > 0; if (repair_lower) { - lower = fit_endpoint(dist_lower, grid.head(n_lower).array() - xmin_); + lower = fit_endpoint( + dist_lower, grid.head(n_lower).array() - xmin_, weights_lower); repair_lower = lower.density.size() > 0; } if (repair_upper) { Eigen::VectorXd upper_eval_dist = (xmax_ - grid.tail(n_upper).array()).reverse(); - upper = fit_endpoint(dist_upper, upper_eval_dist); + upper = fit_endpoint(dist_upper, upper_eval_dist, weights_upper); repair_upper = upper.density.size() > 0; } if (!repair_lower && !repair_upper) diff --git a/test/test.cpp b/test/test.cpp index fa574ff..1722567 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -255,7 +255,7 @@ TEST_CASE("two-sided exploding endpoints retain the bulk fit", CHECK(fit.get_edf() == Approx(bulk.get_edf()).epsilon(1e-12)); } -TEST_CASE("unsupported expert options retain the transformed bulk fit", +TEST_CASE("boundary experts support weights and manual bandwidths", "[boundary-expert]") { const Eigen::VectorXd probabilities = @@ -266,10 +266,43 @@ TEST_CASE("unsupported expert options retain the transformed bulk fit", Kde1d weighted(0.0, NAN, "continuous"); weighted.fit(observations, weights); - Kde1d weighted_bulk(0.0, NAN, "continuous", 1.0, weighted.get_bandwidth()); - weighted_bulk.fit(observations, weights); - CHECK(weighted.get_values().isApprox(weighted_bulk.get_values(), 1e-12)); - CHECK(weighted.get_edf() == Approx(weighted_bulk.get_edf()).epsilon(1e-12)); + Kde1d weighted_manual(0.0, NAN, "continuous", 1.0, weighted.get_bandwidth()); + weighted_manual.fit(observations, weights); + CHECK(weighted.get_values().isApprox(weighted_manual.get_values(), 1e-12)); + CHECK(weighted.get_edf() == Approx(weighted_manual.get_edf()).epsilon(1e-12)); + + Kde1d rescaled_weights(0.0, NAN, "continuous"); + rescaled_weights.fit(observations, 7.0 * weights); + CHECK(weighted.get_values().isApprox(rescaled_weights.get_values(), 1e-12)); + CHECK(weighted.get_edf() == + Approx(rescaled_weights.get_edf()).epsilon(1e-12)); + CHECK(weighted.get_loglik() == + Approx(rescaled_weights.get_loglik()).epsilon(1e-12)); + + Eigen::VectorXd zero_weights = weights; + for (Eigen::Index i = 1; i < zero_weights.size(); i += 5) + zero_weights(i) = 0.0; + Eigen::VectorXd retained_observations(160); + Eigen::VectorXd retained_weights(160); + Eigen::Index retained_index = 0; + for (Eigen::Index i = 0; i < zero_weights.size(); ++i) { + if (zero_weights(i) > 0.0) { + retained_observations(retained_index) = observations(i); + retained_weights(retained_index++) = zero_weights(i); + } + } + Kde1d with_zeros(0.0, NAN, "continuous"); + with_zeros.fit(observations, zero_weights); + Kde1d without_zeros(0.0, NAN, "continuous"); + without_zeros.fit(retained_observations, retained_weights); + CHECK(with_zeros.get_values().isApprox(without_zeros.get_values(), 1e-12)); + CHECK(with_zeros.get_edf() == Approx(without_zeros.get_edf()).epsilon(1e-12)); + + Kde1d reflected(NAN, 0.0, "continuous"); + reflected.fit(-observations, weights); + CHECK( + weighted.get_values().isApprox(reflected.get_values().reverse(), 1e-12)); + CHECK(weighted.get_edf() == Approx(reflected.get_edf()).epsilon(1e-12)); Kde1d linear(0.0, NAN, "continuous", 1.0, NAN, 1); linear.fit(observations); From 831c62b49df88c499fb9e3cb596d4423e3c861fc Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 19:57:04 +0200 Subject: [PATCH 14/25] Enable boundary repair for all degrees --- diagnostic/one-sided-repair/NATIVE_CPP.md | 42 ++++++--------- include/kde1d/kde1d.hpp | 2 +- test/test_numerical_invariants.cpp | 62 +++++++++++++---------- 3 files changed, 51 insertions(+), 55 deletions(-) diff --git a/diagnostic/one-sided-repair/NATIVE_CPP.md b/diagnostic/one-sided-repair/NATIVE_CPP.md index 76a351c..68c5801 100644 --- a/diagnostic/one-sided-repair/NATIVE_CPP.md +++ b/diagnostic/one-sided-repair/NATIVE_CPP.md @@ -13,20 +13,19 @@ path: The existing transformed estimator remains the bulk component in both cases. Unbounded continuous, discrete, and zero-inflated behavior remains unchanged. -The production estimator activates for degree-two continuous fits with at least -16 observations and effective sample size at least 16. Public case weights and -manual bandwidths are supported. Nondefault degrees retain the transformed -bulk estimator pending separate evaluation. Apply the bandwidth multiplier to -every expert bandwidth after selection and flooring. +The production estimator activates for continuous fits of degrees zero through +two with at least 16 observations and effective sample size at least 16. Public +case weights and manual bandwidths are supported. Apply the bandwidth +multiplier to every expert bandwidth after selection and flooring. Do not add a public method switch or another fitted-object representation. ## Minimal integration point Call the repair coordinator only when `type_ == VarType::continuous`, at least -one support bound is finite, at least 16 cleaned observations remain, and -`degree_ == 2`. The coordinator additionally retains the bulk fit when the -effective sample size is below 16. +one support bound is finite, and at least 16 cleaned observations remain. The +coordinator additionally retains the bulk fit when the effective sample size is +below 16. Keep the current body of `Kde1d::fit()` through construction of the normalized bulk `InterpolationGrid`. Preserve the cleaned observations on their original @@ -319,22 +318,14 @@ existing bulk bandwidth selector interprets public weights through effective sample size rather than as frequency counts. Supporting frequency weights would require a separate change to the bulk estimator's weight semantics. -### Required follow-up: degrees zero and one +### Degrees zero and one -Keep boundary-expert activation for `degree_ < 2` as an important open task. -The current estimator must continue to retain the transformed bulk fit for -these degrees until this is evaluated. Compare at least: - -- retaining the averaged local-linear/local-quadratic boundary expert for all - bulk degrees; -- matching the endpoint expert to the requested bulk degree; -- using local linear at the endpoint for both degree-zero and degree-one bulk - fits. - -Evaluate global and boundary ISE, bias and variance, visual boundary stability, -EDF behavior, and runtime for both support types, including weighted and manual- -bandwidth fits. Do not activate degrees zero or one based only on API symmetry; -the selected degree-two expert deliberately averages degrees one and two. +The same averaged local-linear/local-quadratic boundary expert is used for all +three bulk degrees. It outperformed matching-order and local-linear-only +alternatives in global and boundary ISE. The gains persisted for weighted and +manual-bandwidth fits, and boundary scale equivariance is tested for every +degree. Degree zero primarily trades substantially lower boundary bias for a +small one-sided variance increase; degree one reduces both bias and variance. ## Native tests @@ -350,9 +341,8 @@ Shared coverage: - scaling over several orders of magnitude; - ties, observations exactly at an endpoint, small samples, and nearly degenerate samples; -- regression coverage proving that unbounded, discrete, zero-inflated, - weighted, fixed-bandwidth, and nondefault-degree fits retain the current - path; +- regression coverage for unbounded, discrete, zero-inflated, weighted, + fixed-bandwidth, and nondefault-degree fits; - fit-time benchmarks at representative $n$ values. One-sided coverage: diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index b29afd3..930941e 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -347,7 +347,7 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) tools::remove_nans(xx, w); const bool use_boundary_repair = type_ == VarType::continuous && - xx.size() >= 16 && degree_ == 2 && + xx.size() >= 16 && (!std::isnan(xmin_) || !std::isnan(xmax_)); Eigen::VectorXd boundary_observations; if (use_boundary_repair) diff --git a/test/test_numerical_invariants.cpp b/test/test_numerical_invariants.cpp index 98e8c86..a29345f 100644 --- a/test/test_numerical_invariants.cpp +++ b/test/test_numerical_invariants.cpp @@ -85,20 +85,23 @@ TEST_CASE("finite-support fits are scale equivariant", Eigen::VectorXd points(10); points << 0.0, 1e-10, 1e-8, 1e-6, 1e-4, 1e-2, 0.1, 0.5, 0.9, 1.0; - kde1d::Kde1d reference(0.0, 1.0, "continuous", 1.0, 0.3, 2, 400); - reference.fit(observations); - - for (double scale : { 1e-4, 1e4 }) { - INFO("scale=" << scale); - kde1d::Kde1d scaled( - 0.0, scale, "continuous", 1.0, 0.3, 2, 400); - scaled.fit(observations * scale); - - CHECK((scaled.get_grid_points() / scale) - .isApprox(reference.get_grid_points(), 1e-11)); - CHECK((scaled.pdf(points * scale) * scale) - .isApprox(reference.pdf(points), 1e-10)); - CHECK(scaled.cdf(points * scale).isApprox(reference.cdf(points), 1e-10)); + for (size_t degree = 0; degree < 3; ++degree) { + kde1d::Kde1d reference( + 0.0, 1.0, "continuous", 1.0, 0.3, degree, 400); + reference.fit(observations); + + for (double scale : { 1e-4, 1e4 }) { + INFO("degree=" << degree << ", scale=" << scale); + kde1d::Kde1d scaled( + 0.0, scale, "continuous", 1.0, 0.3, degree, 400); + scaled.fit(observations * scale); + + CHECK((scaled.get_grid_points() / scale) + .isApprox(reference.get_grid_points(), 1e-11)); + CHECK((scaled.pdf(points * scale) * scale) + .isApprox(reference.pdf(points), 1e-10)); + CHECK(scaled.cdf(points * scale).isApprox(reference.cdf(points), 1e-10)); + } } } @@ -111,20 +114,23 @@ TEST_CASE("one-sided fits are scale equivariant", Eigen::VectorXd points(10); points << 0.0, 1e-10, 1e-8, 1e-6, 1e-4, 1e-2, 0.1, 0.5, 1.0, 5.0; - kde1d::Kde1d reference(0.0, NAN, "continuous", 1.0, 0.3, 2, 400); - reference.fit(observations); - - for (double scale : { 1e-4, 1e4 }) { - INFO("scale=" << scale); - kde1d::Kde1d scaled( - 0.0, NAN, "continuous", 1.0, 0.3, 2, 400); - scaled.fit(observations * scale); - - CHECK((scaled.get_grid_points() / scale) - .isApprox(reference.get_grid_points(), 1e-11)); - CHECK((scaled.pdf(points * scale) * scale) - .isApprox(reference.pdf(points), 1e-10)); - CHECK(scaled.cdf(points * scale).isApprox(reference.cdf(points), 1e-10)); + for (size_t degree = 0; degree < 3; ++degree) { + kde1d::Kde1d reference( + 0.0, NAN, "continuous", 1.0, 0.3, degree, 400); + reference.fit(observations); + + for (double scale : { 1e-4, 1e4 }) { + INFO("degree=" << degree << ", scale=" << scale); + kde1d::Kde1d scaled( + 0.0, NAN, "continuous", 1.0, 0.3, degree, 400); + scaled.fit(observations * scale); + + CHECK((scaled.get_grid_points() / scale) + .isApprox(reference.get_grid_points(), 1e-11)); + CHECK((scaled.pdf(points * scale) * scale) + .isApprox(reference.pdf(points), 1e-10)); + CHECK(scaled.cdf(points * scale).isApprox(reference.cdf(points), 1e-10)); + } } } From e1218b16148e0b708b3b3457f6a86c566d1f68d1 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 20:02:40 +0200 Subject: [PATCH 15/25] Add boundary repair option --- diagnostic/one-sided-repair/NATIVE_CPP.md | 4 ++- include/kde1d/kde1d.hpp | 30 +++++++++++++++++------ test/test.cpp | 26 ++++++++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/diagnostic/one-sided-repair/NATIVE_CPP.md b/diagnostic/one-sided-repair/NATIVE_CPP.md index 68c5801..3b9bdb2 100644 --- a/diagnostic/one-sided-repair/NATIVE_CPP.md +++ b/diagnostic/one-sided-repair/NATIVE_CPP.md @@ -18,7 +18,9 @@ two with at least 16 observations and effective sample size at least 16. Public case weights and manual bandwidths are supported. Apply the bandwidth multiplier to every expert bandwidth after selection and flooring. -Do not add a public method switch or another fitted-object representation. +Expose boundary repair as a constructor option that defaults to enabled. When +disabled, retain the transformed bulk estimator. Do not add another fitted- +object representation. ## Minimal integration point diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 930941e..3921b4f 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -27,7 +27,8 @@ class Kde1d double multiplier = 1.0, double bandwidth = NAN, size_t degree = 2, - size_t grid_size = 400); + size_t grid_size = 400, + bool boundary_repair = true); Kde1d(double xmin = NAN, double xmax = NAN, @@ -35,7 +36,8 @@ class Kde1d double multiplier = 1.0, double bandwidth = NAN, size_t degree = 2, - size_t grid_size = 400); + size_t grid_size = 400, + bool boundary_repair = true); Kde1d(const interp::InterpolationGrid& grid, double xmin, @@ -92,6 +94,8 @@ class Kde1d //! @return the requested number of grid points (the value passed //! to the constructor). size_t get_grid_size() const { return grid_size_; } + //! @return whether boundary-expert repair is enabled. + bool get_boundary_repair() const { return boundary_repair_; } //! @return the actual number of grid points after fitting (which //! may differ slightly from `get_grid_size()` due to //! boundary-snapping in `finalize_grid()`). @@ -113,7 +117,9 @@ class Kde1d << "xmin=" << xmin_ << ", xmax=" << xmax_ << ", type='" << this->as_str(type_) << "'" << ", bandwidth=" << bandwidth_ << ", multiplier=" << multiplier_ - << ", degree=" << degree_ << ")"; + << ", degree=" << degree_ + << ", boundary_repair=" << (boundary_repair_ ? "true" : "false") + << ")"; return ss.str(); } @@ -143,6 +149,7 @@ class Kde1d double bandwidth_{ NAN }; size_t degree_{ 2 }; size_t grid_size_; + bool boundary_repair_{ true }; double prob0_{ 0.0 }; double loglik_{ NAN }; double edf_{ NAN }; @@ -221,13 +228,16 @@ class Kde1d //! selection). //! @param degree degree of the local polynomial. //! @param grid_size number of grid points for the interpolation grid. +//! @param boundary_repair whether to use boundary experts at finite support +//! endpoints. inline Kde1d::Kde1d(double xmin, double xmax, VarType type, double multiplier, double bandwidth, size_t degree, - size_t grid_size) + size_t grid_size, + bool boundary_repair) : xmin_(xmin) , xmax_(xmax) , type_(type) @@ -236,6 +246,7 @@ inline Kde1d::Kde1d(double xmin, , bandwidth_(bandwidth) , degree_(degree) , grid_size_(grid_size) + , boundary_repair_(boundary_repair) { this->check_xmin_xmax(xmin, xmax); if (multiplier <= 0.0) { @@ -295,20 +306,24 @@ inline Kde1d::Kde1d(const interp::InterpolationGrid& grid, //! selection). //! @param degree degree of the local polynomial. //! @param grid_size number of grid points for the interpolation grid. +//! @param boundary_repair whether to use boundary experts at finite support +//! endpoints. inline Kde1d::Kde1d(double xmin, double xmax, std::string type, double multiplier, double bandwidth, size_t degree, - size_t grid_size) + size_t grid_size, + bool boundary_repair) : Kde1d(xmin, xmax, this->as_enum(type), multiplier, bandwidth, degree, - grid_size) + grid_size, + boundary_repair) { } @@ -346,7 +361,8 @@ Kde1d::fit(const Eigen::VectorXd& x, const Eigen::VectorXd& weights) Eigen::VectorXd w = weights; tools::remove_nans(xx, w); - const bool use_boundary_repair = type_ == VarType::continuous && + const bool use_boundary_repair = boundary_repair_ && + type_ == VarType::continuous && xx.size() >= 16 && (!std::isnan(xmin_) || !std::isnan(xmax_)); Eigen::VectorXd boundary_observations; diff --git a/test/test.cpp b/test/test.cpp index 1722567..9b58f6a 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -167,6 +167,31 @@ TEST_CASE("one-sided finite endpoints use the boundary expert", CHECK(fit.get_edf() == Approx(reflected.get_edf()).epsilon(1e-12)); } +TEST_CASE("boundary experts can be disabled", "[boundary-expert]") +{ + const Eigen::VectorXd probabilities = + Eigen::VectorXd::LinSpaced(200, 0.5 / 200.0, 1.0 - 0.5 / 200.0); + const Eigen::VectorXd observations = (-(1.0 - probabilities.array()).log()); + + Kde1d default_fit(0.0, NAN, "continuous"); + default_fit.fit(observations); + Kde1d enabled(0.0, NAN, "continuous", 1.0, NAN, 2, 400, true); + enabled.fit(observations); + Kde1d disabled(0.0, NAN, "continuous", 1.0, NAN, 2, 400, false); + disabled.fit(observations); + Kde1d disabled_manual( + 0.0, NAN, "continuous", 1.0, disabled.get_bandwidth(), 2, 400, false); + disabled_manual.fit(observations); + + CHECK(default_fit.get_boundary_repair()); + CHECK(enabled.get_boundary_repair()); + CHECK_FALSE(disabled.get_boundary_repair()); + CHECK(default_fit.get_values().isApprox(enabled.get_values(), 1e-12)); + CHECK_FALSE(default_fit.get_values().isApprox(disabled.get_values(), 1e-6)); + CHECK(disabled.get_values().isApprox(disabled_manual.get_values(), 1e-12)); + CHECK(disabled.str().find("boundary_repair=false") != std::string::npos); +} + TEST_CASE("one-sided vanishing endpoints retain the bulk fit", "[boundary-expert]") { @@ -625,6 +650,7 @@ TEST_CASE("bandwidth selection on refit", "[bandwidth][refit]") CHECK(std::isnan(from_grid.get_bandwidth())); CHECK(from_grid.get_multiplier() == Approx(1.0)); CHECK(from_grid.get_degree() == 2); + CHECK(from_grid.get_boundary_repair()); } } From a9a13570c13db6f255b2fb63d75cde44cd27cf2c Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 20:20:59 +0200 Subject: [PATCH 16/25] Refactor boundary repair helpers --- include/kde1d/kde1d.hpp | 396 ++++++++++++++++++++++++++-------------- 1 file changed, 260 insertions(+), 136 deletions(-) diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 3921b4f..f1f6f10 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -133,6 +133,37 @@ class Kde1d Eigen::VectorXd influence_num; }; + enum class EndpointSide + { + lower, + upper + }; + + struct EndpointData + { + Eigen::VectorXd dist; + Eigen::VectorXd weights; + bool finite{ false }; + }; + + struct BoundaryConvolutions + { + Eigen::VectorXd f0; + Eigen::VectorXd f1; + Eigen::VectorXd f2; + Eigen::VectorXd influence_weight; + double upper{ 0.0 }; + }; + + struct BoundaryKernelCoefficients + { + double c10; + double c11; + double c20; + double c21; + double c22; + }; + // data members interp::InterpolationGrid grid_; double xmin_; @@ -200,11 +231,28 @@ class Kde1d const Eigen::VectorXd& weights) const; bool is_finite_endpoint(const Eigen::VectorXd& dist, const Eigen::VectorXd& weights) const; + EndpointData prepare_endpoint(const Eigen::VectorXd& x, + const Eigen::VectorXd& weights, + EndpointSide side) const; + double select_boundary_bandwidth(const EndpointData& endpoint, + double fraction) const; + BoundaryConvolutions compute_boundary_convolutions( + const Eigen::VectorXd& dist, + const Eigen::VectorXd& weights, + double bandwidth, + double eval_upper) const; + BoundaryKernelCoefficients boundary_kernel_coefficients(double a) const; BoundaryComponent fit_boundary_component( const Eigen::VectorXd& dist, const Eigen::VectorXd& eval_dist, double bandwidth, const Eigen::VectorXd& weights) const; + void fuse_boundary_components(const Eigen::VectorXd& grid, + const Eigen::VectorXd& w_lower, + const Eigen::VectorXd& w_upper, + const BoundaryComponent& lower, + const BoundaryComponent& upper, + Eigen::VectorXd& influences); void repair_boundaries(const Eigen::VectorXd& x, const Eigen::VectorXd& grid, Eigen::VectorXd& influences, @@ -1017,6 +1065,136 @@ Kde1d::is_finite_endpoint(const Eigen::VectorXd& dist, beta * (1.0 - 1.6448536269514722 / std::sqrt(tail_mass)) <= 1.0; } +//! Constructs sorted distances and case weights for one support endpoint, then +//! classifies its local density behavior. +//! @param x observations on the original scale. +//! @param weights normalized case weights with mean one. +//! @param side endpoint from which distances are measured. +//! @return sorted endpoint data and its finite-endpoint decision. +inline Kde1d::EndpointData +Kde1d::prepare_endpoint(const Eigen::VectorXd& x, + const Eigen::VectorXd& weights, + EndpointSide side) const +{ + EndpointData endpoint; + if (side == EndpointSide::lower) + endpoint.dist = x.array() - xmin_; + else + endpoint.dist = xmax_ - x.array(); + endpoint.weights.resize(x.size()); + const Eigen::VectorXi order = tools::get_order(endpoint.dist); + const Eigen::VectorXd unsorted_dist = endpoint.dist; + for (Eigen::Index i = 0; i < endpoint.dist.size(); ++i) { + endpoint.dist(i) = unsorted_dist(order(i)); + endpoint.weights(i) = weights(order(i)); + } + endpoint.finite = is_finite_endpoint(endpoint.dist, endpoint.weights); + return endpoint; +} + +//! Selects the shared original-scale bandwidth for a boundary expert. The +//! closest `fraction` of positive-weight observations are used by row count. +//! @param endpoint sorted endpoint distances and case weights. +//! @param fraction fraction of positive-weight observations used for selection. +//! @return degree-two plug-in bandwidth after applying the public multiplier. +inline double +Kde1d::select_boundary_bandwidth(const EndpointData& endpoint, + double fraction) const +{ + const Eigen::Index n_positive = (endpoint.weights.array() > 0.0).count(); + Eigen::VectorXd dist(n_positive); + Eigen::VectorXd weights(n_positive); + Eigen::Index j = 0; + for (Eigen::Index i = 0; i < endpoint.dist.size(); ++i) { + if (endpoint.weights(i) > 0.0) { + dist(j) = endpoint.dist(i); + weights(j++) = endpoint.weights(i); + } + } + const Eigen::Index n_bw = std::min( + dist.size(), + std::max( + 4, static_cast(std::ceil(fraction * dist.size())))); + bandwidth::PluginBandwidthSelector selector(dist.head(n_bw), + weights.head(n_bw)); + return selector.select_bandwidth(2) * multiplier_; +} + +//! Computes the ordinary Gaussian KDE and its first two derivatives on the +//! regular FFT grid used by a boundary component. The influence weights are +//! the average normalized case weights in the same bins. +//! @param dist ordered endpoint distances. +//! @param weights correspondingly ordered normalized case weights. +//! @param bandwidth boundary-component bandwidth. +//! @param eval_upper largest endpoint distance that will be evaluated. +//! @return FFT convolutions, influence weights, and FFT-grid upper limit. +inline Kde1d::BoundaryConvolutions +Kde1d::compute_boundary_convolutions(const Eigen::VectorXd& dist, + const Eigen::VectorXd& weights, + double bandwidth, + double eval_upper) const +{ + BoundaryConvolutions convolutions; + convolutions.upper = eval_upper + 6.0 * bandwidth; + const double* last = std::upper_bound( + dist.data(), dist.data() + dist.size(), convolutions.upper); + const Eigen::Index n_fft = last - dist.data(); + const double fft_weight = weights.head(n_fft).sum(); + if (n_fft == 0 || !(fft_weight > 0.0)) + return convolutions; + + // This resolution kept the worst paired ISE perturbation below 0.7%. + const size_t num_bins = 256; + fft::KdeFFT kde_fft(dist.head(n_fft), + bandwidth, + 0.0, + convolutions.upper, + weights.head(n_fft), + num_bins); + const double scale = fft_weight / weights.sum(); + convolutions.f0 = scale * kde_fft.kde_drv(0); + convolutions.f1 = scale * kde_fft.kde_drv(1); + convolutions.f2 = scale * kde_fft.kde_drv(2); + convolutions.influence_weight = Eigen::VectorXd::Ones(num_bins + 1); + if (weights.minCoeff() != weights.maxCoeff()) { + const Eigen::VectorXd count = tools::linbin(dist.head(n_fft), + 0.0, + convolutions.upper, + num_bins, + Eigen::VectorXd::Ones(n_fft)); + convolutions.influence_weight = + (count.array() == 0.0) + .select(Eigen::VectorXd::Zero(count.size()), + weights.head(n_fft).mean() * + kde_fft.get_bin_counts().cwiseQuotient(count)); + } + return convolutions; +} + +//! Computes the first inverse-moment rows for degree-one and degree-two +//! Gaussian boundary kernels at standardized endpoint distance @f$a@f$. +//! @param a endpoint distance divided by bandwidth. +//! @return coefficients @f$c_{10},c_{11},c_{20},c_{21},c_{22}@f$. +inline Kde1d::BoundaryKernelCoefficients +Kde1d::boundary_kernel_coefficients(double a) const +{ + const double phi = K0_ * std::exp(-0.5 * a * a); + const double mu0 = 0.5 * std::erfc(-a * 0.7071067811865475); + const double mu1 = -phi; + const double mu2 = mu0 - a * phi; + const double mu3 = -(a * a + 2.0) * phi; + const double mu4 = 3.0 * mu0 - (a * a * a + 3.0 * a) * phi; + const double det1 = mu0 * mu2 - mu1 * mu1; + const double det2 = mu0 * (mu2 * mu4 - mu3 * mu3) - + mu1 * (mu1 * mu4 - mu2 * mu3) + + mu2 * (mu1 * mu3 - mu2 * mu2); + return { mu2 / det1, + -mu1 / det1, + (mu2 * mu4 - mu3 * mu3) / det2, + (mu2 * mu3 - mu1 * mu4) / det2, + (mu1 * mu3 - mu2 * mu2) / det2 }; +} + //! Fits the average of Gaussian local-linear and local-quadratic equivalent //! kernels from sample distances @f$d@f$ to endpoint-distance grid @f$t@f$. //! For degree @f$p@f$, shared bandwidth @f$h@f$, truncated Gaussian moments @@ -1065,63 +1243,28 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, if (eval_dist.size() == 0) return fit; - // Compute the ordinary Gaussian KDE and its first two derivatives on a - // regular grid, then interpolate them to the endpoint grid. - const double fft_upper = eval_dist(eval_dist.size() - 1) + 6.0 * h; - const double* last = - std::upper_bound(dist.data(), dist.data() + dist.size(), fft_upper); - const Eigen::Index n_fft = last - dist.data(); - const double fft_weight = weights.head(n_fft).sum(); - if (n_fft == 0 || !(fft_weight > 0.0)) + const BoundaryConvolutions convolutions = compute_boundary_convolutions( + dist, weights, h, eval_dist(eval_dist.size() - 1)); + if (convolutions.f0.size() == 0) return fit; - // This resolution kept the worst paired ISE perturbation below 0.7%. - const size_t num_bins = 256; - fft::KdeFFT kde_fft( - dist.head(n_fft), h, 0.0, fft_upper, weights.head(n_fft), num_bins); - const double scale = fft_weight / weights.sum(); - const Eigen::VectorXd f0 = scale * kde_fft.kde_drv(0); - const Eigen::VectorXd f1 = scale * kde_fft.kde_drv(1); - const Eigen::VectorXd f2 = scale * kde_fft.kde_drv(2); - Eigen::VectorXd local_weight = Eigen::VectorXd::Ones(num_bins + 1); - if (weights.minCoeff() != weights.maxCoeff()) { - const Eigen::VectorXd count = tools::linbin( - dist.head(n_fft), 0.0, fft_upper, num_bins, Eigen::VectorXd::Ones(n_fft)); - local_weight = (count.array() == 0.0) - .select(Eigen::VectorXd::Zero(count.size()), - weights.head(n_fft).mean() * - kde_fft.get_bin_counts().cwiseQuotient(count)); - } + const size_t num_bins = convolutions.f0.size() - 1; for (Eigen::Index j = 0; j < eval_dist.size(); ++j) { - // c1 and c2 are the first inverse-moment rows for degrees 1 and 2. const double a = eval_dist(j) / h; - const double phi = K0_ * std::exp(-0.5 * a * a); - const double mu0 = 0.5 * std::erfc(-a * 0.7071067811865475); - const double mu1 = -phi; - const double mu2 = mu0 - a * phi; - const double mu3 = -(a * a + 2.0) * phi; - const double mu4 = 3.0 * mu0 - (a * a * a + 3.0 * a) * phi; - const double det1 = mu0 * mu2 - mu1 * mu1; - const double c10 = mu2 / det1; - const double c11 = -mu1 / det1; - const double det2 = mu0 * (mu2 * mu4 - mu3 * mu3) - - mu1 * (mu1 * mu4 - mu2 * mu3) + - mu2 * (mu1 * mu3 - mu2 * mu2); - const double c20 = (mu2 * mu4 - mu3 * mu3) / det2; - const double c21 = (mu2 * mu3 - mu1 * mu4) / det2; - const double c22 = (mu1 * mu3 - mu2 * mu2) / det2; - - const double position = eval_dist(j) * num_bins / fft_upper; + const BoundaryKernelCoefficients c = boundary_kernel_coefficients(a); + const double position = eval_dist(j) * num_bins / convolutions.upper; const size_t bin = std::min(static_cast(position), num_bins - 1); const double fraction = position - static_cast(bin); auto interpolate = [&](const Eigen::VectorXd& values) { return (1.0 - fraction) * values(bin) + fraction * values(bin + 1); }; fit.density(j) = - 0.5 * ((c10 + c20 + c22) * interpolate(f0) - - h * (c11 + c21) * interpolate(f1) + h * h * c22 * interpolate(f2)); - fit.influence_num(j) = K0_ * (c10 + c20) * interpolate(local_weight) / - (2.0 * static_cast(dist.size()) * h); + 0.5 * ((c.c10 + c.c20 + c.c22) * interpolate(convolutions.f0) - + h * (c.c11 + c.c21) * interpolate(convolutions.f1) + + h * h * c.c22 * interpolate(convolutions.f2)); + fit.influence_num(j) = + K0_ * (c.c10 + c.c20) * interpolate(convolutions.influence_weight) / + (2.0 * static_cast(dist.size()) * h); } // Remove unstable local-polynomial values. @@ -1135,6 +1278,50 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, return fit; } +//! Fuses the bulk density and influence numerators with available lower and +//! upper boundary components. Upper components are stored by increasing +//! distance from the upper endpoint and are therefore indexed in reverse. +//! @param grid increasing evaluation grid on the original scale. +//! @param w_lower lower-endpoint fusion weights on `grid`. +//! @param w_upper upper-endpoint fusion weights on `grid`. +//! @param lower lower boundary component; empty means unavailable. +//! @param upper upper boundary component; empty means unavailable. +//! @param influences on input, bulk influences; on output, fused influences. +inline void +Kde1d::fuse_boundary_components(const Eigen::VectorXd& grid, + const Eigen::VectorXd& w_lower, + const Eigen::VectorXd& w_upper, + const BoundaryComponent& lower, + const BoundaryComponent& upper, + Eigen::VectorXd& influences) +{ + const Eigen::VectorXd f_bulk = grid_.get_values(); + Eigen::VectorXd f(grid.size()); + Eigen::VectorXd influence_num(grid.size()); + for (Eigen::Index j = 0; j < grid.size(); ++j) { + const bool use_lower = + w_lower(j) > 0.0 && j < lower.density.size(); + const Eigen::Index upper_j = grid.size() - 1 - j; + const bool use_upper = + w_upper(j) > 0.0 && upper_j < upper.density.size(); + const double w_bulk = + 1.0 - (use_lower ? w_lower(j) : 0.0) - + (use_upper ? w_upper(j) : 0.0); + f(j) = w_bulk * f_bulk(j); + influence_num(j) = w_bulk * f_bulk(j) * influences(j); + if (use_lower) { + f(j) += w_lower(j) * lower.density(j); + influence_num(j) += w_lower(j) * lower.influence_num(j); + } + if (use_upper) { + f(j) += w_upper(j) * upper.density(upper_j); + influence_num(j) += w_upper(j) * upper.influence_num(upper_j); + } + influences(j) = f(j) > 0.0 ? influence_num(j) / f(j) : 0.0; + } + grid_ = interp::InterpolationGrid(grid, f.cwiseMax(0.0), 3); +} + //! Fuses the transformed bulk density @f$\widehat f_B@f$ with endpoint //! densities @f$\widehat f_L@f$ and @f$\widehat f_U@f$. Each endpoint density //! averages local-linear and local-quadratic kernels using one degree-2 @@ -1167,40 +1354,20 @@ Kde1d::repair_boundaries(const Eigen::VectorXd& x, Eigen::VectorXd& influences, const Eigen::VectorXd& weights) { - Eigen::VectorXd dist_lower; - Eigen::VectorXd dist_upper; - Eigen::VectorXd weights_lower; - Eigen::VectorXd weights_upper; const Eigen::VectorXd case_weights = weights.size() > 0 ? weights : Eigen::VectorXd::Ones(x.size()); const double n_eff = case_weights.sum() * case_weights.sum() / case_weights.squaredNorm(); if (n_eff < 16.0) return; - auto sort_endpoint = [&](Eigen::VectorXd& dist, - Eigen::VectorXd& sorted_weights) { - const Eigen::VectorXi order = tools::get_order(dist); - const Eigen::VectorXd unsorted_dist = dist; - for (Eigen::Index i = 0; i < dist.size(); ++i) { - dist(i) = unsorted_dist(order(i)); - sorted_weights(i) = case_weights(order(i)); - } - }; - bool repair_lower = !std::isnan(xmin_); - bool repair_upper = !std::isnan(xmax_); - if (repair_lower) { - dist_lower = x.array() - xmin_; - weights_lower.resize(x.size()); - sort_endpoint(dist_lower, weights_lower); - repair_lower = is_finite_endpoint(dist_lower, weights_lower); - } - if (repair_upper) { - dist_upper = xmax_ - x.array(); - weights_upper.resize(x.size()); - sort_endpoint(dist_upper, weights_upper); - repair_upper = is_finite_endpoint(dist_upper, weights_upper); - } - if (!repair_lower && !repair_upper) + + EndpointData lower_endpoint; + EndpointData upper_endpoint; + if (!std::isnan(xmin_)) + lower_endpoint = prepare_endpoint(x, case_weights, EndpointSide::lower); + if (!std::isnan(xmax_)) + upper_endpoint = prepare_endpoint(x, case_weights, EndpointSide::upper); + if (!lower_endpoint.finite && !upper_endpoint.finite) return; // q is the shrinking probability width of each endpoint weight. @@ -1211,86 +1378,43 @@ Kde1d::repair_boundaries(const Eigen::VectorXd& x, }; // Only evaluate endpoint fits where their fusion weights are nonzero. - const Eigen::VectorXd f_bulk = grid_.get_values(); const Eigen::VectorXd bulk_cdf = grid_.integrate(grid, true); Eigen::VectorXd w_l = Eigen::VectorXd::Zero(grid.size()); Eigen::VectorXd w_u = Eigen::VectorXd::Zero(grid.size()); for (Eigen::Index j = 0; j < grid.size(); ++j) { - if (repair_lower) + if (lower_endpoint.finite) w_l(j) = endpoint_weight(bulk_cdf(j)); - if (repair_upper) + if (upper_endpoint.finite) w_u(j) = endpoint_weight(1.0 - bulk_cdf(j)); } const Eigen::Index n_lower = (w_l.array() > 0.0).count(); const Eigen::Index n_upper = (w_u.array() > 0.0).count(); - // Select one shared degree-2 bandwidth, using the local 75% one-sided rule. - const double bw_fraction = + // Reflection invariance gives both endpoints the same degree-2 bandwidth. + const double bandwidth_fraction = (!std::isnan(xmin_) && !std::isnan(xmax_)) ? 1.0 : 0.75; - const Eigen::VectorXd endpoint_dist = repair_lower ? dist_lower : dist_upper; - const Eigen::VectorXd endpoint_weights = - repair_lower ? weights_lower : weights_upper; - const Eigen::Index n_positive = (endpoint_weights.array() > 0.0).count(); - Eigen::VectorXd bw_dist(n_positive); - Eigen::VectorXd bw_weights(n_positive); - Eigen::Index positive_index = 0; - for (Eigen::Index i = 0; i < endpoint_dist.size(); ++i) { - if (endpoint_weights(i) > 0.0) { - bw_dist(positive_index) = endpoint_dist(i); - bw_weights(positive_index++) = endpoint_weights(i); - } - } - const Eigen::Index n_bw = std::min( - bw_dist.size(), - std::max( - 4, static_cast(std::ceil(bw_fraction * bw_dist.size())))); - bandwidth::PluginBandwidthSelector selector(bw_dist.head(n_bw), - bw_weights.head(n_bw)); - const double h = selector.select_bandwidth(2) * multiplier_; - - auto fit_endpoint = [&](const Eigen::VectorXd& dist, - const Eigen::VectorXd& eval_dist, - const Eigen::VectorXd& endpoint_weights) { - return fit_boundary_component(dist, eval_dist, h, endpoint_weights); - }; + const EndpointData& bandwidth_endpoint = + lower_endpoint.finite ? lower_endpoint : upper_endpoint; + const double h = + select_boundary_bandwidth(bandwidth_endpoint, bandwidth_fraction); BoundaryComponent lower; BoundaryComponent upper; - repair_lower = repair_lower && n_lower > 0; - repair_upper = repair_upper && n_upper > 0; - if (repair_lower) { - lower = fit_endpoint( - dist_lower, grid.head(n_lower).array() - xmin_, weights_lower); - repair_lower = lower.density.size() > 0; + if (lower_endpoint.finite && n_lower > 0) { + lower = fit_boundary_component(lower_endpoint.dist, + grid.head(n_lower).array() - xmin_, + h, + lower_endpoint.weights); } - if (repair_upper) { + if (upper_endpoint.finite && n_upper > 0) { Eigen::VectorXd upper_eval_dist = (xmax_ - grid.tail(n_upper).array()).reverse(); - upper = fit_endpoint(dist_upper, upper_eval_dist, weights_upper); - repair_upper = upper.density.size() > 0; + upper = fit_boundary_component( + upper_endpoint.dist, upper_eval_dist, h, upper_endpoint.weights); } - if (!repair_lower && !repair_upper) + if (lower.density.size() == 0 && upper.density.size() == 0) return; - - // Fuse densities and influence numerators with the same weights. - Eigen::VectorXd f(grid.size()); - Eigen::VectorXd infl_num(grid.size()); - for (Eigen::Index j = 0; j < grid.size(); ++j) { - const double w_b = 1.0 - w_l(j) - w_u(j); - f(j) = w_b * f_bulk(j); - infl_num(j) = w_b * f_bulk(j) * influences(j); - if (w_l(j) > 0.0) { - f(j) += w_l(j) * lower.density(j); - infl_num(j) += w_l(j) * lower.influence_num(j); - } - if (w_u(j) > 0.0) { - const Eigen::Index upper_j = grid.size() - 1 - j; - f(j) += w_u(j) * upper.density(upper_j); - infl_num(j) += w_u(j) * upper.influence_num(upper_j); - } - influences(j) = f(j) > 0.0 ? infl_num(j) / f(j) : 0.0; - } - grid_ = interp::InterpolationGrid(grid, f.cwiseMax(0.0), 3); + fuse_boundary_components(grid, w_l, w_u, lower, upper, influences); } // Bandwidth for Kernel Density Estimation From a3a896ded3168fdd0054ed15aa74484d8694d955 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 20:28:02 +0200 Subject: [PATCH 17/25] Clean boundary repair docs and diagnostics --- cmake/buildTargets.cmake | 4 - cmake/options.cmake | 1 - cmake/printInfo.cmake | 1 - diagnostic/CMakeLists.txt | 6 - diagnostic/NATIVE_RESULTS.md | 159 ++----- diagnostic/README.md | 70 ++-- diagnostic/boundary-repair/HANDOFF.md | 51 --- diagnostic/boundary-repair/NATIVE_CPP.md | 5 - diagnostic/boundary-repair/README.md | 68 --- diagnostic/boundary-repair/RESULTS.md | 59 --- .../plots/bounded-estimator-validation.pdf | Bin 70646 -> 0 bytes .../plots/endpoint-classifier-ablation.pdf | Bin 77147 -> 0 bytes .../results/bounded-estimator-validation.csv | 25 -- .../results/endpoint-classifier-ablation.csv | 85 ---- .../scripts/ablate_endpoint_classifier.R | 235 ----------- .../scripts/bounded_estimator.R | 376 ----------------- .../plot_bounded_estimator_validation.R | 208 ---------- .../plot_endpoint_classifier_ablation.R | 234 ----------- .../scripts/validate_bounded_estimator.R | 195 --------- diagnostic/boundary_diagnostic.cpp | 155 ------- diagnostic/one-sided-repair/HANDOFF.md | 33 -- diagnostic/one-sided-repair/NATIVE_CPP.md | 387 ------------------ diagnostic/one-sided-repair/README.md | 46 --- diagnostic/one-sided-repair/RESULTS.md | 59 --- .../plots/local-floor-fraction-ablation.pdf | Bin 77662 -> 0 bytes .../results/local-floor-fraction-ablation.csv | 111 ----- .../scripts/ablate_local_floor_fraction.R | 212 ---------- .../scripts/one_sided_estimator.R | 360 ---------------- .../plot_local_floor_fraction_ablation.R | 163 -------- diagnostic/plot_boundary_diagnostics.R | 101 ----- diagnostic/run_boundary_diagnostics.sh | 20 - diagnostic/validate_native_boundary_experts.R | 115 ++++-- docs/overview-continuous.dox | 111 ++++- include/kde1d/dpik.hpp | 2 +- include/kde1d/kde1d.hpp | 40 +- include/kde1d/kdefft.hpp | 2 +- 36 files changed, 290 insertions(+), 3409 deletions(-) delete mode 100644 diagnostic/CMakeLists.txt delete mode 100644 diagnostic/boundary-repair/HANDOFF.md delete mode 100644 diagnostic/boundary-repair/NATIVE_CPP.md delete mode 100644 diagnostic/boundary-repair/README.md delete mode 100644 diagnostic/boundary-repair/RESULTS.md delete mode 100644 diagnostic/boundary-repair/plots/bounded-estimator-validation.pdf delete mode 100644 diagnostic/boundary-repair/plots/endpoint-classifier-ablation.pdf delete mode 100644 diagnostic/boundary-repair/results/bounded-estimator-validation.csv delete mode 100644 diagnostic/boundary-repair/results/endpoint-classifier-ablation.csv delete mode 100644 diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R delete mode 100644 diagnostic/boundary-repair/scripts/bounded_estimator.R delete mode 100644 diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R delete mode 100644 diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R delete mode 100644 diagnostic/boundary-repair/scripts/validate_bounded_estimator.R delete mode 100644 diagnostic/boundary_diagnostic.cpp delete mode 100644 diagnostic/one-sided-repair/HANDOFF.md delete mode 100644 diagnostic/one-sided-repair/NATIVE_CPP.md delete mode 100644 diagnostic/one-sided-repair/README.md delete mode 100644 diagnostic/one-sided-repair/RESULTS.md delete mode 100644 diagnostic/one-sided-repair/plots/local-floor-fraction-ablation.pdf delete mode 100644 diagnostic/one-sided-repair/results/local-floor-fraction-ablation.csv delete mode 100644 diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R delete mode 100644 diagnostic/one-sided-repair/scripts/one_sided_estimator.R delete mode 100644 diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R delete mode 100644 diagnostic/plot_boundary_diagnostics.R delete mode 100755 diagnostic/run_boundary_diagnostics.sh diff --git a/cmake/buildTargets.cmake b/cmake/buildTargets.cmake index eff6110..00a69c6 100755 --- a/cmake/buildTargets.cmake +++ b/cmake/buildTargets.cmake @@ -17,10 +17,6 @@ if(BUILD_BENCHMARKS) add_subdirectory(benchmark) endif(BUILD_BENCHMARKS) -if(BUILD_DIAGNOSTICS) - add_subdirectory(diagnostic) -endif(BUILD_DIAGNOSTICS) - # Related to exports for linux/mac and code coverage #### # Installation diff --git a/cmake/options.cmake b/cmake/options.cmake index 5434743..da71e6c 100755 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -9,5 +9,4 @@ option(WARNINGS_AS_ERRORS "Compiler warnings as errors" "OFF") option(OPT_ASAN "Use adress sanitizer (debug)" "ON") option(BUILD_TESTING "Build tests." "ON") option(BUILD_BENCHMARKS "Build benchmarks." "OFF") -option(BUILD_DIAGNOSTICS "Build numerical diagnostics." "OFF") option(CODE_COVERAGE "Code coverage." "OFF") diff --git a/cmake/printInfo.cmake b/cmake/printInfo.cmake index 0b2c2ac..254fa14 100755 --- a/cmake/printInfo.cmake +++ b/cmake/printInfo.cmake @@ -14,6 +14,5 @@ message( STATUS "CMAKE_CXX_FLAGS_RELEASE= ${CMAKE_CXX_FLAGS_RELEASE}") message( STATUS ) message( STATUS "BUILD_TESTING= ${BUILD_TESTING}") message( STATUS "BUILD_BENCHMARKS= ${BUILD_BENCHMARKS}") -message( STATUS "BUILD_DIAGNOSTICS= ${BUILD_DIAGNOSTICS}") message( STATUS "CODE_COVERAGE= ${CODE_COVERAGE}") message( STATUS ) diff --git a/diagnostic/CMakeLists.txt b/diagnostic/CMakeLists.txt deleted file mode 100644 index b27293b..0000000 --- a/diagnostic/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_executable(kde1d-boundary-diagnostic boundary_diagnostic.cpp) -target_link_libraries(kde1d-boundary-diagnostic kde1d) -set_target_properties( - kde1d-boundary-diagnostic - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin -) diff --git a/diagnostic/NATIVE_RESULTS.md b/diagnostic/NATIVE_RESULTS.md index f39455f..dcdfd56 100644 --- a/diagnostic/NATIVE_RESULTS.md +++ b/diagnostic/NATIVE_RESULTS.md @@ -1,135 +1,52 @@ -# Native boundary-expert validation +# Native boundary-expert evidence -## Statistical validation +The final comparison with the pre-PR estimator has not yet been run. Its +protocol is in [`README.md`](README.md). In particular, the one-sided primary +benchmark will be the actual production log-transform fit from pre-PR `main`, +not the unrepaired fourth-root fit used during development. -The native candidate was compared with commit `4f3d148`, immediately before -the expert implementation. The paired experiment used 100 replications at -$n=25,100,1000,2000$. One-sided scenarios were Exponential, half-normal, -Gamma$(2)$, Gamma$(0.75)$, and Lomax$(2)$; two-sided scenarios were Uniform and -six symmetric or asymmetric beta densities. Ratios below average the -scenario-specific ratios of mean ISE. Parentheses contain paired Monte Carlo -standard errors. +The following implementation checks remain relevant to the selected method. -| support | $n$ | global ISE ratio | boundary ISE ratio | -|---|---:|---:|---:| -| one-sided | 25 | 0.932 (0.008) | 0.896 (0.016) | -| one-sided | 100 | 0.929 (0.009) | 0.903 (0.016) | -| one-sided | 1000 | 0.907 (0.012) | 0.857 (0.017) | -| one-sided | 2000 | 0.881 (0.015) | 0.824 (0.020) | -| two-sided | 25 | 0.874 (0.021) | 0.862 (0.020) | -| two-sided | 100 | 0.911 (0.008) | 0.917 (0.007) | -| two-sided | 1000 | 0.939 (0.007) | 0.954 (0.006) | -| two-sided | 2000 | 0.944 (0.007) | 0.955 (0.006) | +## Selected implementation -Average integrated variance ratios range from 0.93 to 0.94 one-sided and from -0.87 to 0.96 two-sided. Boundary variance ratios range from 0.88 to 0.90 and -from 0.86 to 0.97, respectively. The extra small-sample bias is the intended -price for smoother boundary realizations; at $n=1000,2000$, average integrated -squared bias is also lower than baseline. +- Finite endpoints use the equal average of local-linear and local-quadratic + Gaussian equivalent kernels; the same expert is used for bulk degrees zero, + one, and two. +- Both kernels share an automatically selected degree-two bandwidth. Selection + uses all positive-weight observations on bounded support and the closest 75% + by row count on one-sided support. A manual bandwidth controls only the bulk; + the public multiplier scales both bandwidths. +- Public case weights are used by the classifier, expert estimand, expert + bandwidth selector, effective sample size, and influence approximation. +- A cubic CDF-based fusion region has probability width + $\min(0.25,n_e^{-1/2})$. Endpoints classified as exploding, vanishing, or + ambiguous retain the bulk fit. -The main accepted losses remain the difficult shapes identified by the R -experiments. At $n=2000$, Gamma$(0.75)$ has global/boundary ratios -1.085/1.098, Beta$(0.75,2)$ has 1.075/1.072, and the reflected -Beta$(2,0.75)$ has 1.027/1.026. Gamma$(2)$ and Beta$(2,2)$ select bulk in every -large-sample replication and are exactly unchanged. Uniform, Beta$(1,2)$, and -Beta$(2,1)$ have $n=2000$ global ratios 0.844, 0.817, and 0.830. +## FFT accuracy and runtime -The deterministic native tests cover lower/upper reflection, independent -two-sided endpoint decisions, exploding/vanishing fallback, and affine support -changes. Their golden values were refreshed for the simplified evaluator. +The endpoint kernels are pointwise combinations of an ordinary Gaussian KDE +and its first two derivatives, evaluated on a shared 256-bin FFT grid. In the +100-replication development suite, the mean relative ISE perturbation from FFT +binning was at most 0.011% in every support/sample-size group. Among active +experts, the median absolute paired ISE change was 0.023%, the 99th percentile +was 0.18%, and the maximum was 0.66%. -## Runtime simplification ablation +The direct-kernel fallback was rejected. Across 51--401 output grid points at +$n=25,100$, always using FFT slowed the worst case by 1.25x. On the default +grid at $n=100$, one active endpoint changed from 0.64 to 0.67 ms and two +active endpoints from 0.77 to 0.74 ms. At $n=2000$, FFT reduced one-endpoint +fit time from 1.21 to 0.92 ms and two-endpoint time from 2.25 to 0.96 ms. -The direct native evaluator was simplified after the main validation. The -local-linear and local-quadratic equivalent kernels now share the degree-2 -bandwidth and are averaged in one observation loop. On bounded support this -bandwidth uses all endpoint distances; on one-sided support it uses the closest -75%. Endpoint kernels are evaluated only where their smooth fusion weights are -nonzero, Gaussian terms beyond six bandwidths are omitted, and the fused grid -is normalized once at the end. +## EDF approximation -A paired 100-replication check compared this implementation with commit -`cbde530` over Exponential, half-normal, Gamma$(2)$, Gamma$(0.75)$, Lomax$(2)$, -Uniform, Beta$(1,2)$, Beta$(0.75,2)$, Beta$(0.75,0.75)$, and Beta$(2,2)$. -Ratios compare the simplified evaluator with `cbde530`; parentheses contain -paired Monte Carlo standard errors: - -| support | $n$ | global ISE ratio | boundary ISE ratio | -|---|---:|---:|---:| -| one-sided | 25 | 0.996 (0.002) | 0.999 (0.004) | -| one-sided | 100 | 0.983 (0.003) | 0.982 (0.003) | -| one-sided | 1000 | 0.993 (0.003) | 0.992 (0.003) | -| one-sided | 2000 | 0.992 (0.003) | 0.991 (0.003) | -| two-sided | 25 | 1.010 (0.003) | 1.014 (0.006) | -| two-sided | 100 | 0.999 (0.002) | 1.002 (0.004) | -| two-sided | 1000 | 0.999 (0.003) | 0.992 (0.004) | -| two-sided | 2000 | 0.994 (0.003) | 0.986 (0.004) | - -The largest scenario-level increases were about 3.5% for Gamma$(0.75)$ and -3.9% for Beta$(0.75,0.75)$; Uniform, Beta$(1,2)$, Exponential, half-normal, -and Lomax generally improved. This supports the simpler shared-bandwidth -kernel average without a material aggregate accuracy cost. - -## EDF check - -The conditional mixture EDF was compared with +The conditional mixture EDF was checked against $$ 1+\sum_i\{\log\widehat f(X_i)-\log\widehat f_{-i}(X_i)\}. $$ -For deterministic finite-endpoint samples at $n=25,50,100$, the discrepancy -was 0.08--0.30 EDF units for Uniform and Exponential examples. The asymmetric -Beta$(1,2)$ discrepancy was 0.27--0.33 at $n=50,100$ and 0.84 at $n=25$. -This is adequate for the existing asymptotic EDF convention and does not -justify a weight-derivative correction. Pure-bulk fits retain the old EDF -exactly. - -## Fit time - -Release builds were timed against `4f3d148`. Bulk-classified fits incur only -sorting and remain close to baseline. With a 401-point output grid, the -simplified active-expert timings are: - -| active endpoints | $n=100$ | $n=1000$ | $n=2000$ | -|---|---:|---:|---:| -| one | 0.65 ms (1.7x) | 0.94 ms (2.0x) | 1.22 ms (2.1x) | -| two | 0.78 ms (2.0x) | 1.63 ms (3.7x) | 2.26 ms (4.4x) | - -Relative to `cbde530`, this is a speedup of 2.6--8.7x for one active endpoint -and 3.7--8.3x for two. Absolute expert-fit cost remains below 2.3 ms at -$n=2000$ in this benchmark. - -### FFT evaluation - -The endpoint kernel can be written as a pointwise combination of an ordinary -Gaussian KDE and its first two derivatives. The implementation now evaluates -these three translation-invariant convolutions on a regular 256-bin grid and -interpolates them to the endpoint grid. - -Against the direct endpoint evaluator, total fit times with the default -401-point grid were: - -| active endpoints | $n$ | direct | FFT | speedup | -|---|---:|---:|---:|---:| -| one | 1000 | 0.93 ms | 0.78 ms | 1.19x | -| one | 2000 | 1.21 ms | 0.92 ms | 1.32x | -| two | 1000 | 1.62 ms | 0.84 ms | 1.93x | -| two | 2000 | 2.25 ms | 0.96 ms | 2.35x | - -The direct-kernel fallback was removed after a separate $n=25,100$ benchmark. -Across 51--401 grid points, the worst total-fit slowdown from always using FFT -was 1.25x. With the default grid at $n=100$, one endpoint slowed from 0.64 to -0.67 ms while two endpoints improved slightly from 0.77 to 0.74 ms. In the -100-replication validation suite, the mean relative ISE perturbation from FFT -binning was at most 0.011% for every support/sample-size group. Among fits -whose endpoint expert was active, the median absolute paired ISE change was -0.023%, the 99th percentile was 0.18%, and the maximum was 0.66%. - -## Reproduction - -Install the package with a clean native rebuild at each revision and run -`validate_native_boundary_experts.R`, giving each run a distinct method label -and output file. The script writes replication-level ISE/EDF/log-likelihood and -a companion bias/variance summary. Join the two raw files by support, -scenario, sample size, and replication for paired ratios and uncertainty. +For deterministic finite-endpoint samples at $n=25,50,100$, discrepancies +were 0.08--0.30 EDF units for Uniform and Exponential examples. For +Beta$(1,2)$ they were 0.27--0.33 at $n=50,100$ and 0.84 at $n=25$. This was +considered adequate for an asymptotic trace approximation that already holds +bandwidths fixed. Pure-bulk fits retain the prior EDF calculation exactly. diff --git a/diagnostic/README.md b/diagnostic/README.md index 85687d3..b3d7eec 100644 --- a/diagnostic/README.md +++ b/diagnostic/README.md @@ -1,42 +1,48 @@ -# Boundary diagnostics +# Boundary-expert validation -The diagnostic sweep evaluates deterministic samples from distributions with -known densities and CDFs. It covers finite and one-sided supports, support -scales from `1e-4` to `1e4`, polynomial degrees 0--2, grid sizes 100--1,000, -and fixed or automatically selected bandwidths. Evaluation points approach the -boundary on a logarithmic scale. +This directory contains the retained validation path for the native estimator. +The estimator itself, including the support transforms, endpoint classifier, +boundary kernels, fusion, bandwidth handling, and EDF approximation, is +documented in [`../docs/overview-continuous.dox`](../docs/overview-continuous.dox). -Generate the raw CSV data and an optional summary and PDF with: +## Final comparison -```sh -diagnostic/run_boundary_diagnostics.sh > boundary-diagnostics.csv -Rscript diagnostic/plot_boundary_diagnostics.R boundary-diagnostics.csv -``` +`validate_native_boundary_experts.R` evaluates one installed implementation at +a time. Run it with these method labels: -The executable is deliberately not registered with CTest. Its output is for -comparing numerical behavior between revisions; stable invariants discovered -through the sweep should be promoted to focused regression tests. +| method | installed revision | estimator | +|---|---|---| +| `pre-pr` | pre-PR `main` (`1260b5e` for the planned comparison) | production log transform on one-sided support and probit transform on two-sided support | +| `bulk` | candidate | fourth-root/probit bulk with `boundary_repair = FALSE` | +| `expert` | candidate | fourth-root/probit bulk with the selected boundary experts | -The summary reports four complementary diagnostics: +Using the actual pre-PR revision is intentional: emulating its log transform in +the candidate would miss other grid and numerical behavior of the production +benchmark. -- PDF and CDF error against known distributions near the boundary; -- equivariance when the same data are expressed at different scales; -- agreement between left-bounded fits and reflected right-bounded fits; -- sensitivity to the interpolation grid size. +The suite covers lower- and upper-bounded versions of five one-sided densities +at scales `1e-4`, `1`, and `1e4`, seven two-sided densities, and sample sizes +25, 100, 1,000, and 2,000. It writes replication-level global and boundary ISE, +EDF, and log-likelihood, plus integrated squared bias and variance summaries. +Paired seeds are shared across methods. -The metrics deliberately remain separate. Relative density error is not useful -where the true density vanishes, while CDF error can remain small despite a -severely unstable pointwise density. Candidate repairs should therefore be -checked against both finite nonzero boundary densities and densities that tend -to zero. +From the R-package root, install each requested revision into a separate +library and run, for example: -The separate transformation-boundary investigation, its retained simulation -results, and its current recommendations live in -[`boundary-repair/`](boundary-repair/README.md). +```sh +Rscript inst/include/kde1d-cpp/diagnostic/validate_native_boundary_experts.R \ + pre-pr diagnostic-results/pre-pr.csv 100 /path/to/pre-pr-library +Rscript inst/include/kde1d-cpp/diagnostic/validate_native_boundary_experts.R \ + bulk diagnostic-results/bulk.csv 100 /path/to/candidate-library +Rscript inst/include/kde1d-cpp/diagnostic/validate_native_boundary_experts.R \ + expert diagnostic-results/expert.csv 100 /path/to/candidate-library +``` -The follow-up for supports with exactly one finite endpoint lives in -[`one-sided-repair/`](one-sided-repair/README.md). +Generated CSVs and figures are not versioned. The final aggregate comparison +and representative plots should be recorded in `NATIVE_RESULTS.md` after the +validation is complete. -The shared native implementation is evaluated by -[`validate_native_boundary_experts.R`](validate_native_boundary_experts.R), -with current results summarized in [`NATIVE_RESULTS.md`](NATIVE_RESULTS.md). +`NATIVE_RESULTS.md` currently retains only implementation-level evidence that +still applies to the selected estimator. Superseded R prototypes, candidate +estimators, tuning outputs, and the standalone C++ diagnostic were removed; +stable numerical properties are covered by the unit and invariant tests. diff --git a/diagnostic/boundary-repair/HANDOFF.md b/diagnostic/boundary-repair/HANDOFF.md deleted file mode 100644 index 3d66ef0..0000000 --- a/diagnostic/boundary-repair/HANDOFF.md +++ /dev/null @@ -1,51 +0,0 @@ -# Two-boundary repair handoff - -## Current state - -The directory now contains one experimental estimator for continuous data -with two known finite bounds. It fits the current probit bulk estimator once, -adds an averaged local-linear/local-quadratic kernel expert for confidently -finite endpoints, and otherwise reuses bulk. The kernels share one degree-2 -bandwidth and smooth CDF-scale weights shrink as $n^{-1/2}$. The -finite-endpoint classifier uses -$k=\min(n-1,\lceil2\sqrt n\rceil)$ order statistics and a 95% decision. - -There is no exploding-tail expert, power warp, transformation offset, or CV -selector. Superseded oversmoothing and offset code and outputs were removed. -The retained 100-replication validation and classifier ablation are summarized -in `RESULTS.md`. - -## Reproduce - -From the R-package root: - -```sh -Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R -Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R -Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R 100 -Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R -``` - -For a smoke test, pass a smaller replication count and temporary output path -as the first two arguments to either simulation script. - -## Known limitations - -- The R reference assumes support $[0,1]$; native code must apply an affine - map for arbitrary finite bounds. -- Weighted observations have not been specified or validated for the tail - index or shrinking weights. -- The finite-versus-bulk decision is hard, so between-sample endpoint behavior - can still change discretely. -- Before release, test affine support changes, weaker and stronger endpoint - singularities, interior modes, ties, and weighted data. - -## Next work - -The immediate next investigation is the analogous one-sided estimator. Keep -that work in a separate sibling diagnostic directory so this two-boundary -reference remains stable. Native implementation of this estimator should -follow `NATIVE_CPP.md` after the one-sided design has settled enough to assess -shared infrastructure. - -Unrelated top-level generated documentation changes were left untouched. diff --git a/diagnostic/boundary-repair/NATIVE_CPP.md b/diagnostic/boundary-repair/NATIVE_CPP.md deleted file mode 100644 index 45608d8..0000000 --- a/diagnostic/boundary-repair/NATIVE_CPP.md +++ /dev/null @@ -1,5 +0,0 @@ -# Native C++ implementation plan - -The canonical native roadmap now covers the shared one- and two-sided -boundary-expert implementation. See -[`../one-sided-repair/NATIVE_CPP.md`](../one-sided-repair/NATIVE_CPP.md). diff --git a/diagnostic/boundary-repair/README.md b/diagnostic/boundary-repair/README.md deleted file mode 100644 index 0fbb4e6..0000000 --- a/diagnostic/boundary-repair/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# Two-sided boundary repair - -This directory contains the selected experimental estimator for continuous -densities on a known finite interval, its paired validation against the -current probit estimator, and the retained endpoint-classifier ablation. - -## Selected estimator - -The reference implementation assumes the support has been mapped affinely to -$[0,1]$. First fit the current unweighted probit estimator $\widehat f_B$ and -use its CDF to define sample-shrinking endpoint weights. With -$r_n=\min(0.25,n^{-1/2})$ and $s(t)=3t^2-2t^3$, - -$$ -w_L(x)=1-s\left(\min\left\{1,\frac{\widehat F_B(x)}{r_n}\right\}\right), -\qquad -w_U(x)=1-s\left(\min\left\{1,\frac{1-\widehat F_B(x)}{r_n}\right\}\right), -$$ - -and $w_B(x)=1-w_L(x)-w_U(x)$. The finite-boundary expert averages Gaussian -equivalent-kernel local-linear and local-quadratic kernels using one degree-2 -bandwidth selected from all endpoint distances. Density contributions remain -unweighted, so the estimand does not change. The native evaluator computes the -expert only where its fusion weight is nonzero, truncates negative values, and -normalizes once after fusion. - -Finite endpoint behavior is identified from -$k=\min(n-1,\lceil2\sqrt n\rceil)$ order statistics. At the lower endpoint, - -$$ -\widehat\beta_L -= -\frac{k}{\sum_{i=1}^k -\log\{X_{(k+1)}/X_{(i)}\}}, -$$ - -with the analogous calculation on $1-X$ at the upper endpoint. The finite -expert is used if -$\widehat\beta\geq0.9$ and -$\widehat\beta(1-1.645/\sqrt{k})\leq1$; otherwise the endpoint reuses the bulk -estimator. Thus exploding, vanishing, and ambiguous endpoints require no -additional fit. - -The finite or bulk endpoint components are fused with $w_L,w_B,w_U$, -truncated at zero, and normalized numerically. There is no power transform, -offset transform, oversmoothed tail expert, or cross-validation selector. - -## Retained files - -- `scripts/bounded_estimator.R`: pre-native tuning implementation. -- `scripts/validate_bounded_estimator.R`: paired validation against current. -- `scripts/plot_bounded_estimator_validation.R`: numerical and realization - report. -- `scripts/ablate_endpoint_classifier.R`: paired classifier ablation. -- `scripts/plot_endpoint_classifier_ablation.R`: classifier report. -- `results/` and `plots/`: corresponding 100-replication outputs. -- `RESULTS.md`: final numerical conclusions. -- `HANDOFF.md`: concise continuation state. -- `NATIVE_CPP.md`: pointer to the shared one- and two-sided native roadmap. - -Run from the R-package root: - -```sh -Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R -Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R -Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R 100 -Rscript inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R -``` diff --git a/diagnostic/boundary-repair/RESULTS.md b/diagnostic/boundary-repair/RESULTS.md deleted file mode 100644 index 128f69e..0000000 --- a/diagnostic/boundary-repair/RESULTS.md +++ /dev/null @@ -1,59 +0,0 @@ -# Validation results - -## Final estimator - -The final two-boundary estimator combines the current probit bulk fit with an -equal local-linear/local-quadratic expert at endpoints classified as finite. -All other endpoint types reuse bulk. The validation uses 100 paired -replications for Uniform, Beta$(1,2)$, Beta$(0.75,2)$, and -Beta$(0.75,0.75)$ at $n=100,1000,2000$. The primary measure is integrated -squared error (ISE). - -Global ISE ratios to the current bounded estimator are: - -| density | $n=100$ | $n=1000$ | $n=2000$ | -|---|---:|---:|---:| -| Uniform | 0.884 | 0.830 | 0.814 | -| Beta$(1,2)$ | 0.879 | 0.818 | 0.802 | -| Beta$(0.75,2)$ | 0.943 | 1.050 | 1.045 | -| Beta$(0.75,0.75)$ | 0.945 | 1.037 | 1.033 | - -Mean ratios across the four densities are 0.913, 0.934, and 0.923. The -finite-endpoint cases improve clearly. Losses for exploding densities are -small and accepted in exchange for keeping a generic, shape-agnostic finite -expert. - -All retained estimates are nonnegative and normalized numerically. The -maximum mass error in the validation is $2.2\times10^{-16}$. - -## Endpoint classifier - -The selected rule uses one tail-index estimate with -$k=\min(n-1,\lceil2\sqrt n\rceil)$ and a 95% finite-endpoint decision. It was -compared with single scales $\sqrt n$ and $1.5\sqrt n$, and multiscale median -and voting rules. Mean ISE ratios to current are: - -| $n$ | $\sqrt n$, 95% | $2\sqrt n$, 95% | multiscale vote, 90% | -|---:|---:|---:|---:| -| 100 | 0.885 | 0.912 | 0.919 | -| 1000 | 0.976 | 0.936 | 0.996 | -| 2000 | 0.994 | 0.921 | 0.981 | - -The smaller scale is slightly better at $n=100$, but $2\sqrt n$ is clearly -better at $n=1000,2000$ and substantially reduces the worst exploding-tail -loss. Multiscale classification adds complexity without improving ISE or the -representative fits. - -## Bulk decision for nonfinite endpoints - -A final focused comparison used asymmetric Beta$(a,2)$ and symmetric -Beta$(a,a)$ densities for $a=0.9,0.75,0.6$. An oversmoothed probit tail reduced -integrated variance by roughly one third, but its mean ISE ratios to simply -reusing bulk were 0.948, 1.079, and 1.095 at $n=100,1000,2000$. Bulk won all -six large-sample scenarios. The additional transformed fit, offset, bandwidth -multiplier, and fusion branch were therefore removed from the selected -estimator. - -The retained CSVs contain global and endpoint-local ISE, squared bias, -integrated variance, selection rates, minimum density, and mass error. The -PDFs add representative full-density and logarithmic-distance endpoint plots. diff --git a/diagnostic/boundary-repair/plots/bounded-estimator-validation.pdf b/diagnostic/boundary-repair/plots/bounded-estimator-validation.pdf deleted file mode 100644 index 4cc2542177c80985f191f43a8d52acb5cdb2772c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70646 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 diff --git a/diagnostic/boundary-repair/plots/endpoint-classifier-ablation.pdf b/diagnostic/boundary-repair/plots/endpoint-classifier-ablation.pdf deleted file mode 100644 index 3a26b5f5df5054e02c34bae2be7271be24263b64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77147 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
3B95lS$8S)-dE*iAfbmqDABh24aHIAT`!kQ= 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 QVX-K@prWF&wTa;W0UT{W6951J diff --git a/diagnostic/boundary-repair/results/bounded-estimator-validation.csv b/diagnostic/boundary-repair/results/bounded-estimator-validation.csv deleted file mode 100644 index 2266312..0000000 --- a/diagnostic/boundary-repair/results/bounded-estimator-validation.csv +++ /dev/null @@ -1,25 +0,0 @@ -"distribution","sample_size","replications","method","global_ise","global_ise_median","global_squared_bias","global_variance","left_ise","left_squared_bias","left_variance","right_ise","right_squared_bias","right_variance","lower_finite_rate","upper_finite_rate","lower_bulk_rate","upper_bulk_rate","minimum_density","maximum_mass_error" -"uniform",100,100,"current",0.0394376359325329,0.0338111604704578,0.000617180948333801,0.0388204549841991,0.0143090894493515,0.000329356842577829,0.0139797326067737,0.0119951702383231,5.07569694759032e-05,0.0119444132688472,NA,NA,NA,NA,0,1.11022302462516e-16 -"uniform",100,100,"selected",0.0348777989524127,0.026772428104564,0.000732746013117419,0.0341450529392953,0.0113822372997225,0.000287103069134737,0.0110951342305877,0.0105132810395891,0.000250949704263428,0.0102623313353256,0.67,0.71,0.33,0.29,0,2.22044604925031e-16 -"uniform",1000,100,"current",0.00455374226860925,0.00377493251816298,0.000120426238243223,0.00443331603036602,0.00166512497918556,7.02679895893482e-05,0.00159485698959621,0.00156545415124511,1.10297242802776e-05,0.00155442442696484,NA,NA,NA,NA,6.32797475579434e-09,2.22044604925031e-16 -"uniform",1000,100,"selected",0.00377752447828285,0.00300211604552172,9.73413970320961e-05,0.00368018308125076,0.00130195385815075,3.46665195773036e-05,0.00126728733857345,0.00116196816839797,3.04849796492858e-05,0.00113148318874868,0.78,0.75,0.22,0.25,1.93936477529325e-05,2.22044604925031e-16 -"uniform",2000,100,"current",0.00219073406404686,0.00192055379535926,5.53558190218886e-05,0.00213537824502498,0.000783683950013612,3.33444879551106e-05,0.000750339462058502,0.000815932318097777,1.52965600524858e-05,0.000800635758045291,NA,NA,NA,NA,0.00041306652255468,1.11022302462516e-16 -"uniform",2000,100,"selected",0.00178253309691287,0.00151417624660391,2.00338606849405e-05,0.00176249923622793,0.00055128516716811,6.31058532121784e-06,0.000544974581846892,0.000642140498147629,7.02233285931979e-06,0.000635118165288309,0.88,0.82,0.12,0.18,0.000427940598708137,1.11022302462516e-16 -"beta-1-2",100,100,"current",0.0454039530333344,0.0378817494739727,0.000294496132934666,0.0451094569003997,0.0308242314704997,9.61419783217316e-05,0.0307280894921779,0.000619383994696991,7.68869882163405e-06,0.000611695295875357,NA,NA,NA,NA,0,1.11022302462516e-16 -"beta-1-2",100,100,"selected",0.0398899718020702,0.0284120449632399,0.000575661274437074,0.0393143105276331,0.0251426161241531,0.000399150610548051,0.0247434655136051,0.000761578605536506,9.98520133962911e-06,0.000751593404196877,0.59,0.13,0.41,0.87,0,1.11022302462516e-16 -"beta-1-2",1000,100,"current",0.00619849332649953,0.00538986832082836,8.06843343984859e-05,0.00611780899210105,0.0044487283767016,7.43173699097184e-05,0.00437441100679188,8.71119362452834e-05,7.00981152975579e-08,8.70418381299858e-05,NA,NA,NA,NA,0,1.11022302462516e-16 -"beta-1-2",1000,100,"selected",0.00507124781292705,0.0038351154993051,6.30407278622915e-05,0.00500820708506475,0.00332739234761219,5.50301044221794e-05,0.00327236224319001,8.69390062784019e-05,8.23561012186089e-08,8.68566501771833e-05,0.8,0,0.2,1,0,1.11022302462516e-16 -"beta-1-2",2000,100,"current",0.00269830501263795,0.00240268850898862,5.7379479881232e-05,0.00264092553275672,0.00188144723847374,4.60804519336171e-05,0.00183536678654012,3.44468945601477e-05,7.21472861216931e-07,3.37254216989307e-05,NA,NA,NA,NA,0,2.22044604925031e-16 -"beta-1-2",2000,100,"selected",0.00216467208617947,0.00176963180531096,3.74612394644642e-05,0.002127210846715,0.00135151630196739,2.58746584550445e-05,0.00132564164351235,3.44241145998833e-05,7.33286870140865e-07,3.36908277297425e-05,0.82,0,0.18,1,0,2.22044604925031e-16 -"beta-0.75-2",100,100,"current",0.104720547076617,0.078388069609558,0.0109053419453534,0.0938152051312638,0.092826145012719,0.010755039731205,0.082071105281514,0.000294257769639688,4.31895439320073e-07,0.000293825874200368,NA,NA,NA,NA,0,1.11022302462516e-16 -"beta-0.75-2",100,100,"selected",0.0987766159045782,0.0786622783748146,0.0100657362740795,0.0887108796304987,0.0868085593832687,0.00992193113189107,0.0768866282513777,0.000333570896186141,1.43319523306781e-06,0.000332137700953073,0.18,0.05,0.82,0.95,0,1.11022302462516e-16 -"beta-0.75-2",1000,100,"current",0.0191565263143446,0.0164151173872431,0.00755189921993969,0.0116046270944049,0.0178080933087401,0.00752360339569207,0.010284489913048,4.7184329064819e-05,4.95109523993255e-07,4.66892195408257e-05,NA,NA,NA,NA,0,2.22044604925031e-16 -"beta-0.75-2",1000,100,"selected",0.0201222594239744,0.0164151173872431,0.00773244033317598,0.0123898190907984,0.0187711681332489,0.00770407109713924,0.0110670970361096,4.72294630729243e-05,4.92309258282758e-07,4.67371538146415e-05,0.06,0,0.94,1,0,2.22044604925031e-16 -"beta-0.75-2",2000,100,"current",0.0148612960341197,0.0130187542490117,0.00855237291074781,0.00630892312337185,0.0141683912522109,0.00851857159113627,0.00564981966107461,2.40093648581477e-05,5.78564251466386e-08,2.39515084330011e-05,NA,NA,NA,NA,0,2.22044604925031e-16 -"beta-0.75-2",2000,100,"selected",0.0155261390665641,0.0130187542490117,0.0086390314906581,0.00688710757590605,0.014830894988867,0.00860545745293673,0.00622543753593024,2.40038076246844e-05,5.64761885801453e-08,2.39473314361043e-05,0.06,0,0.94,1,0,1.11022302462516e-16 -"beta-0.75-0.75",100,100,"current",0.0698084190975684,0.0581896383336078,0.00155949393231754,0.0682489251652509,0.02982964896149,0.000960676657862926,0.0288689723036271,0.0328385552456753,0.000592860451193691,0.0322456947944816,NA,NA,NA,NA,1.00337510605646e-53,1.11022302462516e-16 -"beta-0.75-0.75",100,100,"selected",0.0659995179633665,0.05319205202227,0.00163226917192385,0.0643672487914426,0.028467322042892,0.000940245360854324,0.0275270766820377,0.0304420977085639,0.000682184099958427,0.0297599136086055,0.25,0.23,0.75,0.77,2.70295283383755e-08,1.11022302462516e-16 -"beta-0.75-0.75",1000,100,"current",0.00989852286075191,0.0088598631051671,0.00274707166757628,0.00715145119317563,0.00455528025338978,0.00135139391358385,0.00320388633980593,0.00446910740708714,0.00138765866671413,0.00308144874037302,NA,NA,NA,NA,0.163655037117267,1.11022302462516e-16 -"beta-0.75-0.75",1000,100,"selected",0.0102687283458827,0.0088598631051671,0.00279848820038407,0.00747024014549865,0.0047423306796736,0.00138733024305387,0.00335500043661973,0.00464944672637947,0.00140255271122454,0.00324689401515493,0.09,0.06,0.91,0.94,0.639857430838072,1.11022302462516e-16 -"beta-0.75-0.75",2000,100,"current",0.0067112597444121,0.00593016483343542,0.00268017857954491,0.00403108116486719,0.00294324243876054,0.0013077911745055,0.00163545126425505,0.00329549979435017,0.00135110913373508,0.00194439066061508,NA,NA,NA,NA,0.37705599508214,2.22044604925031e-16 -"beta-0.75-0.75",2000,100,"selected",0.00693306659961766,0.00593016483343542,0.002711448599349,0.00422161800026865,0.00309305200309237,0.00133529603139543,0.00175775597169694,0.00336651740633136,0.00135459479260747,0.00201192261372389,0.05,0.04,0.95,0.96,0.37705599508214,1.11022302462516e-16 diff --git a/diagnostic/boundary-repair/results/endpoint-classifier-ablation.csv b/diagnostic/boundary-repair/results/endpoint-classifier-ablation.csv deleted file mode 100644 index 0ee71bb..0000000 --- a/diagnostic/boundary-repair/results/endpoint-classifier-ablation.csv +++ /dev/null @@ -1,85 +0,0 @@ -"distribution","sample_size","replications","method","global_ise","global_squared_bias","global_variance","left_ise","left_squared_bias","left_variance","right_ise","right_squared_bias","right_variance","lower_accuracy","upper_accuracy","lower_finite_rate","upper_finite_rate","minimum_density","maximum_mass_error" -"uniform",100,100,"kde-current",0.0395679608211775,0.000660315183665581,0.0389076456375119,0.0147140524945475,0.000353115726237842,0.0143609367683097,0.0119536069470872,7.93565361068368e-05,0.0118742504109804,NA,NA,NA,NA,0,1.11022302462516e-16 -"uniform",100,100,"single-95",0.0349551478183599,0.00096855258259265,0.0339865952357673,0.0119457705109792,0.000482444078260364,0.0114633264327188,0.0102912035338974,0.000305160231532077,0.00998604330236527,0.65,0.7,0.65,0.7,0,1.11022302462516e-16 -"uniform",100,100,"single-1.5-95",0.0351633913177871,0.000761433247192275,0.0344019580705948,0.012279634075376,0.000348221453612649,0.0119314126217634,0.0101504943845229,0.000232186903384519,0.00991830748113841,0.65,0.7,0.65,0.7,0,1.11022302462516e-16 -"uniform",100,100,"single-2-95",0.0349793140593923,0.000738228342999683,0.0342410857163926,0.0118474696512444,0.000350856077199829,0.0114966135740446,0.0103898593304783,0.000205771048124749,0.0101840882823535,0.67,0.73,0.67,0.73,0,2.22044604925031e-16 -"uniform",100,100,"median-90",0.0338757899115898,0.000435282615478925,0.0334405072961109,0.011397903010171,0.000210110326641735,0.0111877926835293,0.00966537216799255,3.69414920130523e-05,0.0096284306759795,0.79,0.79,0.79,0.79,0,1.11022302462516e-16 -"uniform",100,100,"vote-90",0.0338757899115898,0.000435282615478925,0.0334405072961109,0.011397903010171,0.000210110326641735,0.0111877926835293,0.00966537216799255,3.69414920130523e-05,0.0096284306759795,0.79,0.79,0.79,0.79,0,1.11022302462516e-16 -"uniform",100,100,"vote-95",0.0318854637679857,0.000444412789471119,0.0314410509785145,0.010832802032572,0.000206756505177359,0.0106260455273946,0.00823194765557557,5.0710003529682e-05,0.00818123765204589,0.87,0.9,0.87,0.9,0,1.11022302462516e-16 -"uniform",1000,100,"kde-current",0.00458911943386039,0.000123195088823585,0.00446592434503681,0.00166683029146066,6.92227494859114e-05,0.00159760754197475,0.00159673304722858,9.62432316008856e-06,0.0015871087240685,NA,NA,NA,NA,6.32797475579434e-09,2.22044604925031e-16 -"uniform",1000,100,"single-95",0.00379607956960838,0.000130996098302809,0.00366508347130558,0.0012843866686856,4.22612830929953e-05,0.00124212538559261,0.00120052007613777,5.1345594302538e-05,0.00114917448183523,0.74,0.7,0.74,0.7,6.33057767207451e-09,2.22044604925031e-16 -"uniform",1000,100,"single-1.5-95",0.00381767885835155,0.00012084718079626,0.00369683167755529,0.00127592738886872,3.27515762536521e-05,0.00124317581261507,0.00122912103360067,5.05283620314296e-05,0.00117859267156924,0.82,0.69,0.82,0.69,1.93936477529325e-05,2.22044604925031e-16 -"uniform",1000,100,"single-2-95",0.00381184942018333,9.90963734823122e-05,0.00371275304670102,0.00130522324074235,3.29075871114687e-05,0.00127231565363089,0.00118972143822462,2.83245258226514e-05,0.00116139691240197,0.78,0.75,0.78,0.75,1.93936477529325e-05,2.22044604925031e-16 -"uniform",1000,100,"median-90",0.0037637571051833,7.23407522910959e-05,0.0036914163528922,0.00127012675606472,2.79819544724081e-05,0.00124214480159231,0.0011777664292238,4.68625980623549e-06,0.00117308016941756,0.84,0.84,0.84,0.84,6.33057767207451e-09,2.22044604925031e-16 -"uniform",1000,100,"vote-90",0.0037637571051833,7.23407522910959e-05,0.0036914163528922,0.00127012675606472,2.79819544724081e-05,0.00124214480159231,0.0011777664292238,4.68625980623549e-06,0.00117308016941756,0.84,0.84,0.84,0.84,6.33057767207451e-09,2.22044604925031e-16 -"uniform",1000,100,"vote-95",0.00362762827836124,7.16661316866633e-05,0.00355596214667458,0.00120149079406307,2.56391144121468e-05,0.00117585167965092,0.00110939276034633,6.92558501454552e-06,0.00110246717533179,0.91,0.9,0.91,0.9,6.33057767207451e-09,2.22044604925031e-16 -"uniform",2000,100,"kde-current",0.00222178056987251,6.21791105355296e-05,0.00215960145933698,0.000768223716127646,2.96354139538484e-05,0.000738588302173798,0.000849021464606157,2.40080442937546e-05,0.000825013420312402,NA,NA,NA,NA,0.00041306652255468,1.11022302462516e-16 -"uniform",2000,100,"single-95",0.00182951975894074,2.90388099639102e-05,0.00180048094897683,0.000562771588628805,1.08061577264253e-05,0.00055196543090238,0.000664099182943261,9.85263060748603e-06,0.000654246552335775,0.81,0.79,0.81,0.79,0.000427940598708137,1.11022302462516e-16 -"uniform",2000,100,"single-1.5-95",0.00187194506155839,1.90093424679686e-05,0.00185293571909043,0.000600490360408868,5.22292067570678e-06,0.000595267439733161,0.000669679998506429,5.52531321147942e-06,0.00066415468529495,0.83,0.84,0.83,0.84,0.000427940598708137,1.11022302462516e-16 -"uniform",2000,100,"single-2-95",0.00180757806700822,2.34784277748362e-05,0.00178409963923338,0.000541100385218893,8.4533907650244e-06,0.000532646994453868,0.000664183635669372,6.68871426274667e-06,0.000657494921406625,0.88,0.84,0.88,0.84,0.000427940598708137,1.11022302462516e-16 -"uniform",2000,100,"median-90",0.00187888201249991,1.88665212566633e-05,0.00186001549124325,0.000564349997872153,5.29231814880099e-06,0.000559057679723352,0.000710664021296797,5.35257580931804e-06,0.000705311445487479,0.91,0.8,0.91,0.8,0.000427940598708137,1.11022302462516e-16 -"uniform",2000,100,"vote-90",0.00187888201249991,1.88665212566633e-05,0.00186001549124325,0.000564349997872153,5.29231814880099e-06,0.000559057679723352,0.000710664021296797,5.35257580931804e-06,0.000705311445487479,0.91,0.8,0.91,0.8,0.000427940598708137,1.11022302462516e-16 -"uniform",2000,100,"vote-95",0.00175012124004211,1.88458399207556e-05,0.00173127540012135,0.000543857025510756,5.57575581703163e-06,0.000538281269693724,0.00060376351646917,5.03215654702641e-06,0.000598731359922143,0.93,0.92,0.93,0.92,0.000427940598708137,1.11022302462516e-16 -"beta-1-2",100,100,"kde-current",0.0452169408150938,0.000354970969907924,0.0448619698451858,0.0306893049739044,0.00014262362515346,0.0305466813487509,0.000611637781132187,6.38147426040877e-06,0.000605256306871778,NA,NA,NA,NA,0,1.11022302462516e-16 -"beta-1-2",100,100,"single-95",0.0381578421479701,0.000645417448081303,0.0375124246998888,0.02355364871879,0.000457175981001329,0.0230964727377887,0.000768062583551767,1.92362063564655e-05,0.000748826377195302,0.67,0.51,0.67,0.49,0,2.22044604925031e-16 -"beta-1-2",100,100,"single-1.5-95",0.0391447581497541,0.000761530465982772,0.0383832276837713,0.0245139853396121,0.000573167886424792,0.0239408174531873,0.000768694620224218,1.26444380310741e-05,0.000756050182193144,0.59,0.75,0.59,0.25,0,1.11022302462516e-16 -"beta-1-2",100,100,"single-2-95",0.0394500514824982,0.000571865397191171,0.038878186085307,0.0247654009525492,0.000381396460769478,0.0243840044917797,0.000753658240802613,8.76337172050094e-06,0.000744894869082112,0.59,0.87,0.59,0.13,0,1.11022302462516e-16 -"beta-1-2",100,100,"median-90",0.0389604014953733,0.000299480749325628,0.0386609207460477,0.0242918518204971,8.17788016543939e-05,0.0242100730188427,0.000702443494037229,8.07378453048265e-06,0.000694369709506746,0.77,0.94,0.77,0.06,0,1.11022302462516e-16 -"beta-1-2",100,100,"vote-90",0.0389604014953733,0.000299480749325628,0.0386609207460477,0.0242918518204971,8.17788016543939e-05,0.0242100730188427,0.000702443494037229,8.07378453048265e-06,0.000694369709506746,0.77,0.94,0.77,0.06,0,1.11022302462516e-16 -"beta-1-2",100,100,"vote-95",0.0356643678809153,0.000217751309885197,0.0354466165710301,0.0210358597203943,1.81187809165201e-05,0.0210177409394778,0.000741777849535933,8.91808306355962e-06,0.000732859766472373,0.89,0.84,0.89,0.16,0,1.11022302462516e-16 -"beta-1-2",1000,100,"kde-current",0.00622941335597601,0.000101587564273177,0.00612782579170284,0.00451672337826204,9.43554387791781e-05,0.00442236793948286,9.02072744846522e-05,1.55460319135784e-08,9.01917284527386e-05,NA,NA,NA,NA,0,1.11022302462516e-16 -"beta-1-2",1000,100,"single-95",0.00529124863096217,0.000110121698790694,0.00518112693217148,0.00357825537492738,0.000100014564090765,0.00347824081083661,8.97843633139735e-05,1.1840214358906e-08,8.97725230996146e-05,0.66,0.99,0.66,0.01,0,1.11022302462516e-16 -"beta-1-2",1000,100,"single-1.5-95",0.00525536506766485,0.000101544516058266,0.00515382055160659,0.00354473395881986,9.15539265449705e-05,0.00345318003227489,9.00401007445582e-05,1.17497403758797e-08,9.00283510041823e-05,0.74,1,0.74,0,0,1.11022302462516e-16 -"beta-1-2",1000,100,"single-2-95",0.00513761227662957,5.78945891361482e-05,0.00507971768749342,0.00342972281757982,4.87076055548851e-05,0.00338101521202494,9.00239701021473e-05,1.24358879462303e-08,9.00115342142011e-05,0.77,1,0.77,0,0,1.11022302462516e-16 -"beta-1-2",1000,100,"median-90",0.0049123689857565,4.93722850242422e-05,0.00486299670073226,0.00320691875823006,4.07493449194204e-05,0.00316616941331064,9.00442888497998e-05,1.30619411365843e-08,9.00312269086632e-05,0.85,1,0.85,0,0,1.11022302462516e-16 -"beta-1-2",1000,100,"vote-90",0.0049123689857565,4.93722850242422e-05,0.00486299670073226,0.00320691875823006,4.07493449194204e-05,0.00316616941331064,9.00442888497998e-05,1.30619411365843e-08,9.00312269086632e-05,0.85,1,0.85,0,0,1.11022302462516e-16 -"beta-1-2",1000,100,"vote-95",0.00479175426470969,4.91523689740518e-05,0.00474260189573564,0.00308282424744127,4.05622837487035e-05,0.00304226196369257,9.01045323537463e-05,1.31951660768547e-08,9.00913371876695e-05,0.9,1,0.9,0,0,1.11022302462516e-16 -"beta-1-2",2000,100,"kde-current",0.00272230305310735,5.59676809242751e-05,0.00266633537218308,0.0019056790375289,4.31831657209516e-05,0.00186249587180795,3.49019550540507e-05,5.12563386140297e-07,3.43893916679104e-05,NA,NA,NA,NA,0,2.22044604925031e-16 -"beta-1-2",2000,100,"single-95",0.00227842226439808,3.40702721838305e-05,0.00224435199221425,0.00146586980788403,2.1089106066304e-05,0.00144478070181773,3.4873876560525e-05,5.18956936090987e-07,3.4354919624434e-05,0.74,1,0.74,0,0,2.22044604925031e-16 -"beta-1-2",2000,100,"single-1.5-95",0.00217658515518833,3.81566931004108e-05,0.00213842846208792,0.00136388840900227,2.50752121402069e-05,0.00133881319686206,3.4835864163282e-05,5.21680567860125e-07,3.43141835954219e-05,0.8,1,0.8,0,0,2.22044604925031e-16 -"beta-1-2",2000,100,"single-2-95",0.00215978434563467,3.94198605827913e-05,0.00212036448505188,0.00134606968415594,2.63280331240295e-05,0.00131974165103191,3.48458558427712e-05,5.21477750032391e-07,3.43243780927388e-05,0.82,1,0.82,0,0,2.22044604925031e-16 -"beta-1-2",2000,100,"median-90",0.00217684309476441,2.91319321580093e-05,0.0021477111626064,0.00136459368425178,1.62432324012425e-05,0.00134835045185054,3.48334709044314e-05,5.16930699224826e-07,3.43165402052066e-05,0.88,1,0.88,0,0,2.22044604925031e-16 -"beta-1-2",2000,100,"vote-90",0.00217684309476441,2.91319321580093e-05,0.0021477111626064,0.00136459368425178,1.62432324012425e-05,0.00134835045185054,3.48334709044314e-05,5.16930699224826e-07,3.43165402052066e-05,0.88,1,0.88,0,0,2.22044604925031e-16 -"beta-1-2",2000,100,"vote-95",0.00207141291327238,2.9292340230164e-05,0.00204212057304222,0.00125919314973815,1.63959872555449e-05,0.0012427971624826,3.4846487209274e-05,5.17220111703576e-07,3.43292670975705e-05,0.95,1,0.95,0,0,2.22044604925031e-16 -"beta-0.75-2",100,100,"kde-current",0.10333078278857,0.0119855482130719,0.0913452345754977,0.0917400982146583,0.0118000473232489,0.0799400508914094,0.000303702741962194,7.78354490929604e-07,0.000302924387471264,NA,NA,NA,NA,0,1.11022302462516e-16 -"beta-0.75-2",100,100,"single-95",0.0941217388781045,0.011349458756582,0.0827722801215225,0.0822135251348918,0.0111930600083389,0.0710204651265529,0.000450939023734345,1.53201727591279e-05,0.000435618850975217,0.75,0.52,0.25,0.48,0,1.11022302462516e-16 -"beta-0.75-2",100,100,"single-1.5-95",0.0947974087167762,0.0107399481755028,0.0840574605412734,0.0829664350643179,0.0105821776101739,0.072384257454144,0.000418017455627756,7.39349579874081e-06,0.000410623959829015,0.78,0.78,0.22,0.22,0,1.11022302462516e-16 -"beta-0.75-2",100,100,"single-2-95",0.0973258478625205,0.0110919402209551,0.0862339076415654,0.0856409967361105,0.0109161650043089,0.0747248317318016,0.00034650333943378,2.17330109423369e-06,0.000344330038339546,0.82,0.94,0.18,0.06,0,1.11022302462516e-16 -"beta-0.75-2",100,100,"median-90",0.104073466961675,0.0174343600649418,0.0866391068967335,0.092400973768718,0.0171693962689645,0.0752315774997535,0.000336932160326384,1.85192848496392e-06,0.00033508023184142,0.47,0.97,0.53,0.03,0,1.11022302462516e-16 -"beta-0.75-2",100,100,"vote-90",0.104073466961675,0.0174343600649418,0.0866391068967335,0.092400973768718,0.0171693962689645,0.0752315774997535,0.000336932160326384,1.85192848496392e-06,0.00033508023184142,0.47,0.97,0.53,0.03,0,1.11022302462516e-16 -"beta-0.75-2",100,100,"vote-95",0.107767494152978,0.0259133115617868,0.081854182591191,0.0958601247621016,0.0255811216121714,0.0702790031499302,0.000376011903308601,3.97172603832936e-06,0.000372040177270272,0.28,0.91,0.72,0.09,0,1.11022302462516e-16 -"beta-0.75-2",1000,100,"kde-current",0.0190167719805673,0.00748364876693982,0.0115331232136275,0.0176652908776476,0.00746281474640339,0.0102024761312443,4.61718908311821e-05,4.11391362501522e-07,4.57604994686805e-05,NA,NA,NA,NA,0,2.22044604925031e-16 -"beta-0.75-2",1000,100,"single-95",0.0216750884821827,0.00822517975230909,0.0134499087298736,0.0203126662836491,0.00820358015740727,0.0121090861262418,4.98199501522167e-05,5.36008590649573e-07,4.92839415615672e-05,0.87,0.97,0.13,0.03,0,2.22044604925031e-16 -"beta-0.75-2",1000,100,"single-1.5-95",0.0202283486798806,0.00777517646021835,0.0124531722196622,0.0188772549433714,0.00775421341037295,0.0111230415329985,4.62140569238117e-05,4.09161767609483e-07,4.58048951562022e-05,0.92,1,0.08,0,0,2.22044604925031e-16 -"beta-0.75-2",1000,100,"single-2-95",0.0199825050901971,0.00766579347108848,0.0123167116191086,0.0186283657021565,0.00764487387625293,0.0109834918259035,4.62170248392874e-05,4.09703777269343e-07,4.5807321062018e-05,0.94,1,0.06,0,0,2.22044604925031e-16 -"beta-0.75-2",1000,100,"median-90",0.0233981416545154,0.0088848493319451,0.0145132923225703,0.0220381666775545,0.00886288556872924,0.0131752811088253,4.62377835826615e-05,4.02073096310369e-07,4.58357104863512e-05,0.78,1,0.22,0,0,2.22044604925031e-16 -"beta-0.75-2",1000,100,"vote-90",0.0233981416545154,0.0088848493319451,0.0145132923225703,0.0220381666775545,0.00886288556872924,0.0131752811088253,4.62377835826615e-05,4.02073096310369e-07,4.58357104863512e-05,0.78,1,0.22,0,0,2.22044604925031e-16 -"beta-0.75-2",1000,100,"vote-95",0.0257620203679631,0.00985650758645671,0.0159055127815063,0.0244022726252111,0.00983354998846533,0.0145687226367458,4.63290826975616e-05,3.98468524490173e-07,4.59306141730714e-05,0.68,1,0.32,0,0,2.22044604925031e-16 -"beta-0.75-2",2000,100,"kde-current",0.01508555489414,0.00850923175013998,0.00657632314399997,0.0143894041053101,0.0084756555891786,0.00591374851613146,2.29872314005426e-05,1.83641597051423e-07,2.28035898034912e-05,NA,NA,NA,NA,0,2.22044604925031e-16 -"beta-0.75-2",2000,100,"single-95",0.0178927623292423,0.00931447188432378,0.00857829044491854,0.0171909169521438,0.00928145051848341,0.00790946643366039,2.30109518469592e-05,1.73395168733203e-07,2.2837556678226e-05,0.81,1,0.19,0,0,1.11022302462516e-16 -"beta-0.75-2",2000,100,"single-1.5-95",0.0164612710663761,0.0087588645792512,0.00770240648712489,0.0157624921763759,0.00872563247402369,0.00703685970235222,2.29791810666458e-05,1.79354615629126e-07,2.27998264510167e-05,0.9,1,0.1,0,0,1.11022302462516e-16 -"beta-0.75-2",2000,100,"single-2-95",0.0157503979265844,0.0085827190900329,0.00716767883655155,0.0150519078419661,0.0085493769885552,0.00650253085341095,2.29816741670793e-05,1.81112470633985e-07,2.28005616964453e-05,0.94,1,0.06,0,0,1.11022302462516e-16 -"beta-0.75-2",2000,100,"median-90",0.017694420737506,0.00919636996660086,0.00849805077090512,0.0169936481569977,0.00916327791737292,0.00783037023962477,2.30001070652951e-05,1.74838196823934e-07,2.28252688684712e-05,0.83,1,0.17,0,0,1.11022302462516e-16 -"beta-0.75-2",2000,100,"vote-90",0.017694420737506,0.00919636996660086,0.00849805077090512,0.0169936481569977,0.00916327791737292,0.00783037023962477,2.30001070652951e-05,1.74838196823934e-07,2.28252688684712e-05,0.83,1,0.17,0,0,1.11022302462516e-16 -"beta-0.75-2",2000,100,"vote-95",0.0189734607854946,0.00967388755222815,0.00929957323326641,0.0182724507734024,0.00964087574067331,0.00863157503272911,2.30170026525439e-05,1.71432647905287e-07,2.28455700046386e-05,0.77,1,0.23,0,0,1.11022302462516e-16 -"beta-0.75-0.75",100,100,"kde-current",0.0701482728754187,0.00155813534598916,0.0685901375294296,0.0304626880324348,0.000949055694439168,0.0295136323379957,0.0325734665545723,0.000599057090266889,0.0319744094643054,NA,NA,NA,NA,1.00337510605646e-53,1.11022302462516e-16 -"beta-0.75-0.75",100,100,"single-95",0.0633027826564518,0.00155650647026388,0.0617462761861879,0.0265330555588591,0.000844633122721144,0.025688422436138,0.0297734339887635,0.000697285110476889,0.0290761488782866,0.71,0.7,0.29,0.3,2.70295283383755e-08,1.11022302462516e-16 -"beta-0.75-0.75",100,100,"single-1.5-95",0.0653837942836675,0.00156500048051562,0.0638187938031519,0.0279714803616632,0.000867686562138423,0.0271037937995248,0.0303574143960939,0.000683053509164122,0.0296743608869298,0.73,0.76,0.27,0.24,5.68124764878753e-08,1.11022302462516e-16 -"beta-0.75-0.75",100,100,"single-2-95",0.0664838619258033,0.00163330495450213,0.0648505569713012,0.0291088443155113,0.000933175566093991,0.0281756687494173,0.0303121944539524,0.000686289887512471,0.0296259045664399,0.75,0.79,0.25,0.21,2.70295283383755e-08,1.11022302462516e-16 -"beta-0.75-0.75",100,100,"median-90",0.0668447189934785,0.00213687174922969,0.0647078472442488,0.028657209378944,0.00148416979983781,0.0271730395791061,0.03112554574768,0.000642603244003097,0.0304829425036769,0.46,0.51,0.54,0.49,1.74518520713497e-07,1.11022302462516e-16 -"beta-0.75-0.75",100,100,"vote-90",0.0668447189934785,0.00213687174922969,0.0647078472442488,0.028657209378944,0.00148416979983781,0.0271730395791061,0.03112554574768,0.000642603244003097,0.0304829425036769,0.46,0.51,0.54,0.49,1.74518520713497e-07,1.11022302462516e-16 -"beta-0.75-0.75",100,100,"vote-95",0.0651942669000884,0.00390161803235702,0.0612926488677314,0.0280949089361279,0.00231658005540894,0.025778328880719,0.0300949288785869,0.00157248430593897,0.0285224445726479,0.34,0.31,0.66,0.69,7.59886136601248e-06,1.11022302462516e-16 -"beta-0.75-0.75",1000,100,"kde-current",0.00988648152079718,0.00273966149466241,0.00714682002613477,0.00460950574110299,0.00138524004010197,0.00322426570100101,0.00442155731559371,0.00134556387167816,0.00307599344391555,NA,NA,NA,NA,0.163655037117267,1.11022302462516e-16 -"beta-0.75-0.75",1000,100,"single-95",0.0107405089864702,0.00286916198635601,0.00787134700011416,0.00499918531901173,0.0014468169621687,0.00355236835684303,0.00487935167031932,0.00141164183742496,0.00346770983289435,0.87,0.88,0.13,0.12,0.7863851245034,1.11022302462516e-16 -"beta-0.75-0.75",1000,100,"single-1.5-95",0.0102870666247854,0.00278567543416402,0.00750139119062134,0.00471646598499695,0.00139127994492352,0.00332518604007342,0.00471221266704946,0.00138465804761353,0.00332755461943593,0.92,0.91,0.08,0.09,0.639857430838072,1.11022302462516e-16 -"beta-0.75-0.75",1000,100,"single-2-95",0.010256687005928,0.00279203515035173,0.00746465185557625,0.00479655616738681,0.0014232208918276,0.00337333527555921,0.00460189663488603,0.00135933149427092,0.00324256514061511,0.91,0.94,0.09,0.06,0.639857430838072,1.11022302462516e-16 -"beta-0.75-0.75",1000,100,"median-90",0.0113341946744834,0.00303692624943848,0.00829726842504488,0.00552601607198135,0.00161612956839203,0.00390988650358932,0.0049441561729981,0.00140943241263818,0.00353472376035992,0.77,0.85,0.23,0.15,0.639857430838072,1.11022302462516e-16 -"beta-0.75-0.75",1000,100,"vote-90",0.0113341946744834,0.00303692624943848,0.00829726842504488,0.00552601607198135,0.00161612956839203,0.00390988650358932,0.0049441561729981,0.00140943241263818,0.00353472376035992,0.77,0.85,0.23,0.15,0.639857430838072,1.11022302462516e-16 -"beta-0.75-0.75",1000,100,"vote-95",0.0127905333626411,0.00350784384396239,0.00928268951867866,0.00628801233826839,0.00189437702781669,0.00439363531045169,0.00563172873977056,0.00159931848395278,0.00403241025581779,0.66,0.74,0.34,0.26,0.7863851245034,1.11022302462516e-16 -"beta-0.75-0.75",2000,100,"kde-current",0.00684077886201357,0.00270665655031356,0.00413412231170002,0.00304691730201407,0.0013214906725532,0.00172542662946087,0.00332276610510772,0.00136989453476547,0.00195287157034225,NA,NA,NA,NA,0.37705599508214,2.22044604925031e-16 -"beta-0.75-0.75",2000,100,"single-95",0.00772900065720123,0.00299776559822408,0.00473123505897715,0.00352806248353887,0.00141371011658039,0.00211435236695848,0.0037271196112084,0.00156706684549027,0.00216005276571813,0.88,0.86,0.12,0.14,0.793775176927469,1.11022302462516e-16 -"beta-0.75-0.75",2000,100,"single-1.5-95",0.00713066662475509,0.0027464281638779,0.00438423846087719,0.00318155231896237,0.00133992409120143,0.00184162822776094,0.00347775798206784,0.00139074625748771,0.00208701172458013,0.94,0.93,0.06,0.07,0.793775176927469,1.11022302462516e-16 -"beta-0.75-0.75",2000,100,"single-2-95",0.00706075203244803,0.00273322696679824,0.00432752506564979,0.003194836709572,0.00134366972475958,0.00185116698481242,0.00339375219571971,0.00137397305064016,0.00201977914507954,0.94,0.96,0.06,0.04,0.37705599508214,1.11022302462516e-16 -"beta-0.75-0.75",2000,100,"median-90",0.0075581872325074,0.0028437896946846,0.0047143975378228,0.0034810219983618,0.00140846040120306,0.00207256159715873,0.00360446463231341,0.00141899086237187,0.00218547376994154,0.88,0.9,0.12,0.1,0.793775176927469,1.11022302462516e-16 -"beta-0.75-0.75",2000,100,"vote-90",0.00756867245068476,0.00285026956433839,0.00471840288634637,0.00348103301206084,0.00140849467309012,0.00207253833897071,0.00361509248622447,0.00142545271887366,0.00218963976735082,0.88,0.91,0.12,0.09,0.37705599508214,1.11022302462516e-16 -"beta-0.75-0.75",2000,100,"vote-95",0.00871945752096456,0.00320121654235764,0.00551824097860691,0.00416036224794122,0.00162157367055352,0.0025387885773877,0.00408287571203191,0.0015617130318416,0.00252116268019031,0.77,0.82,0.23,0.18,0.793775176927469,1.11022302462516e-16 diff --git a/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R b/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R deleted file mode 100644 index 65cf569..0000000 --- a/diagnostic/boundary-repair/scripts/ablate_endpoint_classifier.R +++ /dev/null @@ -1,235 +0,0 @@ -# Paired ablation of order-statistic endpoint classifiers. -# Run from the root of the kde1d R package. - -if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { - stop("run from the kde1d package root with pkgload installed") -} -pkgload::load_all(".", quiet = TRUE) -source(paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/", - "bounded_estimator.R" -)) - -arguments <- commandArgs(trailingOnly = TRUE) -replication_count <- if (length(arguments) >= 1L) { - as.integer(arguments[[1L]]) -} else { - 100L -} -output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/results/", - "endpoint-classifier-ablation.csv" -) -if (length(arguments) > 2L || !is.finite(replication_count) || - replication_count < 2L) { - stop("usage: ablate_endpoint_classifier.R [replications] [output.csv]") -} - -make_beta_distribution <- function(shape1, shape2, endpoint_truth) { - list( - random = function(sample_size) rbeta(sample_size, shape1, shape2), - density = function(values) dbeta(values, shape1, shape2), - endpoint_truth = endpoint_truth - ) -} -validation_distributions <- list( - uniform = list( - random = runif, - density = dunif, - endpoint_truth = c(lower = "finite", upper = "finite") - ), - `beta-1-2` = make_beta_distribution( - 1, 2, c(lower = "finite", upper = "bulk") - ), - `beta-0.75-2` = make_beta_distribution( - 0.75, 2, c(lower = "bulk", upper = "bulk") - ), - `beta-0.75-0.75` = make_beta_distribution( - 0.75, 0.75, c(lower = "bulk", upper = "bulk") - ) -) -sample_sizes <- c(100L, 1000L, 2000L) -classifier_methods <- c( - "single-95", "single-1.5-95", "single-2-95", - "median-90", "vote-90", "vote-95" -) -methods <- c("kde-current", classifier_methods) -evaluation_points <- sort(unique(c( - 10^seq(-10, -2, length.out = 101L), - seq(0.01, 0.99, length.out = 301L), - 1 - 10^seq(-2, -10, length.out = 101L) -))) -left_points <- evaluation_points <= 0.1 -right_points <- evaluation_points >= 0.9 -result_rows <- list() - -make_classifier_selections <- function(observations) { - list( - `single-95` = select_bounded_endpoint_experts_single_scale(observations), - `single-1.5-95` = select_bounded_endpoint_experts_single_scale( - observations, - tail_multiplier = 1.5 - ), - `single-2-95` = select_bounded_endpoint_experts_single_scale( - observations, - tail_multiplier = 2 - ), - `median-90` = select_bounded_endpoint_experts_multiscale( - observations, - evidence_threshold = qnorm(0.90), - rule = "median" - ), - `vote-90` = select_bounded_endpoint_experts_multiscale( - observations, - evidence_threshold = qnorm(0.90), - rule = "vote" - ), - `vote-95` = select_bounded_endpoint_experts_multiscale( - observations, - evidence_threshold = qnorm(0.95), - rule = "vote" - ) - ) -} - -summarize_estimates <- function(estimates, true_density, region_points) { - mean_density <- rowMeans(estimates) - integrated_errors <- vapply( - seq_len(ncol(estimates)), - function(replication) { - trapezoid_integral( - evaluation_points[region_points], - (estimates[region_points, replication] - - true_density[region_points])^2 - ) - }, - numeric(1L) - ) - c( - ise = mean(integrated_errors), - squared_bias = trapezoid_integral( - evaluation_points[region_points], - (mean_density[region_points] - true_density[region_points])^2 - ), - variance = trapezoid_integral( - evaluation_points[region_points], - rowMeans((estimates[region_points, , drop = FALSE] - - mean_density[region_points])^2) - ) - ) -} - -for (distribution_index in seq_along(validation_distributions)) { - true_density <- validation_distributions[[distribution_index]]$density( - evaluation_points - ) - for (sample_size in sample_sizes) { - estimates <- setNames( - lapply(methods, function(method) { - matrix(NA_real_, length(evaluation_points), replication_count) - }), - methods - ) - choices <- setNames( - lapply(classifier_methods, function(method) { - matrix( - NA_character_, replication_count, 2L, - dimnames = list(NULL, c("lower", "upper")) - ) - }), - classifier_methods - ) - for (replication in seq_len(replication_count)) { - set.seed( - 20260909L + 100000L * distribution_index + - 1000L * match(sample_size, sample_sizes) + replication - ) - observations <- validation_distributions[[distribution_index]]$random( - sample_size - ) - estimates$`kde-current`[, replication] <- normalize_density( - evaluation_points, - dkde1d( - evaluation_points, - kde1d(observations, xmin = 0, xmax = 1) - ) - ) - estimator_components <- fit_bounded_estimator_components( - observations, - evaluation_points - ) - classifier_selections <- make_classifier_selections(observations) - for (method in classifier_methods) { - estimator_components$selection <- classifier_selections[[method]] - estimates[[method]][, replication] <- - fuse_bounded_estimator_components( - evaluation_points, - estimator_components - )$density - choices[[method]][replication, ] <- - classifier_selections[[method]]$expert_choices - } - } - for (method in methods) { - global_summary <- summarize_estimates( - estimates[[method]], true_density, rep(TRUE, length(evaluation_points)) - ) - left_summary <- summarize_estimates( - estimates[[method]], true_density, left_points - ) - right_summary <- summarize_estimates( - estimates[[method]], true_density, right_points - ) - endpoint_truth <- validation_distributions[[distribution_index]]$endpoint_truth - result_rows[[length(result_rows) + 1L]] <- data.frame( - distribution = names(validation_distributions)[[distribution_index]], - sample_size = sample_size, - replications = replication_count, - method = method, - global_ise = global_summary[["ise"]], - global_squared_bias = global_summary[["squared_bias"]], - global_variance = global_summary[["variance"]], - left_ise = left_summary[["ise"]], - left_squared_bias = left_summary[["squared_bias"]], - left_variance = left_summary[["variance"]], - right_ise = right_summary[["ise"]], - right_squared_bias = right_summary[["squared_bias"]], - right_variance = right_summary[["variance"]], - lower_accuracy = if (method == "kde-current") { - NA_real_ - } else { - mean(choices[[method]][, "lower"] == endpoint_truth[["lower"]]) - }, - upper_accuracy = if (method == "kde-current") { - NA_real_ - } else { - mean(choices[[method]][, "upper"] == endpoint_truth[["upper"]]) - }, - lower_finite_rate = if (method == "kde-current") NA_real_ else - mean(choices[[method]][, "lower"] == "finite"), - upper_finite_rate = if (method == "kde-current") NA_real_ else - mean(choices[[method]][, "upper"] == "finite"), - minimum_density = min(estimates[[method]]), - maximum_mass_error = max(abs(vapply( - seq_len(replication_count), - function(replication) { - trapezoid_integral( - evaluation_points, - estimates[[method]][, replication] - ) - 1 - }, - numeric(1L) - ))) - ) - } - message( - names(validation_distributions)[[distribution_index]], - ", n = ", sample_size - ) - } -} - -results <- do.call(rbind, result_rows) -dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) -write.csv(results, output_file, row.names = FALSE) -message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/boundary-repair/scripts/bounded_estimator.R b/diagnostic/boundary-repair/scripts/bounded_estimator.R deleted file mode 100644 index 7ef12c0..0000000 --- a/diagnostic/boundary-repair/scripts/bounded_estimator.R +++ /dev/null @@ -1,376 +0,0 @@ -# Reference R implementation of the selected two-sided boundary estimator. - -trapezoid_integral <- function(evaluation_points, values) { - sum(diff(evaluation_points) * - (values[-length(values)] + values[-1L]) / 2) -} - -normalize_density <- function(evaluation_points, density) { - density <- pmax(0, density) - density_mass <- trapezoid_integral(evaluation_points, density) - if (!is.finite(density_mass) || density_mass <= 0) { - stop("density cannot be normalized") - } - density / density_mass -} - -smoothstep <- function(normalized_distance) { - 3 * normalized_distance^2 - 2 * normalized_distance^3 -} - -make_bounded_expert_weights <- function(probabilities, sample_size, - concentration = 1, - shrinkage_exponent = 0.5) { - boundary_fraction <- min( - 0.25, - concentration / sample_size^shrinkage_exponent - ) - lower_weights <- 1 - smoothstep(pmin(1, probabilities / boundary_fraction)) - upper_weights <- 1 - smoothstep(pmin( - 1, - (1 - probabilities) / boundary_fraction - )) - cbind( - lower = lower_weights, - bulk = pmax(0, 1 - lower_weights - upper_weights), - upper = upper_weights - ) -} - -fit_local_polynomial_boundary <- function( - observations, - evaluation_points, - bandwidth_weights, - minimum_bandwidth, - degree) { - if (!degree %in% c(1, 2)) { - stop("local boundary degree must be 1 or 2") - } - selected_bandwidth <- kde1d( - observations, - weights = bandwidth_weights, - deg = degree - )$bw - bandwidth <- max(selected_bandwidth, minimum_bandwidth) - standardized_boundary <- evaluation_points / bandwidth - truncated_moment_0 <- pnorm(standardized_boundary) - truncated_moment_1 <- -dnorm(standardized_boundary) - truncated_moment_2 <- truncated_moment_0 - - standardized_boundary * dnorm(standardized_boundary) - if (degree == 1) { - moment_determinant <- truncated_moment_0 * truncated_moment_2 - - truncated_moment_1^2 - equivalent_kernel_coefficients <- cbind( - truncated_moment_2 / moment_determinant, - -truncated_moment_1 / moment_determinant - ) - } else { - truncated_moment_3 <- -( - standardized_boundary^2 + 2 - ) * dnorm(standardized_boundary) - truncated_moment_4 <- 3 * truncated_moment_0 - ( - standardized_boundary^3 + 3 * standardized_boundary - ) * dnorm(standardized_boundary) - moment_determinant <- - truncated_moment_0 * ( - truncated_moment_2 * truncated_moment_4 - truncated_moment_3^2 - ) - - truncated_moment_1 * ( - truncated_moment_1 * truncated_moment_4 - - truncated_moment_2 * truncated_moment_3 - ) + - truncated_moment_2 * ( - truncated_moment_1 * truncated_moment_3 - truncated_moment_2^2 - ) - equivalent_kernel_coefficients <- cbind( - ( - truncated_moment_2 * truncated_moment_4 - truncated_moment_3^2 - ) / moment_determinant, - ( - truncated_moment_2 * truncated_moment_3 - - truncated_moment_1 * truncated_moment_4 - ) / moment_determinant, - ( - truncated_moment_1 * truncated_moment_3 - truncated_moment_2^2 - ) / moment_determinant - ) - } - density <- numeric(length(evaluation_points)) - for (chunk_start in seq(1L, length(evaluation_points), by = 128L)) { - chunk_indices <- chunk_start:min( - chunk_start + 127L, - length(evaluation_points) - ) - kernel_arguments <- outer( - evaluation_points[chunk_indices], - observations, - "-" - ) / bandwidth - base_kernels <- dnorm(kernel_arguments) - corrected_kernels <- base_kernels * - equivalent_kernel_coefficients[chunk_indices, 1L] - for (polynomial_order in seq_len(degree)) { - corrected_kernels <- corrected_kernels + - base_kernels * - equivalent_kernel_coefficients[ - chunk_indices, - polynomial_order + 1L - ] * kernel_arguments^polynomial_order - } - density[chunk_indices] <- rowMeans(corrected_kernels) / bandwidth - } - list( - density = normalize_density(evaluation_points, density), - bandwidth = bandwidth, - selected_bandwidth = selected_bandwidth - ) -} - -fit_bounded_finite_expert <- function(observations, evaluation_points, - concentration = 1, - shrinkage_exponent = 0.5) { - probability_ranks <- (rank(observations, ties.method = "average") - 0.5) / - length(observations) - bandwidth_weights <- make_bounded_expert_weights( - probability_ranks, - length(observations), - concentration, - shrinkage_exponent - ) - bulk_model <- kde1d(observations, xmin = 0, xmax = 1) - bulk_density <- normalize_density( - evaluation_points, - dkde1d(evaluation_points, bulk_model) - ) - endpoint_densities <- lapply(c(1L, 2L), function(degree) { - minimum_bandwidth <- kde1d(observations, deg = degree)$bw - lower_density <- fit_local_polynomial_boundary( - observations, - evaluation_points, - bandwidth_weights[, "lower"], - minimum_bandwidth, - degree - )$density - upper_density <- rev(fit_local_polynomial_boundary( - 1 - observations, - rev(1 - evaluation_points), - bandwidth_weights[, "upper"], - minimum_bandwidth, - degree - )$density) - cbind(lower = lower_density, bulk = bulk_density, upper = upper_density) - }) - component_densities <- ( - endpoint_densities[[1L]] + endpoint_densities[[2L]] - ) / 2 - evaluation_weights <- make_bounded_expert_weights( - pkde1d(evaluation_points, bulk_model), - length(observations), - concentration, - shrinkage_exponent - ) - list( - density = normalize_density( - evaluation_points, - rowSums(evaluation_weights * component_densities) - ), - component_densities = component_densities, - evaluation_weights = evaluation_weights, - boundary_fraction = min( - 0.25, - concentration / length(observations)^shrinkage_exponent - ) - ) -} - -estimate_bounded_tail_indices <- function(observations, tail_counts) { - if (any(tail_counts < 1L) || any(tail_counts >= length(observations))) { - stop("tail_counts must be between one and sample size minus one") - } - ordered_observations <- sort(observations) - upper_distances <- sort(1 - observations) - tail_indices <- vapply(tail_counts, function(tail_count) { - c( - lower = tail_count / sum(log( - ordered_observations[[tail_count + 1L]] / - pmax( - .Machine$double.eps, - ordered_observations[seq_len(tail_count)] - ) - )), - upper = tail_count / sum(log( - upper_distances[[tail_count + 1L]] / - pmax(.Machine$double.eps, upper_distances[seq_len(tail_count)]) - )) - ) - }, numeric(2L)) - if (length(tail_counts) == 1L) { - tail_indices <- matrix( - tail_indices, - nrow = 2L, - dimnames = list(c("lower", "upper"), NULL) - ) - } - rownames(tail_indices) <- c("lower", "upper") - colnames(tail_indices) <- as.character(tail_counts) - tail_indices -} - -select_bounded_endpoint_experts_single_scale <- function( - observations, - tail_multiplier = 1, - evidence_threshold = qnorm(0.95), - minimum_finite_index = 0.9) { - if (!is.finite(tail_multiplier) || tail_multiplier <= 0) { - stop("tail_multiplier must be finite and positive") - } - tail_count <- min( - length(observations) - 1L, - ceiling(tail_multiplier * sqrt(length(observations))) - ) - tail_indices <- estimate_bounded_tail_indices( - observations, - tail_count - )[, 1L] - expert_choices <- rep("bulk", length(tail_indices)) - names(expert_choices) <- names(tail_indices) - expert_choices[ - tail_indices >= minimum_finite_index & - tail_indices * (1 - evidence_threshold / sqrt(tail_count)) <= 1 - ] <- "finite" - list( - expert_choices = expert_choices, - tail_indices = tail_indices, - tail_count = tail_count, - evidence_threshold = evidence_threshold, - minimum_finite_index = minimum_finite_index - ) -} - -select_bounded_endpoint_experts_multiscale <- function( - observations, - evidence_threshold = qnorm(0.90), - tail_multipliers = c(1, 1.5, 2), - maximum_tail_fraction = 0.15, - rule = c("vote", "median")) { - rule <- match.arg(rule) - tail_counts <- pmin( - floor(maximum_tail_fraction * length(observations)), - ceiling(tail_multipliers * sqrt(length(observations))) - ) - tail_counts <- pmax(1L, pmin(length(observations) - 1L, tail_counts)) - tail_indices <- estimate_bounded_tail_indices(observations, tail_counts) - standardized_indices <- sweep( - log(tail_indices), - 2L, - sqrt(tail_counts), - "*" - ) - expert_choices <- apply(standardized_indices, 1L, function(scores) { - if (rule == "median") { - median_score <- median(scores) - if (abs(median_score) <= evidence_threshold) { - "finite" - } else { - "bulk" - } - } else { - required_votes <- floor(length(scores) / 2) + 1L - if (sum(abs(scores) <= evidence_threshold) >= required_votes) { - "finite" - } else { - "bulk" - } - } - }) - list( - expert_choices = expert_choices, - tail_indices = tail_indices, - standardized_indices = standardized_indices, - tail_counts = tail_counts, - evidence_threshold = evidence_threshold, - tail_multipliers = tail_multipliers, - maximum_tail_fraction = maximum_tail_fraction, - rule = rule - ) -} - -select_bounded_endpoint_experts <- function( - observations, - evidence_threshold = qnorm(0.95), - minimum_finite_index = 0.9) { - select_bounded_endpoint_experts_single_scale( - observations, - tail_multiplier = 2, - evidence_threshold, - minimum_finite_index - ) -} - -fit_bounded_estimator_components <- function( - observations, - evaluation_points, - concentration = 1, - shrinkage_exponent = 0.5) { - if (length(observations) < 4L || any(!is.finite(observations)) || - any(observations < 0 | observations > 1)) { - stop("observations must contain at least four finite values in [0, 1]") - } - if (any(!is.finite(evaluation_points)) || - is.unsorted(evaluation_points, strictly = TRUE) || - any(evaluation_points < 0 | evaluation_points > 1)) { - stop("evaluation_points must be strictly increasing in [0, 1]") - } - finite_fit <- fit_bounded_finite_expert( - observations, - evaluation_points, - concentration, - shrinkage_exponent - ) - selection <- select_bounded_endpoint_experts(observations) - list( - finite_fit = finite_fit, - selection = selection - ) -} - -fuse_bounded_estimator_components <- function( - evaluation_points, - estimator_components) { - finite_fit <- estimator_components$finite_fit - selection <- estimator_components$selection - component_densities <- finite_fit$component_densities - for (boundary in c("lower", "upper")) { - if (selection$expert_choices[[boundary]] != "finite") { - component_densities[, boundary] <- component_densities[, "bulk"] - } - } - list( - density = normalize_density( - evaluation_points, - rowSums(finite_fit$evaluation_weights * component_densities) - ), - component_densities = component_densities, - evaluation_weights = finite_fit$evaluation_weights, - expert_choices = selection$expert_choices, - tail_indices = selection$tail_indices, - tail_count = selection$tail_count, - boundary_fraction = finite_fit$boundary_fraction - ) -} - -fit_bounded_selected_estimator <- function( - observations, - evaluation_points, - concentration = 1, - shrinkage_exponent = 0.5) { - fuse_bounded_estimator_components( - evaluation_points, - fit_bounded_estimator_components( - observations, - evaluation_points, - concentration, - shrinkage_exponent - ) - ) -} diff --git a/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R b/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R deleted file mode 100644 index ddb2597..0000000 --- a/diagnostic/boundary-repair/scripts/plot_bounded_estimator_validation.R +++ /dev/null @@ -1,208 +0,0 @@ -# Plot the paired validation of the selected bounded estimator. -# Run from the root of the kde1d R package. - -if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { - stop("run from the kde1d package root with pkgload installed") -} -pkgload::load_all(".", quiet = TRUE) -source(paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/", - "bounded_estimator.R" -)) - -arguments <- commandArgs(trailingOnly = TRUE) -input_file <- if (length(arguments) >= 1L) arguments[[1L]] else paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/results/", - "bounded-estimator-validation.csv" -) -output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/plots/", - "bounded-estimator-validation.pdf" -) -if (length(arguments) > 2L) { - stop("usage: plot_bounded_estimator_validation.R [input.csv] [output.pdf]") -} - -results <- read.csv(input_file) -replication_count <- unique(results$replications) -if (length(replication_count) != 1L) { - stop("input must contain a single replication count") -} -method_colors <- c(current = "grey45", selected = "#009E73") -validation_distributions <- list( - uniform = list(random = runif, density = dunif), - `beta-1-2` = list( - random = function(sample_size) rbeta(sample_size, 1, 2), - density = function(values) dbeta(values, 1, 2) - ), - `beta-0.75-2` = list( - random = function(sample_size) rbeta(sample_size, 0.75, 2), - density = function(values) dbeta(values, 0.75, 2) - ), - `beta-0.75-0.75` = list( - random = function(sample_size) rbeta(sample_size, 0.75, 0.75), - density = function(values) dbeta(values, 0.75, 0.75) - ) -) -evaluation_points <- sort(unique(c( - 10^seq(-10, -2, length.out = 101L), - seq(0.01, 0.99, length.out = 301L), - 1 - 10^seq(-2, -10, length.out = 101L) -))) - -pdf(output_file, width = 12, height = 8) -par(mfrow = c(3, 4), mar = c(4.5, 4.2, 2.4, 0.5), oma = c(0, 0, 3.5, 0)) -for (sample_size in sort(unique(results$sample_size))) { - for (distribution in names(validation_distributions)) { - scenario_results <- results[ - results$sample_size == sample_size & - results$distribution == distribution, - ] - current_result <- scenario_results[scenario_results$method == "current", ] - selected_result <- scenario_results[scenario_results$method == "selected", ] - ratios <- c( - ISE = selected_result$global_ise / current_result$global_ise, - bias = selected_result$global_squared_bias / - current_result$global_squared_bias, - variance = selected_result$global_variance / - current_result$global_variance - ) - barplot( - ratios, col = c("grey45", "#E69F00", "#56B4E9"), - ylim = range(c(0, 1, ratios)), ylab = "selected / current", - main = sprintf("%s, n = %d", distribution, sample_size) - ) - abline(h = 1, lty = 2) - } -} -mtext( - sprintf("Selected estimator: %d paired replications", replication_count), - outer = TRUE, font = 2, cex = 1.1 -) - -par(mfrow = c(3, 4), mar = c(4.5, 4.2, 2.4, 0.5), oma = c(0, 0, 3.5, 0)) -for (sample_size in sort(unique(results$sample_size))) { - for (distribution in names(validation_distributions)) { - selected_result <- results[ - results$sample_size == sample_size & - results$distribution == distribution & - results$method == "selected", - ] - barplot( - rbind( - bulk = c(selected_result$lower_bulk_rate, selected_result$upper_bulk_rate), - finite = c( - selected_result$lower_finite_rate, - selected_result$upper_finite_rate - ) - ), - names.arg = c("lower", "upper"), col = c("grey60", "#0072B2"), - ylim = c(0, 1), ylab = "selection rate", - main = sprintf("%s, n = %d", distribution, sample_size) - ) - if (sample_size == min(results$sample_size) && - distribution == names(validation_distributions)[[1L]]) { - legend( - "topright", c("bulk", "finite"), - fill = c("grey60", "#0072B2"), bty = "n", cex = 0.75 - ) - } - } -} -mtext("Effective endpoint components", outer = TRUE, font = 2, cex = 1.1) - -sample_size <- 1000L -for (distribution_index in seq_along(validation_distributions)) { - true_density <- validation_distributions[[distribution_index]]$density( - evaluation_points - ) - par(mfrow = c(2, 3), mar = c(4, 4.2, 2.3, 0.6), oma = c(0, 0, 3, 0)) - for (replication in 1:2) { - set.seed( - 20260906L + 100000L * distribution_index + 1000L * 2L + replication - ) - observations <- validation_distributions[[distribution_index]]$random( - sample_size - ) - selected_fit <- fit_bounded_selected_estimator( - observations, - evaluation_points - ) - estimates <- list( - current = normalize_density( - evaluation_points, - dkde1d( - evaluation_points, - kde1d(observations, xmin = 0, xmax = 1) - ) - ), - selected = selected_fit$density - ) - plot( - evaluation_points, true_density, type = "l", lwd = 3, col = "black", - ylim = c(0, quantile(c(true_density, unlist(estimates)), 0.98)), - xlab = "x", ylab = "density", - main = sprintf( - "realization %d: L=%s, U=%s", - replication, - selected_fit$expert_choices[["lower"]], - selected_fit$expert_choices[["upper"]] - ) - ) - for (method in names(estimates)) { - lines( - evaluation_points, estimates[[method]], col = method_colors[[method]], - lwd = if (method == "selected") 2.5 else 1.5, - lty = match(method, names(estimates)) - ) - } - if (replication == 1L) { - legend( - "topright", c("truth", "current", "selected"), - col = c("black", method_colors), lty = c(1, 1, 2), - lwd = c(3, 1.5, 2.5), bty = "n", cex = 0.75 - ) - } - for (boundary in c("left", "right")) { - boundary_points <- if (boundary == "left") { - evaluation_points >= 1e-6 & evaluation_points <= 0.1 - } else { - evaluation_points >= 0.9 & evaluation_points <= 1 - 1e-6 - } - boundary_distances <- if (boundary == "left") { - evaluation_points[boundary_points] - } else { - 1 - evaluation_points[boundary_points] - } - boundary_order <- order(boundary_distances) - plot( - boundary_distances[boundary_order], - true_density[boundary_points][boundary_order], - type = "l", log = "x", lwd = 3, col = "black", - ylim = c(0, quantile(c( - true_density[boundary_points], - unlist(lapply(estimates, function(density) density[boundary_points])) - ), 0.99)), - xlab = "distance from boundary", ylab = "density", main = boundary - ) - for (method in names(estimates)) { - lines( - boundary_distances[boundary_order], - estimates[[method]][boundary_points][boundary_order], - col = method_colors[[method]], - lwd = if (method == "selected") 2.5 else 1.5, - lty = match(method, names(estimates)) - ) - } - } - } - mtext( - sprintf( - "%s, n = %d; effective choices shown in panel titles", - names(validation_distributions)[[distribution_index]], sample_size - ), - outer = TRUE, font = 2, cex = 1.1 - ) -} -dev.off() -message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R b/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R deleted file mode 100644 index 89b6a40..0000000 --- a/diagnostic/boundary-repair/scripts/plot_endpoint_classifier_ablation.R +++ /dev/null @@ -1,234 +0,0 @@ -# Plot the paired endpoint-classifier ablation and representative fits. -# Run from the root of the kde1d R package. - -if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { - stop("run from the kde1d package root with pkgload installed") -} -pkgload::load_all(".", quiet = TRUE) -source(paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/", - "bounded_estimator.R" -)) - -arguments <- commandArgs(trailingOnly = TRUE) -input_file <- if (length(arguments) >= 1L) arguments[[1L]] else paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/results/", - "endpoint-classifier-ablation.csv" -) -output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/plots/", - "endpoint-classifier-ablation.pdf" -) -if (length(arguments) > 2L) { - stop("usage: plot_endpoint_classifier_ablation.R [input.csv] [output.pdf]") -} - -results <- read.csv(input_file) -classifier_methods <- c( - "single-95", "single-1.5-95", "single-2-95", - "median-90", "vote-90", "vote-95" -) -method_labels <- c( - `single-95` = "1x", `single-1.5-95` = "1.5x", `single-2-95` = "2x", - `median-90` = "median", `vote-90` = "vote 90", `vote-95` = "vote 95" -) -method_colors <- c( - `single-95` = "#009E73", `single-1.5-95` = "#56B4E9", - `single-2-95` = "#E69F00", `median-90` = "#CC79A7", - `vote-90` = "#7B3294", `vote-95` = "#D55E00" -) -validation_distributions <- list( - uniform = list(random = runif, density = dunif), - `beta-1-2` = list( - random = function(sample_size) rbeta(sample_size, 1, 2), - density = function(values) dbeta(values, 1, 2) - ), - `beta-0.75-2` = list( - random = function(sample_size) rbeta(sample_size, 0.75, 2), - density = function(values) dbeta(values, 0.75, 2) - ), - `beta-0.75-0.75` = list( - random = function(sample_size) rbeta(sample_size, 0.75, 0.75), - density = function(values) dbeta(values, 0.75, 0.75) - ) -) -evaluation_points <- sort(unique(c( - 10^seq(-10, -2, length.out = 101L), - seq(0.01, 0.99, length.out = 301L), - 1 - 10^seq(-2, -10, length.out = 101L) -))) - -dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) -pdf(output_file, width = 12, height = 8) - -par(mfrow = c(3, 4), mar = c(4.5, 4.2, 2.4, 0.5), oma = c(0, 0, 3.5, 0)) -for (sample_size in sort(unique(results$sample_size))) { - for (distribution in names(validation_distributions)) { - scenario_results <- results[ - results$sample_size == sample_size & - results$distribution == distribution, - ] - current_ise <- scenario_results$global_ise[ - scenario_results$method == "kde-current" - ] - scenario_results <- scenario_results[ - match(classifier_methods, scenario_results$method), - ] - ratios <- scenario_results$global_ise / current_ise - barplot( - ratios, - names.arg = method_labels[classifier_methods], - col = method_colors[classifier_methods], las = 2, cex.names = 0.7, - ylim = range(c(0, 1, ratios)), ylab = "global ISE / current", - main = sprintf("%s, n = %d", distribution, sample_size) - ) - abline(h = 1, lty = 2) - } -} -mtext( - sprintf( - "Classifier ISE: %d paired replications", - unique(results$replications) - ), - outer = TRUE, font = 2, cex = 1.1 -) - -par(mfrow = c(3, 4), mar = c(4.5, 4.2, 2.4, 0.5), oma = c(0, 0, 3.5, 0)) -for (sample_size in sort(unique(results$sample_size))) { - for (distribution in names(validation_distributions)) { - scenario_results <- results[ - results$sample_size == sample_size & - results$distribution == distribution & - results$method %in% classifier_methods, - ] - scenario_results <- scenario_results[ - match(classifier_methods, scenario_results$method), - ] - barplot( - rowMeans(scenario_results[, c("lower_accuracy", "upper_accuracy")]), - names.arg = method_labels[classifier_methods], - col = method_colors[classifier_methods], las = 2, cex.names = 0.7, - ylim = c(0, 1), ylab = "mean endpoint accuracy", - main = sprintf("%s, n = %d", distribution, sample_size) - ) - } -} -mtext( - "Classification accuracy (finite versus bulk endpoint component)", - outer = TRUE, font = 2, cex = 1.1 -) - -visual_methods <- c("single-95", "single-2-95", "vote-90") -sample_size <- 1000L -for (distribution_index in seq_along(validation_distributions)) { - true_density <- validation_distributions[[distribution_index]]$density( - evaluation_points - ) - par(mfrow = c(2, 3), mar = c(4, 4.2, 2.4, 0.6), oma = c(0, 0, 3, 0)) - for (replication in 1:2) { - set.seed( - 20260909L + 100000L * distribution_index + 1000L * 2L + replication - ) - observations <- validation_distributions[[distribution_index]]$random( - sample_size - ) - estimator_components <- fit_bounded_estimator_components( - observations, - evaluation_points - ) - selections <- list( - `single-95` = select_bounded_endpoint_experts_single_scale(observations), - `single-2-95` = select_bounded_endpoint_experts_single_scale( - observations, - tail_multiplier = 2 - ), - `vote-90` = select_bounded_endpoint_experts_multiscale( - observations, - evidence_threshold = qnorm(0.90), - rule = "vote" - ) - ) - estimates <- list( - current = normalize_density( - evaluation_points, - dkde1d( - evaluation_points, - kde1d(observations, xmin = 0, xmax = 1) - ) - ) - ) - for (method in visual_methods) { - estimator_components$selection <- selections[[method]] - estimates[[method]] <- fuse_bounded_estimator_components( - evaluation_points, - estimator_components - )$density - } - plot( - evaluation_points, true_density, type = "l", lwd = 3, col = "black", - ylim = c(0, quantile(c(true_density, unlist(estimates)), 0.98)), - xlab = "x", ylab = "density", - main = sprintf("realization %d", replication) - ) - lines(evaluation_points, estimates$current, col = "grey45", lwd = 1.5) - for (method in visual_methods) { - lines( - evaluation_points, estimates[[method]], col = method_colors[[method]], - lwd = if (method == "single-2-95") 2.5 else 1.5, - lty = match(method, visual_methods) - ) - } - if (replication == 1L) { - legend( - "topright", c("truth", "current", method_labels[visual_methods]), - col = c("black", "grey45", method_colors[visual_methods]), - lty = c(1, 1, seq_along(visual_methods)), - lwd = c(3, 1.5, 1.5, 2.5, 1.5), bty = "n", cex = 0.72 - ) - } - for (boundary in c("left", "right")) { - boundary_points <- if (boundary == "left") { - evaluation_points >= 1e-6 & evaluation_points <= 0.1 - } else { - evaluation_points >= 0.9 & evaluation_points <= 1 - 1e-6 - } - boundary_distances <- if (boundary == "left") { - evaluation_points[boundary_points] - } else { - 1 - evaluation_points[boundary_points] - } - boundary_order <- order(boundary_distances) - plot( - boundary_distances[boundary_order], - true_density[boundary_points][boundary_order], - type = "l", log = "x", lwd = 3, col = "black", - ylim = c(0, quantile(c( - true_density[boundary_points], - unlist(lapply(estimates, function(density) density[boundary_points])) - ), 0.98)), - xlab = "distance from boundary", ylab = "density", main = boundary - ) - lines( - boundary_distances[boundary_order], - estimates$current[boundary_points][boundary_order], - col = "grey45", lwd = 1.5 - ) - for (method in visual_methods) { - lines( - boundary_distances[boundary_order], - estimates[[method]][boundary_points][boundary_order], - col = method_colors[[method]], - lwd = if (method == "single-2-95") 2.5 else 1.5, - lty = match(method, visual_methods) - ) - } - } - } - mtext( - sprintf("%s, n = %d", names(validation_distributions)[distribution_index], sample_size), - outer = TRUE, font = 2, cex = 1.1 - ) -} - -dev.off() -message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R b/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R deleted file mode 100644 index 32cddd6..0000000 --- a/diagnostic/boundary-repair/scripts/validate_bounded_estimator.R +++ /dev/null @@ -1,195 +0,0 @@ -# Paired validation of the selected bounded estimator against current kde1d. -# Run from the root of the kde1d R package. - -if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { - stop("run from the kde1d package root with pkgload installed") -} -pkgload::load_all(".", quiet = TRUE) -source(paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/scripts/", - "bounded_estimator.R" -)) - -arguments <- commandArgs(trailingOnly = TRUE) -replication_count <- if (length(arguments) >= 1L) { - as.integer(arguments[[1L]]) -} else { - 100L -} -output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( - "inst/include/kde1d-cpp/diagnostic/boundary-repair/results/", - "bounded-estimator-validation.csv" -) -if (length(arguments) > 2L || !is.finite(replication_count) || - replication_count < 2L) { - stop("usage: validate_bounded_estimator.R [replications] [output.csv]") -} - -make_beta_distribution <- function(shape1, shape2) { - list( - random = function(sample_size) rbeta(sample_size, shape1, shape2), - density = function(values) dbeta(values, shape1, shape2) - ) -} -validation_distributions <- list( - uniform = list(random = runif, density = dunif), - `beta-1-2` = make_beta_distribution(1, 2), - `beta-0.75-2` = make_beta_distribution(0.75, 2), - `beta-0.75-0.75` = make_beta_distribution(0.75, 0.75) -) -sample_sizes <- c(100L, 1000L, 2000L) -methods <- c("current", "selected") -evaluation_points <- sort(unique(c( - 10^seq(-10, -2, length.out = 101L), - seq(0.01, 0.99, length.out = 301L), - 1 - 10^seq(-2, -10, length.out = 101L) -))) -left_points <- evaluation_points <= 0.1 -right_points <- evaluation_points >= 0.9 -result_rows <- list() - -summarize_estimates <- function(estimates, true_density, region_points) { - mean_density <- rowMeans(estimates) - integrated_errors <- vapply( - seq_len(ncol(estimates)), - function(replication) { - trapezoid_integral( - evaluation_points[region_points], - (estimates[region_points, replication] - - true_density[region_points])^2 - ) - }, - numeric(1L) - ) - c( - ise = mean(integrated_errors), - ise_median = median(integrated_errors), - squared_bias = trapezoid_integral( - evaluation_points[region_points], - (mean_density[region_points] - true_density[region_points])^2 - ), - variance = trapezoid_integral( - evaluation_points[region_points], - rowMeans((estimates[region_points, , drop = FALSE] - - mean_density[region_points])^2) - ) - ) -} - -for (distribution_index in seq_along(validation_distributions)) { - true_density <- validation_distributions[[distribution_index]]$density( - evaluation_points - ) - for (sample_size in sample_sizes) { - estimates <- setNames( - lapply(methods, function(method) { - matrix(NA_real_, length(evaluation_points), replication_count) - }), - methods - ) - expert_choices <- array( - NA_character_, - dim = c(replication_count, 2L), - dimnames = list(NULL, c("lower", "upper")) - ) - for (replication in seq_len(replication_count)) { - set.seed( - 20260906L + 100000L * distribution_index + - 1000L * match(sample_size, sample_sizes) + replication - ) - observations <- validation_distributions[[distribution_index]]$random( - sample_size - ) - estimates$current[, replication] <- normalize_density( - evaluation_points, - dkde1d( - evaluation_points, - kde1d(observations, xmin = 0, xmax = 1) - ) - ) - estimator_components <- fit_bounded_estimator_components( - observations, - evaluation_points - ) - selected_fit <- fuse_bounded_estimator_components( - evaluation_points, - estimator_components - ) - estimates$selected[, replication] <- selected_fit$density - expert_choices[replication, ] <- selected_fit$expert_choices - } - for (method in methods) { - global_summary <- summarize_estimates( - estimates[[method]], - true_density, - rep(TRUE, length(evaluation_points)) - ) - left_summary <- summarize_estimates( - estimates[[method]], - true_density, - left_points - ) - right_summary <- summarize_estimates( - estimates[[method]], - true_density, - right_points - ) - result_rows[[length(result_rows) + 1L]] <- data.frame( - distribution = names(validation_distributions)[[distribution_index]], - sample_size = sample_size, - replications = replication_count, - method = method, - global_ise = global_summary[["ise"]], - global_ise_median = global_summary[["ise_median"]], - global_squared_bias = global_summary[["squared_bias"]], - global_variance = global_summary[["variance"]], - left_ise = left_summary[["ise"]], - left_squared_bias = left_summary[["squared_bias"]], - left_variance = left_summary[["variance"]], - right_ise = right_summary[["ise"]], - right_squared_bias = right_summary[["squared_bias"]], - right_variance = right_summary[["variance"]], - lower_finite_rate = if (method == "selected") { - mean(expert_choices[, "lower"] == "finite") - } else { - NA_real_ - }, - upper_finite_rate = if (method == "selected") { - mean(expert_choices[, "upper"] == "finite") - } else { - NA_real_ - }, - lower_bulk_rate = if (method == "selected") { - mean(expert_choices[, "lower"] == "bulk") - } else { - NA_real_ - }, - upper_bulk_rate = if (method == "selected") { - mean(expert_choices[, "upper"] == "bulk") - } else { - NA_real_ - }, - minimum_density = min(estimates[[method]]), - maximum_mass_error = max(abs(vapply( - seq_len(replication_count), - function(replication) { - trapezoid_integral( - evaluation_points, - estimates[[method]][, replication] - ) - 1 - }, - numeric(1L) - ))) - ) - } - message( - names(validation_distributions)[[distribution_index]], - ", n = ", sample_size - ) - } -} - -results <- do.call(rbind, result_rows) -dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) -write.csv(results, output_file, row.names = FALSE) -message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/boundary_diagnostic.cpp b/diagnostic/boundary_diagnostic.cpp deleted file mode 100644 index 27cc53a..0000000 --- a/diagnostic/boundary_diagnostic.cpp +++ /dev/null @@ -1,155 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - -struct Scenario -{ - std::string name; - Eigen::VectorXd observations; - double xmin; - double xmax; - double scale; -}; - -Eigen::VectorXd -probabilities(Eigen::Index size) -{ - return Eigen::VectorXd::LinSpaced( - size, 0.5 / static_cast(size), - 1.0 - 0.5 / static_cast(size)); -} - -Scenario -make_scenario(const std::string& name, Eigen::Index size, double scale) -{ - Eigen::VectorXd probability = probabilities(size); - if (name == "uniform") { - return { name, probability * scale, 0.0, scale, scale }; - } else if (name == "beta-2-1") { - return { name, probability.array().sqrt() * scale, 0.0, scale, scale }; - } else if (name == "beta-1-2") { - return { name, - (1.0 - (1.0 - probability.array()).sqrt()) * scale, - 0.0, - scale, - scale }; - } else if (name == "exponential-left") { - return { name, - (-(1.0 - probability.array()).log()) * scale, - 0.0, - NAN, - scale }; - } - return { name, - (1.0 - probability.array()).log() * scale, - NAN, - 0.0, - scale }; -} - -double -true_pdf(const std::string& name, double position, double scale) -{ - if (name == "uniform") - return 1.0 / scale; - if (name == "beta-2-1") - return 2.0 * position / scale; - if (name == "beta-1-2") - return 2.0 * (1.0 - position) / scale; - return std::exp(-position) / scale; -} - -double -true_cdf(const std::string& name, double position) -{ - if (name == "uniform") - return position; - if (name == "beta-2-1") - return position * position; - if (name == "beta-1-2") - return 1.0 - (1.0 - position) * (1.0 - position); - if (name == "exponential-left") - return 1.0 - std::exp(-position); - return std::exp(-position); -} - -double -evaluation_point(const Scenario& scenario, double position) -{ - if (scenario.name == "exponential-right") - return -position * scenario.scale; - return position * scenario.scale; -} - -void -run_scenario(const Scenario& scenario, - size_t degree, - size_t grid_size, - double bandwidth, - const Eigen::VectorXd& positions) -{ - kde1d::Kde1d fit(scenario.xmin, - scenario.xmax, - "continuous", - 1.0, - bandwidth, - degree, - grid_size); - fit.fit(scenario.observations); - - for (Eigen::Index i = 0; i < positions.size(); ++i) { - const double point = evaluation_point(scenario, positions(i)); - const double estimated_pdf = - fit.pdf(Eigen::VectorXd::Constant(1, point))(0); - const double estimated_cdf = - fit.cdf(Eigen::VectorXd::Constant(1, point))(0); - std::cout << scenario.name << ',' << scenario.scale << ',' << degree << ',' - << grid_size << ',' - << (std::isnan(bandwidth) ? "automatic" - : std::to_string(bandwidth)) - << ',' << positions(i) << ',' << point << ',' << estimated_pdf - << ',' << true_pdf(scenario.name, positions(i), scenario.scale) - << ',' << estimated_cdf << ',' - << true_cdf(scenario.name, positions(i)) << '\n'; - } -} - -} // namespace - -int -main() -{ - std::cout << std::setprecision(17); - std::cout << "scenario,scale,degree,grid_size,bandwidth,position,x," - "estimated_pdf,true_pdf,estimated_cdf,true_cdf\n"; - - Eigen::VectorXd positions(12); - positions << 0.0, 1e-12, 1e-10, 1e-8, 1e-6, 1e-5, 1e-4, 1e-3, - 1e-2, 1e-1, 0.5, 1.0; - const std::array scenario_names = { - "uniform", "beta-2-1", "beta-1-2", "exponential-left", - "exponential-right" - }; - - for (const std::string& scenario_name : scenario_names) { - for (double scale : { 1e-4, 1.0, 1e4 }) { - Scenario scenario = make_scenario(scenario_name, 2000, scale); - for (size_t degree = 0; degree < 3; ++degree) { - for (size_t grid_size : { 100, 400, 1000 }) { - for (double bandwidth : - { 0.15, 0.3, std::numeric_limits::quiet_NaN() }) { - run_scenario( - scenario, degree, grid_size, bandwidth, positions); - } - } - } - } - } -} diff --git a/diagnostic/one-sided-repair/HANDOFF.md b/diagnostic/one-sided-repair/HANDOFF.md deleted file mode 100644 index be19ba3..0000000 --- a/diagnostic/one-sided-repair/HANDOFF.md +++ /dev/null @@ -1,33 +0,0 @@ -# One-sided repair handoff - -The production branch already uses a scale-equivariant power-$3/4$ transform -for one-sided supports. The diagnostic candidate keeps that estimator as the -unweighted bulk and adds the selected two-boundary method's finite expert: -an averaged local-linear/local-quadratic kernel, a shrinking CDF weight, and a -$2\sqrt n$ order-statistic finite-versus-bulk decision. - -The native kernels share the degree-2 bandwidth fitted to the lowest 75% of -boundary distances. A 30-replication ablation compared fixed fractions from -15% through 100% and a $\sqrt n$ shrinking subset. Performance improved up to -75%; using all observations reversed the long-tail gains because remote Lomax -observations again controlled the floor. The 75% choice has mean global ISE -ratios to current of 0.902 at $n=100$ and 0.889 at $n=1000$, with corresponding -boundary ratios 0.854 and 0.834. - -The representative plots confirm that 75% removes most residual finite-endpoint -spiking. It is visually close to the full-sample floor for Exponential and -half-normal cases, but remains stable for Lomax. The main remaining loss is a -small-sample false finite classification for Gamma$(2)$: global ISE is 1.026 -and boundary ISE is 1.083 relative to current at $n=100$. At $n=1000$ the -classifier always chooses bulk for both Gamma examples, so the result is -exactly current. - -The log transform was rejected and removed. The working diagnostic now contains -only the current power-transform candidate and the floor-fraction validation. - -Before native C++ implementation, expand the scenario suite around the selected -75% value and classifier edge cases. In particular, add finite-boundary shapes -with steep nonzero slopes, heavier remote tails, upper-bounded reflections, and -sample sizes between 100 and 1000. Keep paired global/boundary ISE, bias, -variance, normalization, nonnegativity, reflection, scale, and realization -checks. diff --git a/diagnostic/one-sided-repair/NATIVE_CPP.md b/diagnostic/one-sided-repair/NATIVE_CPP.md deleted file mode 100644 index 3b9bdb2..0000000 --- a/diagnostic/one-sided-repair/NATIVE_CPP.md +++ /dev/null @@ -1,387 +0,0 @@ -# Native boundary-expert implementation roadmap - -## Scope - -Implement both selected finite-boundary repairs through one concise internal -path: - -| support | unchanged bulk estimator | candidate endpoints | bandwidth floor | -|---|---|---|---| -| exactly one finite endpoint | power-$3/4$ transform | the finite endpoint | closest 75% of boundary distances | -| two finite endpoints | probit transform | lower and upper, classified independently | all boundary distances | - -The existing transformed estimator remains the bulk component in both cases. -Unbounded continuous, discrete, and zero-inflated behavior remains unchanged. - -The production estimator activates for continuous fits of degrees zero through -two with at least 16 observations and effective sample size at least 16. Public -case weights and manual bandwidths are supported. Apply the bandwidth -multiplier to every expert bandwidth after selection and flooring. - -Expose boundary repair as a constructor option that defaults to enabled. When -disabled, retain the transformed bulk estimator. Do not add another fitted- -object representation. - -## Minimal integration point - -Call the repair coordinator only when `type_ == VarType::continuous`, at least -one support bound is finite, and at least 16 cleaned observations remain. The -coordinator additionally retains the bulk fit when the effective sample size is -below 16. - -Keep the current body of `Kde1d::fit()` through construction of the normalized -bulk `InterpolationGrid`. Preserve the cleaned observations on their original -scale before applying `boundary_transform()`. Immediately after constructing -the bulk grid: - -1. classify every finite endpoint from original-scale boundary distances; -2. return to the unchanged bulk path if no endpoint is confidently finite; -3. fit a boundary component only for each selected endpoint, using the existing - original-scale grid; -4. form endpoint weights from the normalized bulk CDF; -5. fuse bulk and selected endpoint values and replace `grid_` with the - normalized fused grid. - -The existing PDF, CDF, quantile, simulation, support truncation, and -log-likelihood code then operates on the fused grid. `bandwidth_` continues to -report the bulk bandwidth. - -Boundary distances and local densities can stay in the original units. Every -classifier ratio is dimensionless, and the boundary bandwidths -scale with the data, so this is equivalent to the R reference's affine map to -$[0,1]$ without adding a second normalization path. - -No changes should be required in `boundary_transform()`, `boundary_correct()`, -`construct_grid_points()`, `InterpolationGrid`, `PluginBandwidthSelector`, or -the public constructors. - -## Shared private helpers in `kde1d.hpp` - -Keep the implementation in the existing header and add three focused helpers. - -### 1. Endpoint classifier - -Given ascending distances from one endpoint, use -$k=\min(n-1,\lceil2\sqrt n\rceil)$ and - -$$ -\widehat\beta= -\frac{k}{\sum_{i=1}^k -\log\{d_{(k+1)}/\max(d_{(i)},\epsilon d_{(k+1)})\}}}. -$$ - -The scale-relative numerical floor preserves scale equivariance. Select the -finite expert when - -$$ -\widehat\beta\geq0.9, -\qquad -\widehat\beta\left\{1- -\frac{\Phi^{-1}(0.95)}{\sqrt{k}}\right\}\leq1. -$$ - -Run this helper once for the one-sided finite endpoint and independently on -lower and upper distances for two-sided support. Exploding, vanishing, and -ambiguous endpoints all select bulk. A nonpositive $(k+1)$st distance or a -nonfinite/nonpositive logarithmic denominator is a degenerate classifier input -and must also select bulk. - -### 2. Local-polynomial boundary component - -The helper takes boundary distances, ascending evaluation distances, rank -weights, a floor fraction, and degree one or two. - -- Select the weighted bandwidth with `PluginBandwidthSelector`. -- Select one unweighted degree-2 bandwidth from the closest - $\max(4,\lceil q n\rceil)$ distances, where $q=0.75$ for one-sided support - and $q=1$ for two-sided support. -- Share it between the degree-one and degree-two kernels, then apply the public - multiplier. Evaluate density contributions with equal observation weights - so the estimand remains the original density. - -Construct the equivalent-kernel coefficients as the first row of the inverse -truncated-normal moment matrix. Generate the moments with - -$$ -\mu_0(a)=\Phi(a),\qquad -\mu_1(a)=-\phi(a),\qquad -\mu_j(a)=(j-1)\mu_{j-2}(a)-a^{j-1}\phi(a). -$$ - -Use the explicit degree-one and degree-two determinants to avoid a dynamic -matrix inverse at every evaluation point. Average the two kernels before -fusion, clamp negative values, and return both the density and its influence -numerator for the EDF calculation described below. - -Evaluate directly only where the endpoint weight is nonzero. With ordered -distances, omit observations more than six bandwidths from an evaluation -point; the omitted Gaussian tail mass is below $2\times10^{-9}$. Normalize the -fused grid once at the end. - -### 3. Boundary-repair coordinator - -This helper owns endpoint distances, classification, local component calls, -CDF weights, reflection, and fusion. - -For an upper endpoint, compute on ascending reflected distances and reverse the -component once. The floor fraction is the only local-component policy that -differs between one- and two-sided support. - -The helper should return an empty result when every endpoint selects bulk. -`Kde1d::fit()` can then leave the already constructed bulk grid untouched. - -## Weights and fusion - -Let $F_B(x)$ be the bulk CDF and - -$$ -q_n=\min(0.25,n^{-1/2}), -\qquad -s(r)=3r^2-2r^3. -$$ - -For a lower endpoint use - -$$ -w_L(x)=1-s\left(\min\{1,F_B(x)/q_n\}\right), -$$ - -and for an upper endpoint use - -$$ -w_U(x)=1-s\left(\min\{1,(1-F_B(x))/q_n\}\right). -$$ - -Set the weight of every bulk-classified endpoint to zero. The final values are - -$$ -\widehat f(x)= -w_L(x)\widehat f_L(x) -+\{1-w_L(x)-w_U(x)\}\widehat f_B(x) -+w_U(x)\widehat f_U(x). -$$ - -With $q_n\leq0.25$, the endpoint weights do not overlap. The same expression -covers one-sided support by setting the absent endpoint weight to zero. Clamp -the fused values at zero and construct a normalized `InterpolationGrid` on the -existing original-scale grid. - -## Conditional EDF approximation - -The current EDF is already a conditional influence-trace approximation: it -holds the selected bandwidth and final grid normalization fixed. Extend the -same convention to expert selection and fusion rather than returning `NaN`. - -For a degree-$p$ boundary component, let $M_p(a)$ be the truncated-normal -moment matrix above, let $h$ be the shared bandwidth, and let -$\widetilde f_p$ denote its value before clamping. Its influence numerator is - -$$ -\nu_p(x)= -\mathbf 1\{\widetilde f_p(x)>0\} -\frac{\phi(0)}{n h} -\left[M_p\{d(x)/h\}^{-1}\right]_{00}. -$$ - -Only the constant equivalent-kernel coefficient remains because a -self-contribution has kernel argument zero. For the equal linear/quadratic -expert, use - -$$ -f_E(x)=\frac{f_1(x)+f_2(x)}{2}, -\qquad -\nu_E(x)=\frac{\nu_1(x)+\nu_2(x)}{2}. -$$ - -For the bulk component, the existing influence column is its log-density -leverage $\ell_B(x)$, so its influence numerator is -$\nu_B(x)=f_B(x)\ell_B(x)$. Fuse the numerators with exactly the same weights -as the densities: - -$$ -\begin{aligned} -g(x)&=w_L(x)f_L(x) - +\{1-w_L(x)-w_U(x)\}f_B(x)+w_U(x)f_U(x),\\ -\nu(x)&=w_L(x)\nu_L(x) - +\{1-w_L(x)-w_U(x)\}\nu_B(x)+w_U(x)\nu_U(x),\\ -\ell(x)&=\frac{\nu(x)}{g(x)}. -\end{aligned} -$$ - -Thus the mixture leverage is weighted by local density shares, not just by -the fusion weights. Estimate - -$$ -\operatorname{edf}=\sum_{i=1}^n -\min\{3,\max(0,\ell(X_i))\}, -$$ - -retaining the current per-observation cap. The final common normalization of -$g$ and $\nu$ cancels in their ratio when its derivative is ignored. - -This approximation conditions on bandwidths, endpoint classifications, CDF -weights, clamp states, and normalization constants. It deliberately omits the -derivatives of those data-adaptive choices. That keeps it consistent with the -existing EDF convention and costs only additional grid-vector arithmetic; no -refits or per-observation matrices are needed. Validate it diagnostically -against the corresponding leave-one-out approximation - -$$ -1+\sum_{i=1}^n -\{\log \widehat f(X_i)-\log \widehat f_{-i}(X_i)\}. -$$ - -First confirm that this diagnostic reproduces the existing bulk EDF to the -expected approximation error. A weight-derivative correction is worth -considering only if the active-expert comparison then shows an additional -systematic discrepancy. - -## Weights and remaining fit metadata - -Expert density contributions use the normalized public case weights, matching -the weighted bulk estimand. Effective sample size determines the minimum sample -check, fusion width, tail order, and classifier confidence. The weighted -classifier uses a conservative lower threshold of 0.975. The one-sided -bandwidth uses the closest 75% of positive-weight observations by row count and -passes their case weights to the plug-in selector. The influence numerator uses -the local average case weight on the FFT grid. - -Recompute `loglik_` from the final grid using the existing code. Use the -conditional mixture trace above for `edf_` whenever a finite expert is active, -and retain the current calculation unchanged for pure-bulk fits. - -No classifier choice, tail index, boundary bandwidth, or weight state needs to -persist in the fitted object for the first implementation. Diagnostic values -belong in tests and validation scripts rather than the public class layout. - -## Exact production changes - -The intended implementation footprint is: - -1. `include/kde1d/kde1d.hpp` - - preserve original-scale cleaned observations; - - add the three private helpers; - - call the coordinator after bulk-grid construction; - - carry the bulk and expert influence numerators through fusion for EDF. -2. `test/test.cpp` - - deterministic golden results and fallback behavior. -3. `test/test_numerical_invariants.cpp` - - active-expert normalization, reflection, scale, support, and quantile - invariants. -4. `diagnostic/one-sided-repair/` and `diagnostic/boundary-repair/` - - thin R evaluators and final baseline-versus-native reports. - -Avoid modifying `interpolation.hpp`, `dpik.hpp`, `stats.hpp`, constructors, or -public getters unless implementation evidence shows that it is necessary. - -## Implementation sequence - -1. Synchronize this branch with the isolated PR #34 fix so - `boundary_offset_` is `NaN` before fitting. Record the current production - head and run the native R evaluators once to create one- and two-sided - baseline outputs before changing estimator behavior. -2. Add the eligibility check and preserve original-scale observations. With - the coordinator returning bulk, verify tight numerical parity for every - existing support type. -3. Implement the shared endpoint classifier and deterministic finite/bulk - tests for lower and upper endpoints. -4. Implement the shared degree-one/two equivalent-kernel evaluator. Validate - both bandwidth-floor policies against the retained R references. -5. Activate one-sided fusion with the 75% floor and verify the selected - one-sided scenarios. -6. Activate two-sided fusion with the full-sample floor and verify independent - lower/upper decisions, including asymmetric densities. -7. Complete log-likelihood and conditional-EDF handling, numerical regression - tests, and fit-time benchmarks. -8. Run the larger R validation against the recorded native baselines, retain - only final comparison artifacts, and prepare the PR report. - -Each step should be a separately testable commit. Avoid refactoring unrelated -fit logic while implementing the method. - -## Weighted and manual-bandwidth resolution - -Manual bandwidths control only the transformed bulk fit. Boundary bandwidths -remain independently selected in original data units, exactly as when the bulk -bandwidth is automatic. The public multiplier remains the common smoothing -control and scales both bulk and expert bandwidths. - -Weighted experiments rejected defining the one-sided 75% bandwidth subset by -cumulative weight: concentrated weights made that subset too narrow and -unstable. Counting positive-weight observations was both simpler and more -accurate. Effective sample size gave a small but consistent improvement for the -fusion width under concentrated weights. A weighted classifier threshold of -0.975 avoided most false repair of exploding targets while retaining the -finite-boundary gains. Global weight rescaling and insertion or removal of -zero-weight observations are numerically invariant. - -Integer-weight replication equivalence is not required here because the -existing bulk bandwidth selector interprets public weights through effective -sample size rather than as frequency counts. Supporting frequency weights -would require a separate change to the bulk estimator's weight semantics. - -### Degrees zero and one - -The same averaged local-linear/local-quadratic boundary expert is used for all -three bulk degrees. It outperformed matching-order and local-linear-only -alternatives in global and boundary ISE. The gains persisted for weighted and -manual-bandwidth fits, and boundary scale equivariance is tested for every -degree. Degree zero primarily trades substantially lower boundary bias for a -small one-sided variance increase; degree one reduces both bias and variance. - -## Native tests - -Add compact tests to the existing executables. - -Shared coverage: - -- nonnegativity, unit mass, monotone CDF, quantile round trips, finite - log-likelihood and EDF, and support truncation; -- exact EDF parity with the current path when no expert is active, plus - diagnostic comparison with leave-one-out log-likelihood optimism when an - expert is active; -- scaling over several orders of magnitude; -- ties, observations exactly at an endpoint, small samples, and nearly - degenerate samples; -- regression coverage for unbounded, discrete, zero-inflated, weighted, - fixed-bandwidth, and nondefault-degree fits; -- fit-time benchmarks at representative $n$ values. - -One-sided coverage: - -- deterministic Exponential, half-normal, Gamma$(2)$, Gamma$(0.75)$, and - Lomax samples; -- lower/upper reflection while the expert is active; -- finite and bulk classifier outcomes; -- golden grid or PDF values against `one_sided_estimator.R`. - -Two-sided coverage: - -- deterministic Uniform, Beta$(1,2)$, Beta$(0.75,2)$, and - Beta$(0.75,0.75)$ samples; -- lower and upper finite/bulk outcomes, including asymmetric decisions; -- affine equivariance on non-unit intervals; -- golden grid or PDF values against `bounded_estimator.R`. - -If direct local evaluation is materially expensive, optimize only after a -profile identifies it as the relevant fit cost. - -## R validation without C++ experiment bloat - -Keep Monte Carlo comparisons in R. Use small native-evaluator scripts that run -the installed estimator for deterministic scenario seeds and write -replication-level global and boundary ISE plus aggregate squared bias and -variance. Run them once at the recorded baseline commit and once at the -candidate commit, then join the outputs in reporting scripts. - -This avoids a legacy-mode switch in the public C++ API and avoids maintaining -two production estimator paths solely for benchmarking. - -The final one-sided suite should expand the retained scenarios with -intermediate sample sizes, steeper finite-endpoint slopes, heavier remote -tails, upper-bounded reflections, and visual realizations. The final two-sided -suite should retain varied symmetric and asymmetric finite, vanishing, and -exploding endpoint shapes plus local boundary plots. Report paired ISE ratios -with Monte Carlo uncertainty, global and local bias/variance, classifier rates -computed by matching R code, visual examples, and fit time relative to the -current transformed baselines. diff --git a/diagnostic/one-sided-repair/README.md b/diagnostic/one-sided-repair/README.md deleted file mode 100644 index 41b2b56..0000000 --- a/diagnostic/one-sided-repair/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# One-sided boundary repair - -This workspace applies the selected two-boundary idea to continuous densities -with exactly one known finite endpoint. It is deliberately separate from -`boundary-repair/`, which is stable. - -## Current candidate - -The power-$3/4$ transformation estimator is the unweighted bulk fit. A single -order-statistic tail index classifies the finite endpoint using -$k=\min(n-1,\lceil2\sqrt n\rceil)$ and the same 95% rule as in the -two-boundary estimator. A confidently finite endpoint receives the averaged -local-linear/local-quadratic kernel expert; exploding, vanishing, and ambiguous -endpoints reuse bulk. - -The boundary expert is blended with bulk through a smooth weight based on the -bulk CDF, with boundary probability $\min(0.25,n^{-1/2})$. Both kernels share -the degree-2 bandwidth fitted to the closest 75% of boundary distances. The -native evaluator only computes expert values where this weight is nonzero and -normalizes once after fusion. This preserves the stabilizing information in -most of the sample without allowing the most remote observations to dominate. -The construction is reflection- and scale-equivariant. - -The validation suite uses 30 paired replications at $n=100,1000$ for -Exponential, half-normal, Gamma$(2)$, Gamma$(0.75)$, and Lomax$(2)$ densities. -The log transform was rejected and its experimental implementation and outputs -have been removed. - -## Files - -- `scripts/one_sided_estimator.R`: pre-native tuning implementation. -- `scripts/ablate_local_floor_fraction.R`: selected floor-fraction ablation. -- `scripts/plot_local_floor_fraction_ablation.R`: tuning curves and example - estimates. -- `results/local-floor-fraction-ablation.csv` and - `plots/local-floor-fraction-ablation.pdf`: current tuning evidence. -- `RESULTS.md`: numerical conclusions. -- `HANDOFF.md`: implementation state and next steps. -- `NATIVE_CPP.md`: shared one- and two-sided native implementation roadmap. - -Run from the R-package root: - -```sh -Rscript inst/include/kde1d-cpp/diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R 30 -Rscript inst/include/kde1d-cpp/diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R -``` diff --git a/diagnostic/one-sided-repair/RESULTS.md b/diagnostic/one-sided-repair/RESULTS.md deleted file mode 100644 index b302222..0000000 --- a/diagnostic/one-sided-repair/RESULTS.md +++ /dev/null @@ -1,59 +0,0 @@ -# One-sided boundary-repair results - -## Estimator held fixed during the ablation - -The candidate uses the power-$3/4$ estimator as unweighted bulk. If the -order-statistic classifier identifies a finite nonzero endpoint, equal -local-linear and local-quadratic estimates are blended into the shrinking -boundary region. Only the bandwidth-floor sample fraction changes. - -The experiment uses 30 paired replications for five densities at $n=100$ and -$n=1000$. It compares the lowest 15%, 20%, 25%, 30%, 35%, 40%, 50%, 75%, and -100% of boundary distances, plus a shrinking subset of $\lceil\sqrt n\rceil$ -distances. All values below are candidate/current ratios, so smaller is better. - -## Aggregate result - -| $n$ | floor subset | global ISE | boundary ISE | squared bias | variance | -|---:|---:|---:|---:|---:|---:| -| 100 | 25% | 0.989 | 0.986 | 0.895 | 1.007 | -| 100 | 50% | 0.933 | 0.899 | 0.860 | 0.949 | -| 100 | 75% | **0.902** | **0.854** | **0.829** | **0.917** | -| 100 | 100% | 0.941 | 0.911 | 1.004 | 0.923 | -| 100 | $\sqrt n$ | 1.073 | 1.127 | 0.905 | 1.102 | -| 1000 | 25% | 0.933 | 0.896 | 0.801 | 0.976 | -| 1000 | 50% | 0.909 | 0.863 | 0.797 | 0.946 | -| 1000 | 75% | **0.889** | **0.834** | **0.789** | **0.924** | -| 1000 | 100% | 0.983 | 0.959 | 0.963 | 0.986 | -| 1000 | $\sqrt n$ | 1.043 | 1.064 | 0.806 | 1.112 | - -The old 25% floor is too local. Increasing the subset through 75% reduces both -bias and variance. A shrinking $\sqrt n$ subset is clearly too small and -reintroduces instability. Using the full sample overshoots the optimum because -remote tail observations again inflate the floor. - -## Selected 75% floor by density - -| density | $n$ | global ISE | boundary ISE | squared bias | variance | -|---|---:|---:|---:|---:|---:| -| Exponential | 100 | 0.808 | 0.709 | 0.575 | 0.841 | -| Exponential | 1000 | 0.805 | 0.722 | 0.455 | 0.890 | -| half-normal | 100 | 0.869 | 0.744 | 0.817 | 0.878 | -| half-normal | 1000 | 0.808 | 0.672 | 0.868 | 0.801 | -| Gamma$(2)$ | 100 | 1.026 | 1.083 | 1.174 | 1.019 | -| Gamma$(2)$ | 1000 | 1.000 | 1.000 | 1.000 | 1.000 | -| Gamma$(0.75)$ | 100 | 0.985 | 0.983 | 0.913 | 0.992 | -| Gamma$(0.75)$ | 1000 | 1.000 | 1.000 | 1.000 | 1.000 | -| Lomax$(2)$ | 100 | 0.819 | 0.752 | 0.670 | 0.857 | -| Lomax$(2)$ | 1000 | 0.833 | 0.774 | 0.622 | 0.926 | - -The full-sample floor would improve the finite light-tail cases further, but it -raises Lomax global ISE to 1.075 at $n=100$ and 1.392 at $n=1000$. The 75% -floor retains large improvements for both light and long remote tails and is -therefore the selected default. - -The realization plots show the same trade-off. Relative to 25%, the selected -floor substantially calms the near-endpoint estimates. Relative to 100%, it -avoids the flattened Lomax boundary while remaining visually smooth for -Exponential data. All simulated estimates are nonnegative and normalized to -numerical precision. diff --git a/diagnostic/one-sided-repair/plots/local-floor-fraction-ablation.pdf b/diagnostic/one-sided-repair/plots/local-floor-fraction-ablation.pdf deleted file mode 100644 index 1fafa4a0116d914812a2ef0062d64719a4959a6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77662 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 SvU4buHcSVktZZsy2KpbMJ4BcO diff --git a/diagnostic/one-sided-repair/results/local-floor-fraction-ablation.csv b/diagnostic/one-sided-repair/results/local-floor-fraction-ablation.csv deleted file mode 100644 index 9aebb6c..0000000 --- a/diagnostic/one-sided-repair/results/local-floor-fraction-ablation.csv +++ /dev/null @@ -1,111 +0,0 @@ -"distribution","sample_size","replications","method","global_ise","global_squared_bias","global_variance","boundary_ise","boundary_squared_bias","boundary_variance","finite_rate","mean_floor_ratio","minimum_density","maximum_mass_error" -"exponential",100,30,"current",0.0165472389855547,0.00205016560497188,0.0144970733805828,0.0106234994208158,0.00126599700538637,0.00935750241542941,NA,NA,1.87620764495024e-15,1.11022302462516e-16 -"exponential",100,30,"fixed-15pct",0.0164068280322217,0.00176173524182124,0.0146450927904004,0.0104884088522769,0.000969273783595678,0.00951913506868119,0.666666666666667,2.26138933228023,0,1.11022302462516e-16 -"exponential",100,30,"fixed-20pct",0.0157245002505956,0.00165925024528034,0.0140652500053152,0.00977827871653413,0.000871272403187169,0.00890700631334696,0.666666666666667,2.72230964287038,1.8683320459021e-15,1.11022302462516e-16 -"exponential",100,30,"fixed-25pct",0.0154464207902959,0.00159454865963953,0.0138518721306564,0.0094772157298769,0.00081402806341869,0.00866318766645821,0.666666666666667,3.3746911588894,1.86756569172953e-15,1.11022302462516e-16 -"exponential",100,30,"fixed-30pct",0.0152787565880896,0.00159907933870905,0.0136796772493806,0.00929504572248738,0.000818405451515906,0.00847664027097147,0.666666666666667,4.09079193231902,1.87053078117119e-15,1.11022302462516e-16 -"exponential",100,30,"fixed-35pct",0.0150985550244765,0.00157889875105775,0.0135196562734187,0.00910619553077884,0.00080019644459805,0.00830599908618079,0.666666666666667,4.74814780644128,1.87467719387415e-15,1.11022302462516e-16 -"exponential",100,30,"fixed-40pct",0.0148474205746887,0.00152076471560491,0.0133266558590838,0.00886082377495489,0.000749827554669101,0.00811099622028579,0.666666666666667,5.28142581925347,1.87508377257283e-15,2.22044604925031e-16 -"exponential",100,30,"fixed-50pct",0.0144525145480613,0.00140802584850766,0.0130444886995537,0.00850068136672482,0.000655265975954673,0.00784541539077015,0.666666666666667,6.6658845934232,1.87677765384802e-15,1.11022302462516e-16 -"exponential",100,30,"fixed-75pct",0.013372535861314,0.0011785272962235,0.0121940085650905,0.00753230138812056,0.000480751354051795,0.00705155003406876,0.666666666666667,11.0333560732554,1.8732244279489e-15,1.11022302462516e-16 -"exponential",100,30,"fixed-100pct",0.0122027604558946,0.00112660422901432,0.0110761562268802,0.00650597734670406,0.000461015912509725,0.00604496143419433,0.666666666666667,25.0263770275047,1.87799591395489e-15,1.11022302462516e-16 -"exponential",100,30,"shrinking",0.017856701300014,0.00171894251195662,0.0161377587880574,0.0119985964464945,0.000950185514962622,0.0110484109315318,0.666666666666667,1.53936144201145,0,1.11022302462516e-16 -"exponential",1000,30,"current",0.00240917299788813,0.000470619160762849,0.00193855383712528,0.00165537707098662,0.000403802822230112,0.00125157424875651,NA,NA,1.84245192195729e-08,1.11022302462516e-16 -"exponential",1000,30,"fixed-15pct",0.00226862893387558,0.000267541194142079,0.0020010877397335,0.00151319998629151,0.000204448971019676,0.00130875101527183,0.8,4.74481059084514,1.84460227396814e-08,1.11022302462516e-16 -"exponential",1000,30,"fixed-20pct",0.00225442266571058,0.000262749740050737,0.00199167292565984,0.00149821118453056,0.000200035780791981,0.00129817540373858,0.8,5.98252748718848,1.84548529261594e-08,1.11022302462516e-16 -"exponential",1000,30,"fixed-25pct",0.00223163792088978,0.000257242065644417,0.00197439585524536,0.0014751821032443,0.000194947305987805,0.00128023479725649,0.8,7.22495317992321,1.84584351924974e-08,2.22044604925031e-16 -"exponential",1000,30,"fixed-30pct",0.00221870029017855,0.000252826191135576,0.00196587409904297,0.00146218422878417,0.000190827664872001,0.00127135656391217,0.8,8.52165916461346,1.84604292036413e-08,1.11022302462516e-16 -"exponential",1000,30,"fixed-35pct",0.00219384531132905,0.000247241712589002,0.00194660359874005,0.00143795550079077,0.000185653506736015,0.00125230199405476,0.8,9.8649716598902,1.84610565220666e-08,1.11022302462516e-16 -"exponential",1000,30,"fixed-40pct",0.00217145301439129,0.000242349204881074,0.00192910380951022,0.00141640854005911,0.000181158632597437,0.00123524990746168,0.8,11.0937383479702,1.84608070901668e-08,2.22044604925031e-16 -"exponential",1000,30,"fixed-50pct",0.00211986240298299,0.000235244426606243,0.00188461797637675,0.00136696335158836,0.00017465441086855,0.00119230894071981,0.8,14.2235753638748,1.84549854155193e-08,1.11022302462516e-16 -"exponential",1000,30,"fixed-75pct",0.00193955914179103,0.000214004486169561,0.00172555465562147,0.00119551447318874,0.000155328617762214,0.00104018585542653,0.8,23.6847920686692,1.84070208807465e-08,1.11022302462516e-16 -"exponential",1000,30,"fixed-100pct",0.00179827087563706,0.000210590735373438,0.00158768014026362,0.0010637085141229,0.000152188847628034,0.00091151966649487,0.8,59.0059636907067,1.83724706743234e-08,1.11022302462516e-16 -"exponential",1000,30,"shrinking",0.00273822412309522,0.00028350698150981,0.00245471714158541,0.00198144991484761,0.000219256056318021,0.00176219385852959,0.8,1.39713095946284,0,1.11022302462516e-16 -"half_normal",100,30,"current",0.0219941368244042,0.0030219174956199,0.0189722193287843,0.0110161925675509,0.000849741178896194,0.0101664513886547,NA,NA,0,2.22044604925031e-16 -"half_normal",100,30,"fixed-15pct",0.0227249965243955,0.00273111590377345,0.019993880620622,0.0117287333016139,0.000600066952616288,0.0111286663489976,0.8,2.37019396388901,0,1.11022302462516e-16 -"half_normal",100,30,"fixed-20pct",0.0224219661004901,0.00271727802633407,0.0197046880741561,0.011438676091904,0.000586237600351728,0.0108524384915523,0.8,2.71464262028137,0,1.11022302462516e-16 -"half_normal",100,30,"fixed-25pct",0.0219269324508956,0.00269041598616543,0.0192365164647302,0.0109498342362696,0.000558589786947187,0.0103912444493225,0.8,3.14072469187916,0,1.11022302462516e-16 -"half_normal",100,30,"fixed-30pct",0.0215633488241571,0.00267166572203566,0.0188916831021214,0.0105948753978839,0.000542078086840766,0.0100527973110432,0.8,3.60955830997078,0,1.11022302462516e-16 -"half_normal",100,30,"fixed-35pct",0.0210312218425393,0.00266532168736644,0.0183659001551728,0.0100696160284695,0.000533729203646682,0.00953588682482281,0.8,4.16410671809387,0,1.11022302462516e-16 -"half_normal",100,30,"fixed-40pct",0.0206204333336116,0.0026483827572441,0.0179720505763675,0.00965859372516434,0.000516888221053642,0.0091417055041107,0.8,4.81231426826691,0,1.11022302462516e-16 -"half_normal",100,30,"fixed-50pct",0.0200327113370716,0.00263109300195777,0.0174016183351138,0.00906277994189698,0.000497753785072715,0.00856502615682426,0.8,5.9807411308278,3.06939566084117e-10,1.11022302462516e-16 -"half_normal",100,30,"fixed-75pct",0.0191219774632953,0.00246802725978619,0.0166539502035091,0.00820055137292614,0.000374255974420255,0.00782629539850588,0.8,9.15049092595185,3.07494413352088e-10,1.11022302462516e-16 -"half_normal",100,30,"fixed-100pct",0.0177911170386674,0.00223295181803002,0.0155581652206374,0.00704315204661345,0.000232650073862045,0.0068105019727514,0.8,14.7602804283356,3.06779576076905e-10,1.11022302462516e-16 -"half_normal",100,30,"shrinking",0.0237532831195187,0.00267081247804823,0.0210824706414705,0.0127376215859904,0.000545114336237087,0.0121925072497533,0.8,1.70499785686247,0,1.11022302462516e-16 -"half_normal",1000,30,"current",0.00274341237242215,0.000280571449502999,0.00246284092291915,0.00156264121910904,8.45358254246363e-05,0.00147810539368441,NA,NA,4.07601257168278e-10,2.22044604925031e-16 -"half_normal",1000,30,"fixed-15pct",0.00239860475791024,0.00023031830376732,0.00216828645414292,0.00122490802991675,4.12353743580945e-05,0.00118367265555866,0.7,4.34564987912544,1.13038952589692e-05,2.22044604925031e-16 -"half_normal",1000,30,"fixed-20pct",0.00234511782877151,0.000233818969557785,0.00211129885921373,0.00117410137914751,4.61022224571394e-05,0.00112799915669037,0.7,5.32984658897953,1.13034006367537e-05,2.22044604925031e-16 -"half_normal",1000,30,"fixed-25pct",0.00232711352945201,0.000237367111878006,0.00208974641757401,0.00115726236610121,5.02670537112527e-05,0.00110699531238995,0.7,6.43401199260486,1.13040847624379e-05,2.22044604925031e-16 -"half_normal",1000,30,"fixed-30pct",0.00231117000000692,0.000240171907376736,0.00207099809263018,0.00114228501393874,5.35257957790126e-05,0.00108875921815973,0.7,7.48910434944926,1.13047763103815e-05,2.22044604925031e-16 -"half_normal",1000,30,"fixed-35pct",0.00229686297939699,0.000242642686529828,0.00205422029286716,0.00112882622241208,5.63660204190984e-05,0.00107246020199298,0.7,8.43677378168733,1.13050274090261e-05,2.22044604925031e-16 -"half_normal",1000,30,"fixed-40pct",0.00228944963338305,0.000242831116619971,0.00204661851676308,0.00112179246612444,5.655341339539e-05,0.00106523905272905,0.7,9.34145379661723,1.13047290481858e-05,2.22044604925031e-16 -"half_normal",1000,30,"fixed-50pct",0.00227344588313635,0.000243474537140234,0.00202997134599611,0.00110571228344061,5.71353280387194e-05,0.00104857695540189,0.7,11.3280875827355,1.13029900215361e-05,2.22044604925031e-16 -"half_normal",1000,30,"fixed-75pct",0.00221714034673766,0.000243482061837878,0.00197365828489979,0.00104976938408884,5.78750403428966e-05,0.000991894343745948,0.7,16.7479465148207,1.1293032196771e-05,2.22044604925031e-16 -"half_normal",1000,30,"fixed-100pct",0.0021329497805297,0.000243836210442882,0.00188911357008682,0.000968433716153227,6.06661299234941e-05,0.000907767586229733,0.7,27.3251884944149,1.12679030054272e-05,2.22044604925031e-16 -"half_normal",1000,30,"shrinking",0.00284213353017322,0.000230931420125264,0.00261120211004796,0.00166941156763807,4.14921749166945e-05,0.00162791939272138,0.7,1.35077773725852,0,2.22044604925031e-16 -"gamma_2",100,30,"current",0.00448352076124264,0.000201561828895339,0.00428195893234731,0.00146327990980918,0.000135018357992683,0.0013282615518165,NA,NA,0,2.22044604925031e-16 -"gamma_2",100,30,"fixed-15pct",0.00459371029079864,0.000201207501479278,0.00439250278931936,0.00158037848320732,0.000136949605033015,0.00144342887817431,0.333333333333333,1.91525005228117,0,1.11022302462516e-16 -"gamma_2",100,30,"fixed-20pct",0.00455634729915098,0.000208004490920689,0.00434834280823029,0.00154236062875898,0.000142810162262304,0.00139955046649668,0.333333333333333,2.29761042217586,0,1.11022302462516e-16 -"gamma_2",100,30,"fixed-25pct",0.00455623114841961,0.000214821631304367,0.00434140951711525,0.00154202356205872,0.000149333840245232,0.00139268972181349,0.333333333333333,2.77544275831225,0,1.11022302462516e-16 -"gamma_2",100,30,"fixed-30pct",0.00455120479869776,0.000215698390397887,0.00433550640829987,0.00153831983882578,0.000150238994097621,0.00138808084472816,0.333333333333333,2.90797508198628,0,1.11022302462516e-16 -"gamma_2",100,30,"fixed-35pct",0.0045471326651577,0.000217952041254612,0.00432918062390309,0.00153459820934171,0.00015244906752056,0.00138214914182115,0.333333333333333,2.99786682361582,0,1.11022302462516e-16 -"gamma_2",100,30,"fixed-40pct",0.00454576337060127,0.000220363954783064,0.0043253994158182,0.00153287357090786,0.000154975717175496,0.00137789785373237,0.333333333333333,3.23371893266245,0,1.11022302462516e-16 -"gamma_2",100,30,"fixed-50pct",0.00455160765603087,0.000226965756163114,0.00432464189986776,0.00153792876544311,0.000162076200268522,0.00137585256517459,0.333333333333333,3.75543047296855,0,1.11022302462516e-16 -"gamma_2",100,30,"fixed-75pct",0.00460136779113603,0.000236565440002761,0.00436480235113327,0.00158461737904955,0.000173807172003612,0.00141081020704594,0.333333333333333,5.25961330940397,0,1.11022302462516e-16 -"gamma_2",100,30,"fixed-100pct",0.00474861631473468,0.00023424922057421,0.00451436709416047,0.00171685956647603,0.000174884739131384,0.00154197482734464,0.333333333333333,8.06494615215408,0,1.11022302462516e-16 -"gamma_2",100,30,"shrinking",0.0046866663853133,0.000191314677613302,0.00449535170769999,0.00167153051624082,0.000128138743162736,0.00154339177307808,0.333333333333333,1.46249077481671,0,1.11022302462516e-16 -"gamma_2",1000,30,"current",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,NA,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"fixed-15pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"fixed-20pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"fixed-25pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"fixed-30pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"fixed-35pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"fixed-40pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"fixed-50pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"fixed-75pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"fixed-100pct",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_2",1000,30,"shrinking",0.000647619657310632,2.25272471129222e-05,0.00062509241019771,0.000297582963303315,5.0444987514047e-06,0.000292538464551911,0,NA,0,1.11022302462516e-16 -"gamma_0.75",100,30,"current",0.0662130479543093,0.00603847252934643,0.0601745754249629,0.0596204629596765,0.00509342274353279,0.0545270402161437,NA,NA,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"fixed-15pct",0.0688437108923025,0.00596993002684055,0.062873780865462,0.0622764116383608,0.00502879344888837,0.0572476181894724,0.233333333333333,2.51217988508221,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"fixed-20pct",0.0681154550739925,0.00587067138602011,0.0622447836879724,0.0615411348528898,0.00493451100349295,0.0566066238493968,0.233333333333333,3.00451108242131,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"fixed-25pct",0.0669550767706018,0.00570743403616402,0.0612476427344378,0.0603956774670474,0.00477713459093501,0.0556185428761124,0.233333333333333,3.60367826811898,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"fixed-30pct",0.0658758521149039,0.00556660841555187,0.060309243699352,0.0593383501020204,0.004642953742049,0.0546953963599714,0.233333333333333,5.02363090385764,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"fixed-35pct",0.0654203316851601,0.00548660007863664,0.0599337316065235,0.0588890777872092,0.00456762074901735,0.0543214570381918,0.233333333333333,6.27557902395686,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"fixed-40pct",0.0650860242835899,0.00542694184924156,0.0596590824343483,0.0585561390714141,0.00451209769209147,0.0540440413793226,0.233333333333333,7.16425287464413,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"fixed-50pct",0.0647090006418789,0.00533834478367925,0.0593706558581996,0.0581738553795754,0.00442938224035204,0.0537444731392233,0.233333333333333,10.0698415841485,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"fixed-75pct",0.0651901055934623,0.00551032830221601,0.0596797772912463,0.0586057654421702,0.0045791668266887,0.0540265986154815,0.233333333333333,19.660134936497,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"fixed-100pct",0.0676880390463463,0.0060496287625182,0.0616384102838281,0.0609849876154783,0.00506658758002695,0.0559184000354514,0.233333333333333,51.1114722569795,2.97020597181301e-32,2.22044604925031e-16 -"gamma_0.75",100,30,"shrinking",0.0708120152547144,0.00622858341689876,0.0645834318378157,0.0642682642137913,0.0052944469595103,0.058973817254281,0.233333333333333,1.56444490537761,0,2.22044604925031e-16 -"gamma_0.75",1000,30,"current",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,NA,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"fixed-15pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"fixed-20pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"fixed-25pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"fixed-30pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"fixed-35pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"fixed-40pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"fixed-50pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"fixed-75pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"fixed-100pct",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"gamma_0.75",1000,30,"shrinking",0.00800935397940015,0.00240562435989908,0.00560372961950107,0.00685770784468224,0.00230260733820975,0.00455510050647249,0,NA,2.36840057628249e-09,1.11022302462516e-16 -"lomax_2",100,30,"current",0.0320268987246898,0.00648388858700561,0.0255430101376842,0.022571498829797,0.00539273643819479,0.0171787623916022,NA,NA,0,1.11022302462516e-16 -"lomax_2",100,30,"fixed-15pct",0.0341784289040103,0.00545431820112166,0.0287241107028886,0.0246692629391396,0.00437317194694695,0.0202960909921927,0.7,1.74298292023704,0,1.11022302462516e-16 -"lomax_2",100,30,"fixed-20pct",0.0329364272846334,0.00531565631751246,0.0276207709671209,0.0234373427192617,0.00422860716891606,0.0192087355503456,0.7,2.25345608974253,0,1.11022302462516e-16 -"lomax_2",100,30,"fixed-25pct",0.0315504362882948,0.00516885482754763,0.0263815814607472,0.022037140835904,0.00407275491685668,0.0179643859190473,0.7,2.77239130253995,0,1.11022302462516e-16 -"lomax_2",100,30,"fixed-30pct",0.0302487831990908,0.00501418054191126,0.0252346026571795,0.0207106798807081,0.00390287366269442,0.0168078062180136,0.7,3.42851685390775,0,1.11022302462516e-16 -"lomax_2",100,30,"fixed-35pct",0.0299454664033389,0.00498769968054349,0.0249577667227954,0.0204190781644711,0.00387799504835325,0.0165410831161179,0.7,4.08323232164168,0,1.11022302462516e-16 -"lomax_2",100,30,"fixed-40pct",0.0294528981772044,0.00493738819233153,0.0245155099848729,0.0199445389599459,0.00382085750427208,0.0161236814556738,0.7,4.72644379724695,0,1.11022302462516e-16 -"lomax_2",100,30,"fixed-50pct",0.0285189100946901,0.00474155087942755,0.0237773592152626,0.0190556289633984,0.00360673315380207,0.0154488958095963,0.7,6.18958080513734,0,1.11022302462516e-16 -"lomax_2",100,30,"fixed-75pct",0.0262364414943695,0.00434160891191695,0.0218948325824526,0.0169627470963472,0.00315960086719081,0.0138031462291564,0.7,11.9477658059949,0,1.11022302462516e-16 -"lomax_2",100,30,"fixed-100pct",0.0344264830854107,0.0101608357551471,0.0242656473302637,0.0250325446664152,0.00909821530212285,0.0159343293642923,0.7,92.7046182399041,0,1.11022302462516e-16 -"lomax_2",100,30,"shrinking",0.0349986902781772,0.0053166941988258,0.0296819960793514,0.0255221859554241,0.00423518037423045,0.0212870055811936,0.7,1.33704272336928,0,1.11022302462516e-16 -"lomax_2",1000,30,"current",0.00466466138729923,0.00143513707469976,0.00322952431259947,0.00350149716851033,0.00112671300315472,0.00237478416535561,NA,NA,0,1.11022302462516e-16 -"lomax_2",1000,30,"fixed-15pct",0.00436099990888606,0.000878121257830974,0.00348287865105509,0.00320092795758196,0.000564160869336452,0.00263676708824551,0.666666666666667,4.4932550558715,0,1.11022302462516e-16 -"lomax_2",1000,30,"fixed-20pct",0.00423966119040754,0.000876618726807714,0.00336304246359983,0.00307622311705505,0.000560854659297538,0.00251536845775752,0.666666666666667,5.81675470465849,0,1.11022302462516e-16 -"lomax_2",1000,30,"fixed-25pct",0.0041430445540767,0.000876082849395204,0.0032669617046815,0.00297729161922663,0.00055846411536554,0.00241882750386109,0.666666666666667,7.11933483971629,0,2.22044604925031e-16 -"lomax_2",1000,30,"fixed-30pct",0.0040731577359026,0.000877330147025215,0.00319582758887738,0.00290481115181225,0.00055813996746545,0.0023466711843468,0.666666666666667,8.52294235352961,0,1.11022302462516e-16 -"lomax_2",1000,30,"fixed-35pct",0.00401937859112426,0.000878730832829979,0.00314064775829428,0.00284942159321027,0.000558245311673399,0.00229117628153687,0.666666666666667,9.97469592167928,0,1.11022302462516e-16 -"lomax_2",1000,30,"fixed-40pct",0.00397052028672156,0.000880354759175136,0.00309016552754642,0.0027996394210534,0.00055854532208646,0.00224109409896694,0.666666666666667,11.5527001556363,0,1.11022302462516e-16 -"lomax_2",1000,30,"fixed-50pct",0.00390556519468693,0.000885414325502173,0.00302015086918476,0.00273302688240551,0.000561236325944702,0.0021717905564608,0.666666666666667,15.168288605388,0,1.11022302462516e-16 -"lomax_2",1000,30,"fixed-75pct",0.00388389723608418,0.000892559922975234,0.00299133731310895,0.00271109831571414,0.000567744771275972,0.00214335354443817,0.666666666666667,28.0685793643946,0,1.11022302462516e-16 -"lomax_2",1000,30,"fixed-100pct",0.00649334812218761,0.00215366087792471,0.0043396872442629,0.00536551738685692,0.00189185791667889,0.00347365947017803,0.666666666666667,316.351208853879,0,1.11022302462516e-16 -"lomax_2",1000,30,"shrinking",0.00485525856366109,0.000865000667250043,0.00399025789641104,0.00369570145755347,0.000550680684486621,0.00314502077306685,0.666666666666667,1.32912073570791,0,1.11022302462516e-16 diff --git a/diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R b/diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R deleted file mode 100644 index ec0bd78..0000000 --- a/diagnostic/one-sided-repair/scripts/ablate_local_floor_fraction.R +++ /dev/null @@ -1,212 +0,0 @@ -# Paired ablation of the local probability mass used for the bandwidth floor. -# Run from the root of the kde1d R package. - -if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { - stop("run from the kde1d package root with pkgload installed") -} -pkgload::load_all(".", quiet = TRUE) -source(paste0( - "inst/include/kde1d-cpp/diagnostic/one-sided-repair/scripts/", - "one_sided_estimator.R" -)) - -arguments <- commandArgs(trailingOnly = TRUE) -replication_count <- if (length(arguments) >= 1L) { - as.integer(arguments[[1L]]) -} else { - 30L -} -output_file <- if (length(arguments) >= 2L) arguments[[2L]] else paste0( - "inst/include/kde1d-cpp/diagnostic/one-sided-repair/results/", - "local-floor-fraction-ablation.csv" -) -if (length(arguments) > 2L || !is.finite(replication_count) || - replication_count < 2L) { - stop("usage: ablate_local_floor_fraction.R [replications] [output.csv]") -} - -validation_distributions <- list( - exponential = list(random = rexp, density = dexp, quantile = qexp), - half_normal = list( - random = function(sample_size) abs(rnorm(sample_size)), - density = function(values) 2 * dnorm(values), - quantile = function(probabilities) qnorm((probabilities + 1) / 2) - ), - gamma_2 = list( - random = function(sample_size) rgamma(sample_size, 2), - density = function(values) dgamma(values, 2), - quantile = function(probabilities) qgamma(probabilities, 2) - ), - gamma_0.75 = list( - random = function(sample_size) rgamma(sample_size, 0.75), - density = function(values) dgamma(values, 0.75), - quantile = function(probabilities) qgamma(probabilities, 0.75) - ), - lomax_2 = list( - random = function(sample_size) (1 - runif(sample_size))^(-0.5) - 1, - density = function(values) 2 / (1 + values)^3, - quantile = function(probabilities) (1 - probabilities)^(-0.5) - 1 - ) -) -sample_sizes <- c(100L, 1000L) -local_floor_fractions <- c( - 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.50, 0.75, 1 -) -fraction_methods <- paste0( - "fixed-", - format(100 * local_floor_fractions, trim = TRUE), - "pct" -) -candidate_methods <- c(fraction_methods, "shrinking") -methods <- c("current", candidate_methods) -evaluation_probabilities <- sort(unique(c( - 10^seq(-10, -2, length.out = 101L), - seq(0.01, 0.999, length.out = 401L), - 0.9999, 0.99999 -))) -result_rows <- list() - -summarize_fraction_estimates <- function( - evaluation_points, - estimates, - true_density, - region_points) { - mean_density <- rowMeans(estimates) - integrated_errors <- vapply(seq_len(ncol(estimates)), function(replication) { - one_sided_trapezoid_integral( - evaluation_points[region_points], - (estimates[region_points, replication] - true_density[region_points])^2 - ) - }, numeric(1L)) - c( - ise = mean(integrated_errors), - squared_bias = one_sided_trapezoid_integral( - evaluation_points[region_points], - (mean_density[region_points] - true_density[region_points])^2 - ), - variance = one_sided_trapezoid_integral( - evaluation_points[region_points], - rowMeans((estimates[region_points, , drop = FALSE] - - mean_density[region_points])^2) - ) - ) -} - -for (distribution_index in seq_along(validation_distributions)) { - evaluation_points <- validation_distributions[[distribution_index]]$quantile( - evaluation_probabilities - ) - true_density <- validation_distributions[[distribution_index]]$density( - evaluation_points - ) - boundary_points <- evaluation_probabilities <= 0.1 - for (sample_size in sample_sizes) { - estimates <- setNames(lapply(methods, function(method) { - matrix(NA_real_, length(evaluation_points), replication_count) - }), methods) - finite_choices <- logical(replication_count) - floor_ratios <- setNames(lapply(candidate_methods, function(method) { - rep(NA_real_, replication_count) - }), candidate_methods) - for (replication in seq_len(replication_count)) { - set.seed( - 20260914L + 100000L * distribution_index + - 1000L * match(sample_size, sample_sizes) + replication - ) - observations <- validation_distributions[[distribution_index]]$random( - sample_size - ) - estimates$current[, replication] <- normalize_one_sided_density( - evaluation_points, - dkde1d(evaluation_points, kde1d(observations, xmin = 0)) - ) - for (fraction_index in seq_along(local_floor_fractions)) { - method <- fraction_methods[[fraction_index]] - candidate_fit <- fit_one_sided_candidate( - observations, - evaluation_points, - bandwidth_floor = "local", - local_floor_fraction = local_floor_fractions[[fraction_index]] - ) - estimates[[method]][, replication] <- candidate_fit$density - floor_ratios[[method]][[replication]] <- mean( - candidate_fit$boundary_bandwidths / - candidate_fit$selected_boundary_bandwidths - ) - if (fraction_index == 1L) { - finite_choices[[replication]] <- - candidate_fit$expert_choice == "finite" - } - } - shrinking_fit <- fit_one_sided_candidate( - observations, - evaluation_points, - bandwidth_floor = "shrinking" - ) - estimates$shrinking[, replication] <- shrinking_fit$density - floor_ratios$shrinking[[replication]] <- mean( - shrinking_fit$boundary_bandwidths / - shrinking_fit$selected_boundary_bandwidths - ) - } - for (method in methods) { - global_summary <- summarize_fraction_estimates( - evaluation_points, - estimates[[method]], - true_density, - rep(TRUE, length(evaluation_points)) - ) - boundary_summary <- summarize_fraction_estimates( - evaluation_points, - estimates[[method]], - true_density, - boundary_points - ) - result_rows[[length(result_rows) + 1L]] <- data.frame( - distribution = names(validation_distributions)[[distribution_index]], - sample_size = sample_size, - replications = replication_count, - method = method, - global_ise = global_summary[["ise"]], - global_squared_bias = global_summary[["squared_bias"]], - global_variance = global_summary[["variance"]], - boundary_ise = boundary_summary[["ise"]], - boundary_squared_bias = boundary_summary[["squared_bias"]], - boundary_variance = boundary_summary[["variance"]], - finite_rate = if (method %in% candidate_methods) { - mean(finite_choices) - } else { - NA_real_ - }, - mean_floor_ratio = if ( - method %in% candidate_methods && - any(is.finite(floor_ratios[[method]])) - ) { - mean(floor_ratios[[method]], na.rm = TRUE) - } else { - NA_real_ - }, - minimum_density = min(estimates[[method]]), - maximum_mass_error = max(abs(vapply( - seq_len(replication_count), - function(replication) { - one_sided_trapezoid_integral( - evaluation_points, - estimates[[method]][, replication] - ) - 1 - }, - numeric(1L) - ))) - ) - } - message( - names(validation_distributions)[[distribution_index]], - ", n = ", sample_size - ) - } -} - -results <- do.call(rbind, result_rows) -dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) -write.csv(results, output_file, row.names = FALSE) -message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/one-sided-repair/scripts/one_sided_estimator.R b/diagnostic/one-sided-repair/scripts/one_sided_estimator.R deleted file mode 100644 index 8a9ec0b..0000000 --- a/diagnostic/one-sided-repair/scripts/one_sided_estimator.R +++ /dev/null @@ -1,360 +0,0 @@ -# Reference R implementation of the one-sided finite-boundary candidate. - -one_sided_trapezoid_integral <- function(evaluation_points, values) { - sum(diff(evaluation_points) * - (values[-length(values)] + values[-1L]) / 2) -} - -normalize_one_sided_density <- function(evaluation_points, density) { - density <- pmax(0, density) - density_mass <- one_sided_trapezoid_integral(evaluation_points, density) - if (!is.finite(density_mass) || density_mass <= 0) { - stop("density cannot be normalized") - } - density / density_mass -} - -one_sided_smoothstep <- function(normalized_distance) { - 3 * normalized_distance^2 - 2 * normalized_distance^3 -} - -make_one_sided_expert_weights <- function(probabilities, sample_size, - concentration = 1, - shrinkage_exponent = 0.5) { - boundary_fraction <- min( - 0.25, - concentration / sample_size^shrinkage_exponent - ) - boundary_weights <- 1 - one_sided_smoothstep(pmin( - 1, - probabilities / boundary_fraction - )) - cbind(boundary = boundary_weights, bulk = 1 - boundary_weights) -} - -one_sided_weighted_quantile <- function(values, weights, probability) { - value_order <- order(values) - ordered_weights <- weights[value_order] - values[value_order][which( - cumsum(ordered_weights) / sum(ordered_weights) >= probability - )[[1L]]] -} - -select_one_sided_bandwidth_floor <- function( - boundary_distances, - bandwidth_weights, - degree, - bandwidth_floor = c("local", "shrinking", "global", "none", "robust"), - local_floor_fraction = 0.75) { - bandwidth_floor <- match.arg(bandwidth_floor) - if (bandwidth_floor == "none") { - return(0) - } - if (bandwidth_floor == "global") { - return(kde1d(boundary_distances, deg = degree)$bw) - } - if (bandwidth_floor == "local" || bandwidth_floor == "shrinking") { - if (!is.finite(local_floor_fraction) || local_floor_fraction <= 0 || - local_floor_fraction > 1) { - stop("local_floor_fraction must lie in (0, 1]") - } - local_count <- if (bandwidth_floor == "shrinking") { - max(4L, ceiling(sqrt(length(boundary_distances)))) - } else { - max(4L, ceiling(local_floor_fraction * length(boundary_distances))) - } - return(kde1d(sort(boundary_distances)[seq_len(local_count)], deg = degree)$bw) - } - weighted_median <- one_sided_weighted_quantile( - boundary_distances, - bandwidth_weights, - 0.5 - ) - weighted_mad <- one_sided_weighted_quantile( - abs(boundary_distances - weighted_median), - bandwidth_weights, - 0.5 - ) - if (!(weighted_mad > 0)) { - weighted_mad <- one_sided_weighted_quantile( - boundary_distances, - bandwidth_weights, - 0.75 - ) - weighted_median - } - if (!(weighted_mad > 0)) { - weighted_mad <- max(boundary_distances) * .Machine$double.eps - } - winsorized_distances <- pmin( - boundary_distances, - weighted_median + 6 * weighted_mad - ) - kde1d(winsorized_distances, deg = degree)$bw -} - -fit_one_sided_bulk <- function( - observations, - evaluation_points, - lower_bound, - upper_bound) { - lower_bounded <- !is.na(lower_bound) - bulk_model <- if (lower_bounded) { - kde1d(observations, xmin = lower_bound) - } else { - kde1d(observations, xmax = upper_bound) - } - list( - density = normalize_one_sided_density( - evaluation_points, - dkde1d(evaluation_points, bulk_model) - ), - boundary_probabilities = if (lower_bounded) { - pkde1d(evaluation_points, bulk_model) - } else { - 1 - pkde1d(evaluation_points, bulk_model) - } - ) -} - -fit_one_sided_local_polynomial <- function( - boundary_distances, - evaluation_distances, - bandwidth_weights, - minimum_bandwidth, - degree) { - if (!degree %in% c(1, 2)) { - stop("local boundary degree must be 1 or 2") - } - selected_bandwidth <- kde1d( - boundary_distances, - weights = bandwidth_weights, - deg = degree - )$bw - bandwidth <- max(selected_bandwidth, minimum_bandwidth) - standardized_boundary <- evaluation_distances / bandwidth - truncated_moment_0 <- pnorm(standardized_boundary) - truncated_moment_1 <- -dnorm(standardized_boundary) - truncated_moment_2 <- truncated_moment_0 - - standardized_boundary * dnorm(standardized_boundary) - if (degree == 1) { - moment_determinant <- truncated_moment_0 * truncated_moment_2 - - truncated_moment_1^2 - equivalent_kernel_coefficients <- cbind( - truncated_moment_2 / moment_determinant, - -truncated_moment_1 / moment_determinant - ) - } else { - truncated_moment_3 <- -( - standardized_boundary^2 + 2 - ) * dnorm(standardized_boundary) - truncated_moment_4 <- 3 * truncated_moment_0 - ( - standardized_boundary^3 + 3 * standardized_boundary - ) * dnorm(standardized_boundary) - moment_determinant <- - truncated_moment_0 * ( - truncated_moment_2 * truncated_moment_4 - truncated_moment_3^2 - ) - - truncated_moment_1 * ( - truncated_moment_1 * truncated_moment_4 - - truncated_moment_2 * truncated_moment_3 - ) + - truncated_moment_2 * ( - truncated_moment_1 * truncated_moment_3 - truncated_moment_2^2 - ) - equivalent_kernel_coefficients <- cbind( - ( - truncated_moment_2 * truncated_moment_4 - truncated_moment_3^2 - ) / moment_determinant, - ( - truncated_moment_2 * truncated_moment_3 - - truncated_moment_1 * truncated_moment_4 - ) / moment_determinant, - ( - truncated_moment_1 * truncated_moment_3 - truncated_moment_2^2 - ) / moment_determinant - ) - } - density <- numeric(length(evaluation_distances)) - for (chunk_start in seq(1L, length(evaluation_distances), by = 128L)) { - chunk_indices <- chunk_start:min( - chunk_start + 127L, - length(evaluation_distances) - ) - kernel_arguments <- outer( - evaluation_distances[chunk_indices], - boundary_distances, - "-" - ) / bandwidth - base_kernels <- dnorm(kernel_arguments) - corrected_kernels <- base_kernels * - equivalent_kernel_coefficients[chunk_indices, 1L] - for (polynomial_order in seq_len(degree)) { - corrected_kernels <- corrected_kernels + - base_kernels * - equivalent_kernel_coefficients[ - chunk_indices, - polynomial_order + 1L - ] * kernel_arguments^polynomial_order - } - density[chunk_indices] <- rowMeans(corrected_kernels) / bandwidth - } - list( - density = normalize_one_sided_density(evaluation_distances, density), - bandwidth = bandwidth, - selected_bandwidth = selected_bandwidth - ) -} - -select_one_sided_endpoint_expert <- function( - boundary_distances, - tail_multiplier = 2, - evidence_threshold = qnorm(0.95), - minimum_finite_index = 0.9) { - tail_count <- min( - length(boundary_distances) - 1L, - ceiling(tail_multiplier * sqrt(length(boundary_distances))) - ) - ordered_distances <- sort(boundary_distances) - tail_index <- tail_count / sum(log( - ordered_distances[[tail_count + 1L]] / - pmax(.Machine$double.eps, ordered_distances[seq_len(tail_count)]) - )) - list( - expert_choice = if ( - tail_index >= minimum_finite_index && - tail_index * (1 - evidence_threshold / sqrt(tail_count)) <= 1 - ) { - "finite" - } else { - "bulk" - }, - tail_index = tail_index, - tail_count = tail_count - ) -} - -fit_one_sided_candidate <- function( - observations, - evaluation_points, - lower_bound = 0, - upper_bound = NA_real_, - concentration = 1, - shrinkage_exponent = 0.5, - bandwidth_floor = c("local", "shrinking", "global", "none", "robust"), - local_floor_fraction = 0.75) { - bandwidth_floor <- match.arg(bandwidth_floor) - if (is.na(lower_bound) == is.na(upper_bound)) { - stop("exactly one finite boundary must be supplied") - } - if (length(observations) < 4L || any(!is.finite(observations)) || - any(!is.finite(evaluation_points)) || - is.unsorted(evaluation_points, strictly = TRUE)) { - stop("observations and evaluation_points must be finite and ordered") - } - lower_bounded <- !is.na(lower_bound) - boundary_distances <- if (lower_bounded) { - observations - lower_bound - } else { - upper_bound - observations - } - if (any(boundary_distances < 0)) { - stop("observations must lie inside the supplied support") - } - evaluation_distances <- if (lower_bounded) { - evaluation_points - lower_bound - } else { - rev(upper_bound - evaluation_points) - } - bulk_fit <- fit_one_sided_bulk( - observations, - evaluation_points, - lower_bound, - upper_bound - ) - selection <- select_one_sided_endpoint_expert(boundary_distances) - if (selection$expert_choice == "bulk") { - return(list( - density = bulk_fit$density, - expert_choice = "bulk", - tail_index = selection$tail_index, - tail_count = selection$tail_count, - boundary_bandwidths = c(linear = NA_real_, quadratic = NA_real_), - selected_boundary_bandwidths = c( - linear = NA_real_, quadratic = NA_real_ - ), - bandwidth_floor = bandwidth_floor, - local_floor_fraction = local_floor_fraction, - boundary_fraction = min( - 0.25, - concentration / length(observations)^shrinkage_exponent - ) - )) - } - probability_ranks <- (rank( - boundary_distances, - ties.method = "average" - ) - 0.5) / length(observations) - bandwidth_weights <- make_one_sided_expert_weights( - probability_ranks, - length(observations), - concentration, - shrinkage_exponent - )[, "boundary"] - local_fits <- lapply(c(1L, 2L), function(degree) { - fit_one_sided_local_polynomial( - boundary_distances, - evaluation_distances, - bandwidth_weights, - select_one_sided_bandwidth_floor( - boundary_distances, - bandwidth_weights, - degree, - bandwidth_floor, - local_floor_fraction - ), - degree - ) - }) - boundary_density <- rowMeans(vapply( - local_fits, - function(local_fit) local_fit$density, - numeric(length(evaluation_distances)) - )) - if (!lower_bounded) { - boundary_density <- rev(boundary_density) - } - evaluation_weights <- make_one_sided_expert_weights( - bulk_fit$boundary_probabilities, - length(observations), - concentration, - shrinkage_exponent - ) - list( - density = normalize_one_sided_density( - evaluation_points, - evaluation_weights[, "boundary"] * boundary_density + - evaluation_weights[, "bulk"] * bulk_fit$density - ), - expert_choice = "finite", - tail_index = selection$tail_index, - tail_count = selection$tail_count, - boundary_bandwidths = setNames( - vapply(local_fits, function(local_fit) local_fit$bandwidth, numeric(1L)), - c("linear", "quadratic") - ), - selected_boundary_bandwidths = setNames( - vapply( - local_fits, - function(local_fit) local_fit$selected_bandwidth, - numeric(1L) - ), - c("linear", "quadratic") - ), - bandwidth_floor = bandwidth_floor, - local_floor_fraction = local_floor_fraction, - boundary_fraction = min( - 0.25, - concentration / length(observations)^shrinkage_exponent - ) - ) -} diff --git a/diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R b/diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R deleted file mode 100644 index ce84da5..0000000 --- a/diagnostic/one-sided-repair/scripts/plot_local_floor_fraction_ablation.R +++ /dev/null @@ -1,163 +0,0 @@ -# Plot the local bandwidth-floor fraction ablation. -# Run from the root of the kde1d R package. - -if (!requireNamespace("pkgload", quietly = TRUE) || !file.exists("DESCRIPTION")) { - stop("run from the kde1d package root with pkgload installed") -} -pkgload::load_all(".", quiet = TRUE) -source(paste0( - "inst/include/kde1d-cpp/diagnostic/one-sided-repair/scripts/", - "one_sided_estimator.R" -)) - -input_file <- paste0( - "inst/include/kde1d-cpp/diagnostic/one-sided-repair/results/", - "local-floor-fraction-ablation.csv" -) -output_file <- paste0( - "inst/include/kde1d-cpp/diagnostic/one-sided-repair/plots/", - "local-floor-fraction-ablation.pdf" -) -results <- read.csv(input_file) -fractions <- as.numeric(sub( - "pct$", "", sub("fixed-", "", results$method[grepl("^fixed", results$method)]), - fixed = FALSE -)) -fractions <- sort(unique(fractions)) -comparison_distributions <- list( - exponential = list(random = rexp, density = dexp, quantile = qexp), - gamma_2 = list( - random = function(sample_size) rgamma(sample_size, 2), - density = function(values) dgamma(values, 2), - quantile = function(probabilities) qgamma(probabilities, 2) - ), - lomax_2 = list( - random = function(sample_size) (1 - runif(sample_size))^(-0.5) - 1, - density = function(values) 2 / (1 + values)^3, - quantile = function(probabilities) (1 - probabilities)^(-0.5) - 1 - ) -) -evaluation_probabilities <- sort(unique(c( - 10^seq(-10, -2, length.out = 101L), - seq(0.01, 0.999, length.out = 401L), - 0.9999, 0.99999 -))) -method_colors <- c( - current = "grey45", `25%` = "#0072B2", `75%` = "#009E73", - `100%` = "#D55E00" -) - -dir.create(dirname(output_file), recursive = TRUE, showWarnings = FALSE) -pdf(output_file, width = 11, height = 7.5) -par(mfrow = c(2, 2), mar = c(4.3, 4.5, 2.3, 0.8), oma = c(0, 0, 3, 0)) -for (sample_size in sort(unique(results$sample_size))) { - current_results <- results[ - results$sample_size == sample_size & results$method == "current", - ] - fixed_results <- results[ - results$sample_size == sample_size & grepl("^fixed", results$method), - ] - fixed_results <- merge( - fixed_results, - current_results[, c("distribution", "global_ise", "boundary_ise")], - by = "distribution", suffixes = c("", "_current") - ) - for (metric in c("global", "boundary")) { - ratio_matrix <- vapply(fractions, function(fraction) { - selected_results <- fixed_results[ - fixed_results$method == paste0("fixed-", fraction, "pct"), - ] - selected_results[[paste0(metric, "_ise")]] / - selected_results[[paste0(metric, "_ise_current")]] - }, numeric(nrow(current_results))) - matplot( - fractions, t(ratio_matrix), type = "l", lty = 1, lwd = 1.4, - col = adjustcolor("grey40", 0.45), ylim = range(c(0.7, 1.1, ratio_matrix)), - xlab = "lowest sample fraction used for floor (%)", - ylab = "candidate / current ISE", - main = sprintf("%s ISE, n=%d", metric, sample_size) - ) - lines(fractions, colMeans(ratio_matrix), lwd = 3, col = "#009E73") - abline(h = 1, lty = 2) - } -} -mtext("Bandwidth-floor fraction: density-specific curves and mean", outer = TRUE, - font = 2, cex = 1.1) - -for (boundary_zoom in c(FALSE, TRUE)) { - par(mfrow = c(2, 3), mar = c(4.2, 4.2, 2.5, 0.5), oma = c(0, 0, 3, 0)) - for (sample_size in c(100L, 1000L)) { - for (distribution_index in seq_along(comparison_distributions)) { - evaluation_points <- comparison_distributions[[distribution_index]]$quantile( - evaluation_probabilities - ) - true_density <- comparison_distributions[[distribution_index]]$density( - evaluation_points - ) - set.seed( - 20260914L + 100000L * match( - names(comparison_distributions)[[distribution_index]], - c("exponential", "half_normal", "gamma_2", "gamma_0.75", "lomax_2") - ) + 1000L * match(sample_size, c(100L, 1000L)) + 1L - ) - observations <- comparison_distributions[[distribution_index]]$random( - sample_size - ) - estimates <- list( - current = normalize_one_sided_density( - evaluation_points, - dkde1d(evaluation_points, kde1d(observations, xmin = 0)) - ), - `25%` = fit_one_sided_candidate( - observations, evaluation_points, local_floor_fraction = 0.25 - )$density, - `75%` = fit_one_sided_candidate( - observations, evaluation_points, local_floor_fraction = 0.75 - )$density, - `100%` = fit_one_sided_candidate( - observations, evaluation_points, local_floor_fraction = 1 - )$density - ) - plotted_points <- if (boundary_zoom) { - evaluation_probabilities <= 0.2 - } else { - evaluation_probabilities <= 0.999 - } - plot( - evaluation_points[plotted_points], true_density[plotted_points], - type = "l", lwd = 3, col = "black", log = if (boundary_zoom) "x" else "", - ylim = c(0, quantile(c( - true_density[plotted_points], - unlist(lapply(estimates, function(density) density[plotted_points])) - ), 0.995)), - xlab = if (boundary_zoom) "distance from boundary" else "x", - ylab = "density", - main = sprintf( - "%s, n=%d", names(comparison_distributions)[[distribution_index]], - sample_size - ) - ) - for (method in names(estimates)) { - lines( - evaluation_points[plotted_points], estimates[[method]][plotted_points], - col = method_colors[[method]], lwd = if (method == "75%") 2.5 else 1.5, - lty = match(method, names(estimates)) - ) - } - if (sample_size == 100L && distribution_index == 1L) { - legend( - "topright", c("truth", names(estimates)), - col = c("black", method_colors), lty = c(1, seq_along(estimates)), - lwd = c(3, 1.5, 1.5, 2.5, 1.5), bty = "n", cex = 0.72 - ) - } - } - } - mtext( - if (boundary_zoom) "Representative boundary views" else - "Representative full-density views", - outer = TRUE, font = 2, cex = 1.1 - ) -} -dev.off() -message("wrote ", normalizePath(output_file)) diff --git a/diagnostic/plot_boundary_diagnostics.R b/diagnostic/plot_boundary_diagnostics.R deleted file mode 100644 index f7b4517..0000000 --- a/diagnostic/plot_boundary_diagnostics.R +++ /dev/null @@ -1,101 +0,0 @@ -args <- commandArgs(trailingOnly = TRUE) -if (length(args) != 1L) { - stop("usage: Rscript diagnostic/plot_boundary_diagnostics.R diagnostics.csv") -} - -results <- read.csv(args[[1]]) -results$pdf_ratio <- results$estimated_pdf / results$true_pdf -results$pdf_ratio[!is.finite(results$pdf_ratio) | results$pdf_ratio <= 0] <- - NA_real_ -results$cdf_error <- abs(results$estimated_cdf - results$true_cdf) - -tail_results <- subset(results, position <= 1e-2 & true_pdf > 0) -summary <- aggregate( - cbind(log_pdf_error = abs(log(pdf_ratio)), cdf_error = cdf_error) ~ - scenario + scale + degree + grid_size + bandwidth, - data = tail_results, - FUN = function(x) max(x, na.rm = TRUE) -) -summary <- summary[order(summary$log_pdf_error, summary$cdf_error), ] -cat("Worst tail errors\n") -print(head(summary[order(-summary$log_pdf_error), ], 20L), row.names = FALSE) - -results$scaled_pdf <- results$estimated_pdf * results$scale -scale_summary <- aggregate( - cbind(scaled_pdf = scaled_pdf, estimated_cdf = estimated_cdf) ~ - scenario + degree + grid_size + bandwidth + position, - data = subset(results, true_pdf > 0), - FUN = function(x) max(x) - min(x) -) -scale_summary$discrepancy <- pmax( - scale_summary$scaled_pdf, - scale_summary$estimated_cdf -) -cat("\nLargest scale-equivariance discrepancies\n") -print( - head(scale_summary[order(-scale_summary$discrepancy), ], 20L), - row.names = FALSE -) - -left <- subset(results, scenario == "exponential-left") -right <- subset(results, scenario == "exponential-right") -reflection <- merge( - left, - right, - by = c("scale", "degree", "grid_size", "bandwidth", "position"), - suffixes = c("_left", "_right") -) -reflection$pdf_error <- abs( - reflection$scaled_pdf_left - reflection$scaled_pdf_right -) -reflection$cdf_error <- abs( - reflection$estimated_cdf_left + reflection$estimated_cdf_right - 1 -) -cat("\nReflection-equivariance maxima\n") -cat("PDF:", max(reflection$pdf_error), "CDF:", max(reflection$cdf_error), "\n") - -grid_summary <- aggregate( - cbind(scaled_pdf = scaled_pdf, estimated_cdf = estimated_cdf) ~ - scenario + scale + degree + bandwidth + position, - data = subset(results, true_pdf > 0), - FUN = function(x) max(x) - min(x) -) -grid_summary$discrepancy <- pmax( - grid_summary$scaled_pdf, - grid_summary$estimated_cdf -) -cat("\nLargest grid-size discrepancies\n") -print( - head(grid_summary[order(-grid_summary$discrepancy), ], 20L), - row.names = FALSE -) - -pdf(sub("[.]csv$", ".pdf", args[[1]])) -for (scenario_name in unique(results$scenario)) { - selected <- subset( - results, - scenario == scenario_name & scale == 1 & grid_size == 400 & - bandwidth == "0.300000" & position > 0 & position <= 0.1 - ) - matplot( - selected$position[selected$degree == 0], - sapply(0:2, function(polynomial_degree) { - selected$estimated_pdf[selected$degree == polynomial_degree] - }), - type = "l", - log = "x", - lty = 1, - xlab = "distance from boundary / support scale", - ylab = "density", - main = scenario_name - ) - lines( - selected$position[selected$degree == 0], - selected$true_pdf[selected$degree == 0], - lty = 2, - lwd = 2 - ) - legend("topright", c("degree 0", "degree 1", "degree 2", "truth"), - col = c(1:3, 1), lty = c(1, 1, 1, 2), bty = "n") -} -dev.off() diff --git a/diagnostic/run_boundary_diagnostics.sh b/diagnostic/run_boundary_diagnostics.sh deleted file mode 100755 index a0ad5bb..0000000 --- a/diagnostic/run_boundary_diagnostics.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -set -eu - -diagnostic_source_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) -diagnostic_build_dir=${1:-"$diagnostic_source_dir/build-diagnostic"} - -cmake -S "$diagnostic_source_dir" -B "$diagnostic_build_dir" \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTING=OFF \ - -DBUILD_DIAGNOSTICS=ON 1>&2 -cmake --build "$diagnostic_build_dir" \ - --target kde1d-boundary-diagnostic \ - --config Release 1>&2 - -diagnostic_executable="$diagnostic_build_dir/bin/kde1d-boundary-diagnostic" -if [ ! -x "$diagnostic_executable" ]; then - diagnostic_executable="$diagnostic_build_dir/bin/Release/kde1d-boundary-diagnostic.exe" -fi - -exec "$diagnostic_executable" diff --git a/diagnostic/validate_native_boundary_experts.R b/diagnostic/validate_native_boundary_experts.R index 2a0a79f..c552caf 100644 --- a/diagnostic/validate_native_boundary_experts.R +++ b/diagnostic/validate_native_boundary_experts.R @@ -1,5 +1,6 @@ -# Evaluate one native kde1d revision. Run once at the baseline commit and once -# at the candidate commit, then compare rows by scenario, size, and replication. +# Evaluate one native kde1d method. Install the pre-PR revision for `pre-pr`; +# install the candidate revision for `bulk` and `expert`. The pre-PR one-sided +# fit is the production log-transform estimator, not a local emulation of it. arguments <- commandArgs(trailingOnly = TRUE) if (length(arguments) < 2L || length(arguments) > 4L) { @@ -12,6 +13,9 @@ library(kde1d) method <- arguments[[1L]] output_file <- arguments[[2L]] +if (!method %in% c("pre-pr", "bulk", "expert")) { + stop("method must be one of: pre-pr, bulk, expert") +} replications <- if (length(arguments) >= 3L) { as.integer(arguments[[3L]]) } else { @@ -25,6 +29,14 @@ integrate_values <- function(points, values) { sum(diff(points) * (values[-length(values)] + values[-1L]) / 2) } +fit_kde1d <- function(observations, xmin = NA_real_, xmax = NA_real_) { + arguments <- list(x = observations, xmin = xmin, xmax = xmax) + if (method != "pre-pr") { + arguments$boundary_repair <- method == "expert" + } + do.call(kde1d, arguments) +} + one_sided <- list( exponential = list( random = function(n) rexp(n), @@ -62,6 +74,8 @@ two_sided <- list( beta_2_2 = c(2, 2) ) sample_sizes <- c(25L, 100L, 1000L, 2000L) +one_sided_scales <- c(1e-4, 1, 1e4) +one_sided_directions <- c("lower", "upper") result_rows <- list() summary_rows <- list() @@ -87,44 +101,69 @@ summarize_estimates <- function(points, estimates, truth, boundary) { for (scenario_index in seq_along(one_sided)) { scenario <- one_sided[[scenario_index]] - points <- sort(unique(c( + base_points <- sort(unique(c( 1e-10, scenario$quantile(10^seq(-8, -1, length.out = 100L)), scenario$quantile(seq(0.1, 0.9999, length.out = 401L)) ))) - truth <- scenario$density(points) - boundary <- points <= scenario$quantile(0.1) - for (sample_size in sample_sizes) { - estimates <- matrix(NA_real_, length(points), replications) - for (replication in seq_len(replications)) { - set.seed(20260824L + 100000L * scenario_index + - 1000L * match(sample_size, sample_sizes) + replication) - fit <- kde1d(scenario$random(sample_size), xmin = 0) - estimates[, replication] <- dkde1d(points, fit) - result_rows[[length(result_rows) + 1L]] <- data.frame( - support = "one-sided", - scenario = names(one_sided)[[scenario_index]], - sample_size = sample_size, - replication = replication, - method = method, - global_ise = integrate_values( - points, (estimates[, replication] - truth)^2 - ), - boundary_ise = integrate_values( - points[boundary], - (estimates[boundary, replication] - truth[boundary])^2 - ), - edf = fit$edf, - loglik = fit$loglik - ) + for (scale_index in seq_along(one_sided_scales)) { + scale <- one_sided_scales[[scale_index]] + scaled_points <- scale * base_points + scaled_truth <- scenario$density(base_points) / scale + for (direction_index in seq_along(one_sided_directions)) { + direction <- one_sided_directions[[direction_index]] + if (direction == "lower") { + points <- scaled_points + truth <- scaled_truth + boundary <- points <= scale * scenario$quantile(0.1) + } else { + points <- -rev(scaled_points) + truth <- rev(scaled_truth) + boundary <- points >= -scale * scenario$quantile(0.1) + } + for (sample_size in sample_sizes) { + estimates <- matrix(NA_real_, length(points), replications) + for (replication in seq_len(replications)) { + set.seed(20260824L + 10000000L * scenario_index + + 1000000L * scale_index + 100000L * direction_index + + 1000L * match(sample_size, sample_sizes) + replication) + observations <- scale * scenario$random(sample_size) + if (direction == "lower") { + fit <- fit_kde1d(observations, xmin = 0) + } else { + fit <- fit_kde1d(-observations, xmax = 0) + } + estimates[, replication] <- dkde1d(points, fit) + result_rows[[length(result_rows) + 1L]] <- data.frame( + support = "one-sided", + direction = direction, + scale = scale, + scenario = names(one_sided)[[scenario_index]], + sample_size = sample_size, + replication = replication, + method = method, + global_ise = integrate_values( + points, (estimates[, replication] - truth)^2 + ), + boundary_ise = integrate_values( + points[boundary], + (estimates[boundary, replication] - truth[boundary])^2 + ), + edf = fit$edf, + loglik = fit$loglik + ) + } + summary_rows[[length(summary_rows) + 1L]] <- data.frame( + support = "one-sided", + direction = direction, + scale = scale, + scenario = names(one_sided)[[scenario_index]], + sample_size = sample_size, + method = method, + as.list(summarize_estimates(points, estimates, truth, boundary)) + ) + } } - summary_rows[[length(summary_rows) + 1L]] <- data.frame( - support = "one-sided", - scenario = names(one_sided)[[scenario_index]], - sample_size = sample_size, - method = method, - as.list(summarize_estimates(points, estimates, truth, boundary)) - ) } } @@ -142,7 +181,7 @@ for (scenario_index in seq_along(two_sided)) { for (replication in seq_len(replications)) { set.seed(20260825L + 100000L * scenario_index + 1000L * match(sample_size, sample_sizes) + replication) - fit <- kde1d( + fit <- fit_kde1d( rbeta(sample_size, shapes[[1L]], shapes[[2L]]), xmin = 0, xmax = 1 @@ -150,6 +189,8 @@ for (scenario_index in seq_along(two_sided)) { estimates[, replication] <- dkde1d(points, fit) result_rows[[length(result_rows) + 1L]] <- data.frame( support = "two-sided", + direction = NA_character_, + scale = 1, scenario = names(two_sided)[[scenario_index]], sample_size = sample_size, replication = replication, @@ -167,6 +208,8 @@ for (scenario_index in seq_along(two_sided)) { } summary_rows[[length(summary_rows) + 1L]] <- data.frame( support = "two-sided", + direction = NA_character_, + scale = 1, scenario = names(two_sided)[[scenario_index]], sample_size = sample_size, method = method, diff --git a/docs/overview-continuous.dox b/docs/overview-continuous.dox index 28c1ed3..c3bd932 100644 --- a/docs/overview-continuous.dox +++ b/docs/overview-continuous.dox @@ -1,4 +1,113 @@ -/** @page overview-continuous Continuous Distributions +/** @page overview-continuous Continuous distributions +Continuous fits combine a transformed local-likelihood bulk estimator with an +optional finite-endpoint repair. The public `degree`, `bandwidth`, and +`multiplier` arguments retain their usual meaning for the bulk fit. Boundary +repair is enabled by default and can be disabled with `boundary_repair=false`. + +@section continuous-bulk Bulk estimator and support transforms + +With no finite support endpoint, data are fitted on their original scale. If +both endpoints @f$a power-3/4 transform + // left boundary -> regularized fourth-root transform x_new = 4.0 * (((boundary_offset_ + x.array() - xmin_) / boundary_scale_) .pow(0.25) - std::pow(boundary_offset_ / boundary_scale_, 0.25)); } else if (!std::isnan(xmax_)) { - // right boundary -> reflected power-3/4 transform + // right boundary -> reflected regularized fourth-root transform x_new = 4.0 * (((boundary_offset_ + xmax_ - x.array()) / boundary_scale_) .pow(0.25) - @@ -893,14 +900,14 @@ Kde1d::boundary_transform(const Eigen::VectorXd& x, bool inverse) auto rng = xmax_ - xmin_; x_new = stats::pnorm(x).array() * 1.0001 * rng + xmin_ - 5e-5 * rng; } else if (!std::isnan(xmin_)) { - // left boundary -> inverse power-3/4 transform + // left boundary -> inverse regularized fourth-root transform x_new = boundary_scale_ * (x.array() / 4.0 + std::pow(boundary_offset_ / boundary_scale_, 0.25)) .pow(4) + xmin_ - boundary_offset_; } else if (!std::isnan(xmax_)) { - // right boundary -> inverse reflected power-3/4 transform + // right boundary -> inverse reflected regularized fourth-root transform x_new = xmax_ + boundary_offset_ - boundary_scale_ * (x.array() / 4.0 + @@ -935,12 +942,12 @@ Kde1d::boundary_correct(const Eigen::VectorXd& x, const Eigen::VectorXd& fhat) corr_term /= (xmax_ - xmin_ + 1e-4 * rng); corr_term = 1.0 / corr_term.array(); } else if (!std::isnan(xmin_)) { - // left boundary -> power-3/4 transform + // left boundary -> fourth-root-transform Jacobian corr_term = ((boundary_offset_ + x.array() - xmin_) / boundary_scale_) .pow(-0.75) / boundary_scale_; } else if (!std::isnan(xmax_)) { - // right boundary -> reflected power-3/4 transform + // right boundary -> reflected fourth-root-transform Jacobian corr_term = ((boundary_offset_ + xmax_ - x.array()) / boundary_scale_) .pow(-0.75) / boundary_scale_; @@ -1420,8 +1427,7 @@ Kde1d::repair_boundaries(const Eigen::VectorXd& x, // Bandwidth for Kernel Density Estimation //' @param x vector of observations //' @param bandwidth bandwidth parameter, NA for automatic selection. -//' @param multiplier bandwidth multiplieriplier. -//' @param discrete whether a jittered estimate is computed. +//' @param multiplier bandwidth multiplier. //' @param weights vector of weights for each observation (can be empty). //' @param degree polynomial degree. //' @return the selected bandwidth diff --git a/include/kde1d/kdefft.hpp b/include/kde1d/kdefft.hpp index 1434486..8485027 100644 --- a/include/kde1d/kdefft.hpp +++ b/include/kde1d/kdefft.hpp @@ -38,7 +38,7 @@ class KdeFFT //! @param bandwidth the bandwidth parameter. //! @param lower lower bound of the grid. //! @param upper bound of the grid. -//! @param weigths optional vector of weights for each observation. +//! @param weights optional vector of weights for each observation. //! @param num_bins number of bins for the FFT grid. inline KdeFFT::KdeFFT(const Eigen::VectorXd& x, double bandwidth, From 6d019672888a2d878e885166f70e6ed1581993a3 Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 21:04:27 +0200 Subject: [PATCH 18/25] Validate boundary repair for PR --- diagnostic/NATIVE_RESULTS.md | 52 ---- diagnostic/PR_COMMENT.md | 242 ++++++++++++++++++ diagnostic/README.md | 32 ++- .../benchmark_native_boundary_experts.R | 59 +++++ diagnostic/boundary-examples.png | Bin 0 -> 170831 bytes diagnostic/extract_native_boundary_examples.R | 116 +++++++++ diagnostic/plot_native_boundary_examples.R | 25 ++ .../summarize_native_boundary_validation.R | 228 +++++++++++++++++ diagnostic/validate_native_boundary_experts.R | 166 +++++++----- 9 files changed, 793 insertions(+), 127 deletions(-) delete mode 100644 diagnostic/NATIVE_RESULTS.md create mode 100644 diagnostic/PR_COMMENT.md create mode 100644 diagnostic/benchmark_native_boundary_experts.R create mode 100644 diagnostic/boundary-examples.png create mode 100644 diagnostic/extract_native_boundary_examples.R create mode 100644 diagnostic/plot_native_boundary_examples.R create mode 100644 diagnostic/summarize_native_boundary_validation.R diff --git a/diagnostic/NATIVE_RESULTS.md b/diagnostic/NATIVE_RESULTS.md deleted file mode 100644 index dcdfd56..0000000 --- a/diagnostic/NATIVE_RESULTS.md +++ /dev/null @@ -1,52 +0,0 @@ -# Native boundary-expert evidence - -The final comparison with the pre-PR estimator has not yet been run. Its -protocol is in [`README.md`](README.md). In particular, the one-sided primary -benchmark will be the actual production log-transform fit from pre-PR `main`, -not the unrepaired fourth-root fit used during development. - -The following implementation checks remain relevant to the selected method. - -## Selected implementation - -- Finite endpoints use the equal average of local-linear and local-quadratic - Gaussian equivalent kernels; the same expert is used for bulk degrees zero, - one, and two. -- Both kernels share an automatically selected degree-two bandwidth. Selection - uses all positive-weight observations on bounded support and the closest 75% - by row count on one-sided support. A manual bandwidth controls only the bulk; - the public multiplier scales both bandwidths. -- Public case weights are used by the classifier, expert estimand, expert - bandwidth selector, effective sample size, and influence approximation. -- A cubic CDF-based fusion region has probability width - $\min(0.25,n_e^{-1/2})$. Endpoints classified as exploding, vanishing, or - ambiguous retain the bulk fit. - -## FFT accuracy and runtime - -The endpoint kernels are pointwise combinations of an ordinary Gaussian KDE -and its first two derivatives, evaluated on a shared 256-bin FFT grid. In the -100-replication development suite, the mean relative ISE perturbation from FFT -binning was at most 0.011% in every support/sample-size group. Among active -experts, the median absolute paired ISE change was 0.023%, the 99th percentile -was 0.18%, and the maximum was 0.66%. - -The direct-kernel fallback was rejected. Across 51--401 output grid points at -$n=25,100$, always using FFT slowed the worst case by 1.25x. On the default -grid at $n=100$, one active endpoint changed from 0.64 to 0.67 ms and two -active endpoints from 0.77 to 0.74 ms. At $n=2000$, FFT reduced one-endpoint -fit time from 1.21 to 0.92 ms and two-endpoint time from 2.25 to 0.96 ms. - -## EDF approximation - -The conditional mixture EDF was checked against - -$$ -1+\sum_i\{\log\widehat f(X_i)-\log\widehat f_{-i}(X_i)\}. -$$ - -For deterministic finite-endpoint samples at $n=25,50,100$, discrepancies -were 0.08--0.30 EDF units for Uniform and Exponential examples. For -Beta$(1,2)$ they were 0.27--0.33 at $n=50,100$ and 0.84 at $n=25$. This was -considered adequate for an asymptotic trace approximation that already holds -bandwidths fixed. Pure-bulk fits retain the prior EDF calculation exactly. diff --git a/diagnostic/PR_COMMENT.md b/diagnostic/PR_COMMENT.md new file mode 100644 index 0000000..9ee0435 --- /dev/null +++ b/diagnostic/PR_COMMENT.md @@ -0,0 +1,242 @@ +## Boundary-repair estimator + +This PR changes continuous fits with known finite support in two steps. + +For a one-sided support, write $d(x)$ for distance from the finite endpoint, +let $s$ be the weighted median observed distance, and set +$\epsilon=10^{-5}s$. The transformed bulk estimator now uses + +$$ +T\{d(x)\} +=4\left[\left\{\frac{d(x)+\epsilon}{s}\right\}^{1/4} +-\left(\frac{\epsilon}{s}\right)^{1/4}\right], +\qquad +|T'(x)| +=\frac{1}{s}\left\{\frac{d(x)+\epsilon}{s}\right\}^{-3/4}. +$$ + +This replaces the previous log transform and makes the construction scale +equivariant. Two-sided fits retain the regularized probit bulk transform. + +Each finite endpoint is then classified independently from its first +$k\simeq2\sqrt{n_e}$ order statistics. In the unweighted case, + +$$ +\widehat\beta +=\frac{k}{\sum_{i=1}^k +\log\{d_{(k+1)}/d_{(i)}\}}. +$$ + +Endpoints consistent with a finite nonzero limiting density receive a boundary +expert. Exploding, vanishing, ambiguous, and degenerate endpoints retain the +bulk. The expert is the equal average + +$$ +\widehat f_E=(\widehat f_{\mathrm{local\ linear}} + +\widehat f_{\mathrm{local\ quadratic}})/2 +$$ + +of Gaussian equivalent-kernel estimates. Both kernels share an automatically +selected degree-2 plug-in bandwidth on the original scale, using all +positive-weight observations on bounded support and the closest 75% by row +count on one-sided support. The three required Gaussian convolutions are +evaluated on a shared 256-bin FFT grid. + +Let $F_B$ be the normalized bulk CDF, + +$$ +q=\min(1/4,n_e^{-1/2}), +\qquad +g(p)=1-3\min(1,p/q)^2+2\min(1,p/q)^3. +$$ + +Selected lower and upper experts receive weights +$w_L(x)=g\{F_B(x)\}$ and $w_U(x)=g\{1-F_B(x)\}$, giving + +$$ +\widehat f(x) +=w_L(x)\widehat f_L(x) ++\{1-w_L(x)-w_U(x)\}\widehat f_B(x) ++w_U(x)\widehat f_U(x). +$$ + +The result is clamped at zero and normalized. The same boundary expert is used +for bulk degrees 0, 1, and 2. EDF is a conditional influence-trace +approximation that holds the classifier, selected bandwidths, fusion weights, +clamps, and normalization fixed. + +## Validation design + +The primary benchmark is the actual pre-PR package at parent commit `7faec53` +with C++ commit `b16d514`: log transform for one-sided support and probit for +two-sided support. The experiment used 200 paired replications for +$n\in\{25,100,1000,2000\}$ and degrees 0, 1, and 2. + +- One-sided: Exponential, half-normal, Gamma$(0.75)$, Gamma$(2)$, and + Lomax$(2)$, with lower/upper reflections and scales $10^{-4},1,10^4$. +- Two-sided: Uniform and Beta$(1,2)$, Beta$(2,1)$, Beta$(0.75,2)$, + Beta$(2,0.75)$, Beta$(0.75,0.75)$, and Beta$(2,2)$. +- Global ISE and boundary ISE were integrated separately. The boundary region + is the outer 10% probability mass at each finite endpoint. + +The tables below use scale 1; reflected one-sided results agree to numerical +precision. Entries are candidate/baseline ratios, so **values below 1 favor the +PR**. Parentheses are paired Monte Carlo standard errors. + +### Global ISE ratio, averaged over families + +| support | degree | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:|---:|---:| +| one-sided | 0 | 0.748 (0.044) | 0.579 (0.028) | 0.513 (0.011) | 0.475 (0.010) | +| one-sided | 1 | 0.505 (0.020) | 0.411 (0.011) | 0.684 (0.063) | 0.724 (0.050) | +| one-sided | 2 | 0.211 (0.036) | 0.198 (0.021) | 0.208 (0.018) | 0.260 (0.015) | +| two-sided | 0 | 0.951 (0.005) | 0.943 (0.005) | 0.941 (0.006) | 0.925 (0.005) | +| two-sided | 1 | 0.867 (0.006) | 0.823 (0.007) | 0.847 (0.005) | 0.852 (0.004) | +| two-sided | 2 | 0.892 (0.013) | 0.911 (0.006) | 0.940 (0.006) | 0.932 (0.006) | + +### Boundary ratio, averaged over families + +| support | degree | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:|---:|---:| +| one-sided | 0 | 0.702 (0.049) | 0.513 (0.030) | 0.447 (0.013) | 0.399 (0.011) | +| one-sided | 1 | 0.399 (0.022) | 0.303 (0.011) | 0.636 (0.075) | 0.702 (0.059) | +| one-sided | 2 | 0.144 (0.027) | 0.151 (0.027) | 0.159 (0.016) | 0.205 (0.015) | +| two-sided | 0 | 0.923 (0.005) | 0.944 (0.005) | 0.954 (0.005) | 0.939 (0.005) | +| two-sided | 1 | 0.824 (0.008) | 0.826 (0.007) | 0.879 (0.004) | 0.877 (0.004) | +| two-sided | 2 | 0.883 (0.012) | 0.913 (0.005) | 0.955 (0.005) | 0.945 (0.005) | + +The expert also improves over the unrepaired new bulk. Averaged global ISE +ratios range from 0.84--0.94 for degree 0, 0.74--0.89 for degree 1, and +0.88--0.92 for degree 2 on one-sided support. The corresponding bounded ratios +are 0.93--0.95, 0.82--0.87, and 0.89--0.94. + +
+Family-level global / boundary ISE ratios + +#### One-sided, degree 0 + +| family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:|---:| +| Exponential | 0.75 / 0.73 | 0.49 / 0.45 | 0.37 / 0.30 | 0.34 / 0.27 | +| Gamma$(0.75)$ | 0.55 / 0.54 | 0.51 / 0.50 | 0.45 / 0.44 | 0.44 / 0.43 | +| Gamma$(2)$ | 0.71 / 0.52 | 0.76 / 0.58 | 0.81 / 0.69 | 0.80 / 0.67 | +| half-normal | 0.46 / 0.38 | 0.41 / 0.32 | 0.31 / 0.21 | 0.28 / 0.17 | +| Lomax$(2)$ | 1.28 / 1.34 | 0.72 / 0.70 | 0.63 / 0.59 | 0.51 / 0.45 | + +#### One-sided, degree 1 + +| family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:|---:| +| Exponential | 0.49 / 0.37 | 0.31 / 0.22 | 0.38 / 0.26 | 0.38 / 0.27 | +| Gamma$(0.75)$ | 0.27 / 0.25 | 0.25 / 0.21 | 0.45 / 0.43 | 0.53 / 0.52 | +| Gamma$(2)$ | 0.69 / 0.46 | 0.81 / 0.63 | 0.93 / 0.98 | 1.01 / 1.19 | +| half-normal | 0.45 / 0.32 | 0.38 / 0.23 | 0.43 / 0.25 | 0.43 / 0.25 | +| Lomax$(2)$ | 0.62 / 0.60 | 0.31 / 0.22 | 1.23 / 1.26 | 1.27 / 1.28 | + +#### One-sided, degree 2 + +| family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:|---:| +| Exponential | 0.07 / 0.04 | 0.02 / 0.01 | 0.06 / 0.04 | 0.09 / 0.06 | +| Gamma$(0.75)$ | 0.03 / 0.03 | 0.04 / 0.03 | 0.23 / 0.21 | 0.23 / 0.21 | +| Gamma$(2)$ | 0.38 / 0.18 | 0.72 / 0.56 | 0.59 / 0.44 | 0.62 / 0.50 | +| half-normal | 0.09 / 0.04 | 0.03 / 0.02 | 0.03 / 0.01 | 0.06 / 0.03 | +| Lomax$(2)$ | 0.49 / 0.43 | 0.17 / 0.13 | 0.13 / 0.09 | 0.30 / 0.23 | + +#### Two-sided, degree 0 + +| family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:|---:| +| Beta$(0.75,0.75)$ | 1.02 / 1.03 | 1.03 / 1.04 | 1.04 / 1.04 | 1.05 / 1.05 | +| Beta$(0.75,2)$ | 0.99 / 0.98 | 1.01 / 1.00 | 1.07 / 1.07 | 1.06 / 1.06 | +| Beta$(1,2)$ | 0.93 / 0.91 | 0.85 / 0.86 | 0.83 / 0.86 | 0.78 / 0.81 | +| Beta$(2,0.75)$ | 1.00 / 0.99 | 1.01 / 1.00 | 1.09 / 1.08 | 1.06 / 1.05 | +| Beta$(2,1)$ | 0.95 / 0.93 | 0.89 / 0.89 | 0.78 / 0.81 | 0.79 / 0.82 | +| Beta$(2,2)$ | 0.82 / 0.65 | 0.94 / 0.88 | 1.00 / 1.00 | 1.00 / 1.00 | +| Uniform | 0.95 / 0.98 | 0.88 / 0.93 | 0.77 / 0.82 | 0.74 / 0.79 | + +#### Two-sided, degree 1 + +| family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:|---:| +| Beta$(0.75,0.75)$ | 0.91 / 0.91 | 0.87 / 0.88 | 0.94 / 0.95 | 0.97 / 0.97 | +| Beta$(0.75,2)$ | 0.88 / 0.87 | 0.89 / 0.90 | 0.96 / 0.97 | 0.98 / 0.98 | +| Beta$(1,2)$ | 0.81 / 0.76 | 0.72 / 0.74 | 0.73 / 0.76 | 0.69 / 0.73 | +| Beta$(2,0.75)$ | 0.89 / 0.88 | 0.88 / 0.88 | 0.95 / 0.96 | 0.98 / 0.98 | +| Beta$(2,1)$ | 0.86 / 0.82 | 0.74 / 0.76 | 0.70 / 0.75 | 0.71 / 0.74 | +| Beta$(2,2)$ | 0.91 / 0.73 | 0.96 / 0.90 | 1.00 / 1.00 | 1.00 / 1.00 | +| Uniform | 0.82 / 0.78 | 0.70 / 0.72 | 0.64 / 0.77 | 0.62 / 0.74 | + +#### Two-sided, degree 2 + +| family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | +|---|---:|---:|---:|---:| +| Beta$(0.75,0.75)$ | 0.91 / 0.92 | 0.95 / 0.96 | 1.02 / 1.02 | 1.05 / 1.05 | +| Beta$(0.75,2)$ | 0.89 / 0.89 | 0.94 / 0.94 | 1.06 / 1.06 | 1.06 / 1.05 | +| Beta$(1,2)$ | 0.77 / 0.80 | 0.84 / 0.85 | 0.82 / 0.85 | 0.78 / 0.81 | +| Beta$(2,0.75)$ | 0.90 / 0.90 | 0.94 / 0.95 | 1.08 / 1.07 | 1.05 / 1.05 | +| Beta$(2,1)$ | 0.90 / 0.90 | 0.83 / 0.85 | 0.78 / 0.82 | 0.79 / 0.83 | +| Beta$(2,2)$ | 0.99 / 0.89 | 1.02 / 0.95 | 1.00 / 1.00 | 1.00 / 1.00 | +| Uniform | 0.87 / 0.87 | 0.86 / 0.90 | 0.82 / 0.86 | 0.79 / 0.83 | + +
+ +## Bias, variance, classification, and scale + +The ISE gains are primarily a variance reduction, with some deliberate +small-sample boundary bias. Against pre-PR at scale 1, aggregate global +variance ratios are 0.27--0.53 one-sided for degree 0, 0.29--0.43 for degree 1, +and 0.04--0.12 for degree 2. Bounded ratios are 0.99--1.03, 0.86--0.90, and +0.89--1.00, respectively. This matches the visual goal: substantially calmer +one-sided endpoints and moderate smoothing on bounded support. + +Classifier behavior becomes appropriately conservative with sample size. For +one-sided finite targets, selection rates at $n=100/2000$ are 58%/78% +(Exponential), 75%/82% (half-normal), and 56%/76% (Lomax). False finite +selection falls from 22% to 4% for Gamma$(0.75)$ and from 38% to 0% for +Gamma$(2)$. For Uniform, either endpoint is selected in 90%/98% and both in +51%/71% of samples. Beta$(2,2)$ falls from 4.5% both-endpoint selection at +$n=100$ to 0% at $n\geq1000$. + +For Exponential samples at $n=100$, the 5%--95% range of the estimated value +at the endpoint is 0.56--1.44 when the expert is selected, compared with +0.01--49.6 when the classifier retains the raw bulk. Thus the expert delivers +the intended visual stabilization when selected; remaining extreme endpoint +values are primarily classifier false negatives. + + + + +## Coarse runtime + +Median end-to-end R fit times for the default degree-2 estimator are below. + +| case | $n$ | pre-PR | candidate | slowdown | +|---|---:|---:|---:|---:| +| one active endpoint | 100 | 0.48 ms | 0.81 ms | 1.70x | +| one active endpoint | 1,000 | 1.51 ms | 1.96 ms | 1.29x | +| one active endpoint | 10,000 | 12.43 ms | 13.57 ms | 1.09x | +| two active endpoints | 100 | 0.51 ms | 0.87 ms | 1.71x | +| two active endpoints | 1,000 | 1.45 ms | 1.85 ms | 1.27x | +| two active endpoints | 10,000 | 10.97 ms | 11.83 ms | 1.08x | +| one-sided fallback | 100 / 1,000 / 10,000 | -- | -- | 1.09x / 1.05x / 1.02x | +| two-sided fallback | 100 / 1,000 / 10,000 | -- | -- | 1.00x / 1.01x / 1.01x | + +## Less common paths and numerical checks + +- Public case weights are used consistently by the classifier, expert + estimand, bandwidth selector, effective sample size, and EDF approximation. + Tests cover weight rescaling and zero-weight-row invariance. +- A manually supplied bandwidth controls the transformed bulk only. Boundary + experts retain their original-scale automatic bandwidth; the public + multiplier scales both. This unusual path has focused regression tests but + was not included in the full Monte Carlo sweep. +- Setting `boundary_repair=false` recovers the transformed bulk and skips all + expert work. +- Tests cover degrees 0--2, normalization, nonnegativity, monotone CDFs, + quantile round trips, support truncation, reflection, scales $10^{-4}$ to + $10^4$, weights, fixed bandwidths, and pure-bulk EDF parity. +- The conditional EDF approximation differed from leave-one-out optimism by + about 0.08--0.30 EDF units for deterministic Uniform/Exponential examples; + the largest checked discrepancy was 0.84 for Beta$(1,2)$ at $n=25$. diff --git a/diagnostic/README.md b/diagnostic/README.md index b3d7eec..2d73909 100644 --- a/diagnostic/README.md +++ b/diagnostic/README.md @@ -12,7 +12,7 @@ a time. Run it with these method labels: | method | installed revision | estimator | |---|---|---| -| `pre-pr` | pre-PR `main` (`1260b5e` for the planned comparison) | production log transform on one-sided support and probit transform on two-sided support | +| `pre-pr` | parent `7faec53`, with C++ `b16d514` | production log transform on one-sided support and probit transform on two-sided support | | `bulk` | candidate | fourth-root/probit bulk with `boundary_repair = FALSE` | | `expert` | candidate | fourth-root/probit bulk with the selected boundary experts | @@ -22,9 +22,10 @@ benchmark. The suite covers lower- and upper-bounded versions of five one-sided densities at scales `1e-4`, `1`, and `1e4`, seven two-sided densities, and sample sizes -25, 100, 1,000, and 2,000. It writes replication-level global and boundary ISE, -EDF, and log-likelihood, plus integrated squared bias and variance summaries. -Paired seeds are shared across methods. +25, 100, 1,000, and 2,000 for bulk degrees zero, one, and two. It writes +replication-level global and boundary ISE, EDF, and log-likelihood, plus +integrated squared bias and variance summaries. Paired seeds are shared across +methods and degrees. From the R-package root, install each requested revision into a separate library and run, for example: @@ -39,10 +40,21 @@ Rscript inst/include/kde1d-cpp/diagnostic/validate_native_boundary_experts.R \ ``` Generated CSVs and figures are not versioned. The final aggregate comparison -and representative plots should be recorded in `NATIVE_RESULTS.md` after the -validation is complete. +is generated with: -`NATIVE_RESULTS.md` currently retains only implementation-level evidence that -still applies to the selected estimator. Superseded R prototypes, candidate -estimators, tuning outputs, and the standalone C++ diagnostic were removed; -stable numerical properties are covered by the unit and invariant tests. +```sh +Rscript inst/include/kde1d-cpp/diagnostic/summarize_native_boundary_validation.R \ + diagnostic-results/pre-pr.csv diagnostic-results/bulk.csv \ + diagnostic-results/expert.csv diagnostic-results/ratios +``` + +`benchmark_native_boundary_experts.R` performs coarse end-to-end R timings. +`extract_native_boundary_examples.R` and +`plot_native_boundary_examples.R` recreate the representative density montage +using classifier-stratified median-ISE realizations selected by the summary +script. + +Final results are recorded in `NATIVE_RESULTS.md`; `PR_COMMENT.md` contains the +copy-ready methodological description and report. Superseded R prototypes, +candidate estimators, tuning outputs, and the standalone C++ diagnostic were +removed; stable numerical properties are covered by unit and invariant tests. diff --git a/diagnostic/benchmark_native_boundary_experts.R b/diagnostic/benchmark_native_boundary_experts.R new file mode 100644 index 0000000..6458303 --- /dev/null +++ b/diagnostic/benchmark_native_boundary_experts.R @@ -0,0 +1,59 @@ +arguments <- commandArgs(trailingOnly = TRUE) +if (length(arguments) != 3L) { + stop("usage: script method output.csv library-path") +} +.libPaths(c(arguments[[3L]], .libPaths())) +library(kde1d) + +method <- arguments[[1L]] +if (!method %in% c("pre-pr", "bulk", "expert")) { + stop("method must be one of: pre-pr, bulk, expert") +} + +fit_kde1d <- function(observations, xmin, xmax) { + fit_arguments <- list(x = observations, xmin = xmin, xmax = xmax, deg = 2) + if (method != "pre-pr") { + fit_arguments$boundary_repair <- method == "expert" + } + do.call(kde1d, fit_arguments) +} + +make_observations <- function(case, n) { + probabilities <- seq(0.5 / n, 1 - 0.5 / n, length.out = n) + switch( + case, + one_active = -log1p(-probabilities), + one_fallback = sqrt(probabilities), + two_active = probabilities, + two_fallback = qbeta(probabilities, 2, 2) + ) +} + +rows <- list() +for (case in c("one_active", "one_fallback", "two_active", "two_fallback")) { + for (n in c(100L, 1000L, 10000L)) { + observations <- make_observations(case, n) + one_sided <- startsWith(case, "one_") + xmin <- 0 + xmax <- if (one_sided) NaN else 1 + iterations <- if (n == 100L) 500L else if (n == 1000L) 200L else 30L + fit_kde1d(observations, xmin, xmax) + for (batch in seq_len(7L)) { + elapsed <- system.time({ + for (iteration in seq_len(iterations)) { + fit_kde1d(observations, xmin, xmax) + } + })[["elapsed"]] + rows[[length(rows) + 1L]] <- data.frame( + method = method, + case = case, + sample_size = n, + batch = batch, + milliseconds = 1000 * elapsed / iterations + ) + } + } +} + +dir.create(dirname(arguments[[2L]]), recursive = TRUE, showWarnings = FALSE) +write.csv(do.call(rbind, rows), arguments[[2L]], row.names = FALSE) diff --git a/diagnostic/boundary-examples.png b/diagnostic/boundary-examples.png new file mode 100644 index 0000000000000000000000000000000000000000..41094497a3eb6c24df2ae970be7a1fa3a154dd5e GIT binary patch literal 170831 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 b!~DbU{%7#PPdR%E;>lGMH0879OoRRd8;meo literal 0 HcmV?d00001 diff --git a/diagnostic/extract_native_boundary_examples.R b/diagnostic/extract_native_boundary_examples.R new file mode 100644 index 0000000..07ce3b1 --- /dev/null +++ b/diagnostic/extract_native_boundary_examples.R @@ -0,0 +1,116 @@ +arguments <- commandArgs(trailingOnly = TRUE) +if (length(arguments) != 4L) { + stop("usage: script method output.csv library-path selections.csv") +} +.libPaths(c(arguments[[3L]], .libPaths())) +library(kde1d) + +method <- arguments[[1L]] +if (!method %in% c("pre-pr", "bulk", "expert")) { + stop("method must be one of: pre-pr, bulk, expert") +} + +fit_kde1d <- function(observations, xmin, xmax) { + fit_arguments <- list(x = observations, xmin = xmin, xmax = xmax, deg = 2) + if (method != "pre-pr") { + fit_arguments$boundary_repair <- method == "expert" + } + do.call(kde1d, fit_arguments) +} + +one_sided <- list( + exponential = list(random = rexp, density = dexp, quantile = qexp), + half_normal = list( + random = function(n) abs(rnorm(n)), + density = function(x) 2 * dnorm(x), + quantile = function(p) qnorm((p + 1) / 2) + ), + gamma_075 = list( + random = function(n) rgamma(n, 0.75), + density = function(x) dgamma(x, 0.75), + quantile = function(p) qgamma(p, 0.75) + ), + gamma_2 = list( + random = function(n) rgamma(n, 2), + density = function(x) dgamma(x, 2), + quantile = function(p) qgamma(p, 2) + ) +) +two_sided <- list( + uniform = list(shape1 = 1, shape2 = 1), + beta_1_2 = list(shape1 = 1, shape2 = 2), + beta_075_2 = list(shape1 = 0.75, shape2 = 2), + beta_2_2 = list(shape1 = 2, shape2 = 2) +) +selections <- read.csv(arguments[[4L]], stringsAsFactors = FALSE) + +rows <- list() +for (scenario_index in seq_along(one_sided)) { + scenario <- one_sided[[scenario_index]] + selection <- selections[ + selections$support == "one-sided" & + selections$scenario == names(one_sided)[[scenario_index]], + ] + sample_size_index <- match(selection$sample_size, c(25L, 100L, 1000L, 2000L)) + set.seed(20260824L + 10000000L * scenario_index + + 1000L * sample_size_index + selection$replication) + observations <- scenario$random(selection$sample_size) + points <- sort(unique(c( + 1e-10, + scenario$quantile(10^seq(-8, -1, length.out = 120L)), + scenario$quantile(seq(0.1, 0.999, length.out = 300L)) + ))) + if (is.finite(scenario$density(0))) { + points <- c(0, points) + } + fit <- fit_kde1d(observations, 0, NaN) + rows[[length(rows) + 1L]] <- data.frame( + method = method, + support = "one-sided", + scenario = paste0( + names(one_sided)[[scenario_index]], "_n", selection$sample_size + ), + sample_size = selection$sample_size, + x = points, + truth = scenario$density(points), + estimate = dkde1d(points, fit) + ) +} + +points <- sort(unique(c( + 10^seq(-10, -2, length.out = 121L), + seq(0.01, 0.99, length.out = 301L), + 1 - 10^seq(-2, -10, length.out = 121L) +))) +for (scenario_index in seq_along(two_sided)) { + scenario <- two_sided[[scenario_index]] + selection <- selections[ + selections$support == "two-sided" & + selections$scenario == names(two_sided)[[scenario_index]], + ] + sample_size_index <- match(selection$sample_size, c(25L, 100L, 1000L, 2000L)) + set.seed(20260825L + 100000L * scenario_index + + 1000L * sample_size_index + selection$replication) + observations <- rbeta( + selection$sample_size, scenario$shape1, scenario$shape2 + ) + scenario_points <- points + if (scenario$shape1 >= 1 && scenario$shape2 >= 1) { + scenario_points <- c(0, points, 1) + } + fit <- fit_kde1d(observations, 0, 1) + rows[[length(rows) + 1L]] <- data.frame( + method = method, + support = "two-sided", + scenario = paste0( + names(two_sided)[[scenario_index]], "_n", selection$sample_size + ), + sample_size = selection$sample_size, + x = scenario_points, + truth = dbeta(scenario_points, scenario$shape1, scenario$shape2), + estimate = dkde1d(scenario_points, fit) + ) +} + +dir.create(dirname(arguments[[2L]]), recursive = TRUE, showWarnings = FALSE) +write.csv(do.call(rbind, rows), arguments[[2L]], row.names = FALSE) diff --git a/diagnostic/plot_native_boundary_examples.R b/diagnostic/plot_native_boundary_examples.R new file mode 100644 index 0000000..25b8182 --- /dev/null +++ b/diagnostic/plot_native_boundary_examples.R @@ -0,0 +1,25 @@ +arguments <- commandArgs(trailingOnly = TRUE) +if (length(arguments) != 4L) { + stop("usage: script pre-pr.csv bulk.csv expert.csv output.png") +} +library(ggplot2) + +estimates <- do.call(rbind, lapply(arguments[1:3], read.csv)) +estimates$method <- factor( + estimates$method, + levels = c("pre-pr", "bulk", "expert"), + labels = c("pre-PR log/probit", "new bulk", "new bulk + experts") +) +truth <- unique(estimates[c("support", "scenario", "sample_size", "x", "truth")]) + +plot <- ggplot(estimates, aes(x, estimate, color = method)) + + geom_line(linewidth = 0.55) + + geom_line(data = truth, aes(x = x, y = truth), inherit.aes = FALSE, + color = "black", linewidth = 0.65, linetype = 2) + + facet_wrap(~scenario, scales = "free", ncol = 2) + + scale_color_manual(values = c("#777777", "#377eb8", "#e41a1c")) + + labs(x = NULL, y = "density", color = NULL) + + theme_bw(base_size = 9) + + theme(legend.position = "bottom") + +ggsave(arguments[[4L]], plot, width = 8, height = 10, dpi = 160) diff --git a/diagnostic/summarize_native_boundary_validation.R b/diagnostic/summarize_native_boundary_validation.R new file mode 100644 index 0000000..ba24502 --- /dev/null +++ b/diagnostic/summarize_native_boundary_validation.R @@ -0,0 +1,228 @@ +arguments <- commandArgs(trailingOnly = TRUE) +if (length(arguments) != 4L) { + stop("usage: script pre-pr.csv bulk.csv expert.csv output-prefix") +} + +read_results <- function(path) { + results <- read.csv(path, stringsAsFactors = FALSE) + results$direction[is.na(results$direction)] <- "none" + results +} + +pre_pr <- read_results(arguments[[1L]]) +bulk <- read_results(arguments[[2L]]) +expert <- read_results(arguments[[3L]]) +output_prefix <- arguments[[4L]] +keys <- c( + "support", "direction", "scale", "scenario", "degree", "sample_size", + "replication" +) + +paired_ratios <- function(reference, comparison) { + paired <- merge( + expert, + reference, + by = keys, + suffixes = c("_expert", "_reference") + ) + groups <- split( + seq_len(nrow(paired)), + interaction(paired[c( + "support", "direction", "scale", "scenario", "degree", "sample_size" + )], drop = TRUE) + ) + rows <- lapply(groups, function(index) { + lapply(c("global_ise", "boundary_ise"), function(metric) { + candidate <- paired[[paste0(metric, "_expert")]][index] + baseline <- paired[[paste0(metric, "_reference")]][index] + ratio <- mean(candidate) / mean(baseline) + data.frame( + comparison = comparison, + metric = metric, + paired[index[[1L]], c( + "support", "direction", "scale", "scenario", "degree", + "sample_size" + )], + ratio = ratio, + mcse = sd(candidate - ratio * baseline) / + (sqrt(length(index)) * mean(baseline)) + ) + }) + }) + do.call(rbind, unlist(rows, recursive = FALSE)) +} + +cell_ratios <- rbind( + paired_ratios(pre_pr, "pre-pr"), + paired_ratios(bulk, "bulk") +) + +# Average scale/reflection cells within a family while retaining their paired +# covariance. Different families use independent simulation streams. +family_paired_ratios <- function(reference, comparison) { + paired <- merge( + expert, + reference, + by = keys, + suffixes = c("_expert", "_reference") + ) + cell_names <- c( + "support", "direction", "scale", "scenario", "degree", "sample_size" + ) + family_names <- c("support", "scenario", "degree", "sample_size") + rows <- lapply(c("global_ise", "boundary_ise"), function(metric) { + paired$cell <- interaction(paired[cell_names], drop = TRUE) + paired$influence <- NA_real_ + paired$cell_ratio <- NA_real_ + for (index in split(seq_len(nrow(paired)), paired$cell)) { + candidate <- paired[[paste0(metric, "_expert")]][index] + baseline <- paired[[paste0(metric, "_reference")]][index] + ratio <- mean(candidate) / mean(baseline) + paired$cell_ratio[index] <- ratio + paired$influence[index] <- + (candidate - ratio * baseline) / mean(baseline) + } + family_groups <- split( + seq_len(nrow(paired)), interaction(paired[family_names], drop = TRUE) + ) + lapply(family_groups, function(index) { + first_cell_rows <- index[!duplicated(paired$cell[index])] + replication_groups <- split(index, paired$replication[index]) + replication_influence <- vapply( + replication_groups, + function(replication_index) mean(paired$influence[replication_index]), + numeric(1) + ) + data.frame( + comparison = comparison, + metric = metric, + paired[index[[1L]], family_names, drop = FALSE], + ratio = mean(paired$cell_ratio[first_cell_rows]), + mcse = sd(replication_influence) / sqrt(length(replication_influence)), + cells = length(first_cell_rows) + ) + }) + }) + do.call(rbind, unlist(rows, recursive = FALSE)) +} + +family_ratios <- rbind( + family_paired_ratios(pre_pr, "pre-pr"), + family_paired_ratios(bulk, "bulk") +) +support_names <- c( + "comparison", "metric", "support", "degree", "sample_size" +) +support_groups <- split( + seq_len(nrow(family_ratios)), + interaction(family_ratios[support_names], drop = TRUE) +) +support_ratios <- do.call(rbind, lapply(support_groups, function(index) { + data.frame( + family_ratios[index[[1L]], support_names, drop = FALSE], + ratio = mean(family_ratios$ratio[index]), + mcse = sqrt(sum(family_ratios$mcse[index]^2)) / length(index), + cells = sum(family_ratios$cells[index]) + ) +})) + +classification <- expert[ + expert$degree == 0 & + ((expert$support == "one-sided" & expert$scale == 1 & + expert$direction == "lower") | expert$support == "two-sided"), +] +activation_groups <- split( + seq_len(nrow(classification)), + interaction(classification[c("support", "scenario", "sample_size")], + drop = TRUE) +) +activation <- do.call(rbind, lapply(activation_groups, function(index) { + data.frame( + classification[index[[1L]], c("support", "scenario", "sample_size")], + lower_rate = mean(classification$repair_lower[index]), + upper_rate = mean(classification$repair_upper[index]), + any_rate = mean( + classification$repair_lower[index] | classification$repair_upper[index] + ), + both_rate = mean( + classification$repair_lower[index] & classification$repair_upper[index] + ) + ) +})) + +read_summaries <- function(path) { + summary <- read.csv(path, stringsAsFactors = FALSE) + summary$direction[is.na(summary$direction)] <- "none" + summary +} +summary_path <- function(path) sub("\\.csv$", "-summary.csv", path) +pre_pr_summary <- read_summaries(summary_path(arguments[[1L]])) +bulk_summary <- read_summaries(summary_path(arguments[[2L]])) +expert_summary <- read_summaries(summary_path(arguments[[3L]])) +summary_keys <- keys[keys != "replication"] + +component_ratios <- function(reference, comparison) { + paired <- merge( + expert_summary, + reference, + by = summary_keys, + suffixes = c("_expert", "_reference") + ) + metrics <- c( + "global_squared_bias", "global_variance", + "boundary_squared_bias", "boundary_variance" + ) + do.call(rbind, lapply(metrics, function(metric) { + data.frame( + comparison = comparison, + metric = metric, + paired[summary_keys], + ratio = paired[[paste0(metric, "_expert")]] / + paired[[paste0(metric, "_reference")]] + ) + })) +} + +components <- rbind( + component_ratios(pre_pr_summary, "pre-pr"), + component_ratios(bulk_summary, "bulk") +) + +example_targets <- data.frame( + support = c(rep("one-sided", 4), rep("two-sided", 4)), + scenario = c( + "exponential", "half_normal", "gamma_075", "gamma_2", + "uniform", "beta_1_2", "beta_075_2", "beta_2_2" + ), + sample_size = c(100L, 25L, 1000L, 1000L, 100L, 1000L, 1000L, 1000L), + repair_lower = c(TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE), + repair_upper = c(FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE) +) +example_rows <- lapply(seq_len(nrow(example_targets)), function(i) { + target <- example_targets[i, ] + candidates <- expert[ + expert$support == target$support & + expert$scenario == target$scenario & + expert$sample_size == target$sample_size & + expert$degree == 2 & + expert$scale == 1 & + expert$repair_lower == target$repair_lower & + expert$repair_upper == target$repair_upper & + expert$direction == + if (target$support == "one-sided") "lower" else "none", + ] + median_ise <- median(candidates$global_ise) + selected <- candidates[ + which.min(abs(candidates$global_ise - median_ise)), + ] + data.frame(target, replication = selected$replication) +}) +examples <- do.call(rbind, example_rows) + +dir.create(dirname(output_prefix), recursive = TRUE, showWarnings = FALSE) +write.csv(cell_ratios, paste0(output_prefix, "-cells.csv"), row.names = FALSE) +write.csv(family_ratios, paste0(output_prefix, "-families.csv"), row.names = FALSE) +write.csv(support_ratios, paste0(output_prefix, "-support.csv"), row.names = FALSE) +write.csv(activation, paste0(output_prefix, "-activation.csv"), row.names = FALSE) +write.csv(components, paste0(output_prefix, "-components.csv"), row.names = FALSE) +write.csv(examples, paste0(output_prefix, "-examples.csv"), row.names = FALSE) diff --git a/diagnostic/validate_native_boundary_experts.R b/diagnostic/validate_native_boundary_experts.R index c552caf..22c2e1d 100644 --- a/diagnostic/validate_native_boundary_experts.R +++ b/diagnostic/validate_native_boundary_experts.R @@ -29,14 +29,33 @@ integrate_values <- function(points, values) { sum(diff(points) * (values[-length(values)] + values[-1L]) / 2) } -fit_kde1d <- function(observations, xmin = NA_real_, xmax = NA_real_) { - arguments <- list(x = observations, xmin = xmin, xmax = xmax) +fit_kde1d <- function(observations, degree, + xmin = NA_real_, xmax = NA_real_) { + arguments <- list(x = observations, xmin = xmin, xmax = xmax, deg = degree) if (method != "pre-pr") { arguments$boundary_repair <- method == "expert" } do.call(kde1d, arguments) } +classify_finite_endpoint <- function(distances) { + distances <- sort(distances) + k <- min(length(distances) - 1L, ceiling(2 * sqrt(length(distances)))) + reference_distance <- distances[[k + 1L]] + if (!is.finite(reference_distance) || reference_distance <= 0) { + return(FALSE) + } + denominator <- sum(log( + reference_distance / + pmax(distances[seq_len(k)], .Machine$double.eps * reference_distance) + )) + if (!is.finite(denominator) || denominator <= 0) { + return(FALSE) + } + beta <- k / denominator + beta >= 0.9 && beta * (1 - qnorm(0.95) / sqrt(k)) <= 1 +} + one_sided <- list( exponential = list( random = function(n) rexp(n), @@ -74,6 +93,7 @@ two_sided <- list( beta_2_2 = c(2, 2) ) sample_sizes <- c(25L, 100L, 1000L, 2000L) +degrees <- 0:2 one_sided_scales <- c(1e-4, 1, 1e4) one_sided_directions <- c("lower", "upper") result_rows <- list() @@ -121,47 +141,55 @@ for (scenario_index in seq_along(one_sided)) { truth <- rev(scaled_truth) boundary <- points >= -scale * scenario$quantile(0.1) } - for (sample_size in sample_sizes) { - estimates <- matrix(NA_real_, length(points), replications) - for (replication in seq_len(replications)) { - set.seed(20260824L + 10000000L * scenario_index + - 1000000L * scale_index + 100000L * direction_index + - 1000L * match(sample_size, sample_sizes) + replication) - observations <- scale * scenario$random(sample_size) - if (direction == "lower") { - fit <- fit_kde1d(observations, xmin = 0) - } else { - fit <- fit_kde1d(-observations, xmax = 0) + for (degree in degrees) { + for (sample_size in sample_sizes) { + estimates <- matrix(NA_real_, length(points), replications) + for (replication in seq_len(replications)) { + # Reuse the base sample across scales and reflections so departures + # from scale/reflection equivariance are paired directly. + set.seed(20260824L + 10000000L * scenario_index + + 1000L * match(sample_size, sample_sizes) + replication) + observations <- scale * scenario$random(sample_size) + repair_endpoint <- classify_finite_endpoint(observations) + if (direction == "lower") { + fit <- fit_kde1d(observations, degree, xmin = 0) + } else { + fit <- fit_kde1d(-observations, degree, xmax = 0) + } + estimates[, replication] <- dkde1d(points, fit) + result_rows[[length(result_rows) + 1L]] <- data.frame( + support = "one-sided", + direction = direction, + scale = scale, + scenario = names(one_sided)[[scenario_index]], + degree = degree, + sample_size = sample_size, + replication = replication, + method = method, + repair_lower = direction == "lower" && repair_endpoint, + repair_upper = direction == "upper" && repair_endpoint, + global_ise = integrate_values( + points, (estimates[, replication] - truth)^2 + ), + boundary_ise = integrate_values( + points[boundary], + (estimates[boundary, replication] - truth[boundary])^2 + ), + edf = fit$edf, + loglik = fit$loglik + ) } - estimates[, replication] <- dkde1d(points, fit) - result_rows[[length(result_rows) + 1L]] <- data.frame( + summary_rows[[length(summary_rows) + 1L]] <- data.frame( support = "one-sided", direction = direction, scale = scale, scenario = names(one_sided)[[scenario_index]], + degree = degree, sample_size = sample_size, - replication = replication, method = method, - global_ise = integrate_values( - points, (estimates[, replication] - truth)^2 - ), - boundary_ise = integrate_values( - points[boundary], - (estimates[boundary, replication] - truth[boundary])^2 - ), - edf = fit$edf, - loglik = fit$loglik + as.list(summarize_estimates(points, estimates, truth, boundary)) ) } - summary_rows[[length(summary_rows) + 1L]] <- data.frame( - support = "one-sided", - direction = direction, - scale = scale, - scenario = names(one_sided)[[scenario_index]], - sample_size = sample_size, - method = method, - as.list(summarize_estimates(points, estimates, truth, boundary)) - ) } } } @@ -176,45 +204,53 @@ boundary <- points <= 0.1 | points >= 0.9 for (scenario_index in seq_along(two_sided)) { shapes <- two_sided[[scenario_index]] truth <- dbeta(points, shapes[[1L]], shapes[[2L]]) - for (sample_size in sample_sizes) { - estimates <- matrix(NA_real_, length(points), replications) - for (replication in seq_len(replications)) { - set.seed(20260825L + 100000L * scenario_index + - 1000L * match(sample_size, sample_sizes) + replication) - fit <- fit_kde1d( - rbeta(sample_size, shapes[[1L]], shapes[[2L]]), - xmin = 0, - xmax = 1 - ) - estimates[, replication] <- dkde1d(points, fit) - result_rows[[length(result_rows) + 1L]] <- data.frame( + for (degree in degrees) { + for (sample_size in sample_sizes) { + estimates <- matrix(NA_real_, length(points), replications) + for (replication in seq_len(replications)) { + set.seed(20260825L + 100000L * scenario_index + + 1000L * match(sample_size, sample_sizes) + replication) + observations <- rbeta(sample_size, shapes[[1L]], shapes[[2L]]) + fit <- fit_kde1d( + observations, + degree, + xmin = 0, + xmax = 1 + ) + estimates[, replication] <- dkde1d(points, fit) + result_rows[[length(result_rows) + 1L]] <- data.frame( + support = "two-sided", + direction = NA_character_, + scale = 1, + scenario = names(two_sided)[[scenario_index]], + degree = degree, + sample_size = sample_size, + replication = replication, + method = method, + repair_lower = classify_finite_endpoint(observations), + repair_upper = classify_finite_endpoint(1 - observations), + global_ise = integrate_values( + points, (estimates[, replication] - truth)^2 + ), + boundary_ise = integrate_values( + points[boundary], + (estimates[boundary, replication] - truth[boundary])^2 + ), + edf = fit$edf, + loglik = fit$loglik + ) + } + summary_rows[[length(summary_rows) + 1L]] <- data.frame( support = "two-sided", direction = NA_character_, scale = 1, scenario = names(two_sided)[[scenario_index]], + degree = degree, sample_size = sample_size, - replication = replication, method = method, - global_ise = integrate_values( - points, (estimates[, replication] - truth)^2 - ), - boundary_ise = integrate_values( - points[boundary], - (estimates[boundary, replication] - truth[boundary])^2 - ), - edf = fit$edf, - loglik = fit$loglik + as.list(summarize_estimates(points, estimates, truth, boundary)) ) } - summary_rows[[length(summary_rows) + 1L]] <- data.frame( - support = "two-sided", - direction = NA_character_, - scale = 1, - scenario = names(two_sided)[[scenario_index]], - sample_size = sample_size, - method = method, - as.list(summarize_estimates(points, estimates, truth, boundary)) - ) } } From 805abce9dccc79bfd64f1c9d8c4cb279a3b03aac Mon Sep 17 00:00:00 2001 From: tnagler Date: Mon, 24 Aug 2026 22:01:49 +0200 Subject: [PATCH 19/25] Fix strict compiler conversion warnings --- include/kde1d/kde1d.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 0cb77fa..3adc043 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -1121,7 +1121,9 @@ Kde1d::select_boundary_bandwidth(const EndpointData& endpoint, const Eigen::Index n_bw = std::min( dist.size(), std::max( - 4, static_cast(std::ceil(fraction * dist.size())))); + 4, + static_cast( + std::ceil(fraction * static_cast(dist.size()))))); bandwidth::PluginBandwidthSelector selector(dist.head(n_bw), weights.head(n_bw)); return selector.select_bandwidth(2) * multiplier_; @@ -1259,7 +1261,8 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, for (Eigen::Index j = 0; j < eval_dist.size(); ++j) { const double a = eval_dist(j) / h; const BoundaryKernelCoefficients c = boundary_kernel_coefficients(a); - const double position = eval_dist(j) * num_bins / convolutions.upper; + const double position = + eval_dist(j) * static_cast(num_bins) / convolutions.upper; const size_t bin = std::min(static_cast(position), num_bins - 1); const double fraction = position - static_cast(bin); auto interpolate = [&](const Eigen::VectorXd& values) { From ba10d49695b005473b12170d5e7f4390639a641c Mon Sep 17 00:00:00 2001 From: tnagler Date: Wed, 26 Aug 2026 13:15:44 +0200 Subject: [PATCH 20/25] Use biweight boundary fusion --- diagnostic/PR_COMMENT.md | 4 ++-- docs/overview-continuous.dox | 4 ++-- include/kde1d/kde1d.hpp | 4 ++-- test/test.cpp | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/diagnostic/PR_COMMENT.md b/diagnostic/PR_COMMENT.md index 9ee0435..dc26734 100644 --- a/diagnostic/PR_COMMENT.md +++ b/diagnostic/PR_COMMENT.md @@ -47,10 +47,10 @@ Let $F_B$ be the normalized bulk CDF, $$ q=\min(1/4,n_e^{-1/2}), \qquad -g(p)=1-3\min(1,p/q)^2+2\min(1,p/q)^3. +g(p)=\{1-\min(1,p/q)^2\}^2. $$ -Selected lower and upper experts receive weights +Selected lower and upper experts receive the biweight fusion weights $w_L(x)=g\{F_B(x)\}$ and $w_U(x)=g\{1-F_B(x)\}$, giving $$ diff --git a/docs/overview-continuous.dox b/docs/overview-continuous.dox index c3bd932..db7e4b5 100644 --- a/docs/overview-continuous.dox +++ b/docs/overview-continuous.dox @@ -83,10 +83,10 @@ Let @f$F_B@f$ be the normalized bulk CDF and @f[ q=\min(1/4,n_e^{-1/2}), \qquad -g(p)=1-3\min(1,p/q)^2+2\min(1,p/q)^3. +g(p)=\{1-\min(1,p/q)^2\}^2. @f] -For selected lower and upper endpoints, the fusion weights are +For selected lower and upper endpoints, the biweight fusion weights are @f$w_L(x)=g\{F_B(x)\}@f$ and @f$w_U(x)=g\{1-F_B(x)\}@f$; a missing or rejected endpoint has weight zero. The final density before numerical normalization is diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 3adc043..7669aad 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -1342,7 +1342,7 @@ Kde1d::fuse_boundary_components(const Eigen::VectorXd& grid, //! @f[ //! \begin{align*} //! q &= \min(1/4,n_e^{-1/2}), & z(p) &= \min(1,p/q), \\[2pt] -//! g(p) &= 1-3z(p)^2+2z(p)^3, \\[2pt] +//! g(p) &= \{1-z(p)^2\}^2, \\[2pt] //! w_L &= g(F_B), & w_U &= g(1-F_B), \\[2pt] //! \widehat f //! &= w_L\widehat f_L+(1-w_L-w_U)\widehat f_B+w_U\widehat f_U, \\[2pt] @@ -1384,7 +1384,7 @@ Kde1d::repair_boundaries(const Eigen::VectorXd& x, const double q = std::min(0.25, 1.0 / std::sqrt(n_eff)); auto endpoint_weight = [&](double probability) { const double z = std::min(1.0, probability / q); - return 1.0 - (3.0 * z * z - 2.0 * z * z * z); + return (1.0 - z * z) * (1.0 - z * z); }; // Only evaluate endpoint fits where their fusion weights are nonzero. diff --git a/test/test.cpp b/test/test.cpp index 9b58f6a..9116359 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -150,8 +150,8 @@ TEST_CASE("one-sided finite endpoints use the boundary expert", CHECK(fit.get_values().isApprox(manual.get_values(), 1e-12)); Eigen::VectorXd expected_density(6); - expected_density << 0.9884817, 0.9885018, 0.9865198, 0.9465577, 0.7315411, - 0.0077367; + expected_density << 0.9883801, 0.9883894, 0.9865788, 0.9497592, 0.7314455, + 0.0077357; Eigen::VectorXd selected_density(6); selected_density << fit.get_values()(0), fit.get_values()(4), fit.get_values()(24), fit.get_values()(49), fit.get_values()(99), @@ -250,7 +250,7 @@ TEST_CASE("two-sided endpoints are classified independently", fit.fit(observations); Eigen::VectorXd expected_density(6); - expected_density << 1.9984196, 1.9944352, 1.9846050, 0.9946111, 0.0562112, + expected_density << 1.9986281, 1.9954211, 1.9825467, 0.9946342, 0.0562125, 0.0000020; Eigen::VectorXd selected_density(6); selected_density << fit.get_values()(0), fit.get_values()(49), From acf0f32f458a2dabd3e09064c165f383157f62dd Mon Sep 17 00:00:00 2001 From: tnagler Date: Wed, 26 Aug 2026 13:35:05 +0200 Subject: [PATCH 21/25] Use local-linear boundary repair --- diagnostic/PR_COMMENT.md | 16 ++++---- docs/overview-continuous.dox | 10 ++--- include/kde1d/kde1d.hpp | 80 +++++++++++++----------------------- test/test.cpp | 6 +-- 4 files changed, 44 insertions(+), 68 deletions(-) diff --git a/diagnostic/PR_COMMENT.md b/diagnostic/PR_COMMENT.md index dc26734..d93ecfa 100644 --- a/diagnostic/PR_COMMENT.md +++ b/diagnostic/PR_COMMENT.md @@ -29,17 +29,12 @@ $$ Endpoints consistent with a finite nonzero limiting density receive a boundary expert. Exploding, vanishing, ambiguous, and degenerate endpoints retain the -bulk. The expert is the equal average +bulk. The expert is a Gaussian local-linear equivalent-kernel estimate, -$$ -\widehat f_E=(\widehat f_{\mathrm{local\ linear}} - +\widehat f_{\mathrm{local\ quadratic}})/2 -$$ - -of Gaussian equivalent-kernel estimates. Both kernels share an automatically -selected degree-2 plug-in bandwidth on the original scale, using all +using an automatically selected degree-2 plug-in bandwidth on the original +scale. The selector uses all positive-weight observations on bounded support and the closest 75% by row -count on one-sided support. The three required Gaussian convolutions are +count on one-sided support. The two required Gaussian convolutions are evaluated on a shared 256-bin FFT grid. Let $F_B$ be the normalized bulk CDF, @@ -67,6 +62,9 @@ clamps, and normalization fixed. ## Validation design +The large-scale tables below predate the biweight and local-linear +simplifications and will be refreshed before merge. + The primary benchmark is the actual pre-PR package at parent commit `7faec53` with C++ commit `b16d514`: log transform for one-sided support and probit for two-sided support. The experiment used 200 paired replications for diff --git a/docs/overview-continuous.dox b/docs/overview-continuous.dox index db7e4b5..6602539 100644 --- a/docs/overview-continuous.dox +++ b/docs/overview-continuous.dox @@ -63,16 +63,16 @@ Weighted fits use effective counts and the more conservative lower threshold behavior retains the bulk fit. Setting `boundary_repair=false` skips the classifier and all expert calculations. -For a selected endpoint, the expert is the equal average of Gaussian -local-linear and local-quadratic equivalent-kernel estimates on the original -scale. Both use one automatically selected degree-two plug-in bandwidth. On -two-sided support the selector uses all positive-weight observations; on +For a selected endpoint, the expert is a Gaussian local-linear +equivalent-kernel estimate on the original scale. It uses an automatically +selected degree-two plug-in bandwidth. On two-sided support the selector uses +all positive-weight observations; on one-sided support it uses the closest 75% by row count. Public case weights enter the expert estimand and bandwidth selector. A manual bulk `bandwidth` does not replace this expert bandwidth, while `multiplier` scales both. The equivalent kernel is expressed as a pointwise combination of an ordinary -Gaussian KDE and its first two derivatives. These three convolutions are +Gaussian KDE and its first derivative. These two convolutions are evaluated on a 256-bin FFT grid. Invalid or nonpositive local-polynomial values are set to zero before fusion. diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 7669aad..13dc99f 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -20,8 +20,8 @@ enum class VarType //! //! Continuous fits use a transformed local-likelihood estimate as their bulk //! component. When `boundary_repair` is enabled, finite support endpoints may -//! additionally use a nonnegative blend of local-linear and local-quadratic -//! boundary kernels. See @ref overview-continuous for the transforms, +//! additionally use a nonnegative local-linear boundary kernel. See +//! @ref overview-continuous for the transforms, //! endpoint classifier, bandwidths, fusion weights, and EDF approximation. class Kde1d { @@ -157,18 +157,14 @@ class Kde1d { Eigen::VectorXd f0; Eigen::VectorXd f1; - Eigen::VectorXd f2; Eigen::VectorXd influence_weight; double upper{ 0.0 }; }; struct BoundaryKernelCoefficients { - double c10; - double c11; - double c20; - double c21; - double c22; + double c0; + double c1; }; // data members @@ -1129,7 +1125,7 @@ Kde1d::select_boundary_bandwidth(const EndpointData& endpoint, return selector.select_bandwidth(2) * multiplier_; } -//! Computes the ordinary Gaussian KDE and its first two derivatives on the +//! Computes the ordinary Gaussian KDE and its first derivative on the //! regular FFT grid used by a boundary component. The influence weights are //! the average normalized case weights in the same bins. //! @param dist ordered endpoint distances. @@ -1163,7 +1159,6 @@ Kde1d::compute_boundary_convolutions(const Eigen::VectorXd& dist, const double scale = fft_weight / weights.sum(); convolutions.f0 = scale * kde_fft.kde_drv(0); convolutions.f1 = scale * kde_fft.kde_drv(1); - convolutions.f2 = scale * kde_fft.kde_drv(2); convolutions.influence_weight = Eigen::VectorXd::Ones(num_bins + 1); if (weights.minCoeff() != weights.maxCoeff()) { const Eigen::VectorXd count = tools::linbin(dist.head(n_fft), @@ -1180,10 +1175,10 @@ Kde1d::compute_boundary_convolutions(const Eigen::VectorXd& dist, return convolutions; } -//! Computes the first inverse-moment rows for degree-one and degree-two -//! Gaussian boundary kernels at standardized endpoint distance @f$a@f$. +//! Computes the first inverse-moment row for the local-linear Gaussian +//! boundary kernel at standardized endpoint distance @f$a@f$. //! @param a endpoint distance divided by bandwidth. -//! @return coefficients @f$c_{10},c_{11},c_{20},c_{21},c_{22}@f$. +//! @return coefficients @f$c_0,c_1@f$. inline Kde1d::BoundaryKernelCoefficients Kde1d::boundary_kernel_coefficients(double a) const { @@ -1191,50 +1186,35 @@ Kde1d::boundary_kernel_coefficients(double a) const const double mu0 = 0.5 * std::erfc(-a * 0.7071067811865475); const double mu1 = -phi; const double mu2 = mu0 - a * phi; - const double mu3 = -(a * a + 2.0) * phi; - const double mu4 = 3.0 * mu0 - (a * a * a + 3.0 * a) * phi; - const double det1 = mu0 * mu2 - mu1 * mu1; - const double det2 = mu0 * (mu2 * mu4 - mu3 * mu3) - - mu1 * (mu1 * mu4 - mu2 * mu3) + - mu2 * (mu1 * mu3 - mu2 * mu2); - return { mu2 / det1, - -mu1 / det1, - (mu2 * mu4 - mu3 * mu3) / det2, - (mu2 * mu3 - mu1 * mu4) / det2, - (mu1 * mu3 - mu2 * mu2) / det2 }; + const double denom = mu0 * mu2 - mu1 * mu1; + return { mu2 / denom, -mu1 / denom }; } -//! Fits the average of Gaussian local-linear and local-quadratic equivalent -//! kernels from sample distances @f$d@f$ to endpoint-distance grid @f$t@f$. -//! For degree @f$p@f$, shared bandwidth @f$h@f$, truncated Gaussian moments -//! @f$\mu_r(a)@f$, and @f$M_p(a)=[\mu_{j+k}(a)]_{j,k=0}^p@f$, +//! Fits a Gaussian local-linear equivalent kernel from sample distances +//! @f$d@f$ to endpoint-distance grid @f$t@f$. For bandwidth @f$h@f$, +//! truncated Gaussian moments @f$\mu_r(a)@f$, and +//! @f$M(a)=[\mu_{j+k}(a)]_{j,k=0}^1@f$, //! @f[ //! \begin{align*} //! a &= t/h, & u_i &= (t-d_i)/h, \\[2pt] -//! \widehat f_p(t;h) +//! \widehat f_E(t;h) //! &= \frac{1}{nh}\sum_{i=1}^n w_i\phi(u_i)\, -//! e_0^\mathsf{T}M_p(a)^{-1} -//! (1,u_i,\ldots,u_i^p)^\mathsf{T}, \\[2pt] -//! \widehat f_\partial(t) -//! &= \{\widehat f_1(t;h)+\widehat f_2(t;h)\}/2. +//! e_0^\mathsf{T}M(a)^{-1}(1,u_i)^\mathsf{T}. //! \end{align*} //! @f] -//! Writing @f$f^{(r)}@f$ for the @f$r@f$th derivative of the ordinary -//! Gaussian KDE and @f$c_{pj}@f$ for the entries of the first row of -//! @f$M_p(a)^{-1}@f$, the same estimator is +//! Writing @f$f^{(1)}@f$ for the first derivative of the ordinary Gaussian KDE +//! and @f$(c_0,c_1)=e_0^\mathsf{T}M(a)^{-1}@f$, the same estimator is //! @f[ //! \begin{align*} -//! \widehat f_\partial(t) -//! &= \frac{1}{2}\{(c_{10}+c_{20}+c_{22})f(t) -//! -h(c_{11}+c_{21})f^{(1)}(t)+h^2c_{22}f^{(2)}(t)\}. +//! \widehat f_E(t;h) &= c_0f(t)-hc_1f^{(1)}(t). //! \end{align*} //! @f] -//! This identity evaluates the three convolutions by FFT. -//! Both kernels use the same normalized case weights @f$w_i@f$. The returned -//! influence numerator is the corresponding average diagonal contribution. +//! This identity evaluates the two convolutions by FFT. The returned influence +//! numerator is the diagonal contribution with normalized case weights +//! @f$w_i@f$. //! @param dist ordered distances of the observations from the support endpoint. //! @param eval_dist endpoint distances at which to evaluate the component. -//! @param bandwidth shared bandwidth of both equivalent kernels. +//! @param bandwidth bandwidth of the equivalent kernel. //! @param weights correspondingly ordered case weights with mean one. //! @return the density and influence numerator on `eval_dist`. inline Kde1d::BoundaryComponent @@ -1268,13 +1248,11 @@ Kde1d::fit_boundary_component(const Eigen::VectorXd& dist, auto interpolate = [&](const Eigen::VectorXd& values) { return (1.0 - fraction) * values(bin) + fraction * values(bin + 1); }; - fit.density(j) = - 0.5 * ((c.c10 + c.c20 + c.c22) * interpolate(convolutions.f0) - - h * (c.c11 + c.c21) * interpolate(convolutions.f1) + - h * h * c.c22 * interpolate(convolutions.f2)); + fit.density(j) = c.c0 * interpolate(convolutions.f0) - + h * c.c1 * interpolate(convolutions.f1); fit.influence_num(j) = - K0_ * (c.c10 + c.c20) * interpolate(convolutions.influence_weight) / - (2.0 * static_cast(dist.size()) * h); + K0_ * c.c0 * interpolate(convolutions.influence_weight) / + (static_cast(dist.size()) * h); } // Remove unstable local-polynomial values. @@ -1334,8 +1312,8 @@ Kde1d::fuse_boundary_components(const Eigen::VectorXd& grid, //! Fuses the transformed bulk density @f$\widehat f_B@f$ with endpoint //! densities @f$\widehat f_L@f$ and @f$\widehat f_U@f$. Each endpoint density -//! averages local-linear and local-quadratic kernels using one degree-2 -//! bandwidth, selected from all distances on bounded support and the closest +//! uses a local-linear kernel with a degree-2 plug-in bandwidth, selected from +//! all distances on bounded support and the closest //! 75% of positive-weight observations on one-sided support. Smooth weights //! @f$w_L@f$ and @f$w_U@f$ are functions of the weighted bulk CDF and shrink //! with effective sample size @f$n_e@f$: diff --git a/test/test.cpp b/test/test.cpp index 9116359..f1a3ab6 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -150,8 +150,8 @@ TEST_CASE("one-sided finite endpoints use the boundary expert", CHECK(fit.get_values().isApprox(manual.get_values(), 1e-12)); Eigen::VectorXd expected_density(6); - expected_density << 0.9883801, 0.9883894, 0.9865788, 0.9497592, 0.7314455, - 0.0077357; + expected_density << 0.9797951, 0.9798032, 0.9780643, 0.9448344, 0.7316556, + 0.0077380; Eigen::VectorXd selected_density(6); selected_density << fit.get_values()(0), fit.get_values()(4), fit.get_values()(24), fit.get_values()(49), fit.get_values()(99), @@ -250,7 +250,7 @@ TEST_CASE("two-sided endpoints are classified independently", fit.fit(observations); Eigen::VectorXd expected_density(6); - expected_density << 1.9986281, 1.9954211, 1.9825467, 0.9946342, 0.0562125, + expected_density << 1.9985571, 1.9950070, 1.9824915, 0.9946390, 0.0562128, 0.0000020; Eigen::VectorXd selected_density(6); selected_density << fit.get_values()(0), fit.get_values()(49), From bf7484d91e87a32ddeadf7d4c4a273b7f248f47c Mon Sep 17 00:00:00 2001 From: tnagler Date: Wed, 26 Aug 2026 13:40:56 +0200 Subject: [PATCH 22/25] Clarify boundary bandwidth documentation --- diagnostic/PR_COMMENT.md | 2 +- docs/overview-continuous.dox | 2 +- include/kde1d/kde1d.hpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/diagnostic/PR_COMMENT.md b/diagnostic/PR_COMMENT.md index d93ecfa..d3e630c 100644 --- a/diagnostic/PR_COMMENT.md +++ b/diagnostic/PR_COMMENT.md @@ -31,7 +31,7 @@ Endpoints consistent with a finite nonzero limiting density receive a boundary expert. Exploding, vanishing, ambiguous, and degenerate endpoints retain the bulk. The expert is a Gaussian local-linear equivalent-kernel estimate, -using an automatically selected degree-2 plug-in bandwidth on the original +using an automatically selected bandwidth on the original scale. The selector uses all positive-weight observations on bounded support and the closest 75% by row count on one-sided support. The two required Gaussian convolutions are diff --git a/docs/overview-continuous.dox b/docs/overview-continuous.dox index 6602539..8a46cb8 100644 --- a/docs/overview-continuous.dox +++ b/docs/overview-continuous.dox @@ -65,7 +65,7 @@ classifier and all expert calculations. For a selected endpoint, the expert is a Gaussian local-linear equivalent-kernel estimate on the original scale. It uses an automatically -selected degree-two plug-in bandwidth. On two-sided support the selector uses +selected bandwidth. On two-sided support the selector uses all positive-weight observations; on one-sided support it uses the closest 75% by row count. Public case weights enter the expert estimand and bandwidth selector. A manual bulk `bandwidth` diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 13dc99f..54d4e54 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -1099,7 +1099,7 @@ Kde1d::prepare_endpoint(const Eigen::VectorXd& x, //! closest `fraction` of positive-weight observations are used by row count. //! @param endpoint sorted endpoint distances and case weights. //! @param fraction fraction of positive-weight observations used for selection. -//! @return degree-two plug-in bandwidth after applying the public multiplier. +//! @return selected boundary bandwidth after applying the public multiplier. inline double Kde1d::select_boundary_bandwidth(const EndpointData& endpoint, double fraction) const @@ -1312,7 +1312,7 @@ Kde1d::fuse_boundary_components(const Eigen::VectorXd& grid, //! Fuses the transformed bulk density @f$\widehat f_B@f$ with endpoint //! densities @f$\widehat f_L@f$ and @f$\widehat f_U@f$. Each endpoint density -//! uses a local-linear kernel with a degree-2 plug-in bandwidth, selected from +//! uses a local-linear kernel with an automatically selected bandwidth, based on //! all distances on bounded support and the closest //! 75% of positive-weight observations on one-sided support. Smooth weights //! @f$w_L@f$ and @f$w_U@f$ are functions of the weighted bulk CDF and shrink @@ -1378,7 +1378,7 @@ Kde1d::repair_boundaries(const Eigen::VectorXd& x, const Eigen::Index n_lower = (w_l.array() > 0.0).count(); const Eigen::Index n_upper = (w_u.array() > 0.0).count(); - // Reflection invariance gives both endpoints the same degree-2 bandwidth. + // Reflection invariance gives both endpoints the same boundary bandwidth. const double bandwidth_fraction = (!std::isnan(xmin_) && !std::isnan(xmax_)) ? 1.0 : 0.75; const EndpointData& bandwidth_endpoint = From 2c809d4132e0ce1210acb5d5da5a8b69d4937044 Mon Sep 17 00:00:00 2001 From: tnagler Date: Wed, 26 Aug 2026 14:02:47 +0200 Subject: [PATCH 23/25] Document Box-Cox boundary transform --- docs/overview-continuous.dox | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/overview-continuous.dox b/docs/overview-continuous.dox index 8a46cb8..4d3dc0e 100644 --- a/docs/overview-continuous.dox +++ b/docs/overview-continuous.dox @@ -18,7 +18,8 @@ z(x)=\Phi^{-1}\left(\frac{x-a+5\times10^{-5}R}{1.0001R}\right). If exactly one endpoint is finite, let @f$d(x)@f$ denote distance from it. The scale @f$s@f$ is the weighted median of the observed distances, with a maximum-distance and unit fallback for degenerate samples, and -@f$\epsilon=10^{-5}s@f$. The one-sided transform is +@f$\epsilon=10^{-5}s@f$. The one-sided transform is an endpoint-anchored, +scaled member of the Box-Cox family with power parameter @f$\lambda=1/4@f$: @f[ z(x)=4\left[\left\{\frac{\epsilon+d(x)}{s}\right\}^{1/4} @@ -28,7 +29,7 @@ z(x)=4\left[\left\{\frac{\epsilon+d(x)}{s}\right\}^{1/4} =\frac{1}{s}\left\{\frac{\epsilon+d(x)}{s}\right\}^{-3/4}. @f] -The fourth-root transform and its Jacobian are scale equivariant. The small +This Box-Cox transform and its Jacobian are scale equivariant. The small offset keeps the transformed endpoint finite. Density values are transformed back to the original scale and normalized on the interpolation grid. From d1738841ca141212ceea650b2c22c128fa179563 Mon Sep 17 00:00:00 2001 From: tnagler Date: Wed, 26 Aug 2026 13:46:55 +0200 Subject: [PATCH 24/25] Correct probit Jacobian factor --- include/kde1d/kde1d.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/kde1d/kde1d.hpp b/include/kde1d/kde1d.hpp index 54d4e54..1311efa 100644 --- a/include/kde1d/kde1d.hpp +++ b/include/kde1d/kde1d.hpp @@ -935,7 +935,7 @@ Kde1d::boundary_correct(const Eigen::VectorXd& x, const Eigen::VectorXd& fhat) auto rng = xmax_ - xmin_; corr_term = (x.array() - xmin_ + 5e-5 * rng) / (xmax_ - xmin_ + 1e-4 * rng); corr_term = stats::dnorm(stats::qnorm(corr_term)); - corr_term /= (xmax_ - xmin_ + 1e-4 * rng); + corr_term *= (xmax_ - xmin_ + 1e-4 * rng); corr_term = 1.0 / corr_term.array(); } else if (!std::isnan(xmin_)) { // left boundary -> fourth-root-transform Jacobian From fa9fc4a939db38026faae6c8418a8d47a138ae88 Mon Sep 17 00:00:00 2001 From: tnagler Date: Wed, 26 Aug 2026 14:02:56 +0200 Subject: [PATCH 25/25] Refresh boundary validation results --- diagnostic/PR_COMMENT.md | 160 +++++++++++++++---------------- diagnostic/boundary-examples.png | Bin 170831 -> 169415 bytes 2 files changed, 80 insertions(+), 80 deletions(-) diff --git a/diagnostic/PR_COMMENT.md b/diagnostic/PR_COMMENT.md index d3e630c..a2d0fdd 100644 --- a/diagnostic/PR_COMMENT.md +++ b/diagnostic/PR_COMMENT.md @@ -4,19 +4,21 @@ This PR changes continuous fits with known finite support in two steps. For a one-sided support, write $d(x)$ for distance from the finite endpoint, let $s$ be the weighted median observed distance, and set -$\epsilon=10^{-5}s$. The transformed bulk estimator now uses +$\epsilon=10^{-5}s$. The transformed bulk estimator uses an endpoint-anchored, +scaled member of the Box-Cox family with power parameter $\lambda=1/4$: $$ T\{d(x)\} -=4\left[\left\{\frac{d(x)+\epsilon}{s}\right\}^{1/4} --\left(\frac{\epsilon}{s}\right)^{1/4}\right], +=4[\{\frac{d(x)+\epsilon}{s}\}^{1/4} +-\{\frac{\epsilon}{s}\}^{1/4}], \qquad |T'(x)| -=\frac{1}{s}\left\{\frac{d(x)+\epsilon}{s}\right\}^{-3/4}. +=\frac{1}{s}\{\frac{d(x)+\epsilon}{s}\}^{-3/4}. $$ -This replaces the previous log transform and makes the construction scale -equivariant. Two-sided fits retain the regularized probit bulk transform. +This Box-Cox transform replaces the previous log transform and makes the +construction scale equivariant. Two-sided fits retain the regularized probit +bulk transform. Each finite endpoint is then classified independently from its first $k\simeq2\sqrt{n_e}$ order statistics. In the unweighted case, @@ -29,10 +31,8 @@ $$ Endpoints consistent with a finite nonzero limiting density receive a boundary expert. Exploding, vanishing, ambiguous, and degenerate endpoints retain the -bulk. The expert is a Gaussian local-linear equivalent-kernel estimate, - -using an automatically selected bandwidth on the original -scale. The selector uses all +bulk. The expert is a Gaussian local-linear equivalent-kernel estimate with an +automatically selected bandwidth on the original scale. The selector uses all positive-weight observations on bounded support and the closest 75% by row count on one-sided support. The two required Gaussian convolutions are evaluated on a shared 256-bin FFT grid. @@ -62,8 +62,8 @@ clamps, and normalization fixed. ## Validation design -The large-scale tables below predate the biweight and local-linear -simplifications and will be refreshed before merge. +> **Before merging:** remove `diagnostic/`; it is retained in this branch only +> to make the PR validation reproducible during review. The primary benchmark is the actual pre-PR package at parent commit `7faec53` with C++ commit `b16d514`: log transform for one-sided support and probit for @@ -85,28 +85,28 @@ PR**. Parentheses are paired Monte Carlo standard errors. | support | degree | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | |---|---:|---:|---:|---:|---:| -| one-sided | 0 | 0.748 (0.044) | 0.579 (0.028) | 0.513 (0.011) | 0.475 (0.010) | -| one-sided | 1 | 0.505 (0.020) | 0.411 (0.011) | 0.684 (0.063) | 0.724 (0.050) | -| one-sided | 2 | 0.211 (0.036) | 0.198 (0.021) | 0.208 (0.018) | 0.260 (0.015) | -| two-sided | 0 | 0.951 (0.005) | 0.943 (0.005) | 0.941 (0.006) | 0.925 (0.005) | -| two-sided | 1 | 0.867 (0.006) | 0.823 (0.007) | 0.847 (0.005) | 0.852 (0.004) | -| two-sided | 2 | 0.892 (0.013) | 0.911 (0.006) | 0.940 (0.006) | 0.932 (0.006) | +| one-sided | 0 | 1.810 (0.116) | 1.134 (0.049) | 0.586 (0.015) | 0.519 (0.011) | +| one-sided | 1 | 0.789 (0.038) | 0.508 (0.011) | 0.566 (0.042) | 0.612 (0.037) | +| one-sided | 2 | 0.550 (0.034) | 0.394 (0.015) | 0.231 (0.008) | 0.231 (0.008) | +| two-sided | 0 | 0.946 (0.005) | 0.940 (0.005) | 0.943 (0.006) | 0.926 (0.006) | +| two-sided | 1 | 0.856 (0.007) | 0.817 (0.007) | 0.846 (0.005) | 0.850 (0.004) | +| two-sided | 2 | 0.881 (0.013) | 0.906 (0.006) | 0.943 (0.007) | 0.932 (0.007) | ### Boundary ratio, averaged over families | support | degree | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | |---|---:|---:|---:|---:|---:| -| one-sided | 0 | 0.702 (0.049) | 0.513 (0.030) | 0.447 (0.013) | 0.399 (0.011) | -| one-sided | 1 | 0.399 (0.022) | 0.303 (0.011) | 0.636 (0.075) | 0.702 (0.059) | -| one-sided | 2 | 0.144 (0.027) | 0.151 (0.027) | 0.159 (0.016) | 0.205 (0.015) | -| two-sided | 0 | 0.923 (0.005) | 0.944 (0.005) | 0.954 (0.005) | 0.939 (0.005) | -| two-sided | 1 | 0.824 (0.008) | 0.826 (0.007) | 0.879 (0.004) | 0.877 (0.004) | -| two-sided | 2 | 0.883 (0.012) | 0.913 (0.005) | 0.955 (0.005) | 0.945 (0.005) | - -The expert also improves over the unrepaired new bulk. Averaged global ISE -ratios range from 0.84--0.94 for degree 0, 0.74--0.89 for degree 1, and -0.88--0.92 for degree 2 on one-sided support. The corresponding bounded ratios -are 0.93--0.95, 0.82--0.87, and 0.89--0.94. +| one-sided | 0 | 3.149 (0.278) | 1.553 (0.097) | 0.563 (0.020) | 0.461 (0.014) | +| one-sided | 1 | 0.931 (0.073) | 0.437 (0.017) | 0.519 (0.047) | 0.590 (0.042) | +| one-sided | 2 | 0.612 (0.048) | 0.396 (0.024) | 0.190 (0.009) | 0.190 (0.008) | +| two-sided | 0 | 0.918 (0.005) | 0.939 (0.005) | 0.955 (0.006) | 0.940 (0.006) | +| two-sided | 1 | 0.817 (0.009) | 0.821 (0.007) | 0.878 (0.004) | 0.876 (0.004) | +| two-sided | 2 | 0.877 (0.012) | 0.910 (0.005) | 0.958 (0.006) | 0.946 (0.006) | + +Against the unrepaired new bulk, averaged global ISE ratios range from +0.83--0.94 for degree 0, 0.73--0.88 for degree 1, and 0.87--0.92 for degree 2 +on one-sided support. The corresponding bounded ratios are 0.93--0.95, +0.82--0.86, and 0.88--0.94.
Family-level global / boundary ISE ratios @@ -115,78 +115,78 @@ are 0.93--0.95, 0.82--0.87, and 0.89--0.94. | family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | |---|---:|---:|---:|---:| -| Exponential | 0.75 / 0.73 | 0.49 / 0.45 | 0.37 / 0.30 | 0.34 / 0.27 | -| Gamma$(0.75)$ | 0.55 / 0.54 | 0.51 / 0.50 | 0.45 / 0.44 | 0.44 / 0.43 | -| Gamma$(2)$ | 0.71 / 0.52 | 0.76 / 0.58 | 0.81 / 0.69 | 0.80 / 0.67 | -| half-normal | 0.46 / 0.38 | 0.41 / 0.32 | 0.31 / 0.21 | 0.28 / 0.17 | -| Lomax$(2)$ | 1.28 / 1.34 | 0.72 / 0.70 | 0.63 / 0.59 | 0.51 / 0.45 | +| Exponential | 1.48 / 2.67 | 1.36 / 2.41 | 0.58 / 0.56 | 0.51 / 0.45 | +| Gamma$(0.75)$ | 2.05 / 2.76 | 0.91 / 0.97 | 0.33 / 0.32 | 0.28 / 0.27 | +| Gamma$(2)$ | 0.79 / 0.66 | 0.84 / 0.75 | 0.87 / 0.80 | 0.86 / 0.77 | +| half-normal | 0.88 / 1.28 | 0.79 / 1.08 | 0.54 / 0.53 | 0.46 / 0.38 | +| Lomax$(2)$ | 3.84 / 8.37 | 1.77 / 2.56 | 0.61 / 0.60 | 0.50 / 0.44 | #### One-sided, degree 1 | family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | |---|---:|---:|---:|---:| -| Exponential | 0.49 / 0.37 | 0.31 / 0.22 | 0.38 / 0.26 | 0.38 / 0.27 | -| Gamma$(0.75)$ | 0.27 / 0.25 | 0.25 / 0.21 | 0.45 / 0.43 | 0.53 / 0.52 | -| Gamma$(2)$ | 0.69 / 0.46 | 0.81 / 0.63 | 0.93 / 0.98 | 1.01 / 1.19 | -| half-normal | 0.45 / 0.32 | 0.38 / 0.23 | 0.43 / 0.25 | 0.43 / 0.25 | -| Lomax$(2)$ | 0.62 / 0.60 | 0.31 / 0.22 | 1.23 / 1.26 | 1.27 / 1.28 | +| Exponential | 0.70 / 0.83 | 0.47 / 0.43 | 0.37 / 0.25 | 0.35 / 0.24 | +| Gamma$(0.75)$ | 0.72 / 0.88 | 0.33 / 0.30 | 0.32 / 0.30 | 0.36 / 0.34 | +| Gamma$(2)$ | 0.74 / 0.59 | 0.84 / 0.73 | 0.93 / 1.03 | 1.00 / 1.21 | +| half-normal | 0.61 / 0.65 | 0.50 / 0.40 | 0.47 / 0.29 | 0.44 / 0.26 | +| Lomax$(2)$ | 1.17 / 1.71 | 0.40 / 0.32 | 0.74 / 0.72 | 0.91 / 0.90 | #### One-sided, degree 2 | family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | |---|---:|---:|---:|---:| -| Exponential | 0.07 / 0.04 | 0.02 / 0.01 | 0.06 / 0.04 | 0.09 / 0.06 | -| Gamma$(0.75)$ | 0.03 / 0.03 | 0.04 / 0.03 | 0.23 / 0.21 | 0.23 / 0.21 | -| Gamma$(2)$ | 0.38 / 0.18 | 0.72 / 0.56 | 0.59 / 0.44 | 0.62 / 0.50 | -| half-normal | 0.09 / 0.04 | 0.03 / 0.02 | 0.03 / 0.01 | 0.06 / 0.03 | -| Lomax$(2)$ | 0.49 / 0.43 | 0.17 / 0.13 | 0.13 / 0.09 | 0.30 / 0.23 | +| Exponential | 0.43 / 0.53 | 0.32 / 0.38 | 0.10 / 0.07 | 0.10 / 0.07 | +| Gamma$(0.75)$ | 0.47 / 0.56 | 0.18 / 0.17 | 0.12 / 0.11 | 0.10 / 0.10 | +| Gamma$(2)$ | 0.61 / 0.48 | 0.84 / 0.83 | 0.67 / 0.59 | 0.67 / 0.61 | +| half-normal | 0.37 / 0.42 | 0.32 / 0.32 | 0.16 / 0.10 | 0.13 / 0.06 | +| Lomax$(2)$ | 0.87 / 1.09 | 0.30 / 0.28 | 0.11 / 0.08 | 0.15 / 0.11 | #### Two-sided, degree 0 | family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | |---|---:|---:|---:|---:| -| Beta$(0.75,0.75)$ | 1.02 / 1.03 | 1.03 / 1.04 | 1.04 / 1.04 | 1.05 / 1.05 | -| Beta$(0.75,2)$ | 0.99 / 0.98 | 1.01 / 1.00 | 1.07 / 1.07 | 1.06 / 1.06 | -| Beta$(1,2)$ | 0.93 / 0.91 | 0.85 / 0.86 | 0.83 / 0.86 | 0.78 / 0.81 | -| Beta$(2,0.75)$ | 1.00 / 0.99 | 1.01 / 1.00 | 1.09 / 1.08 | 1.06 / 1.05 | -| Beta$(2,1)$ | 0.95 / 0.93 | 0.89 / 0.89 | 0.78 / 0.81 | 0.79 / 0.82 | -| Beta$(2,2)$ | 0.82 / 0.65 | 0.94 / 0.88 | 1.00 / 1.00 | 1.00 / 1.00 | -| Uniform | 0.95 / 0.98 | 0.88 / 0.93 | 0.77 / 0.82 | 0.74 / 0.79 | +| Beta$(0.75,0.75)$ | 1.01 / 1.02 | 1.03 / 1.04 | 1.05 / 1.05 | 1.06 / 1.06 | +| Beta$(0.75,2)$ | 0.98 / 0.97 | 1.01 / 1.01 | 1.09 / 1.08 | 1.07 / 1.07 | +| Beta$(1,2)$ | 0.90 / 0.89 | 0.84 / 0.85 | 0.82 / 0.85 | 0.77 / 0.80 | +| Beta$(2,0.75)$ | 0.99 / 0.98 | 1.01 / 1.01 | 1.11 / 1.10 | 1.07 / 1.06 | +| Beta$(2,1)$ | 0.94 / 0.92 | 0.87 / 0.88 | 0.76 / 0.80 | 0.78 / 0.81 | +| Beta$(2,2)$ | 0.86 / 0.68 | 0.95 / 0.88 | 1.00 / 1.00 | 1.00 / 1.00 | +| Uniform | 0.94 / 0.96 | 0.86 / 0.91 | 0.76 / 0.81 | 0.72 / 0.78 | #### Two-sided, degree 1 | family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | |---|---:|---:|---:|---:| -| Beta$(0.75,0.75)$ | 0.91 / 0.91 | 0.87 / 0.88 | 0.94 / 0.95 | 0.97 / 0.97 | -| Beta$(0.75,2)$ | 0.88 / 0.87 | 0.89 / 0.90 | 0.96 / 0.97 | 0.98 / 0.98 | -| Beta$(1,2)$ | 0.81 / 0.76 | 0.72 / 0.74 | 0.73 / 0.76 | 0.69 / 0.73 | -| Beta$(2,0.75)$ | 0.89 / 0.88 | 0.88 / 0.88 | 0.95 / 0.96 | 0.98 / 0.98 | -| Beta$(2,1)$ | 0.86 / 0.82 | 0.74 / 0.76 | 0.70 / 0.75 | 0.71 / 0.74 | -| Beta$(2,2)$ | 0.91 / 0.73 | 0.96 / 0.90 | 1.00 / 1.00 | 1.00 / 1.00 | -| Uniform | 0.82 / 0.78 | 0.70 / 0.72 | 0.64 / 0.77 | 0.62 / 0.74 | +| Beta$(0.75,0.75)$ | 0.90 / 0.90 | 0.86 / 0.88 | 0.95 / 0.95 | 0.98 / 0.98 | +| Beta$(0.75,2)$ | 0.86 / 0.86 | 0.90 / 0.90 | 0.97 / 0.97 | 0.99 / 0.99 | +| Beta$(1,2)$ | 0.79 / 0.74 | 0.71 / 0.73 | 0.72 / 0.75 | 0.69 / 0.72 | +| Beta$(2,0.75)$ | 0.87 / 0.87 | 0.88 / 0.89 | 0.96 / 0.96 | 0.99 / 0.99 | +| Beta$(2,1)$ | 0.84 / 0.81 | 0.72 / 0.75 | 0.69 / 0.74 | 0.71 / 0.73 | +| Beta$(2,2)$ | 0.93 / 0.78 | 0.97 / 0.90 | 1.00 / 1.00 | 1.00 / 1.00 | +| Uniform | 0.79 / 0.76 | 0.68 / 0.70 | 0.62 / 0.76 | 0.61 / 0.73 | #### Two-sided, degree 2 | family | $n=25$ | $n=100$ | $n=1000$ | $n=2000$ | |---|---:|---:|---:|---:| -| Beta$(0.75,0.75)$ | 0.91 / 0.92 | 0.95 / 0.96 | 1.02 / 1.02 | 1.05 / 1.05 | -| Beta$(0.75,2)$ | 0.89 / 0.89 | 0.94 / 0.94 | 1.06 / 1.06 | 1.06 / 1.05 | -| Beta$(1,2)$ | 0.77 / 0.80 | 0.84 / 0.85 | 0.82 / 0.85 | 0.78 / 0.81 | -| Beta$(2,0.75)$ | 0.90 / 0.90 | 0.94 / 0.95 | 1.08 / 1.07 | 1.05 / 1.05 | -| Beta$(2,1)$ | 0.90 / 0.90 | 0.83 / 0.85 | 0.78 / 0.82 | 0.79 / 0.83 | -| Beta$(2,2)$ | 0.99 / 0.89 | 1.02 / 0.95 | 1.00 / 1.00 | 1.00 / 1.00 | -| Uniform | 0.87 / 0.87 | 0.86 / 0.90 | 0.82 / 0.86 | 0.79 / 0.83 | +| Beta$(0.75,0.75)$ | 0.90 / 0.91 | 0.94 / 0.95 | 1.04 / 1.04 | 1.07 / 1.07 | +| Beta$(0.75,2)$ | 0.87 / 0.88 | 0.95 / 0.96 | 1.09 / 1.08 | 1.08 / 1.07 | +| Beta$(1,2)$ | 0.74 / 0.77 | 0.82 / 0.83 | 0.81 / 0.83 | 0.77 / 0.79 | +| Beta$(2,0.75)$ | 0.89 / 0.89 | 0.95 / 0.96 | 1.11 / 1.10 | 1.07 / 1.07 | +| Beta$(2,1)$ | 0.89 / 0.89 | 0.80 / 0.82 | 0.76 / 0.80 | 0.77 / 0.81 | +| Beta$(2,2)$ | 1.04 / 0.96 | 1.04 / 0.96 | 1.00 / 1.00 | 1.00 / 1.00 | +| Uniform | 0.85 / 0.85 | 0.84 / 0.88 | 0.80 / 0.85 | 0.77 / 0.81 |
## Bias, variance, classification, and scale -The ISE gains are primarily a variance reduction, with some deliberate -small-sample boundary bias. Against pre-PR at scale 1, aggregate global -variance ratios are 0.27--0.53 one-sided for degree 0, 0.29--0.43 for degree 1, -and 0.04--0.12 for degree 2. Bounded ratios are 0.99--1.03, 0.86--0.90, and -0.89--1.00, respectively. This matches the visual goal: substantially calmer -one-sided endpoints and moderate smoothing on bounded support. +The repair primarily reduces variance, with deliberate boundary bias. Against +pre-PR at scale 1, aggregate global variance ratios are 0.38--0.62 one-sided +for degree 0, 0.39--0.56 for degree 1, and 0.20--0.24 for degree 2. Bounded +ratios are 0.96--0.98, 0.84--0.87, and 0.87--0.96, respectively. This matches +the visual goal: substantially calmer one-sided endpoints and moderate +smoothing on bounded support. Classifier behavior becomes appropriately conservative with sample size. For one-sided finite targets, selection rates at $n=100/2000$ are 58%/78% @@ -197,7 +197,7 @@ Gamma$(2)$. For Uniform, either endpoint is selected in 90%/98% and both in $n=100$ to 0% at $n\geq1000$. For Exponential samples at $n=100$, the 5%--95% range of the estimated value -at the endpoint is 0.56--1.44 when the expert is selected, compared with +at the endpoint is 0.64--1.34 when the expert is selected, compared with 0.01--49.6 when the classifier retains the raw bulk. Thus the expert delivers the intended visual stabilization when selected; remaining extreme endpoint values are primarily classifier false negatives. @@ -212,14 +212,14 @@ Median end-to-end R fit times for the default degree-2 estimator are below. | case | $n$ | pre-PR | candidate | slowdown | |---|---:|---:|---:|---:| -| one active endpoint | 100 | 0.48 ms | 0.81 ms | 1.70x | -| one active endpoint | 1,000 | 1.51 ms | 1.96 ms | 1.29x | -| one active endpoint | 10,000 | 12.43 ms | 13.57 ms | 1.09x | -| two active endpoints | 100 | 0.51 ms | 0.87 ms | 1.71x | -| two active endpoints | 1,000 | 1.45 ms | 1.85 ms | 1.27x | -| two active endpoints | 10,000 | 10.97 ms | 11.83 ms | 1.08x | -| one-sided fallback | 100 / 1,000 / 10,000 | -- | -- | 1.09x / 1.05x / 1.02x | -| two-sided fallback | 100 / 1,000 / 10,000 | -- | -- | 1.00x / 1.01x / 1.01x | +| one active endpoint | 100 | 0.48 ms | 0.79 ms | 1.66x | +| one active endpoint | 1,000 | 1.52 ms | 1.90 ms | 1.25x | +| one active endpoint | 10,000 | 12.47 ms | 13.23 ms | 1.06x | +| two active endpoints | 100 | 0.51 ms | 0.83 ms | 1.63x | +| two active endpoints | 1,000 | 1.46 ms | 1.77 ms | 1.22x | +| two active endpoints | 10,000 | 10.97 ms | 11.40 ms | 1.04x | +| one-sided fallback | 100 / 1,000 / 10,000 | -- | -- | 1.08x / 1.03x / 1.00x | +| two-sided fallback | 100 / 1,000 / 10,000 | -- | -- | 1.00x / 0.98x / 0.99x | ## Less common paths and numerical checks diff --git a/diagnostic/boundary-examples.png b/diagnostic/boundary-examples.png index 41094497a3eb6c24df2ae970be7a1fa3a154dd5e..281cf4288417c8eab38156dfc82a2732c9e4f03a 100644 GIT binary patch literal 169415 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

?XBX&~8&;RTt(TM5r`(fyC?F|lDQ z-Ch|6EaSB3FnRurEdwK?ihS3I?D02I;AK8w77R%gcXvVMh~wWu$0!Pwe8}iu`GVBm zS;rb8VQ_^2B6dC$sUuQ0R<*c>81$U0r-KnHz@UKKMl+-m_~O8f7?zd-GPPIrEQ3PA zz4zcL1PSLPm`lJ@`v^dnTheXd4)QG>#Lo6^HMTMcR0C^fsO`|!`W5` z=LGCbhW> z;vN$oZkTM$Z~$g5E6|@~Ue1Sx5?p8a`1)ySwKjW8EZb^{*Ck=!K@n=1EdW^wdiCmZ z@fLV9Jap4R_y|h7f5YA+aOnj-qtXAIQP|{ z{7bd0wFP5}+Pq;1T5Mn=0bFPhl(=1__>bgjVQC9O;10Z0EGf7Sc&}+ej!^%%J7GDl zX4>V(cY_?+;UJ8$#^sYVgu*otwDbV-fE5Hx^xEUC4wQH-QdCS#0K!JY#sJ^~K&TJa z{&3I~LKZ#U4`32LSP4K_1#2B*V^U8ZL+Bm^vjk-U1V}gPWZYY?gAHaGJx8<92T}AC z8dC;eiN6aC!#{yRM!uQUGMFkV*e1u*dQ3q;Moc}{#&r+$2eALU>>PUTu8HKmI&w$b ze=*{B`R2>(@7`4)u$6AxsM*k}Unah*JD|P%bHn_(c_}n*SN9y4{-D16AxML`34QI= zJDPVqw=YXYDdLP&R!vZwZqEe=;d#?dIiF1}e_?XG-|1h)ltKcYJ&B{T z;u-P1>Pyyl?%YvUzC5Z-1K-U@K41pR+u@MuT;eNNwwxGGXT4w;KZMh3xudJrzKKsv z)UU9f0*b|-J6F#H&a*|}#uIQi1DM571P|WigYe+sAfMtx)%qwRgP?c7*aXR!6u}*3 z;@A!boOio-jj$B^Iv*K`geB0)MZ7mNIwO9XFmL_3V%b|MlMd(e2TuB+cYwz&Wxu4C zBM3C=Cnc1N_~JpLOlglw0n1e99D0JR|kJQIgbw<~9Lr{F#!*eN>2>IRO^2(Jf*TX-c zu1hY0C%*Ih_k>l+XL&g}_kOqAC0l<8G|q5(GfT^E2O9o|YHGI;euaEPZVcdbfWYyS zrXBU}57WqwmPcZE*SEI^t!h5YD=AUC9!|FI8w(9CJLVo24%57_umqOOE_N0*%m#kh zL2VtKdwnG}HSVjI2DpG-^hU z6?HYWxcGST9bUN|5JG}dHS6@NjIx@X9Bym}zpT1`BR~*l33(0fU>I3J+q-zEVUy3F61($8#w@%n$9k@fSflQ2xFK{Q+2r3dr5)vs^_dtVn?;HH+8^nd$i z0~;e84NWoHI0HZp&Z({z1?^U38iH=jBy)_BmoXvUZdlj`&;QG0WUUSvIB5@M z6&0VuK00>;0x@BmX-vgFOewXxau2#YaH&htHuUv69FE{34m?jnAgmpr+G{~5Ia*+N zD_Z6oN;q3?mEtkb)dd4>$-ux+ddcg(8CqD!9G*XFRb9BFeEwj<0RD$Y6D>bNkTD;3 zK`vLLn5s1q%;5GQL?4JH7qm727m9JG4}f5Q9~mjN80iItxa7A1JjFiXRCB}@Q^{WB zei#l-z;^RrXlap;D)&=vvoJ@?N6V`prL#o03xqt~$-}#Fp{BZ;)vB

^vH9pBJ{X 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

`QYj5@%z-~c?}8Tp;7;PHzhmx{H(ha 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 literal 170831 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 b!~DbU{%7#PPdR%E;>lGMH0879OoRRd8;meo