ElectionModel
The central class for running electoral simulations.
Constructor
ElectionModel(
n_voters: int = 100_000,
n_constituencies: int = 10,
parties: list[dict] | None = None,
electoral_system: str = "FPTP",
allocation_method: str = "dhondt",
threshold: float = 0.0,
temperature: float = 0.5,
seed: int | None = None,
behavior_engine: BehaviorEngine | None = None,
opinion_dynamics: OpinionDynamics | None = None,
include_nota: bool = False,
constituency_constraints: dict[int, list[str]] | None = None,
anti_incumbency: float = 0.0,
economic_growth: float = 0.0,
national_mood: float = 0.0,
alienation_threshold: float = -2.0,
indifference_threshold: float = 0.3,
event_probs: dict[str, float] | None = None,
use_adaptive_strategy: bool = False,
use_gpu: bool = False,
)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
n_voters |
int | 100,000 | Total number of voter agents |
n_constituencies |
int | 10 | Number of electoral districts |
parties |
list[dict] | None | Party configurations (auto-generated if None) |
electoral_system |
str | "FPTP" | "FPTP" or "PR" |
allocation_method |
str | "dhondt" | For PR: "dhondt", "sainte_lague", "hare", "droop" |
threshold |
float | 0.0 | Electoral threshold (0-1) |
temperature |
float | 0.5 | MNL temperature (lower = more deterministic) |
seed |
int | None | Random seed for reproducibility |
behavior_engine |
BehaviorEngine | None | Custom voter behavior models |
opinion_dynamics |
OpinionDynamics | None | Social network for opinion evolution |
include_nota |
bool | False | Include "None of the Above" option |
anti_incumbency |
float | 0.0 | Penalty to incumbent parties |
economic_growth |
float | 0.0 | Economic growth rate (affects retrospective voting) |
national_mood |
float | 0.0 | Wave election modifier (+ pro-incumbent, - anti-incumbent) |
alienation_threshold |
float | -2.0 | Abstain if max utility below this |
indifference_threshold |
float | 0.3 | Abstain if utility range below this |
use_gpu |
bool | False | Use CuPy GPU acceleration |
Class Methods
from_config
Create model from a Config object.
Example:
from electoral_sim import Config, ElectionModel, PartyConfig
config = Config(
n_voters=100_000,
parties=[
PartyConfig("Left", -0.5, 0.0, 50),
PartyConfig("Right", 0.5, 0.0, 50),
],
electoral_system="PR"
)
model = ElectionModel.from_config(config)
from_preset
Create model from a country preset.
Available presets: "india", "usa", "uk", "germany", "brazil", "france", "japan", "australia_house", "australia_senate", "south_africa"
Example:
Chainable Methods
with_system
Set electoral system ("FPTP" or "PR").with_allocation
Set PR allocation method.with_threshold
Set electoral threshold (0-1).with_temperature
Set MNL temperature.Example:
results = (
ElectionModel(n_voters=50_000)
.with_system("PR")
.with_allocation("sainte_lague")
.with_threshold(0.05)
.run_election()
)
Instance Methods
run_election
Run a single election simulation.
Returns: Dictionary with:
| Key | Type | Description |
|-----|------|-------------|
| seats | np.ndarray | Seats won by each party |
| vote_counts | np.ndarray | Votes received by each party |
| turnout | float | Fraction of voters who voted |
| gallagher | float | Disproportionality index |
| enp_votes | float | ENP by vote share |
| enp_seats | float | ENP by seat share |
| vse | float | Voter Satisfaction Efficiency |
run_elections_batch
Run multiple elections for Monte Carlo analysis.
get_aggregate_stats
Compute statistics across multiple elections.
Returns:
{
"n_elections": 100,
"turnout_mean": 0.754,
"turnout_std": 0.012,
"gallagher_mean": 12.5,
"gallagher_std": 2.1,
...
}
step
Run one simulation step (for opinion dynamics).
Accessing Agent Data
Voters
Columns include:
- constituency — District assignment
- age, gender, education, income, religion — Demographics
- party_id_7pt — Party identification (-3 to +3)
- ideology_x, ideology_y — 2D ideological position
- openness, conscientiousness, extraversion, agreeableness, neuroticism — Big Five
- mf_care, mf_fairness, mf_loyalty, mf_authority, mf_sanctity — Moral Foundations
- political_knowledge, misinfo_susceptibility — Information attributes
- turnout_prob — Base turnout probability
Parties
Columns:
- name — Party name
- position_x, position_y — Ideological position
- valence — Non-policy appeal score
- incumbent — Is incumbent party
- seats, vote_share — Results (after election)
Config
Configuration dataclass for model setup.
@dataclass
class Config:
n_voters: int = 100_000
n_constituencies: int = 10
parties: list[PartyConfig | dict] = field(default_factory=list)
electoral_system: Literal["FPTP", "PR"] = "FPTP"
allocation_method: Literal["dhondt", "sainte_lague", "hare", "droop"] = "dhondt"
threshold: float = 0.0
temperature: float = 0.5
seed: int | None = None
PartyConfig
Party definition dataclass.