Skip to content

runoff: reuse IRV Numba tally helpers for head-to-head round#46

Open
endolith wants to merge 6 commits into
masterfrom
cursor/runoff-irv-tally-c8f5
Open

runoff: reuse IRV Numba tally helpers for head-to-head round#46
endolith wants to merge 6 commits into
masterfrom
cursor/runoff-irv-tally-c8f5

Conversation

@endolith

@endolith endolith commented May 11, 2026

Copy link
Copy Markdown
Owner

Closes #3.

Summary

The contingent-vote / top-two runoff second round used a Python loop with list.index per ballot. That round is equivalent to instant runoff among only the two finalists: skip every other candidate on each ballot, then count first preference among {finalist_0, finalist_1}. That is exactly what _inc_rank_idx + _tally_at_rank_idx do—the same Numba path IRV and Coombs use.

Changes

elsim/methods/runoff.py

  • Replace the per-ballot list.index head-to-head tally with _inc_rank_idx / _tally_at_rank_idx.
  • Build an eliminated_mask (all candidates except the two finalists) and advance each voter's rank cursor past eliminated candidates before tallying.
  • Uses the same boolean-mask API as IRV/Coombs after master dropped reflected Python set in Numba helpers.

tests/test_runoff.py

  • test_docstring_example: exercises the contingent-vote example from the runoff() docstring.
  • test_head_to_head_tally_via_irv_helpers: asserts the shared helpers produce the expected 3–2 split when only finalists A and B remain.

Rebase notes

Rebased onto current master. The original PR passed a Python set into _inc_rank_idx; master now requires a boolean eliminated_mask ndarray, so the second commit updates runoff accordingly.

Testing

  • pytest: 217 passed locally (with [fast] / Numba).
  • Existing runoff property tests (Hypothesis) unchanged and still pass.
Open in Web Open in Cursor 

@what-the-diff

what-the-diff Bot commented May 11, 2026

Copy link
Copy Markdown

PR Summary

  • New Import Functions Introduced: The code now includes two new import functions called _inc_rank_idx and _tally_at_rank_idx from the _common module. These tools help streamline the process of updating ranks and tallying votes.

  • Improved Vote Counting Process: The logic behind counting votes for two options, finalist_0 and finalist_1, has been refined. It now uses a method from the library NumPy, which simplifies calculations and makes the process more efficient than the former looping method.

  • Introduction of eliminated_cands Set: A new set, eliminated_cands, was added. This serves as a check list to keep track of candidates who are no longer under consideration.

  • Maximized use of New Methods: The newly added functions _inc_rank_idx and _tally_at_rank_idx are now being utilized for updating ranking index and tallying votes respectively. This change was made to make the overall workflow more efficient and reliable.

@codecov

codecov Bot commented May 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.39%. Comparing base (3249c6c) to head (4b7478a).

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #46      +/-   ##
==========================================
+ Coverage   96.37%   96.39%   +0.02%     
==========================================
  Files          17       17              
  Lines         496      499       +3     
==========================================
+ Hits          478      481       +3     
  Misses         18       18              
Flag Coverage Δ
no-numba 95.79% <100.00%> (+0.02%) ⬆️
numba 88.17% <100.00%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

dependabot Bot and others added 6 commits May 29, 2026 00:53
Bumps [https://github.com/astral-sh/ruff-pre-commit](https://github.com/astral-sh/ruff-pre-commit) from v0.15.14 to 0.15.15.
- [Release notes](https://github.com/astral-sh/ruff-pre-commit/releases)
- [Commits](astral-sh/ruff-pre-commit@v0.15.14...v0.15.15)

---
updated-dependencies:
- dependency-name: https://github.com/astral-sh/ruff-pre-commit
  dependency-version: 0.15.15
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
…hub.com/astral-sh/ruff-pre-commit-0.15.15

Bump https://github.com/astral-sh/ruff-pre-commit from v0.15.14 to 0.15.15
Bumps [https://github.com/astral-sh/ruff-pre-commit](https://github.com/astral-sh/ruff-pre-commit) from v0.15.15 to 0.15.16.
- [Release notes](https://github.com/astral-sh/ruff-pre-commit/releases)
- [Commits](astral-sh/ruff-pre-commit@v0.15.15...v0.15.16)

---
updated-dependencies:
- dependency-name: https://github.com/astral-sh/ruff-pre-commit
  dependency-version: 0.15.16
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
…hub.com/astral-sh/ruff-pre-commit-0.15.16

Bump https://github.com/astral-sh/ruff-pre-commit from v0.15.15 to 0.15.16
Second-round contingent vote compares two finalists by whoever appears
first on each ballot. That matches advancing each voter's rank index past
all non-finalists then tallying at that rank—the same _inc_rank_idx and
_tally_at_rank_idx path IRV uses.

Co-authored-by: endolith <endolith@gmail.com>
Master replaced reflected-set elimination with a boolean mask in
_inc_rank_idx. Update the head-to-head round to match IRV/Coombs and add
tests for the docstring example and direct tally-helper behavior.

Co-authored-by: endolith <endolith@gmail.com>
@cursor cursor Bot force-pushed the cursor/runoff-irv-tally-c8f5 branch from f66b32a to 4b7478a Compare June 12, 2026 19:04
@cursor cursor Bot marked this pull request as ready for review June 12, 2026 19:10
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.

runoff can use the tally functions from IRV

2 participants