If you’re like me, then you fondly remember the grand debates about voting systems we used to have here, and the voluminous accompanying discussions about what qualities are important in a election method and how to compare them.
If you actually are me, then you’ve spent significant time thinking about this subject over the last few years, and two months ago you starting coding up a voting simulation program to run thousands of virtual elections in order to get quantitative results about how different voting systems perform. And today you finally got it running. Debugged and everything too!
So! Before I get too deep into running simulations and generating results, lets talk about how it works, what makes sense, and how I can improve it. Here’s what the user interface looks like:
The basic idea is to simulate a slate of candidates and a population of voters, run them through each voting system, tally the results, and repeat with a new batch of voters and candidates a whole bunch of times. Then summarize the overall trends.
The summary statistics are pretty straightforward:
• Average utility of the winning candidates for each system
• Average Bayesian regret of each voting system (ie. highest utility among candidates minus utility of winner)
• How many times the candidate with highest utility wins under each voting system
The calculation of utility is a little involved, but should make sense:
Each voter calculates the sum-of-squares weighted distance to each candidate, as s = ∑(wi × (vi - ci))2, where the w’s are the voter’s weights, the v’s are the voter’s positions, and the c’s are the candidate’s positions, and the sum is taken over all n issues.
Then there are two options, selectable by the “Utility” popup in the program. If “Exp” is chosen, then the calculation is u = exp(-s / 2n) and if “RMS” is chosen, then the calculation is u = -√(s / n), where in both cases n is the number of issues.
So that is how voters calculate their true honest utility for each candidate, and those are the values which, when averaged over all voters for a given candidate, are used to compare the quality of winners of different voting systems.
Now, when the simulator is run, it loops through all numbers of candidates and issues in the ranges specified by the user, and carries out the full complement of elections for each voting system with those values. To explain how that works, first I need to describe the “Voter Behaviors” table:
The “Level” values are much simpler to explain: when a voter looks at a pre-election poll, they take each candidate’s vote total, and raise it to the k’th power, where k is the voter’s level, and they treat those values as the candidates’ relative odds of winning. (Technically, the results are scaled at each step so they sum to 1 across all candidate, but the effect is the same.)
So a level-0 voter ignores the polls and treats each candidate as equally likely to win. A level-1 voter treats the percentage of votes that a candidate received in a poll, as that candidate’s odds of winning. And higher-level voters assign progressively higher likelihoods of winning to candidates near the top of the polls, and lower likelihoods to candidates near the bottom.
For example, if the poll results are 40%, 30%, 20%, 10%, then a level-3 voter will consider the candidates to have, respectively, 64%, 27%, 8%, and 1% odds of winning. Voters use their perceived probabilities for each candidate to win, in conjunction with their honest utility values for each candidate, to determine how they will vote in each election.
With all that explained, the elections themselves can be described:
Polls are just miniature elections. For the first poll, the “Electability” popup determines how likely the voters think each candidate is to win. If it is set to “Equal” then voters initially think all candidates have the same chances. If it is “Random” then each candidate is given a “Charisma” score drawn from a standard exponential distribution, and voters apply their strategy-level calculations to it. And if electability is set to “Ignore polls” then the voting system skips all the polls and goes straight to the election, using “Equal” electability so the result is that all voters act honestly (ie. as if they had strategy level 0).
In any case, the first poll is tallied by each voting system, and those results are fed into the next poll for voters to use in calculating their perceived odds for each candidate to win. This continues until all the polls are finished. Note that since the tallies are almost certain to differ between voting systems, that the voters are apt to behave differently in subsequent polls.
When all the polls are done, the results of the last one is used as input for the full election where all voters cast a ballot. And the results of that election show which candidate won under each voting system.
One thing I haven’t mentioned yet is the “Options” column. That just tells a voting system how many spots there are on the ballot for a voter to mark. The value 0 means to use the default for that system. With ranked methods like IRV and Schulze, specifying an options value means that voters indicate their “top x” choices (using their own strategy to determine who those top x are). With rated methods like Score and Majority Judgment, the options value tells how many different ratings are available.
I think that just about covers everything, and this post ended up way longer than I envisioned. So please let me know what you think, if you have questions or ideas, and whether you care to find out how the voter strategies work!