In each of the 51 ballots ranking Seattle first, Puyallup will be given 1 point, Olympia 2 points, Tacoma 3 points, and Seattle 4 points. Multiplying the points per vote times the number of votes allows us to calculate points awarded:
Adding up the points:
- Seattle: points
- Tacoma: points
- Puyallup: points
- Olympia: points
Under the Borda Count method, Tacoma is the winner of this vote.
# Math in Society 2.8 -- Borda Count
# Where should the mathematicians hold their conference?
schedule = [(51, ["Seattle", "Tacoma", "Olympia", "Puyallup"]),
(25, ["Tacoma", "Puyallup", "Olympia", "Seattle"]),
(10, ["Puyallup", "Tacoma", "Olympia", "Seattle"]),
(14, ["Olympia", "Tacoma", "Puyallup", "Seattle"])]
cands = sorted({c for _, r in schedule for c in r})
N = len(cands)
POINTS = list(range(N, 0, -1)) # the book's scale: 4, 3, 2, 1. EDIT: try [3, 2, 1, 0]
total = sum(n for n, _ in schedule)
pts = {c: 0 for c in cands}
detail = {c: [] for c in cands}
for n, ranking in schedule:
for place, c in enumerate(ranking):
pts[c] += POINTS[place] * n
detail[c].append(f"{POINTS[place]}x{n}={POINTS[place]*n:>4}")
print(f"{total} ballots. Point scale, 1st place to last: {POINTS}\n")
w = max(len(c) for c in cands)
for c in sorted(cands, key=lambda c: -pts[c]):
print(f"{c:<{w}} " + " + ".join(detail[c]) + f" = {pts[c]:>4} points")
borda = max(pts, key=lambda c: (pts[c], c))
first = {c: 0 for c in cands}
for n, ranking in schedule:
first[ranking[0]] += n
plur = max(first, key=lambda c: (first[c], c))
ranked = sorted(first, key=lambda c: -first[c])
print("\nFirst-choice votes: " + ", ".join(f"{c} {first[c]}" for c in ranked))
print(f"Plurality winner: {plur} with {first[plur]}/{total} = {first[plur]/total:.0%}")
print(f"Borda winner: {borda} with {pts[borda]} points")
if first[plur] * 2 > total and plur != borda:
print(f"\n{plur} holds an outright MAJORITY of first-choice votes and still loses.")
print("This election violates the Majority Criterion -- and therefore the")
print(f"Condorcet Criterion too, since {plur} would beat anyone one-to-one.")
worst = max(r.index(borda) for _, r in schedule) + 1
print("Borda rewards the broadly acceptable compromise:")
print(f" {borda} is first on only {first[borda]} ballots but never below place {worst}")
print(f" {plur} is first on {first[plur]} ballots"
f" but LAST on the other {total - first[plur]}")
print("\nTry it: set POINTS = [3, 2, 1, 0] and re-run. Every total drops by exactly")
print("one point per ballot, so the ORDER is unchanged -- with complete ballots any")
print("evenly spaced scale gives the same Borda ranking.")
print("Try it: swap Seattle and Tacoma in the 25-voter column to see the winner move.")