Recent Releases of VoteKit

VoteKit - v3.2.2

This minor patch fixes 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.

Scientific Software - Peer-reviewed - Python
Published by cdonnay 8 months ago

VoteKit - v3.2.1

What's 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 an error raised by an empty ranking of ~ symbols being passed to utils.ballots_by_first_cand.

Scientific Software - Peer-reviewed - Python
Published by cdonnay 8 months ago

VoteKit - v3.2.0

[3.2.0] - 2025-06-13

Added

  • created a PreferenceProfile.df attribute that is a pandas DataFrame representation of the profile. The df is in bijection with the profile, and using the df allows for great speed improvements throughout the codebase.
  • a new tutorial notebook replicating the Portland, OR election case study.
  • added a to_pickle and from_pickle method to PreferenceProfile.

Changed

  • separated the computation of the pairwise comparison dictionary from the pairwise comparison graph.
  • renamed dominating_tiers method of pairwise comparison graph to get_dominating_tiers.
  • renamed cleaning.deduplicate_profile to cleaning.remove_repeated_candidates.
  • moved remove_cand from utils to cleaning, and removed the older function remove_noncands.
  • renamed PreferenceProfile.condense_ballots() to PreferenceProfile.group_ballots().
  • removed Ballot.id attribute.
  • rewrote many cleaning functions and utilities to use the underlying dataframe of PreferenceProfile for speed improvements.
  • removed the use of Fraction and use floats instead for speed improvement.
  • altered the various plotting functions for profiles, now in the plots.profiles module.

Fixed

  • PreferenceProfile.group_ballots() now also groups the voter_set attribute of ballots.

Scientific Software - Peer-reviewed - Python
Published by cdonnay 9 months ago

VoteKit - v3.1.0

This is a minor update to VoteKit that includes some new election analysis tools, some refactored visualization code for bar plots, and a minor tweak to how scores are computed from ranked ballots to allow for different averaging conventions for ties.

Added

  • added support for three types of averaging conventions within score_profile_from_rankings: average, low, and high.
  • r-representation scores: compute how "satisfied" voters are with a given winners set.
  • matrices: create three kinds of matrices based on profiles: boost, mentions, and average distance. Accompanying heatmap code that plots them.
  • support for Python 3.12, 3.13
  • contributing guidelines and community resources to our docs.

Changed

  • changed the default Borda scoring to use low averaging, where tied rankings receive the lowest possible points
  • changed the sampling method for boosted_random_dictator and random_dictator to more clearly use the first place votes distribution
  • changed the structure of plot_summary_stats. Is now split into many functions, all called profile_STAT_plot or multi_profile_STAT_plot, where STAT can be fpv, borda, mentions, and ballot_lengths. Built on top of more general bar_plot and multi_bar_plot functions.
  • removed support for Python 3.9.

New Contributors

  • @wkirby made their first contribution in https://github.com/mggg/VoteKit/pull/153

Full Changelog: https://github.com/mggg/VoteKit/compare/v3.0.0...v3.1.0

Scientific Software - Peer-reviewed - Python
Published by cdonnay 12 months ago

VoteKit - v3.0.0

This is a major update to VoteKit that includes some breaking changes for the API and a major refactoring of the code base to make it more organized, maintainable, and (hopefully) easier to contribute to in the future.

Added

  • The election methods thanks to @kevin-q2. The newest election methods are PluralityVeto, RandomDictator, and BoostedRandomDictator.
  • More comprehensive tests for the Ballot class.
  • More comprehensive tests for all of the election types.
  • More comprehensive tests for the PreferenceProfile class.
  • Tests for potential errors in the BallotGenerator classes.

