PrefVote is a project to promote preference voting.
Implementations of several ranked-choice voting methods and algorithms are included in the "LAB" (Legacy Algorithm Base) directory. The Single Transferable Vote (STV) implementation is descended from the Vote::STV software written by Ian Kluft in Perl in 1999, with periodic maintenance over the years. Implemenation and experimentation with Condorcet-based algorithms Schulze and Ranked Pairs showed the flaws of STV, and why it has fallen out of favor.
Since the project's original language Perl has strengths in prototyping, that's the reference implementation in this project for multiple language implementations. With translations to multiple programming languages, the library is designed with a common test suite among the different implementations to verify proper functioning.
The legacy algorithms are in the lab directory. A newer algorithm "KR2" (Kluft Rank-Rate) is under experimentation in the main source directory "src" for the library.
Project-wide documentation is in the doc directory.
The original Vote::STV software implemented the single transferable vote algorithm, which is a subset of ranked-choice voting, also called preference voting. PrefVote has expanded into a library of multiple voting method implementations all based on ranked choice.
STV was the first implemented voting method in PrefVote since it was the original implementation as Vote::STV back to 1998. But STV has largely fallen out of favor because studies of voting methods found it lacking on some desirable characteristics. STV was retained while modernizing the code to develop testing infrastructure.
No voting method can be perfect, due to a long list of desirable properties, some of which turn out to be in conflict. Given that there is no perfect voting method, it's important to have agreement among a community on which method it uses. Methods which meet Condorcet requirements make comparisons between each pair of candidates and, if one exists, always pick a winner who beats all other candidates in pairwise comparisons. Condorcet methods differ in how to handle cases where there isn't a clear Condorcet winner.
The second voting method implemented in PrefVote was the Schulze algorithm (see full definition paper). The method was designed by Marcus Schulze in 1997 to compute a graph out of voter preferences among candidates and pick the ones preferred over all others. An ordering of all the candidates can be computed over multiple rounds after removing the previous round's winner(s).
Next was Ranked Pairs. It was designed by Nicolaus Tideman in 1987. It tallies ranked choice ballots into pairwise comparisons among all choices/candidates. The pairs are sorted by margin of victory from largest margin down to ties at zero. Pairs are "locked" in for consideration of the final order of candidates if they do not conflict with locked pairs with larger margins. Candidates are then ordered starting who beats all other candidates, then each who beat all remaining candidates.
After the reference implementation in Perl, next up for language implementations will be Rust.
The original and primary input file format of PrefVote is YAML with a predefined data structure. There is documentation for the data format. Also, when PrefVote is used as a library any data can be submitted by calling functions directly.
In support of a proposed Open Source standard for preference voting systems, PrefVote also supports the Condorcet Election Format (CEF), or CEF. There is documentation for PrefVote's support for CEF input files.
PrefVote modifies all the algorithms in one way. It adds a tie-breaking factor using the average ballot-position ranking of a choice/candidate. It started as experimentation with intuition that the average ranking of a choice was indicative of the will of the voters. Though it wouldn't be acceptable as a primary factor because averages don't have quantitative data - and quantitative data is paramount to meeting the expectation that the candidate with the most votes must be the winner. Test runs show that it approximates Condorcet results fairly well and converges with Condorcet by around 100 random ballots. It didn't even need to be that close to Condorcet to convey meaning about voter's preferences. So this tie-breaking method restores ballot-position ordering information which Condorcet lacks.
PrefVote's Core module from which all the voting methods inherit common code is not a voting method itself. But in performing the counting of average choice ranking (ACR) for other methods to use for tie-breaking, it contains results which can be displayed for testing purposes. Since it only uses average ranking, it really must not be used for actual voting. There is a principle in voting that every vote counts. That means quantitative factors must be the primary ordering for results. But ACR turns out to be surprisingly well-suited to be a second sorting factor for tie-breaking.