Whether it be determining positions in student councils or electing our nation’s next leaders, voting systems play a crucial role in shaping our society. This project aims to analyze how election results change in different voting systems by modeling systems onto pseudorandom populations. In this project, individuals are represented as lists of numbers that stand for their stance on certain subjects, and votes are cast based on the Euclidean distance between a voter and a candidate. The goal of this project is to examine contrasting voting systems and compare the satisfaction levels voters feel about the winning candidate of each model.

Introduction

A variety of voting systems are used in the world today, some of which are used for smaller-scale elections and some for choosing national leaders. The US primarily uses majority and plurality voting systems, which represent a winning candidate if they receive either the majority or most of the votes. Some states using ranked-choice and runoff voting for smaller political positions, two similar systems that allow voters to organize candidates in order of preference. Other countries and organizations use systems like approval voting to determine a winner based off a binary choice in a ballot for “approval” and “disapproval”.
​
The existence of multiple of voting systems - both in use and theoretical - poses the question: How would election results change if different voting systems were used? If the US used a different presidential voting system, would our leader today still be the same? The objective of this project is to model and test four distinct voting systems (majority, ranked choice, runoff, and approval) on different populations to analyze the results of the elections. To make this analysis nontrivial, votes should be represented pseudorandomly to represent real populations, where there could be overwhelming preferences and bias.

Generating Populations and Candidates

In order to model voting systems, we first need to create representations of voters and candidates. From the first principle, voters vote for candidates who have the same opinions or perspectives as them. So, each candidate and member in a population are represented as a list of four subject matters (e.g {1,0,1,0}) that constitute as their stances on different subjects. For example, the first element ‘1’ in a candidate’s list {1,0,1,0} can represent a certain political party (while if the first element were ‘0’, it would represent the opposing political party), and the second element ‘0’ can represent their stance on healthcare. A voter for this candidate will also be represented the same way, and votes are casted based on the Euclidean distance between a voter and candidate. The size of the Euclidean distance exhibits the level of similarity between a voter and candidate’s views.

Voting Populations

An example of how an individual voter is represented:
In[]:=
generateRandomPerson[]:={RandomInteger[{0,1}],RandomInteger[{0,1}],RandomInteger[{0,1}],RandomInteger[{0,1}]}​​randomPerson=generateRandomPerson[]
Out[]=
{0,1,0,1}
A population of 100 voters:
In[]:=
voterPopulation=Table[generateRandomPerson[],100]
Out[]=
{{1,1,0,0},{1,0,0,1},{1,0,0,1},{0,1,1,0},{0,0,1,0},{1,0,1,0},{0,0,0,1},{0,1,0,1},{1,0,1,0},{1,0,0,0},{1,0,0,0},{1,1,0,1},{0,1,1,1},{1,0,1,0},{0,0,0,0},{1,1,1,0},{1,1,1,0},{1,0,0,1},{1,0,0,1},{0,0,1,0},{0,0,1,0},{0,1,0,1},{1,0,0,0},{0,1,0,0},{0,0,1,1},{0,0,1,0},{1,0,0,0},{0,0,0,0},{1,1,0,0},{1,0,0,1},{1,1,0,0},{0,1,0,0},{1,1,1,1},{0,0,1,1},{0,0,0,1},{0,0,1,0},{1,1,0,1},{0,1,0,1},{0,1,1,1},{1,1,1,0},{0,1,1,0},{1,0,1,1},{1,1,0,1},{0,0,1,1},{0,1,0,1},{1,0,0,1},{1,0,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,1},{0,0,1,1},{0,1,1,0},{1,1,1,1},{1,1,1,1},{0,0,1,1},{1,1,0,0},{0,0,0,0},{0,1,0,0},{1,1,1,1},{1,1,1,1},{0,1,0,0},{0,1,1,0},{0,0,1,1},{0,0,1,0},{1,1,0,0},{0,0,1,1},{0,0,1,0},{1,0,1,0},{0,0,0,0},{0,0,0,0},{1,0,0,1},{1,0,0,1},{0,1,1,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,1,1},{1,1,1,1},{1,1,0,1},{0,0,0,0},{1,1,0,1},{1,0,0,0},{1,1,1,0},{0,1,1,1},{0,0,1,0},{1,0,0,0},{1,0,0,1},{1,0,0,1},{1,0,1,1},{1,0,1,1},{0,0,1,1},{0,1,0,1},{1,1,0,1},{1,0,1,1},{1,0,0,1},{1,0,0,1},{1,1,1,1},{1,0,1,1},{1,1,0,1},{1,1,1,0}}