Changed

  • Moved the following election methods to sorted folders in src/votekit/elections/election_types:

    • approval
      • Approval
      • BlockPlurality
    • ranking
      • RankingElection
      • Alaska
      • BoostedRandomDictator
      • Borda
      • CondoBorda
      • DominatingSets
      • PluralityVeto
      • Plurality
      • SNTV
      • RandomDictator
    • scores
      • GeneralRating
      • Limited
      • Rating
      • Cumulative
  • Updated / added the following methods to src/votekit/utils.py:

    • ballots_by_first_cand
    • remove_cand
    • add_missing_cands
    • validate_score_vector
    • score_profile
    • first_place_votes
    • mentions
    • borda_scores
    • tie_broken_ranking
    • score_dict_to_ranking
    • elect_cands_from_set_ranking
    • expand_tied_ballot
    • resolve_profile_ties
  • Changed the way that the ElectionState class operates. It now operates as a dataclass storing the following data:

    • round_number: The round number of the election.
    • remaining: The remaining candidates in the election that have not been elected.
    • elected: The set of candidates that have been elected.
    • eliminated: The set of candidates that have been eliminated.
    • tiebreak_winners: The set of candidates that were elected due to a tiebreak within a round.
    • scores: The scores for each candidate in the election.
  • The PreferenceProfile class is now a frozen dataclass with the idea being that, once the ballots and candidates for an election have been set, they should not be changed.

    • Several validators have also been added to the PreferenceProfile class to ensure that the ballots and candidates are valid.
  • Updated all documentation to reflect major changes in the API of the package.

New Contributors

  • @kevin-q2 made their first contribution in https://github.com/mggg/VoteKit/pull/130
  • @peterrrock2 made their first contribution in https://github.com/mggg/VoteKit/pull/151

Full Changelog: https://github.com/mggg/VoteKit/compare/v2.0.1...v3.0.0

Scientific Software - Peer-reviewed - Python
Published by peterrrock2 over 1 year ago

VoteKit - v2.0.1

This is a minor patch of votekit. It fixes minor bugs in the slate methods, adapts to the new csv format in the scot-elex repo, and updates some plotting functions.

Added

  • Created a read the docs page.
  • Add scale parameter to ballot_graph.draw() to allow for easier reading of text labels.
  • Allow users to choose which bloc is W/C in historical Cambridge data for CambridgeSampler.

Changed

  • Updated tutorial notebooks; larger focus on slate models, updated notebooks to match current codebase.
  • Removed the seq-RCV transfer rule since it is a dummy function, replaced with lambda function.
  • Update plot MDS to have aspect ratio 1, remove axes labels since they are meaningless in MDS.
  • Update all BLT files in scot-elex repo to be true CSV files, updated load_scottish accordingly. #123 #129

Fixed

  • Fixed bug by which slate-PlackettLuce could not generate ballots when some candidate had 0 support. #131
  • Updated various functions in the ballot generator module to only generate ballots for non-zero candidates.
  • Fixed one bloc s-BT pdf, which was incorrectly giving 0 weight to all ballot types.

Full Changelog: https://github.com/mggg/VoteKit/compare/v2.0.0...v2.0.1

Scientific Software - Peer-reviewed - Python
Published by cdonnay over 1 year ago

VoteKit - v2.0.0

This update will break some of the backwards compatibility, so we have incremented the major version number.

