# How Voting Systems Work 5, Exercise 3: how often do plurality and Borda pick the Condorcet winner? # Two assumed models, 3,000 seeded elections each, 5 candidates, 51 voters. import random from collections import Counter def pairwise(ballots): names = sorted(ballots[0]) return {(x, y): sum(1 for b in ballots if b.index(x) < b.index(y)) for x in names for y in names if x != y} def condorcet(ballots): wins, n = pairwise(ballots), len(ballots) for x in ballots[0]: if all(wins[x, y] > n / 2 for y in ballots[0] if y != x): return x return None random.seed(5) trials, voters, k = 3000, 51, 5 names = [f"C{i}" for i in range(k)] print("model has CW plurality picks CW Borda picks CW") for model in ("line", "random ballots"): found = plural_hits = borda_hits = 0 for _ in range(trials): if model == "line": pos = {c: random.random() for c in names} ballots = [] for _ in range(voters): v = random.random() ballots.append(tuple(sorted(names, key=lambda c: abs(pos[c] - v)))) else: ballots = [tuple(random.sample(names, k)) for _ in range(voters)] cw = condorcet(ballots) if cw is None: continue found += 1 plural = Counter(b[0] for b in ballots) borda = Counter() for b in ballots: for place, c in enumerate(b): borda[c] += k - 1 - place plural_hits += max(plural, key=plural.get) == cw borda_hits += max(borda, key=borda.get) == cw print(f"{model:<15} {found / trials:7.1%} {plural_hits / found:14.1%} {borda_hits / found:20.1%}") # Output when run: # model has CW plurality picks CW Borda picks CW # line 100.0% 40.7% 78.9% # random ballots 74.6% 60.4% 85.3%