This repo contains the logic for Instant Runoff Voting on Wildcat Connection, designed for Slivka Executive Committee Elections, but distributed with the MIT license so any organization may use it.
Instant Runoff Voting Wikipedia
Coming soon: non-technical instructions.
Create python >=3.9 environment with the environment manager of your choice. For conda:
$ conda create -n slivka-irv python=3.9
$ conda activate slivka-irvAll the following steps, and running the program, should be done in your newly created environment. We are on PyPi:
$ python -m pip install slivka-irvEnsure the package is installed correctly.
$ irv
usage: irv [-h] [--args.save ARGS.SAVE] [--args.load ARGS.LOAD] [--args.debug ARGS.DEBUG] [--remove_exhausted_ballots] [--log_to_stderr] [--save_log] [--ballots_output]
[--elections_output ELECTIONS_OUTPUT] [--verbose]
wc_file
irv: error: the following arguments are required: wc_file
See here for detailed instructions on making an election in Wildcat Connection. Some brief points to rememeber are included below:
- Each ranking should be a different question.
- It does not matter if multiple questions or ballots are used.
- No two questions should be named the same.
- Export Wildcat Connection CSV.
Let's say our exported CSV has the filepath wc.csv. To run IRV on wc.csv, enter a shell within your created environment and run:
$ irv wc.csvThis will print the Winner and IRV Rounds for each question.
It will also save the winner and rounds into the folder path --elections_output, which defaults to ./elections.
For more information on the flags, run:
$ irv -hIf you don't have a CSV ready, you can try out our tool with one of our test cases:
$ irv tests/wildcat_connection/test_cases/8_way_race.csv
Election results saved in ./elections
#####
# Q #
#####
=============
= WINNER: C =
=============
There were 7 total ballots cast
In the final round, C received 4 votes, or 57.14%
==========
= ROUNDS =
==========
Round 1: {'B': 0, 'H': 0, 'E': 0, 'D': 0, 'C': 3, 'A': 2, 'G': 1, 'F': 1}
Round 2: {'G': 1, 'F': 1, 'C': 3, 'A': 2}
Round 3: {'F': 1, 'C': 3, 'A': 2}
Round 4: {'A': 3, 'C': 3}
Round 5: Counter({'C': 4})
This project uses the standard IRV algorithm: for each ballot, give a vote to the highest ranked non-eliminated candidate, and then remove the candidate with the lowest votes. In addition, if any at any step one candidate has over half the vote, that candidate is automatically declared the winner.
In the event that several candidates are tied for last, the algorithm attempts to break the tie as follows:
- If the sum of votes of the tied candidates in less than the number of votes received by any non-tied candidate, remove all the tied candidates
- For each tied candidate, the algorithm counts how many people ranked the candidate first, how many ranked them second, etc. If one tied candidate has less than first choices than the others, they are removed. In the event of another tie in the number of first choices, the algorithms proceeds to second choice counts, and so on.
Sometimes, both of these methods fail to break tie, in which case the algorithm will report an ''unbreakable tie''
By default, exhausted ballots (i.e. ballots on which every ranked candidate has been eliminated) are counted of votes of ''no confidence,'' since a ballot can only be exhausted if a voter does not rank every candidate.
In other words, to win a candidate must receive a tally of at least half of all ballots cast, rather than simply being the only candidate remaining after all others have been eliminated.
To declare the last remaining candidate the winner (or equivalently to remove exhausted ballots), run irv with the --remove_exhausted_ballots flag.