Skip to content

Reuse generation-time support grid across Rt Newton updates#1403

Open
ajh-oai wants to merge 4 commits into
epiforecasts:mainfrom
ajh-oai:codex/reuse-rt-newton-support-grid
Open

Reuse generation-time support grid across Rt Newton updates#1403
ajh-oai wants to merge 4 commits into
epiforecasts:mainfrom
ajh-oai:codex/reuse-rt-newton-support-grid

Conversation

@ajh-oai
Copy link
Copy Markdown

@ajh-oai ajh-oai commented May 12, 2026

Description

This PR closes #1273.

This is a focused Stan performance change in the reproduction-number to growth-rate conversion path. R_to_r() now constructs the generation-time support grid once per call and reuses it both for the mean generation-time calculation and for each Newton update, instead of rebuilding linspaced_vector(...) inside every iteration.

The existing 3-argument R_to_r_newton_step() entry point is retained as a thin wrapper so current test-facing usage remains unchanged. This stays separate from #1274, which is working on other Stan hot paths.

Benchmarks

I benchmarked the change locally with paired CmdStan runs on the package's infection-estimation workflow (example_confirmed[1:60], fixed generation time, standard incubation/reporting delays, 2 chains, 250 warmup + 250 sampling draws, seeds 101/202/303/404, order balanced across baseline and branch runs).

Metric Baseline mean Branch mean Mean paired change
infections Stan profile block 2.6146 s 2.5102 s -3.97%
CmdStan total runtime 8.9775 s 8.9130 s -0.70%

All four paired runs improved in the profiled infections block (-3.63% to -4.61%) and in total CmdStan runtime (-0.25% to -1.13%). The repository's Stan benchmark workflow should also post its standard benchmark comparison comment for this PR.

Validation

  • git diff --check
  • Local paired CmdStan benchmark described above; both baseline and branch models compiled and sampled successfully.

AI assistance disclosure

Codex helped identify the optimization seam, benchmark the candidate changes, and prepare this PR. I reviewed the final patch and benchmark results before submission.

Initial submission checklist

  • My PR is based on a package issue and I have explicitly linked it.
  • I have tested my changes locally (using devtools::test() and devtools::check()).
  • I have added or updated unit tests where necessary.
  • I have updated the documentation if required and rebuilt docs if yes (using devtools::document()).
  • I have followed the established coding standards (and checked using lintr::lint_package()).
  • I have added a news item linked to this PR.

After the initial Pull Request

  • I have reviewed Checks for this PR and addressed any issues as far as I am able.

Summary by CodeRabbit

Release Notes

  • Refactor
    • Optimised internal computation logic to reduce redundant calculations and improve processing efficiency.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

Walkthrough

The PR refactors R_to_r_newton_step to support precomputed zero_series through a new 4-argument overload, whilst the existing 3-argument version becomes a wrapper. The calling function R_to_r is updated to compute zero_series once and reuse it across multiple operations, eliminating redundant vector construction during iterative Newton updates.

Changes

Newton-step precomputation optimisation

Layer / File(s) Summary
Precomputed zero_series in Newton iterations
inst/stan/functions/rt.stan
New 4-argument R_to_r_newton_step overload accepts precomputed zero_series; existing 3-argument version refactored to wrapper that constructs zero_series and delegates to the new overload. R_to_r updated to compute zero_series once per call and reuse it for mean_gt computation and Newton iteration loop instead of recomputing inside each iteration.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: reusing the generation-time support grid across Newton updates instead of rebuilding it each iteration.
Linked Issues check ✅ Passed The pull request implements the objective from #1273 by identifying and implementing a micro-optimization that reduces vector construction overhead in iterative Stan code, improving runtime performance.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the R_to_r() and R_to_r_newton_step() functions in the Stan implementation, addressing the stated performance optimisation objective without introducing unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Co-authored-by: Codex <noreply@openai.com>
@ajh-oai ajh-oai force-pushed the codex/reuse-rt-newton-support-grid branch from 2a16124 to 9eac792 Compare May 12, 2026 17:08
@ajh-oai ajh-oai marked this pull request as ready for review May 12, 2026 17:08
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
inst/stan/functions/rt.stan (1)

84-100: ⚡ Quick win

Document the zero_series parameter.

The docstring should document all parameters of the function it precedes. Add an @param entry for zero_series to describe its purpose (the precomputed index sequence [0, 1, ..., len-1]).

📝 Suggested documentation addition
 * `@param` R Reproduction number
 * `@param` r Current estimate of the growth rate
 * `@param` pmf Generation time probability mass function (first index: 0)
+ * `@param` zero_series Precomputed index sequence (0, 1, ..., len-1) for weighted calculations
 * `@return` The Newton step for updating r
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@inst/stan/functions/rt.stan` around lines 84 - 100, Add a missing `@param` doc
for the zero_series argument in the rt_from_R Newton-step function's docstring:
describe zero_series as the precomputed index sequence (0, 1, ..., len-1) used
to align pmf and lagging terms in the calculation, and note its expected
type/length relative to pmf; update the function comment block that contains the
other `@param` entries (R, r, pmf) to include this new `@param` for zero_series so
all parameters are documented.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@inst/stan/functions/rt.stan`:
- Around line 84-100: Add a missing `@param` doc for the zero_series argument in
the rt_from_R Newton-step function's docstring: describe zero_series as the
precomputed index sequence (0, 1, ..., len-1) used to align pmf and lagging
terms in the calculation, and note its expected type/length relative to pmf;
update the function comment block that contains the other `@param` entries (R, r,
pmf) to include this new `@param` for zero_series so all parameters are
documented.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4c34eb22-cd8a-484b-9998-0c140924f8c9

📥 Commits

Reviewing files that changed from the base of the PR and between 4e30598 and 9eac792.

📒 Files selected for processing (1)
  • inst/stan/functions/rt.stan

ajh-oai and others added 2 commits May 12, 2026 10:58
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
@github-actions
Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 187de36 is merged into main:

  • ✔️default: 23s -> 24s [-4.43%, +12.94%]
  • ✔️no_delays: 25.8s -> 25.6s [-8.69%, +7.03%]
  • ✔️random_walk: 22s -> 17.9s [-169.5%, +132.35%]
  • ✔️stationary: 12.3s -> 13.8s [-1.31%, +26.07%]
  • ✔️uncertain: 1.16m -> 1.15m [-9.18%, +8.08%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

Co-authored-by: Codex <noreply@openai.com>
@github-actions
Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 9ae081f is merged into main:

  • ✔️default: 23.5s -> 33.1s [-54.31%, +135.6%]
  • ✔️no_delays: 24.2s -> 23.6s [-9.68%, +5.05%]
  • ✔️random_walk: 22.6s -> 9.52s [-131.52%, +15.59%]
  • ✔️stationary: 11.9s -> 12.4s [-9.98%, +17.63%]
  • ✔️uncertain: 1.09m -> 1.12m [-13.19%, +17.96%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

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.

improve performance of Stan code

1 participant