Added

  • A PreferenceInterval class.
  • MCMC sampling for both BradleyTerry ballot generators.
  • Add print statement to BallotGraph so that when you draw the graph without labels, it prints a dictionary of candidate labels for you.
  • Add an IRV election class, which is just a wrapper for STV with 1 seat.
  • Add default option to Borda election class, so users do not have to input a score vector if they want to use the traditional Borda vector.
  • Add several methods to PairwiseComparisonGraph. Added two boolean methods that return True if there is a condorcet winner or if there is a condorcet cycle. Added two get methods that return the winner or the cycles. Cached the results of dominating_tiers and get_condorcet_cycles.
  • Added optional tofloat method to `firstplacevotesif users want to see them as floats instead of Fractions. -Added abyblocparameter togenerate_profile`. If True, this returns a tuple, the first entry of which is a dictionary of PreferenceProfiles by bloc. The second entry is the aggregated profile. This is very helpful for analyzing the behavior of a single bloc of voters. Defaults to False for backwards compatibility.
  • Created a Cumulative ballot generator class. The Cumulative class works like PL, but samples with replacement instead of without. The ranking order does not matter here, simply that candidates are listed on the ballot with multiplicity.
  • Created a HighestScore election class. This takes in a profile and a score vector, and returns the candidates with highest scores. There is a lot of flexibility in the score vector, so this class can run things like Borda, cumulative, etc.
  • Created a Cumulative election class which is just a subclass of HighestScore with the score vector set to all 1s. Thus anyone appearing on the ballot gets one point for each time they appear.
  • Wrote an __add__ method for PreferenceProfile that combines the ballot lists of two profiles.
  • Created utility functions to compute the winners of a profile given a score vector, as well as to validate a score vector (non-negative and non-increasing).
  • Created a shortPlackettLuce class which allows you to generate ballots of arbitrary length in the style of PL.
  • Added tests for __add__ method of PreferenceProfile.
  • Added SlatePreference model and tests.

Changed

  • Change the way the condense_ballots() method works in profiles. Rather than altering the original profile, it returns a new profile. This gives users the option to preserve the original profile.

  • Alter STV class so that the remaining candidates are always listed in order of current first place votes.

  • Made PlackettLuce a subclass of shortPlackettLuce.

  • Change PlackettLuce, BradleyTerry, and Cumulative ballot generators to have name_ prefix. This is in contrast to the slate_ models we have introduced.

  • Speed improvements for various ballot generators.

  • pref_interval_by_bloc is now pref_intervals_by_bloc in all ballot generators. This is now a dictionary of dictionaries, where the both sets of keys are the blocs, and the values of the sub-dictionaries are PreferenceInterval objects. The slate models require that we sample from the uncombined PreferenceInterval objects, while the name models require that we combine the PreferenceInterval objects using cohesion parameters.

  • MDS plot functionality, splitting it into compute_MDS which computes the coordinates, and plot_MDS which plots them. Made because the computation is the most time intensive.

Fixed

  • Fixed an error in the PreferenceProfile tail method.
  • Errors in bloc labeling in CambridgeSampler.

Deprecations

  • Deprecated PL and BT to namePL and nameBT

Full Changelog: https://github.com/mggg/VoteKit/compare/v1.1.1...v2.0.0

Scientific Software - Peer-reviewed - Python
Published by peterrrock2 almost 2 years ago

VoteKit - v1.1.1

VoteKit 1.1.1 is a patch update aimed primarily at extending the functionality of VoteKit. More specifically, this release implements score-based voting systems, and does so without editing the ballot class. To use a score-based system, you have to decide how many points to assign to each position of the ranking. This is flexible enough to handle things like cumulative and approval voting.

This update also includes some additional functionality that was included after creating and running some tutorials on usage of the software. For recordings and copies of some of these notebooks, please see the main website for VoteKit.

Key Changes

  • Change the way the condense_ballots() method works in profiles. Rather than altering the original profile, it returns a new profile.
  • Altered STV class so that the remaining candidates are always listed in order of current first place votes.
  • Added print statement to BallotGraph so that when you draw the graph without labels, it prints a dictionary of candidate labels for you.

Additions

  • Added a by_bloc parameter to generate_profile. If True, this returns a dictionary of PreferenceProfile objects by bloc. Defaults to False for backwards compatibility.
  • Created a Cumulative ballot generator class. The Cumulative class works like PL, but samples with replacement instead of without. The ranking order does not matter here, simply that candidates are listed on the ballot with multiplicity.
  • Created a HighestScore election class. This takes in a profile and a score vector, and returns the $m$ candidates with highest scores.
  • Created a Cumulative election class which is just a subclass of HighestScore with the score vector set to all 1s.
  • Wrote an __add__ method for PreferenceProfile that combines the ballot lists of two profiles.
  • Created utility functions to compute the winners of a profile given a score vector, as well as to validate a score vector (non-negative and non-increasing).
  • Add an IRV election class, which is just a wrapper for STV with 1 seat.
  • Add default option to Borda election class, so users do not have to input a score vector. Add several methods to PairwiseComparisonGraph.
    • Added two boolean methods that return True if there is a condorcet winner or if there is a condorcet cycle.
    • Added two get methods that return the winner or the cycles. Cached the results of dominating_tiers and get_condorcet_cycles.
  • Added optional to_float method to first_place_votes if users want to see them as floats instead of Fractions.