Candidates

Individual candidates would be represented the same way as voters:
In[]:=
generateRandomCandidate[]:={RandomInteger[{0,1}],RandomInteger[{0,1}],RandomInteger[{0,1}],RandomInteger[{0,1}]}
In[]:=
randomCandidate=generateRandomCandidate[]
Out[]=
{0,0,1,1}
The five candidates in a sample election:
In[]:=
candidatesPop=Table[generateRandomCandidate[],5]
Out[]=
{{0,1,1,0},{0,1,1,0},{0,1,0,1},{1,0,0,1},{1,1,0,0}}

Creating Voting Systems

The next goal is to create different models that represent four voting systems: majority/plurality voting, ranked choice voting, runoff voting, and approval voting. We can do this by tallying the distributions of votes differently for each system, using the same sample voters and candidates for each model.

Majority Voting Model

Note: In real elections, majority and plurality voting, although very similar, are distinct systems. This model is an accurate representation of the plurality voting system, but for simplicity, the term “majority” is used as “plurality” in function and variable names throughout this project.
​​
In plurality voting systems, each voter votes for one candidate from a list of candidates, and the candidate with the most votes wins the election. Using Euclidean distance, this system can be modeled by finding the minimum distance from each candidate to each voter. The candidate closest to a voter will be voted for, and we can tally the end results of the most voted candidates to find the winner of the election.
Since we are generating lists of candidates and voters pseudorandomly, SeedRandom[] needs to be used for the consistency in this essay. However, with different population simulations, SeedRandom[] should not be used.
In[]:=
SeedRandom[1234]
Out[]=
RandomGeneratorState
Method: ExtendedCA
State hash: -7977229337773215043

