Repository navigation
Use a relative tolerance in is_constant - #469
Merged
Merged
Conversation
|
This is how benchmark results would change (along with a 95% confidence interval in relative change) if 641e907 is merged into master:
|
florence-bockting
approved these changes
Oct 15, 2026
florence-bockting
left a comment
Collaborator
There was a problem hiding this comment.
Thank you. Looks good to me. I just added a bullet point in the NEWS.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was assisted by Claude
Summary
is_constant()uses an absolute tolerance:abs(max(x) - min(x)) < .Machine$double.eps. Draws whose values all have a small magnitude are then treated as constant, and the diagnostics that callshould_return_NA()oris_constant()returnNA. The result depends on the units of the variable.This PR makes the tolerance relative to the largest absolute value in
x. The diagnostics then give the same result forxands * x.Problem
ess_sd()works on squared deviations, so it already fails for draws with a standard deviation of about1e-8or less. Examples are parameters in SI units and natural-scale importance weights.The affected functions call
should_return_NA()oris_constant()on the raw draws:rhat_basic(),ess_basic(),ess_mean(),ess_sd(),ess_quantile()and the functions that use it (ess_tail(),ess_median()), themcse_*()functions,rhat_nested(),pareto_khat(),pareto_diags(),pareto_smooth(),ps_tail()andpareto_pit(). Thussummarise_draws()with the default measures showsess_tail = NAfor such a variable.rhat()andess_bulk()are not affected, because they call the check on rank-normalized values. With the samexands = 1e-100, master givesNAforess_tail(),ess_median()andmcse_mean(), and this PR gives 385.2, 330.3 and1e-100times 0.109, the same as forx.Change
xis constant ifmax(x) - min(x) <= tol * max(abs(x)). The result does not depend on the scale ofx.xwith all values equal is constant, also when all values are 0 or all are-Inf. On master, all-InfgaveNA.xwith an infinite spread, for examplec(-Inf, 2), is not constant, the same as on master.xwithNAgivesNA, the same as on master.tolnow says that it is relative.Other behavior change: for values of magnitude above 1, values that differ by about 1 ulp are now constant. For example,
is_constant(c(1, 1 + .Machine$double.eps))isTRUE(on masterFALSE). For magnitudes of 2 or more, master treated values that differ by 1 ulp as different, because 1 ulp is then larger than.Machine$double.eps.Tests
tests/testthat/test-convergence.R:is_constant uses a tolerance relative to the magnitude of x: zeros, small constant values,-Inf, 1-ulp differences, small values that differ, infinite spread,NA.convergence diagnostics do not depend on the scale of the draws:rhat_basic(),ess_basic(),ess_mean(),ess_quantile()andrhat_nested()fors = 1e-10and1e-100, andess_sd()fors = 1e-10and1e-50. Fors = 1e-100, the autocovariance of the squared deviations is of orders^4and underflows.tests/testthat/test-pareto_smooth.R:pareto diagnostics and smoothing do not depend on the scale of the draws:pareto_khat(),pareto_diags(),pareto_smooth()andps_tail()fors = 1e-20and1e-200.tests/testthat/test-pareto_pit.R:pareto_pit does not depend on the scale of the draws, fors = 1e-20and1e-200.On unpatched master, the new tests give 22 failed expectations: 12 in
test-convergence.R, 8 intest-pareto_smooth.Rand 2 intest-pareto_pit.R. With this PR, all tests pass.Effect on other input
On master and with this PR, these results are identical:
summarise_draws(example_draws()), with the default measures and withdefault_convergence_measures().summarise_draws()withdefault_convergence_measures()for draws1e10 + rnorm()and for Poisson draws (integer values with ties).pareto_khat(example_draws())andpareto_pit(example_draws(), rep(1, 10)).Related
#468 (removes the offset at a tied Pareto tail cutoff). That PR makes the Pareto smoothing independent of the scale of the tail excesses. This PR does the same for the checks for constant input.
Tested versions
master6dd1e12383.devtools::test(): 2253 tests, 0 failures, 0 errors, 0 warnings, 4 skips (gbmis not installed).man/is_constant.Rdis generated with roxygen2 8.0.0. This PR does not include the changes that roxygen2 8.0.0 makes to other Rd files and toDESCRIPTION, because the package usesRoxygenNote7.3.3.Copyright and Licensing
By submitting this pull request, the copyright holder is agreeing to
license the submitted work under the following licenses: