Duverger's Law Experiment
Multi-step simulation demonstrating Duverger's Law: FPTP tends toward two-party systems while PR maintains multi-party diversity.
run_duverger_experiment
Run a sequence of elections with strategic voting to observe convergence effects.
from electoral_sim.analysis.duverger import run_duverger_experiment
history = run_duverger_experiment(
n_voters=2000,
n_parties=5,
n_steps=10,
system="FPTP",
seed=42,
)
Parameters:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| n_voters | int | 2000 | Number of voters |
| n_parties | int | 5 | Number of initial parties |
| n_steps | int | 10 | Number of sequential elections |
| system | Literal["FPTP", "PR"] | "FPTP" | Electoral system to simulate |
| seed | int | 42 | Random seed |
| strategic_penalty | float | 50.0 | Utility penalty for voting for unviable parties |
| viability_threshold | float | 0.15 | Vote share threshold for party viability |
| temperature | float | 0.1 | Logit temperature (lower = sharper choices) |
Returns: List of per-step dicts, each containing:
| Key | Type | Description |
|-----|------|-------------|
| step | int | Election number (0-indexed) |
| enp | float | Effective Number of Parties |
| vote_shares | list[float] | Vote share per party |
| winner | int | Index of winning party |
Mechanics: The experiment uses BehaviorEngine with ProximityModel + WastedVoteModel to capture the psychological effect of Duverger's Law. After each election, vote shares become the viability signal for the next round, creating a feedback loop that amplifies strategic voting.
Example:
# Compare FPTP vs PR convergence
import polars as pl
fptp = run_duverger_experiment(n_voters=5000, system="FPTP", n_steps=15)
pr = run_duverger_experiment(n_voters=5000, system="PR", n_steps=15)
for h in fptp:
print(f"Step {h['step']}: ENP = {h['enp']:.2f}")
# Under FPTP, ENP should converge towards ~2
# Under PR, ENP should remain close to n_parties
Research Basis
Duverger's Law mechanics rely on two effects:
- Mechanical Effect: High threshold for representation in FPTP — only the largest party in each constituency wins a seat.
- Psychological Effect: Strategic voting to avoid wasted votes — voters abandon unviable parties over repeated election cycles.
The experiment simulates both effects simultaneously using WastedVoteModel with a viability feedback loop.
See also: Electoral Systems, Behavior Models.