Skip to content

Extract stateless IRV tabulation helpers - #61

Merged
fsargent merged 2 commits into
mainfrom
refactor/irv-tabulation-helpers
Jul 17, 2026
Merged

Extract stateless IRV tabulation helpers#61
fsargent merged 2 commits into
mainfrom
refactor/irv-tabulation-helpers

Conversation

@fsargent

@fsargent fsargent commented Jul 17, 2026

Copy link
Copy Markdown
Member

Summary

  • extract preference counting, elimination, vote ranking, and result conversion into pure module functions
  • retain the existing Irv method API through static aliases
  • replace the mutable keep={} default with None
  • add focused helper-level regression coverage

Stack

Depends on #60. Retarget this PR to main after its parent merges.

Validation

  • uv run python -m pytest (45 passed)
  • trunk check

Summary by Sourcery

Extract stateless IRV tabulation helpers into module-level functions while preserving the existing Irv method API via static aliases.

Enhancements:

  • Refactor IRV preference counting, candidate elimination, vote aggregation, and result conversion into pure helper functions reused by the Irv class.
  • Adjust the IRV least-candidate helper to use a None default instead of a mutable set for the keep parameter.
  • Expose the new IRV tabulation helpers for reuse in other parts of the codebase.

Tests:

  • Add regression tests that exercise the IRV tabulation helper functions directly to ensure stateless behavior and correct vote tabulation.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sourcery-ai

sourcery-ai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Reviewer's Guide

Extracts IRV tabulation logic into stateless module-level helpers while preserving the existing Irv API via static aliases and adds focused regression tests for the helpers and keep semantics.

File-Level Changes

Change Details Files
Refactor IRV tabulation logic from instance methods into stateless module-level helper functions and wire them back into the Irv class via static method aliases.
  • Introduce build_preference_schedule, eliminate_candidate, candidate_votes, least_candidate, rank_vector_to_preference, and finish_order_to_results as pure functions operating on ballots, preference schedules, and finish orders.
  • Replace Irv.buildPreferenceSchedule, Irv.eliminateCandidate, Irv.candidateVotes, Irv.getLeast, Irv.rankVectorToPreference, and Irv.finishOrderToResults implementations with staticmethod aliases to the new helpers.
  • Normalize least_candidate keep parameter semantics by replacing the mutable dict default with a None default and handling it as an empty tuple internally.
src/vse_sim/methods/irv.py
Add regression tests that exercise the new stateless IRV helper functions and ensure existing behavior and contracts are preserved.
  • Import CandidateWithCount and the new IRV helper functions into the regression test module.
  • Add test_irv_tabulation_helpers_are_stateless to validate preference schedule building, candidate vote ranking (including alternates with zero votes), least-candidate selection with and without keep, and candidate elimination aggregation.
  • Keep existing IRV regression tests intact to validate overall results and strategy contracts.
tests/test_regressions.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7b1f830e-3e92-431d-b3c2-c14a9edb7ee1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/irv-tabulation-helpers

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.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • Consider normalizing the eliminate_candidate API so it either always accepts a candidate ID or always requires CandidateWithCount, rather than silently returning the input when given the wrong type, to make misuse easier to detect.
  • In least_candidate, you might want to document or enforce that keep is a set-like collection for efficient membership checks, since callers could currently pass slower container types without realizing the cost.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider normalizing the `eliminate_candidate` API so it either always accepts a candidate ID or always requires `CandidateWithCount`, rather than silently returning the input when given the wrong type, to make misuse easier to detect.
- In `least_candidate`, you might want to document or enforce that `keep` is a set-like collection for efficient membership checks, since callers could currently pass slower container types without realizing the cost.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@fsargent
fsargent changed the base branch from refactor/ranked-method-base to main July 17, 2026 22:33
@fsargent
fsargent merged commit 0f9d1a5 into main Jul 17, 2026
2 checks passed
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