Upper Arlington city elections for City Council and School Board typically have a list of candidates competing for multiple open seats. In a state or federal elections operating where voters only vote for one candidate to fill a single open seat, predicting elections take the form of polling and examining fundamentals. Predicting local elections where voters can select multiple candidates with multiple winners is more challenging.
- With
python3
installed, runpip install pydantic
- Run
python3 election_cli.py
to run a simulation. - To run a single election, add a single argument, like
python3 election_cli.py -s
- Install
docker
anddocker-compose
-> Download Docker Desktop client cd
to the project directory- Run
docker-composer up
- Open
http://localhost:5173
in the web browser.
- Install
python3
from the official Python website. - Download this repository to your computer as a zip file. Double click the zip file to unzip it as a folder called
electionsim-main
. - [Windows only] Open the
electionsim-main.zip
file on your computer and make sure to click "Extract all..." so it gets extracted to a folder calledelectionsim-main
. - [Mac only] Open the Terminal app on Mac.
- [Windows only] Open the Windows Powershell on Windows.
- Type the command
cd
and then drag theelectionsim-main
folder onto the window, then hit Return. - Type
pip install pydantic
- Type
python3 election_cli.py
and it should run. If it gives an error about python3 not being installed, or if it saysNo such file or directory
then type the commandpwd
and hit Enter to make sure your Terminal or Powershell is looking in the right directory where theelectionsim-main
folder is. Feel free to post an issue above if you're having problems. - To customize the electorate data, candidates and voter profiles, see below on working with the
config.json
file.
The command line election_cli.py
app reads in a local file config.json
as its input.
Config parameter | Description |
---|---|
candidates |
The full name of all the candidates on the ballot are listed as a string array. |
voterProfiles |
The default file contains three profiles: DEM , IND , and GOP . You may add more profiles like CENTER-DEM , CENTER-GOP , etc for more fine tuned control.The decimal number following each candidate must be between 0 and 1 , although a value inclusive of the range 0.05 and 0.95 is recommended to generate entropy in the simulation.The decimal number indicates the probability of individual voter selecting this candidate on their ballot. See below for a more detailed discussion of voterProfiles . |
electorate |
Each voterProfile has a corresponding number indicating its percentage of the whole electorate. For example, "GOP":0.39 means that 39% of the electorate has the GOP voter profile. All the electorate values must add up to 1.0 . |
electionSettings |
numOfSims : The number of times the script will run a single election. Higher numbers will increase processing times.totalVoters : The number of voters for each election sim. Higher numbers will increase processing times and also reduce entropy in the final results.ballotWinners: By default, the Upper Arlington School Board election will have 2 winners since there are two open seats. You may customize this value for other elections with more than 2 winners. Set the value to 1 to emulate a traditional single-winner election. |
message |
Unused config parameter that may be used in future versions to add messages contextualizing the election or justifying the voterProfiles . |
The aim of this program is to allow you to create custom voter profiles which represent the probability that a voter of that profile would add that candidate to their ballot. Let's walk through an example using the default values from the repository:
-
"DEM":{"Jenny McKenna":0.60
This says that given a single instance of a voter with theDEM
profile, there is a 60% probability that they will add Jenny McKenna to their ballot. What it does not represent is 60% of allDEM
voters will cast a vote for Jenny McKenna. There is a distinction. -
"IND":{"Jenny McKenna":0.90
This says that given a single instance of a voter with theIND
profile, there is a 90% probability that they will add Jenny McKenna to their ballot.
The program has a simple tie-breaking feature to ensure every voter only selects the number of candidates declared in the ballotWinners
variable. Assuming you set that value to 3
, if a voter ends up selecting 4 candidates, three winners will be chosen from random of that set. Over hundreds of voters and hundreds of election sims, this introduces a small amount of entropy into the results.
Bullet voting is a strategy where a voter casts a ballot for fewer than the maximum allowed, to concentrate their support. This program automatically implements bullet voting by having voters only select candidates that exceed their support threshold. For example, if a voter has an 80% and 90% probability of selecting Candidate A, Candidate B respectively, and the random number generated is 0.85
, the voter will only select Candidate B, since Candidate A's 80% threshold from the profile is lower than the 0.85
value.
In a typical local election, there are no polls to draw from to guess electoral outcomes. That means that you have to use your own knowledge and intuition to assign these numbers. Given that school board elections have become polarized, you can make an educated guess on how likely a DEM
or GOP
voter would select a specific candidate.
The election_cli.py
program will output list with candidates
, numberOfWins
, and probabilityToWin
.
This is an example of one possible outcome based on a custom set of voter profiles. In this case, 300
elections were run, and the probability of a candidate winning is simple numberOfWins
divided by the total number of elections. For example, 247/500 = 0.823
which is 82.3% probability.
"candidates": {
"Glen Dugger": {
"numberOfWins": 247,
"probabilityToWin": "82.3%"
},
"Liz Stump": {
"numberOfWins": 183,
"probabilityToWin": "61.0%"
},
"Sumia Mohamed": {
"numberOfWins": 168,
"probabilityToWin": "56.0%"
},
"Ruth Edmonds": {
"numberOfWins": 2,
"probabilityToWin": "0.7%"
},
"Jenny McKenna": {
"numberOfWins": 0,
"probabilityToWin": "0.0%"
},
"Lori Trent": {
"numberOfWins": 0,
"probabilityToWin": "0.0%"
}