Now for preference voting.
There is a theorem about preference voting called Arrow's Theorem, proved by economist Kenneth Arrow. It states that there is no preference-voting algorithm that always has certain nice properties. It can have one of them, at the expense of some other. However, an algorithm can have them in most common circumstances.
But with circular preferences and the like, one can think of cases like the one in
Math Alive -- Voting & Social Choice -- Lab 1 It features a set of ballots where five different methods give five different results.
Comparison of electoral systems goes into very gory detail
In my code, the ballots are lists of candidates from most preferred on down, with each ballot having a weight value. For unweighted ballots, I've written a function that adds a weight of 1 to each one.
I have implemented a large number of methods. Here are some of them:
TopOne -- simulates single-choice voting.
TopNum -- uses the n top preferences to simulate approval voting.
Borda -- the Borda count -- in each ballot, top choice gets (# cands) votes, next gets (# cands - 1), etc.
ModBorda -- modification of it -- one uses (# ballot entries) instead.
CumulBorda -- like ModBorda, but with division by (# ballot entries) -- simulates cumulative voting.
TopTwoRunoff -- do TopOne, then redo with only the top two candidates in it, wherever they are in the ballots.
SequentialRunoff -- Instant Runoff or Alternative Vote -- do TopOne, then remove the candidate with the fewest votes. Repeat until one candidate gets a majority.
Condorcet methods:
Turn each ballot into all possible one-on-one contests in it. Then add up the results of this virtual round robin. The winner is whoever consistently beats all the others. But there may be no Condorcet winner, and there are several algorithms for finding the winner in such a case.
Schulze -- find beatpaths, paths where each member wins against the next one, find the smallest beat margin in each one, and select the one with the largest one of those smallest margins.
Copeland -- find the count of (individual victories) - (individual defeats) for each candidate.
Minimax -- find the maximum loss of each candidate relative to the other candidates, and the winner is the one with the minimum of these maximum losses.
KemenyYoung -- find the ordering of candidates that makes the largest total of how much each candidate beats the later ones.
Dodgson -- Dodgson's method (Lewis Carroll) -- applies permutations to all the ballots and finds the Condorcet winner for each permutation. The overall winner is the winner for the permutation with the smallest permutation distance from the identity permutation.
RankedPairs -- Tideman -- find the pair of candidates with the largest beat margin, noting the direction of that margin. Then find the others with the next largest beat margins, as long as as one cannot go in a cycle by finding their directions. Then find the overall order.
MaximalLotteries -- generalizes the Condorcet-winner index to be partial values, one for each candidate. For this problem, I had to write some linear-programming functions. First, a random line-search function, then a simplex function.
I also calculate the Schwartz and Smith sets of candidates. The Schwartz set is the smallest set of candidates that beat all the others, while the Smith one is similar, but of candidates that beat or tie all the others. If there is a Condorcet winner, then both sets contain only that winner.
Kemeny-Young and Dodgson are both factorial time in the number of candidates, while all the rest are polynomial time.