feat: add piecewise-constant hazard multiplier and gate - #110
Conversation
Try this Pull Request!Option 1: Julia Package ManagerOpen Julia and type: import Pkg
Pkg.activate(temp=true)
Pkg.add(url="https://github.com/EpiAware/ModifiedDistributions.jl", rev="feat/piecewise-hazard-105")
using ModifiedDistributionsOption 2: Local CheckoutIf you have the repo locally: git checkout feat/piecewise-hazard-105
julia --project=. -e "using Pkg; Pkg.instantiate()" |
|
📖 Documentation preview is ready! View the docs for this PR at: https://EpiAware.github.io/ModifiedDistributions.jl/previews/PR110/ This preview will be updated automatically when you push new commits. |
Codecov Report❌ Patch coverage is
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
Triage: blocked behind #108, which is itself blocked on a maintainer ruling. Please do not merge yet; nothing here needs changing. Two separate blocks:
One point specifically for that ruling rather than for this PR's author: #105 asks for a gated leaf to "emit the same sub-stochastic marginal type the algebra defines for defective laws rather than a private flat-survival object". The CI note: the only failing required-ish check was This was opened by a bot. Please ping @seabbs for any questions. |
|
As flagged on the other PR sonds like we need a new package to hold some concepts for dependong on or we need to move this to composeddistributions |
piecewise_effect(; breaks, multipliers) is a piecewise-constant proportional-hazards multiplier for modify under the log link, with a closed-form cumulative hazard (a sum of base log-survival differences over segments) rather than the numeric quadrature path a callable effect(t) always takes. Segment i applies from breaks[i-1] up to (but not including) breaks[i], matching the right-continuous step-function convention the issue's own illustrative example uses. gate(dist, opens, closes) is a finite-window special case (multipliers 0/1/0 at the opens/closes breakpoints): the hazard is off before opens, runs unmodified inside the window, and switches off again at closes, leaving a deliberately sub-stochastic law whose residual "never occurred" mass reads through total_mass/is_defective (#107) like any other defective wrapper. Stacked on the not-yet-merged #107 branch (PR #108) since gate reuses its total_mass/is_defective accessor directly; total_mass gets one additional dispatch for the piecewise path (exact when the trailing multiplier is zero, the general numeric search otherwise). Closes #105. Co-authored-by: Sam Abbott <contact@samabbott.co.uk>
f0b9c68 to
e823f17
Compare
Summary
piecewise_effect(; breaks, multipliers): a piecewise-constantproportional-hazards multiplier for
modifyunder the log link, witha closed-form cumulative hazard (a sum of base log-survival
differences over segments) — no quadrature backend needed, unlike a
callable
effect(t), which always falls to the numeric path. Segmentiapplies on[breaks[i-1], breaks[i])(right-continuous: abreakpoint value belongs to the segment it opens, matching the
issue's own
t < 1.0 ? ... : ...illustrative convention).gate(dist, opens, closes): the finite-window special case(multipliers
0/1/0at the two breakpoints) — hazard off beforeopens, the base's own hazard inside the window, off again aftercloses. This deliberately produces a sub-stochastic law; itsresidual "never occurred" mass reads through
total_mass/is_defective(Queryable sub-stochastic laws: total_mass and is_defective #107) exactly like any other defective wrapper, perthe issue's ask.
quantile/randuse the same monotone-bisection pattern alreadyestablished for the identity/numeric paths (no new numeric idiom).
support minimum, multipliers, breakpoints, base survival) together,
so a
Dual/tracked multiplier or breakpoint differentiates cleanlywithout narrowing back to
Float64mid-loop.Stacking / history
This was originally stacked on
feat/total-mass-defective-107(PR #108), since
gate's defective-law behaviour builds directly onthat PR's
total_mass/is_defectiveaccessor rather than duplicatingit. #108 has since merged, so this PR has been rebased onto
mainand re-targeted at it: the diff is now just the piecewise/gate additions
on top of the merged #107/#108 accessors. A stale
NEWS.mdbullet fromthe original branch was dropped during the rebase —
mainnow tracksrelease notes via GitHub Releases, so merged-PR bodies auto-document
the change.
Scope notes
mean/varare not defined for the piecewise path, matching theexisting precedent for the numeric/callable-effect path (also
undefined) — no analytic partial-moment machinery exists generically
in this package yet.
test/ad/ADFixtures(the six-backend AD sweepregistry); gradient correctness is verified directly via targeted
ForwardDifftests in this PR instead. Could be added as afollow-up if the maintainers want the full backend matrix on this
surface too.
out of scope —
piecewise_effect's machinery isn't a drop-in forthat issue (it needs the CD#252 epic's tree-level defective-law
primitives, not just a modifier-level closed form), so nothing here
builds ahead of it.
Closes #105.
Test plan
task test-fast— 2309/2309 pass (post-rebase againstmain):piecewise_effectvalidation, log-link-only enforcement, closed formchecked against a brute-force trapezoidal cumulative hazard, the
right-continuous segment-boundary convention, pdf/cdf/ccdf
consistency and properness, quantile/rand round-trip,
gate'sdefective-law behaviour (survival flat before
opensand aftercloses,total_mass/is_defective, a beyond-mass quantilethrowing).
task test-quality— Aqua/formatting/JET/doctests pass (116/116).task test-ad— all AD backends pass (1386/1386).This was opened by a bot. Please ping @seabbs for any questions.