Bug Fixes

  • Fixed an error in the PreferenceProfile tail method.

Full Changelog: v1.1.0..v1.1.1

Scientific Software - Peer-reviewed - Python
Published by peterrrock2 about 2 years ago

VoteKit - v1.1.0

Votekit 1.1.0 features a number of important functional and syntactical changes to the core Ballot, PreferenceProfile, and ElectionState objects. It also includes changes to ballot generation methods to output the correct number of ballots and allow for user-defined block names in the CambridgeSampler class. This release marks an overhaul to the library's documentation, and the addition of section explaining the social choice theory that underpins Votekit's functionality.

Key Changes

  • Method names for ElectionState methods
  • Caches for the results of run_election()
  • Ballot objects made immutable, using Pydantic dataclass
  • Parameter names for CambridgeSampler
  • BallotGraph now always displays vote totals for a ballot
  • ElectionState now prints the current round whenever printing
  • load_blt became load_scottish
  • plot_summary_stats always displays candidates in order inputted
  • PreferenceProfile data frame now has Percent column, removed the Weight Share column
  • Ballot object can take floats and integers as weights
  • Ballot attribute voter changed to voter_set

Additions

  • Added to_dict(), to_json() functions for ElectionState
  • Scores attribute to ElectionState
  • _rename_blocs method to CambridgeSampler to rename blocs to historical names.
  • Added reset and run_to_step methods to Election class
  • sort_by_weight parameter to head and tail methods of PreferenceProfile
  • received_votes parameter to get_candidates method of PreferenceProfile
  • __str__ method for Ballot

Bug Fixes

  • Multiple winners correctly ordered based off previous round's vote totals
  • CambridgeSampler correctly computes the frequency of opposing bloc ballots
  • PreferenceProfile no longer rounds all weights to integer when printing

Special thanks to Chris Donnay (@cdonnay) who made significant contributions to this release and is responsible for the improved tutorials and social choice theory sections of the documentation!

Scientific Software - Peer-reviewed - Python
Published by jgibson517 about 2 years ago

VoteKit - v1.0.2

  • bug fixes to election types
  • lowered pandas version requirements for wider compatibility

Scientific Software - Peer-reviewed - Python
Published by jgibson517 over 2 years ago

VoteKit - v1.0.1

  • added elections submodule (e.g from votekit.elections import STV, fractional_transfer)
  • renamed CVR loaders to load_csv and load_blt
  • better documentation

Scientific Software - Peer-reviewed - Python
Published by jgibson517 over 2 years ago

VoteKit - v1.0.0

Version 1.0 - User determined options for breaking ties - Ballot Simplex object, refactored construction for ballot generator classes - IC/IAC with generalized arguments - Fixed package imports - Improved handling of tied rankings within ballots - Optimization for election helper functions

Scientific Software - Peer-reviewed - Python
Published by jgibson517 over 2 years ago

VoteKit - v0.2.0

Scientific Software - Peer-reviewed - Python
Published by jgibson517 over 2 years ago

VoteKit - v0.1.1

  • Added MDS plotting
  • Updated metrics to include: earth mover and Lp distances
  • Bug fixes to PreferenceProfile and ballot generators
  • More docstrings

Scientific Software - Peer-reviewed - Python
Published by jgibson517 over 2 years ago

VoteKit - v0.0.0

Scientific Software - Peer-reviewed - Python
Published by jgibson517 over 2 years ago