Added
- New election methods:
- `SimultaneousVeto`, which supports `'first_place'`, `'uniform'`, `'borda'`, and `'harmonic'` candidate weighting schemes. (PR 333)
- `SerialVeto`, a variant of `PluralityVeto`. Both are now subclasses of a shared `SequentialVeto` base class. (PR 325)
- `Schulze`, implementing the Schulze/beatpath method. (PR 320, closes 318)
- `AlbanySTV`, `FastIRV`, and `FastSequentialRCV`, built on the new `NumpyInnerSTV` abstract base class. (PR 249)
- `STVAnimation`, a new module for visualizing STV elections as animations via the optional `manim` dependency.
Supports light/dark mode, custom color palettes, candidate nicknames, and inline notebook rendering. (PR 249)
- A `strict` parameter to `PairwiseComparisonGraph.get_condorcet_cycles` for detecting strict Condorcet cycles. (PR 330, closes 327)
- An `allow_zero_support_candidates` parameter to `BlocSlateConfig`. (PR 338, closes 298)
- Docstrings for all spatial ballot generator models. (PR 329, closes 328)
- `go-task` task runner and updated contributing guide. (PR 342, closes 277)
Changed
- Renamed the `m` parameter to `n_seats` in all election classes and in `r_representation_score`.
Old names still accepted via `**kwargs` with a `DeprecationWarning`. (PR 355)
- Renamed `BlocPlurality` to `BlockPlurality`. `BlocPlurality` still works but is now deprecated. (PR 355)
- Renamed parameters in the score election classes (old names still accepted with deprecation warnings): (PR 355)
- `GeneralRating`: `m` → `n_seats`, `k` → `per_candidate_limit`, and added `budget`.
- `Cumulative` and `Limited`: `m` → `n_seats`, `k` → `budget`.
- Overhauled `PluralityVeto`: `tiebreak=None` is no longer accepted (default `'first_place'`,
backup `'lex'`), added a `tiebreak_order` attribute, ~50-60x faster for deterministic
tiebreaks, and unranked candidates are now eligible to be vetoed. (PR 325)
- Refactored `BlocSlateConfig` to reduce nesting; `get_preference_interval_for_bloc_and_slate`
now only validates the target bloc/slate. (PR 338, closes 299)
- Restructured STV as a subpackage; refactored `NumpyElection` into the abstract base class
`NumpyInnerSTV`. Removed `ElectionCore`, `STVCore`, and `NumpyElection`. (PR 249)
- Migrated to `uv` for package management and `go-task` for task running.
Replaced `black`/`isort`/`mypy` with `ruff`/`ty`. (PR 342, 352)
- `PreferenceProfile.to_csv` now uses integer IDs instead of shortened prefix strings
for candidate labels. Old-format CSVs are still readable. (PR 361)
- `to_csv` now accepts `fpath=None` (the default) to return CSV content as a string
instead of writing to disk.
- `BlockPlurality` now accepts both `RankProfile` and `ScoreProfile`. (PR 360, closes 351)
- `RankingElection` validates non-empty profiles and sufficient candidates for seats. (PR 360, closes 356)
- Pre-commit hooks now only run on staged files. (PR 360)
- Tests now run in parallel via `pytest-xdist` (`-n auto`).
Fixed
- Issues 309, 325, 334, 338, 339, 348, 350, 351, 356