Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle truncation endpoints equal to support endpoints #1730

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ararslan
Copy link
Member

Consider truncated(Normal(), -Inf, Inf). Currently, this returns a Truncated-wrapped Normal. However, truncating a normal distribution to ±∞ is... not actually truncating it at all. We handle this case when the bounds are specified as nothing and return the untruncated distribution, but not when one or both bounds are equal to or beyond the respective bounds of the support. If we recode lower <= minimum(d) and/or upper >= maximum(d) to nothing, we're able to avoid a Truncated wrapper in more cases. And when we do make a Truncated, equivalent truncations can now compare equal and hit the same code paths for dispatch on the truncation using nothing as appropriate.

Two things to note with this implementation:

  • truncated(d::D, a, b) is no longer type stable since it can now return either a D or a Truncated{D} whereas before it only returned a D if a === b === nothing.
  • Nonsensical truncation, e.g. truncated(Poisson(), -10, -1), still works and is still nonsensical.

Consider `truncated(Normal(), -Inf, Inf)`. Currently, this returns a
`Truncated`-wrapped `Normal`. However, truncating a normal distribution
to ±∞ is... not actually truncating it at all. We handle this case when
the bounds are specified as `nothing` and return the untruncated
distribution, but not when one or both bounds are equal to or beyond
the respective bounds of the support. If we recode `lower <= minimum(d)`
and/or `upper >= maximum(d)` to `nothing`, we're able to avoid a
`Truncated` wrapper in more cases. And when we do make a `Truncated`,
equivalent truncations can now compare equal and hit the same code paths
for dispatch on the truncation using `nothing` as appropriate.

Two things to note with this implementation:
- `truncated(d::D, a, b)` is no longer type stable since it can now
  return either `D` or `Truncated{D}` whereas before it only returned
  `D` if `a === b === nothing`.
- Nonsensical truncation, e.g. `truncated(Poisson(), -10, -1)`, still
  works and is still nonsensical.
@ararslan ararslan requested a review from devmotion May 28, 2023 19:38
@codecov-commenter
Copy link

codecov-commenter commented May 28, 2023

Codecov Report

Patch coverage: 100.00% and project coverage change: -0.01 ⚠️

Comparison is base (2dee35e) 85.90% compared to head (d40fa49) 85.90%.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1730      +/-   ##
==========================================
- Coverage   85.90%   85.90%   -0.01%     
==========================================
  Files         142      142              
  Lines        8566     8575       +9     
==========================================
+ Hits         7359     7366       +7     
- Misses       1207     1209       +2     
Impacted Files Coverage Δ
src/truncate.jl 89.16% <100.00%> (+0.87%) ⬆️

... and 1 file with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

Copy link
Member

@devmotion devmotion left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see why this behaviour might be convenient (and this approach actually came up in some discussion in a private downstream repo not too long ago). But currently I think that

truncated(d::D, a, b) is no longer typestable

is a major drawback, and that the increased convenience does not justify making truncated type unstable. In particular, since users can easily avoid these problems by specifying correct bounds or nothing (or, IMO more conveniently, the keyword argument syntax).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants