Skip to content

Ci#1

Closed
juanitorduz wants to merge 17 commits intomainfrom
ci
Closed

Ci#1
juanitorduz wants to merge 17 commits intomainfrom
ci

Conversation

@juanitorduz
Copy link
Copy Markdown
Owner

@juanitorduz juanitorduz commented Nov 29, 2025

Note

Introduces CI and improves core distribution utilities.

  • CI: New GitHub Actions workflow ci.yml running pre-commit and test matrix on Python 3.13 with coverage output.
  • BetaBinomial: Refines mode to handle edge cases (monotone/unimodal/undefined) with broadcasting-safe logic; unchanged ppf delegates to improved discrete PPF.
  • Discrete PPF: In distributions/optimization.py, adds _is_scalar_param and _should_use_bisection to choose between direct search over bounded support vs. bisection for wide/unbounded cases; keeps bounds handling and improves performance/readability.
  • Tests: Expands betabinomial cases (including non-unique modes via skip_mode), adjusts logitnormal parameters for numerical stability, and relaxes wald SF/logCDF tolerances slightly.
  • Tooling: Adds optional test extras in pyproject.toml, pytest addopts, switches pre-commit to ruff-check, and updates .gitignore for coverage artifacts.

Written by Cursor Bugbot for commit 3172720. This will update automatically on new commits. Configure here.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

first_idx = pt.argmax(exceeds_q, axis=0)
result = k_vals[first_idx]

return ppf_bounds_disc(result, q, lower, upper)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unreachable dead code after return statement

Medium Severity

The find_ppf_discrete function has unreachable code after line 128. The function returns at line 128 with return ppf_bounds_disc(result, q, lower, upper), but lines 129-133 contain leftover code from the previous implementation that will never execute. This appears to be dead code that was not removed during refactoring.

Fix in Cursor Fix in Web

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.


Logit-normal mode formula returns median instead

Medium Severity

The mode function returns _expit(mu) which is mathematically the median of the logit-normal distribution, not the mode. The mode of a logit-normal distribution depends on both mu and sigma and requires solving a transcendental equation — it has no simple closed form. The current formula is only correct in the limiting case where sigma approaches zero.

distributions/logitnormal.py#L30-L32

def mode(mu, sigma):
return _expit(mu)

Fix in Cursor Fix in Web


Von Mises PPF returns infinity at finite boundaries

Medium Severity

The von_mises_ppf function returns ±inf for q=0 and q=1, but the von Mises distribution has finite support [-π, π]. Following the pattern used by other distributions in this codebase (e.g., beta.py uses ppf_bounds_cont with finite bounds), ppf(0) should return and ppf(1) should return π. This causes incorrect results when querying the PPF at boundary quantiles.

distributions/optimization.py#L169-L171

result = pt.switch(q > 1, pt.nan, result)
result = pt.switch(pt.eq(q, 0), -pt.inf, result)
result = pt.switch(pt.eq(q, 1), pt.inf, result)

Fix in Cursor Fix in Web


# Array case - need broadcasting
exceeds_q = pt.ge(cdf_vals[:, None], q[None, :] - eps)
first_idx = pt.argmax(exceeds_q, axis=0)
result = k_vals[first_idx]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Direct search doesn't handle multi-dimensional q arrays

Low Severity

The _should_use_bisection function checks if params are non-scalar but doesn't check the shape of q. When q has ndim > 1 (multi-dimensional), the direct search path is incorrectly used. The array case broadcasting logic (cdf_vals[:, None] with q[None, :]) assumes q is 1D and would fail or produce incorrect results for higher-dimensional q arrays. The previous implementation always used bisection which handles any q shape correctly.

Additional Locations (1)

Fix in Cursor Fix in Web

@juanitorduz juanitorduz deleted the ci branch January 15, 2026 08:02
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.

1 participant