# How Voting Systems Work 1, Exercise 2: how often do three voters produce a cycle? # Three voters each pick one of the 6 possible strict rankings of A, B, C. # There are 6 x 6 x 6 = 216 equally likely electorates (ordered). Count the # ones with a cycle, then estimate the rate for a larger electorate by # simulation (seeded, so the run is repeatable). import random from itertools import permutations, product rankings = list(permutations("ABC")) def has_cycle(profile): def beats(x, y): return sum(1 for b in profile if b.index(x) < b.index(y)) > len(profile) / 2 return (beats("A", "B") and beats("B", "C") and beats("C", "A")) or \ (beats("B", "A") and beats("C", "B") and beats("A", "C")) cycles = sum(1 for p in product(rankings, repeat=3) if has_cycle(p)) print(f"3 voters: {cycles} of {6 ** 3} electorates have a cycle ({cycles / 6 ** 3:.1%})") random.seed(31) trials = 2000 for voters in (3, 11, 101): hits = sum( 1 for _ in range(trials) if has_cycle([random.choice(rankings) for _ in range(voters)]) ) print(f"{voters:3d} random voters: {hits / trials:.1%} of {trials} simulated electorates had a cycle") # Output when run: # 3 voters: 12 of 216 electorates have a cycle (5.6%) # 3 random voters: 5.4% of 2000 simulated electorates had a cycle # 11 random voters: 7.0% of 2000 simulated electorates had a cycle # 101 random voters: 7.6% of 2000 simulated electorates had a cycle