The sample size of this model can be 11 voters and 2 candidates:
In[]:=
pvoters = RandomInteger[{0,1},{11,4}] ​​pcandidates = RandomInteger[{0,1},{4,4}]
Out[]=
{{1,0,0,1},{1,1,1,1},{0,1,1,1},{0,0,1,0},{1,1,1,1},{1,0,0,0},{0,1,0,0},{1,1,0,0},{0,1,0,1},{1,0,0,0},{0,1,1,0}}
Out[]=
{{0,0,0,1},{0,1,1,0},{0,0,0,1},{0,0,1,0}}
Finding the distance between one voter and one candidate:
In[]:=
voterCandidateDistance[voter_, candidate_]:=N[Sqrt[Total[(voter-candidate)^2]]]
Mapping the previous function to find the distance between one voter and all the candidates:
In[]:=
voterDistance2AllCandidates[voter_,candidates_]:=Map[voterCandidateDistance[voter,#]&,candidates]
In[]:=
voterDistance2AllCandidates[pvoters[[1]],pcandidates]
Out[]=
{1.,2.,1.,1.73205}
Then, we can find the distance between all voters to all candidates, represented as a matrix:
In[]:=
allvoterDistance2AllCandidates[voters_, candidates_]:= Map[voterDistance2AllCandidates[#,candidates]&, voters]
In[]:=
allvoterDistance2AllCandidates[pvoters,pcandidates]
Out[]=
{{1.,2.,1.,1.73205},{1.73205,1.41421,1.73205,1.73205},{1.41421,1.,1.41421,1.41421},{1.41421,1.,1.41421,0.},{1.73205,1.41421,1.73205,1.73205},{1.41421,1.73205,1.41421,1.41421},{1.41421,1.,1.41421,1.41421},{1.73205,1.41421,1.73205,1.73205},{1.,1.41421,1.,1.73205},{1.41421,1.73205,1.41421,1.41421},{1.73205,0.,1.73205,1.}}
We can now find the position of the minimum distance between a candidate and a voter for each row in the matrix, since the candidate with the shortest distance represents who the voter votes for. If the distances between two candidates and a voter are equivalent, the voter will make a random choice between the two candidates. Given the sample size of elements/subject matters, this random choice comes the closest to accurately representing a real voter’s decision in a real election.
Function for finding the minimum distance between candidates and voters:
In[]:=
voter2voted[voters_,candidates_]:=Flatten[Map[​​ RandomChoice[​​ Position[#,Min[#]]​​ ]&,​​ allvoterDistance2AllCandidates[voters,candidates]​​]]
In[]:=
votes=voter2voted[pvoters,pcandidates]
Out[]=
{3,2,2,4,2,3,2,2,3,3,2}
Now that we have who each voter voted for, tally the votes. The first element in the sublist represents the candidate, and the second element in the sublist represents how many votes they have:
In[]:=
Tally[votes]
Out[]=
{{3,4},{2,6},{4,1}}
From the tally, finding the final winner by choosing the greatest number of votes:
In[]:=
MaximalBy[Tally[votes],Last]
Out[]=
{{2,6}}
This is the final function for the results of our plurality voting system. We combine the previous steps and extracting the name of the winning candidate:
In[]:=
majorvotingresult[pvoters_, pcandidates_] := ​​First[Flatten[​​MaximalBy[Tally[voter2voted[pvoters, pcandidates]],Last]​​]]
The name of the winner for this model:
In[]:=
majorvotingresult[pvoters,pcandidates]
Out[]=
2
Resetting the generator:
In[]:=
SeedRandom[]
Out[]=
RandomGeneratorState
Method: ExtendedCA
State hash: -5848180282057060173

An 11 x 4 matrix of the distance between each voter and candidate can be used to visualize the results of this voting model. In the table, the vertical column displays the sample collection of voters and the top row represents the four candidates. The fifth column gives us the winning candidate in each row.
Table visualization of distances between voters and candidates:
Out[]//TableForm=
{0,0,0,1}
{0,1,1,0}
{0,0,0,1}
{0,0,1,0}
Voted Candidate
{1,0,0,1}
1.
2.
1.
1.73205
3
{1,1,1,1}
1.73205
1.41421
1.73205
1.73205
2
{0,1,1,1}
1.41421
1.
1.41421
1.41421
2
{0,0,1,0}
1.41421
1.
1.41421
0.
4
{1,1,1,1}
1.73205
1.41421
1.73205
1.73205
2
{1,0,0,0}
1.41421
1.73205
1.41421
1.41421
4
{0,1,0,0}
1.41421
1.
1.41421
1.41421
2
{1,1,0,0}
1.73205
1.41421
1.73205
1.73205
2
{0,1,0,1}
1.
1.41421
1.
1.73205
3
{1,0,0,0}
1.41421
1.73205
1.41421
1.41421
4
{0,1,1,0}
1.73205
0.
1.73205
1.
2

Ranked Choice Voting Model

The next model is ranked choice voting. In this voting system, voters order their preference for candidates from 1 to n, n being the number of candidates. The result of all votes are tallied, and if a candidate has the majority of first-preference votes, they win. However, if no candidate gets a majority, the lowest voted candidate is eliminated and those who voted for that candidate have their votes redistributed to their next highest ranked choice. This process reiterates until there is a winner with the majority of highest preference votes.
​
Here are the steps for creating this model:
1. Create a preference function that sorts the preferences of one voter, then map the function onto all the voters.
2. Sort the preferences and tally them.
3. Create a function that takes the votes and eliminates candidates with the fewest first-choice votes.
4. Calculate the total number of votes for each remaining candidate.
5. If any candidate receives a majority of the votes, declare them as the winner.
6. If no candidate has a majority, eliminate the candidate with the fewest votes from all of the preference ballots and recount the votes.
7. Repeat the counting process until a winner is determined.
8. Declare the winner.
We should use the same sample 11 voters and 4 candidates in all of these models:
We can sort the preference of one voter by using the same distance functions in the previous model. The smallest distance between a candidate and voter would represent the voter’s first preference.
The function outputs a voter’s preference ballot from most preferred to least, with the candidate name in each sublist:
Sorting all of the voters’ preferences by mapping the previous function. Since preferences are now sorted, we can now delete the distance between voters and candidates and only display the candidate names:
We need to tally all of the voters’ ballots. In the tally, a candidate’s name comes first and is associated with the amount of first-preference votes they received. At first, using the GroupBy function deleted the candidate if they got no first-preference votes. However, this was important to include for the elimination process, so we need to add the candidate who got 0 votes back into the list.
The function rcvVoteTally tallies the ballots:
The final function that returns the winning candidate includes the elimination process. If a candidate has the majority of first-preference votes, which are represented as the Values of voteTally, the function will return the Key of that candidate (which represents their name). If there is no majority of first-preference votes, the model will eliminate the last part of voteTally (the candidate with least votes) from all of the voters’ original preference ballots. We then recount votes from the new preference ballots to determine a winner. The elimination process continues until there is a majority of first-preference votes.
rcvResults outputs the winning candidate and reruns the redistribution of points if there is no majority of first-preference votes:
The winner of the ranked choice model:

Runoff Voting (Two-Round) Model

Runoff voting, or the two-round system, is very similar to the ranked choice voting system. In this system, voters also rank their candidate preferences from most preferred to least preferred. However, instead of the elimination process, the system takes the top two candidates with the most first-preference votes if there is no majority turnout after the first round. Therefore, we can follow a similar framework as the ranked choice model for the runoff model.
Defining the voters and candidates (the same 11 voters and 4 candidates from previous systems):
For the runoff model, we can use the same preferencesAllVoters and rcvVoteTally functions in the ranked choice model. The only modification needed is the process of elimination, where instead of eliminating the last candidate, we take the two candidates with the most first-preference votes and eliminate all of the other candidates from the preference ballots. Then, we can recount and see which one of the two candidates received the most first-preference votes.
runoffResults outputs the winning candidate and takes the top two remaining candidates if there is no majority in the first round:
The winner of the two-round runoff model:

Approval Voting Model

The approval voting system is not used as frequently in elections as the other three voting systems. In 2018, Fargo, North Dakota was the first city in the US to use approval voting for candidate elections. However, it was recently outlawed in February 2023 for lack of control in the system. In approval voting, voters can “approve” or “disapprove” as many candidates as they want in a ballot, and the candidate with the most approval points win the election. To model this system, approval votes can be represented as + 1 point and disapproval votes can be 0 points. The determinants for approval or disapproval can be distance parameters between a voter and a candidate.
​
Here are the steps for creating this model:
1. If the distance between a voter and candidate is less than 1 (half of 2, which is the maximum possible distance between the population vectors), pick approve. If the distance is greater than 1, pick disapprove.
2. Tally the approved and disapproved candidates to see which candidate has the most approvals.
3. Like the majority voting model, if there is a tie of votes between candidates, the winner will be randomly chosen to portray a realistic situation in a real population.
Generate the same list of 11 voters and 4 candidates:
Using the common distance function to display the distance between voters and candidates:
After finding the distance between all voters and candidates, we need to create a function that outputs the disapprovals and approvals for each candidate.
The approvalvoted function determines if a voter should approve (if the distance is less than or equal to 1) or disapprove (if the distance is greater than 1), and returns a nested list with votes and candidate names.
We need to tally the number of approval votes that each candidate receives. Then, we need to compare the tallies to determine a winner.
Finding the total number of votes each candidate has - for instance, the first element in the output of approvalvotes is the number of approvals that candidate 1 has.
The approvalvoteResults function determines the position of the greatest number in approvalvotes, which is the winning candidate.

Pseudorandom Population Results

In our sample populations of voters and candidates, individual opinions were randomly generated and not based off of real groups. To accurately analyze these voting systems, we need to test these systems on populations with weighted preferences. In the following population samples, the ‘1’ in the first element the list represents an affiliation with political Party A, and the ‘0’ in the first element represents affiliating with the opposing political Party B.

Population 1: Political Party A

There is a 65% weight for ‘1’ in the first element, resulting in individuals in Population 1 to mostly identify with Party A.
The candidates do not need weights, as we are comparing the results from the two different parties on the same set of candidates.
Generate 5 random candidates:

Election results:

As seen in these election results for Population 1, different voting systems cause different candidates to win the election. In the majority voting model, candidate 1 won the election. However, in the ranked choice, runoff, and approval voting models, candidate 3 won the election.

Population 2: Political Party B

After gaining some insight on the possible disparities between different voting systems, we need to test the models on a different population with different weighted preferences. In Population 2, there is a 65% weight for '0' in the first element, resulting in individuals in Population 1 to mostly identify with Party B.
Use the same 5 candidates in the election for Population 1:

Election results:

From the election results for population 2, it seems that there is also disparity in the different voting models. Candidate 2 won in the majority voting model, candidate 3 won in the ranked choice and runoff voting models, and candidate 5 won in the approval voting model.

Result Analysis: Optimizing Voter Happiness With Election Results

From the previous simulations, we see a difference in the outcome for different voting systems. To analyze the results of the elections further, we can measure how “happy” the voters are with the winning candidates of different systems by calculating the winner’s distance between all of the voters. Out of the four voting systems, the smallest distance between a candidate and the voters will represent the winner that makes the voters happiest.

Population 1 Happiness Levels

Finding the mean distance between the winning candidate and all of the voters, and compare them to analyze happiness disparities.
Since candidate 1 won in the majority voting model, we can find the distance between the population and part 1 of candidatesPop1.
Candidate 3 won in the other three models, so we can find the distance between the population and part 3 of candidatesPop1.
In Population 1, people are not as happy as they are with the majority voting candidate than the other candidates that won in other models.

Population 2 Happiness Levels

We can compare the happiness levels of voters in Population 2 the same way, using the previous election results.
Majority voting happiness:
Ranked choice and runoff happiness:
Approval voting happiness:

Generalizing Happiness Levels in Voting Systems

To generalize voter satisfaction for all four voting systems, I created a new function that takes in the distance and position of the voting results. In the following simulations, I use the voters from Population 1 and run the election 100 different times to find the average voter happiness of each system, and found that the happiness levels were similar.

Side-By-Side Comparison of Election Disparities

Now we can visualize the distribution of happiness among the voter population for each system. It seems like there are small disparities, with ranked choice and runoff voting yielding the happiest voters, but the differences may negligible.

Conclusion

This project shows us that small disparities may exist within different voting systems. From the sample models tested in this project, we can see that the ranked choice voting system and runoff voting system are the best voting models to use for small population satisfaction. However, on a bigger scale election, the different satisfaction levels of voters may be negligible, as shown in the histograms. The results of my analysis show that different voting systems may influence the results of elections or smaller scale elections. It is crucial to consider the size of the population when considering which voting system to use.
However, it is also important to take into consideration that I measured and analyzed different voting systems based on one factor: satisfaction between voters and candidates based on similarity in political views. Similarity is only one dimension of an evaluation metric, and there may still be good reason to choose one voting model over others from other principles.

Future Work

For future work, I plan on analyzing different voting systems, including a weighted voting model using the Banzhaf Power Index. The systems I used in this project were quite similar - especially the ranked choice and runoff models - and it would be interesting to test out different weights on new models, especially theoretical voting systems. Additionally, I would like to represent populations in more accurate and complex ways by using more numbers and finding possible associations between different qualities and political views. I would also like to conduct more statistical analysis based on these results to find measurements on the exact levels of impact of using different voting systems, because the disparities found in my project may be considered negligible in different elections.

References

◼
  • PR library: Types of voting systems. FairVote. (2022, October 20). https://fairvote.org/archives/types_of_voting_systems/
  • ◼
  • Chapter 7: Voting Systems. coconino.edu. (n.d.). https://coconino.edu/resources/files/pdfs/academics/arts-and-sciences/MAT142/Chapter_7_VotingSystems.pdf
  • ◼
  • The Regents of the University of Michigan. (2023). Candidate Characteristics. icpsr.umich.edu. https://www.icpsr.umich.edu/web/pages/instructors/setups/notes/candidate-characteristics.html
  • ◼
  • Estival, G. (2023, May 23). A detailed approval voting method example. ElectionBuddy. https://electionbuddy.com/blog/2022/02/16/a-detailed-approval-voting-method-example/
  • ◼
  • Hagen, C. S. (2023, March 31). North Dakota lawmakers ban approval voting system used in Fargo. InForum. https://www.inforum.com/news/north-dakota/north-dakota-lawmakers-ban-approval-voting-system-used-in-fargo
  • ◼
  • Kambhampaty, A. P. (2019, November 6). What is ranked-choice voting? here’s how it works. Time. https://time.com/5718941/ranked-choice-voting/
  • Acknowledgements

    I would like to acknowledge and thank Jeremy Stratton-Smith, my project mentor, for their help and guidance throughout my work. I would also like to thank AnnMarie Torresen, the directors of the program, and Stephen Wolfram for making this project possible. Lastly, I would like to thank my family for their continual support throughout my research.

    CITE THIS NOTEBOOK

    Creating and analyzing voting systems using pseudorandom population simulations​
    by Sofia Wang​
    Wolfram Community, STAFF PICKS, July 13, 2023
    ​https://community.wolfram.com/groups/-/m/t/2964799