High-performance agent-based electoral simulation toolkit with support for 11+ countries, multiple voting systems, and advanced voter behavior models
Project description
ElectoralSim
Advanced Agent-Based Electoral Simulation Toolkit
Documentation • PyPI • Quick Start
A modular, high-performance simulation toolkit for electoral systems, voter behavior, and political dynamics. Built on Mesa with Polars DataFrames for vectorized agent-based modeling at scale.
Key Features
Performance
- 1M+ voters with vectorized Polars DataFrames & Numba JIT acceleration (89x speedup)
- 30 elections/second batch simulation capability
- Batch parameter sweeps for systematic exploration
- Parallel execution with multiprocessing
- Optional GPU support via CuPy for massive-scale simulations
Electoral Systems
| System | Methods |
|---|---|
| Plurality | First Past The Post (FPTP) |
| Proportional | D'Hondt, Sainte-Laguë, Hare Quota, Droop Quota |
| Ranked Choice | IRV/RCV, STV (Single Transferable Vote) |
| Other | Approval Voting, Condorcet Winner |
Voter Behavior Models
- Proximity Model — Spatial voting based on ideological distance
- Valence Model — Non-policy candidate appeal (charisma, competence)
- Retrospective Model — Economic voting (reward/punish incumbents)
- Strategic Voting — Duverger's Law, wasted vote model
- Sociotropic/Pocketbook — National vs personal economic evaluation
Voter Psychology
- Big Five (OCEAN) — Personality traits influencing ideology
- Moral Foundations — Haidt's Care, Fairness, Loyalty, Authority, Sanctity
- Media Diet — Voter-specific media bias and misinformation susceptibility
- Affective Polarization — In-group/out-group sentiment
Opinion Dynamics
- Network Topologies — Barabási-Albert, Watts-Strogatz, Erdős-Rényi
- Models — Bounded Confidence, Noisy Voter, Zealots
- Media Effects — Mass media bias with Raducha susceptibility model
Coalition & Government
- Formation — MWC, MCW, Laver-Shepsle portfolio allocation
- Stability — Sigmoid/Linear/Exponential collapse models
- Analysis — Coalition strain, junior partner penalty, Cox hazard
Metrics
- Gallagher Index (disproportionality)
- Effective Number of Parties (Laakso-Taagepera)
- Efficiency Gap, Loosemore-Hanby, Herfindahl-Hirschman Index
- Voter Satisfaction Efficiency (VSE)
Country Presets (11 Countries)
| Region | Countries |
|---|---|
| Asia | 🇮🇳 India (543 Lok Sabha), 🇯🇵 Japan |
| Europe | 🇬🇧 UK, 🇩🇪 Germany, 🇫🇷 France, 🇪🇺 EU Parliament (720 MEPs) |
| Americas | 🇺🇸 USA, 🇧🇷 Brazil |
| Oceania/Africa | 🇦🇺 Australia, 🇿🇦 South Africa |
Installation
pip install electoral-sim
From source:
git clone https://github.com/Ayush12358/ElectoralSim.git
cd ElectoralSim
pip install -e .
Optional dependencies:
pip install electoral-sim[viz] # Visualization (matplotlib, plotly)
pip install electoral-sim[gpu] # GPU acceleration (cupy)
pip install electoral-sim[all] # Everything
Command-Line Interface
Run simulations directly from the command line:
# Basic simulation
electoral-sim run --voters 50000 --constituencies 10
# Use country preset
electoral-sim run --preset india --output results.json
# Batch parameter sweeps
electoral-sim batch --config batch_config.json --output results.csv
# List available presets
electoral-sim list-presets
See the CLI Guide for comprehensive usage.
Quick Start
Basic Election
from electoral_sim import ElectionModel
# Create model with 100K voters
model = ElectionModel(n_voters=100_000, seed=42)
results = model.run_election()
print(f"Turnout: {results['turnout']:.1%}")
print(f"Gallagher Index: {results['gallagher']:.2f}")
print(f"ENP (votes): {results['enp_votes']:.2f}")
Country Presets
# India - Full Lok Sabha simulation
from electoral_sim import simulate_india_election
result = simulate_india_election(n_voters_per_constituency=1000)
print(f"BJP: {result.seats['BJP']} seats")
print(f"NDA Alliance: {result.nda_seats} seats")
# Other countries
model = ElectionModel.from_preset("germany") # MMP with 5% threshold
model = ElectionModel.from_preset("usa") # 435 House districts
model = ElectionModel.from_preset("uk") # 650 Commons seats
Chainable API
results = (
ElectionModel(n_voters=100_000)
.with_system("PR")
.with_allocation("sainte_lague")
.with_threshold(0.05)
.with_temperature(0.3) # More deterministic voting
.run_election()
)
Batch Runner - Parameter Sweeps
Systematic parameter exploration for sensitivity analysis:
from electoral_sim.analysis import BatchRunner, ParameterSweep
# Define parameter sweep
sweep = ParameterSweep({
'n_voters': [10_000, 50_000, 100_000],
'temperature': [0.3, 0.5, 0.7],
'economic_growth': [-0.02, 0.0, 0.02]
})
# Run batch with parallel execution
runner = BatchRunner(
model_class=ElectionModel,
parameter_sweep=sweep,
n_runs_per_config=5,
n_jobs=4
)
results_df = runner.run()
runner.export_results('results.csv')
Custom Behavior Engine
from electoral_sim import (
ElectionModel, BehaviorEngine,
ProximityModel, ValenceModel, StrategicVotingModel
)
# Build custom voter behavior
engine = BehaviorEngine()
engine.add_model(ProximityModel(weight=1.0))
engine.add_model(ValenceModel(weight=0.5))
engine.add_model(StrategicVotingModel(sensitivity=2.0))
model = ElectionModel(n_voters=50_000, behavior_engine=engine)
results = model.run_election()
Opinion Dynamics
from electoral_sim import ElectionModel, OpinionDynamics
# Create social network
od = OpinionDynamics(n_agents=10_000, topology="barabasi_albert", m=3)
# Simulate with opinion evolution
model = ElectionModel(n_voters=10_000, opinion_dynamics=od)
for _ in range(100):
model.step() # Opinions evolve
result = model.run_election()
Coalition Formation
from electoral_sim import form_government, coalition_strain
import numpy as np
seats = np.array([150, 120, 80, 50])
positions = np.array([0.6, -0.3, 0.1, -0.6])
names = ["Right", "Left", "Center", "Far-Left"]
gov = form_government(seats, positions, names)
print(f"Coalition: {gov['coalition_names']}")
print(f"Majority: {gov['seats']} seats")
print(f"Stability: {gov['stability']:.2f}")
Streamlit Dashboard
Launch the interactive election explorer:
streamlit run app.py
Features:
- Multi-country simulation (India, USA, UK, Germany, etc.)
- Dynamic parameters (economic growth, national mood, anti-incumbency)
- Real-time seat distribution and vote share charts
- Swing analysis and ideological landscape visualization
🏗️ Project Structure
electoral_sim/
├── core/ # ElectionModel, Config, Voter Generation
├── agents/ # Voter, Party, Adaptive Strategy
├── behavior/ # Behavior models (Proximity, Valence, Strategic, etc.)
├── dynamics/ # Opinion dynamics (networks, bounded confidence)
├── engine/ # Numba/GPU acceleration, Coalition, Government
├── events/ # Event manager (scandals, economic shocks)
├── metrics/ # Gallagher, ENP, VSE, Efficiency Gap
├── presets/ # Country configs (11 countries + EU)
│ ├── india/ # 543 constituencies, 17 parties
│ ├── eu/ # 27 member states, 720 MEPs
│ └── ...
├── systems/ # Electoral systems (allocation, IRV, STV)
├── visualization/ # Plots, maps, animations
└── data/ # Historical election data
Performance Benchmarks
| Scale | Create Time | Election Time | Memory |
|---|---|---|---|
| 10K voters | 18ms | 5ms | 52 MB |
| 100K voters | 109ms | 35ms | 15 MB |
| 500K voters | 608ms | 176ms | 95 MB |
| 1M voters | 1.2s | 316ms | 148 MB |
| 2M voters | 2.4s | 672ms | 181 MB |
Batch elections: ~200ms/election at 500K voters (5 elections/sec)
Testing
# Run all tests
pytest tests/ -v
# Run integration tests only
pytest tests/test_integration.py -v
# Run stress tests
python tests/stress_test.py
Test coverage: 222 tests with ~70% code coverage, including:
- Property-based tests (Hypothesis) - random input generation
- Parameterized tests - all systems, presets, allocation methods
- Performance benchmarks - 1K, 10K voters timing
- Error handling - invalid inputs, edge cases
- Real-world validation - UK, US, Germany metrics
Documentation
- Usage Guide — Detailed API usage examples
- docs/ — Full documentation
- API Reference — Complete function/class documentation
- Country Presets — India, EU, and other country guides
- Advanced Topics — Voter psychology, performance tuning
Tech Stack
| Component | Library |
|---|---|
| Agent-Based Modeling | Mesa |
| DataFrames | Polars |
| JIT Acceleration | Numba |
| GPU Support | CuPy |
| Social Networks | NetworkX |
| Visualization | Plotly, Matplotlib |
| Dashboard | Streamlit |
License
Apache License 2.0 - see LICENSE for details.
Acknowledgments
- Mesa for the agent-based modeling framework
- Political science research on spatial voting, opinion dynamics, and coalition theory
- Electoral data from various national election commissions
Built with love for computational political science
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file electoral_sim-0.1.0.tar.gz.
File metadata
- Download URL: electoral_sim-0.1.0.tar.gz
- Upload date:
- Size: 111.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e10d1434536d07332d93b3183b1c593073f7d873a3141093c7fb0cd56971e001
|
|
| MD5 |
df458e5f041d0120e7fdc1bb0c63c190
|
|
| BLAKE2b-256 |
d98c93d40e373a716efdc04bf1dc95194b5523ac8d833a8423b292174dadff58
|
Provenance
The following attestation bundles were made for electoral_sim-0.1.0.tar.gz:
Publisher:
release.yml on Ayush12358/ElectoralSim
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
electoral_sim-0.1.0.tar.gz -
Subject digest:
e10d1434536d07332d93b3183b1c593073f7d873a3141093c7fb0cd56971e001 - Sigstore transparency entry: 779917855
- Sigstore integration time:
-
Permalink:
Ayush12358/ElectoralSim@df122a813def87d4389c939634e9ad86f8b286f7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Ayush12358
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@df122a813def87d4389c939634e9ad86f8b286f7 -
Trigger Event:
push
-
Statement type:
File details
Details for the file electoral_sim-0.1.0-py3-none-any.whl.
File metadata
- Download URL: electoral_sim-0.1.0-py3-none-any.whl
- Upload date:
- Size: 101.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1cb9536650d6c6c6f01355327a6dae28f78ee63f308bcecc778031d7b7fa281b
|
|
| MD5 |
8deed5f121acc67ef08ba7a355ed3dcd
|
|
| BLAKE2b-256 |
8f1a049e3f3b8caaf02dc09a4b647d4918ba05ab0ca17a95d0e7d61b7023e895
|
Provenance
The following attestation bundles were made for electoral_sim-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Ayush12358/ElectoralSim
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
electoral_sim-0.1.0-py3-none-any.whl -
Subject digest:
1cb9536650d6c6c6f01355327a6dae28f78ee63f308bcecc778031d7b7fa281b - Sigstore transparency entry: 779917857
- Sigstore integration time:
-
Permalink:
Ayush12358/ElectoralSim@df122a813def87d4389c939634e9ad86f8b286f7 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Ayush12358
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@df122a813def87d4389c939634e9ad86f8b286f7 -
Trigger Event:
push
-
Statement type: