Derive censoring logprob from minimum, maximum, rounding and casting operations#8363
Open
ricardoV94 wants to merge 4 commits into
Open
Derive censoring logprob from minimum, maximum, rounding and casting operations#8363ricardoV94 wants to merge 4 commits into
ricardoV94 wants to merge 4 commits into
Conversation
ricardoV94
commented
Jul 15, 2026
Member
- Infer logprob of maximum/minimum censoring
- Infer logprob of trunc and round_half_away_from_zero rounding
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8363 +/- ##
==========================================
- Coverage 91.79% 87.42% -4.38%
==========================================
Files 128 128
Lines 21007 21068 +61
==========================================
- Hits 19283 18418 -865
- Misses 1724 2650 +926
🚀 New features to boost your workflow:
|
jessegrabowski
approved these changes
Jul 16, 2026
ricardoV94
force-pushed
the
censoring_by_another_name
branch
from
July 16, 2026 14:52
64e51bf to
c821d37
Compare
ricardoV94
marked this pull request as ready for review
July 16, 2026 15:04
ricardoV94
force-pushed
the
censoring_by_another_name
branch
from
July 16, 2026 21:05
c821d37 to
7e07d43
Compare
ricardoV94
force-pushed
the
censoring_by_another_name
branch
2 times, most recently
from
July 16, 2026 21:54
7fd1c82 to
1824e0d
Compare
The rewrite claimed any measurable base and derived the mass of the interval a continuous variable would round into. That interval is only the right one for a continuous base, and the dtype does not settle the question in either direction. A base that already sits on the integers is left untouched by every rounding, save for the upcast the Ops apply to a discrete input. Deriving the mass of the resulting degenerate cell shifted it by one: floor of a poisson(3) at 3 returned the mass of 4. Reducing the rounding to that cast instead leaves the base's own logprob to apply, and also covers a rounding of a rounding, which used to be declined. A float dtype, on the other hand, does not establish continuity, as an intermediate MeasurableVariable can be supported on the integers while carrying one. Rounding a clipped variable pooled the mass at its upper bound into the neighbouring cell and left the bound with a probability of zero: floor(clip(normal(0.5, 1), 0, 3)) at 3 returned -inf instead of log(P(x >= 3)) = -5.08. Only a RandomVariable states its own support, so other bases are now declined rather than assumed continuous.
maximum(x, c) and minimum(x, c) with a single measurable operand are rewritten to one-sided clips (both-measurable graphs are order statistics and are not claimed), reusing the existing clip machinery for the discrete and continuous cases alike. The unbounded side uses the measurable variable itself as its bound, which find_measurable_clips already understood as one-sided clipping and which, unlike +-inf constants, does not upcast discrete variables (previously one-sided clips of discrete variables failed to be claimed for this reason). Whether each side is bounded is decided once at claim time and stored on the MeasurableClip op. Clips of clips are fused eagerly into a single clip by combining the bounds with maximum/minimum (constant bounds fold), so two-sided censoring like maximum(minimum(x, ub), lb) becomes one node. logcdf/icdf are also implemented for clipped variables (the point masses at the bounds absorb the tail quantiles).
Truncation towards zero is the interval [x, x+1) for positive values, (x-1, x] for negative ones, and (-1, 1) pooled at zero. Rounding half away from zero shares the intervals of round half to even, since the tie-breaking rule only differs on a measure-zero set of the continuous base variable.
A float -> int cast rounds towards zero, so it is the `trunc` a user could have written themselves composed with a cast that only relabels the dtype. Rewriting it to that form leaves the judgement of whether the base may be truncated to `find_measurable_roundings`, and the relabelling cast is then claimed as measure-preserving. The other narrowing casts are not truncations and stay unclaimed: casting to an unsigned int wraps around for negative values (-2.7 -> 254 for uint8), and casting to bool tests `x != 0`, which collapses the support onto two points rather than partitioning it. `round_logprob` snaps the value onto the cell whose mass it asks for, and the Op it uses to do so rejects the integer value that a cast to int hands it. The snapping is an identity on such a value, so only its dtype needs adjusting.
ricardoV94
force-pushed
the
censoring_by_another_name
branch
from
July 16, 2026 22:14
1824e0d to
d69246b
Compare
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.