Votekit

Latest version: v3.5.0

Safety actively analyzes 993520 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 1 of 3

3.5.0

Added

- `sum_profiles` utility to sum a list of profile of `RankProfile` or `ScoreProfile`
objects. (PR 369)
- `search_profile_for_rank_pattern` queries rank profiles for strict ranking orders and
candidate pair clones within a certain distance. `include_unranked` flag treats
unranked candidates as tied last. (PR 373)
- `sort_candidates_pseudo_lexicographically` sorts integer and string candidates
canonically by numeric value or ASCII order. (PR 370)
- `sort_strengths_descending` parameter added to `PreferenceInterval.from_dirichlet`
assigns preference strengths in descending order to the `candidates` list when True.
- `rng_seed` parameter added to all public APIs with randomness. Pass an integer for
reproducible results or `None` for non-deterministic. (PR 375)
- `STV`, `IRV`, and `SequentialRCV` support opt-in exact rational arithmetic with `exact=True`
and `fractions.Fraction` ballot weights, part of the broader rational support tracked in
issue 358. Exact mode includes Borda and first-place tiebreak scoring and permits custom
transfer methods, which are responsible for preserving exact weights. `FastSTV` and the other
numpy-based classes remain on their existing numeric paths.

Changed

- `RankBallot` accepts bare singleton values in `ranking` (no need to wrap single
candidates in an iterable). (PR 368)
- `Ballot`, `PreferenceProfile`, and `BlocSlateConfig` classes accept integer and/or
string candidates. Ballot generators, election methods, plots, and utilities are
updated accordingly. A `UserWarning` is raised when a string/integer candidate pair
would collide if cast (e.g. `"1"` and `1`), and a separate `UserWarning` is raised
in plots when two candidates are indistinguishable as strings. (PR 370)
- `PreferenceProfile.to_csv` updated to v2 format to support integer candidates.
Candidates encoded as `name:type:id`. Old format CSVs remain readable via
`PreferenceProfile.from_csv`, which casts candidates to their labeled types in v2
files. (PR 370)
- `":"` is not allowed within candidate names due to breaking
`PreferenceProfile.from_csv`. (PR 370)
- Internal `RankProfile` and `ScoreProfile` DataFrames (`_df`) store candidate sets
and candidates as their integer IDs. `candidate_id_map` and `id_candidate_map`
attributes are added. Public `df` property translates back to original candidate
names. (PR 370)
- Randomly sampled sets are now canonically ordered, ensuring results are stable
across processes regardless of `PYTHONHASHSEED`. (PR 375)

Fixed

- Issues 326, 331, 347, 353, 357, 359,

3.4.0

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

3.3.1

Added

Changed

- implemented speed improvements to sBT, sPL, and CS
- refactored ballot generator tests

Fixed

- fixed a floating point error in STV transfers (311)
- fixed a cohesion issue in Cambridge sampler (313)

3.3.0

Added

- Created a `BlocSlateConfig` class for ballot generators. This validates that all of the inputs to a ballot generator are valid.
- `FastSTV`, a new implementation of the `STV` class that relies more heavily on numpy and should be faster.
- `RankBallot` and `RankProfile`, and `ScoreBallot` and `ScoreProfile`, now allowing us to distinguish between the two types of input. The old
`PreferenceProfile` and `Ballot` constructors still work and create instances of `Rank` and `Score` for you.
- `RankedPairs`, `StarVoting` and `OpenList`, all new election methods.

Changed

- refactored the codebase to use the new updates.
- deprecated the ballot generator classes in favor of functions.
- `PreferenceProfile` and cvr imports can now use urls.

Fixed

- Issues 252, 229, 258, 248, 164, 205, 269, 233, 169, 285, 282, 238, 303, 302

3.2.2

Added

Changed

Fixed

- fixed an error with the `STV` class. In edge cases where not enough candidates receive votes to pass threshold, the class was not properly counting the number of remaining candidates.

3.2.1

Added

Changed

- removed the `PreferenceProfile` warning raised when `max_ranking_length>0` but no rankings provided.
We have decided an empty profile can still have positive max ranking length.

Fixed

- fixed an error raised by an empty ranking of `~` symbols being passed to `utils.ballots_by_first_cand` .

Page 1 of 3

© 2026 Safety CLI Cybersecurity Inc. All Rights Reserved.