This Python implementation simulates elections for all 435 congressional districts using ranked choice voting (instant runoff). It's based on the Scala code in the rcvcore
directory and uses data from the Cook Political Report.
- Python 3.8 or higher
- pip (Python package installer)
-
Clone or download this repository
git clone <repository-url> cd python_election_sim
-
Create a virtual environment (recommended)
# On macOS/Linux: python3 -m venv venv source venv/bin/activate # On Windows: python -m venv venv venv\Scripts\activate
-
Install dependencies
pip install -r requirements.txt
Alternatively, for development (includes testing tools):
pip install -e ".[dev]"
-
Run the simulation
python main.py
That's it! The simulation will run and save results to simulation_results.json
.
To verify everything is working correctly, run the test suite:
pytest tests/
All tests should pass.
The code is organized into two main parts:
Core simulation components:
population_tag.py
- Political party definitions (Democrats, Republicans, Independents, etc.)candidate.py
- Candidate representation with ideology, quality, and party affiliationvoter.py
- Voter behavior and ballot generationballot.py
- Ranked choice voting ballot implementationelection_config.py
- Election parameters (uncertainty, party loyalty, etc.)population_group.py
- Voter population groups with statistical propertiescombined_population.py
- Combined populations from multiple groupsunit_population.py
- Population generation for simulationdistrict_voting_record.py
- District voting history and characteristicscandidate_generator.py
- Various strategies for generating candidatessimulation_config.py
- Configuration for different simulation scenariosinstant_runoff_election.py
- Instant runoff voting implementationelection_result.py
- Election result representationelection_definition.py
- Complete election setupgaussian_generator.py
- Random number generation for simulation
Main simulation logic:
- Loads district data from Cook Political Report CSV
- Simulates elections for all 435 districts
- Generates comprehensive results with statistics
python main.py
This will:
- Load district data from
CookPoliticalData.csv
- Run simulation with default unit configuration
- Save results to
simulation_results.json
- Print summary statistics
python main.py --help
Options:
--data-file
: Path to CSV file with district data--output
: Output file for results--seed
: Random seed for reproducible results--candidates
: Number of candidates per party--verbose
: Enable detailed output
# Run with specific seed for reproducibility
python main.py --seed 42
# Run with 2 candidates per party
python main.py --candidates 2
# Verbose output with custom data file
python main.py --data-file my_districts.csv --verbose
# Generate and display plots
python main.py --plot
# Generate only the winner ideology histogram
python main.py --histogram-only
# Save plots to custom directory
python main.py --plot --plot-dir my_plots
The CSV file should have columns:
State
: State nameNumber
: District numberMember
: Current representative nameParty
: Current party (R/D)2025 Cook PVI
: Partisan Voting Index (e.g., "R+27", "D+5")
The simulation generates:
- Summary statistics: Party wins, percentages, voter satisfaction
- District results: Winner, margin, ideology, satisfaction for each district
- JSON file: Complete results for further analysis
- Visualizations: Histograms and plots of results (optional)
- Ranked Choice Voting: Uses instant runoff voting for all elections
- Realistic Voter Behavior: Voters consider ideology, party loyalty, candidate quality, and uncertainty
- Multiple Candidate Generation: Various strategies for creating candidate fields
- Statistical Population Modeling: Gaussian distributions for voter ideologies
- Comprehensive Results: Detailed statistics and district-by-district results
- Data Visualization: Histograms and plots for analysis of results
The simulation can generate several types of visualizations:
- Winner Ideology Histogram: Distribution of winning candidate ideologies by party
- Voter Satisfaction Histogram: Distribution of voter satisfaction by winning party
- Ideology vs Satisfaction Scatter Plot: Relationship between winner ideology and voter satisfaction
- Party Wins by State: Bar chart showing party wins by state
Visualizations are saved as high-resolution PNG files and can be displayed interactively.
The simulation uses a single, optimized configuration:
- Uncertainty: 0.5 (moderate voter uncertainty)
- Party Loyalty: 1.0 (moderate party loyalty)
- Quality Scale: 1.0 (candidate quality impact)
- Party Bonus Scale: 1.0 (party affiliation bonus)
- Wasted Vote Factor: 0.0 (no wasted vote penalty)
- Population Skew: 0.5/30 (slight population skew)
- Primary Skew: 0.5 (moderate primary skew)
The project has minimal dependencies to keep it lightweight:
- matplotlib (>=3.4.0) - For generating visualizations
- numpy (>=1.21.0, <2.0.0) - For numerical computations in plots
- pytest (>=7.0.0) - Optional, only needed for running tests
All dependencies are listed in requirements.txt
and will be installed automatically when you run pip install -r requirements.txt
.
Issue: ModuleNotFoundError: No module named 'matplotlib'
- Solution: Make sure you've activated your virtual environment and installed dependencies:
source venv/bin/activate # or venv\Scripts\activate on Windows pip install -r requirements.txt
Issue: FileNotFoundError: [Errno 2] No such file or directory: 'CookPoliticalData.csv'
- Solution: Make sure you're running the script from the project root directory where
CookPoliticalData.csv
is located:cd python_election_sim python main.py
Issue: Tests fail with import errors
- Solution: Install pytest and make sure the project is in your Python path:
pip install pytest # Run from project root pytest tests/
Issue: Plots don't display
- Solution: On some systems (especially headless servers or WSL), matplotlib may need a different backend. Either:
- Save plots to files instead of displaying:
python main.py --plot-dir output
- Or install a GUI backend for matplotlib (system-dependent)
- Save plots to files instead of displaying:
If you encounter issues not covered here:
- Check that you're using Python 3.8 or higher:
python --version
- Verify all dependencies are installed:
pip list
- Try running the tests to isolate the issue:
pytest tests/ -v
The simulation typically takes:
- Basic run (435 districts): ~10-30 seconds
- With visualizations: ~30-60 seconds
- Running on a modern CPU with Python 3.9+
Results are deterministic when using the same random seed via --seed
parameter.
python_election_sim/
├── simulation_base/ # Core simulation engine
│ ├── ballot.py # Ranked choice ballot implementation
│ ├── candidate.py # Candidate representation
│ ├── voter.py # Voter behavior
│ ├── election_*.py # Various election types
│ └── ...
├── tests/ # Comprehensive test suite
├── main.py # Main entry point
├── visualization.py # Plotting utilities
├── CookPoliticalData.csv # District data
├── requirements.txt # Python dependencies
├── setup.py # Package installation script
└── README.md # This file
This Python implementation closely follows the structure and logic of the original Scala code in rcvcore/
, adapting the object-oriented design to Python idioms while maintaining the same simulation algorithms and parameters.
The simulation uses only Python standard library for core functionality, with matplotlib and numpy required only for visualization features.