Skip to main content

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

Tests Lint Coverage PyPI Python Downloads License: Apache 2.0 Documentation Code style: black

DocumentationPyPIQuick 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


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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

electoral_sim-0.1.0.tar.gz (111.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

electoral_sim-0.1.0-py3-none-any.whl (101.5 kB view details)

Uploaded Python 3

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

Hashes for electoral_sim-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e10d1434536d07332d93b3183b1c593073f7d873a3141093c7fb0cd56971e001
MD5 df458e5f041d0120e7fdc1bb0c63c190
BLAKE2b-256 d98c93d40e373a716efdc04bf1dc95194b5523ac8d833a8423b292174dadff58

See more details on using hashes here.

Provenance

The following attestation bundles were made for electoral_sim-0.1.0.tar.gz:

Publisher: release.yml on Ayush12358/ElectoralSim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for electoral_sim-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1cb9536650d6c6c6f01355327a6dae28f78ee63f308bcecc778031d7b7fa281b
MD5 8deed5f121acc67ef08ba7a355ed3dcd
BLAKE2b-256 8f1a049e3f3b8caaf02dc09a4b647d4918ba05ab0ca17a95d0e7d61b7023e895

See more details on using hashes here.

Provenance

The following attestation bundles were made for electoral_sim-0.1.0-py3-none-any.whl:

Publisher: release.yml on Ayush12358/ElectoralSim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page