15

Politico's New Yorkers pick a new mayor after chaotic, historic primary begins:

NEW YORK — Polls have closed in New York City’s first ever ranked-choice election and, while the die has been cast, voters may not know the outcome for weeks.

[...] Further extending the ballot count is the advent of ranked-choice voting, which allows New Yorkers to select up to five candidates for each position. The system kicks in when no candidate attains 50 percent of votes on the first pass. The board plans to issue preliminary results of ranked ballots on June 29.

According to this:

More than a dozen Democrats and two Republicans will vie to replace outgoing Mayor Bill de Blasio (D). The ranked-choice election is expected to take weeks to resolve.

So the number of distinct yet valid ways a person could vote is large. I think that it's the sum of 0-, 1-, 2-, 3-, 4- and 5-from-14 possibilities, but I'm not even sure of that (see below).

I'm curious how New York City will physically and computationally implement ranked-choice vote counting.

Question: Algorithmically it can be done via several passes of a sorting function over all ranked-choice votes in a table in memory or on a hard drive, but how do they implement this with the various physical forms of votes cast in New York's mayoral election?

Will they resort to all electronic implementation of the algorithm, all physical, or some hybrid method?


In Python, assuming (for example) exactly 14 candidates available (in math it's number of permutations without repetitions)

from itertools import permutations
possible = []
for k in [0, 1, 2, 3, 4, 5]:
    uniques = list(permutations('abcdefghijklmn', k))
    possible.append(uniques)
    print(k, len(uniques))
all_possible = sum(possible, [])
print('total: ', len(all_possible))

 k        uniques
 0           1
 1          14
 2         182
 3        2184
 4       24024
 5      240240

total:  266645
12
  • 8
    What's your question about? The political and logistical risks and outcomes of choosing what some would consider to be an over-complicated and confusing voting system? Or the algos for it? I really don't think quoting Python code is within the intent of this site. That said, given clear rules of how the ranking works mathematically, the least of the problems is likely getting the results once the ballots have been scanned or uploaded. Jun 23 at 3:13
  • 2
    @ItalianPhilosophers4Monica see the part where it says Question: in bold font, "...but how do they implement this..." It's not about rules, it's about how the rules are implemented; by physical counting sorting 3000+ kinds of votes.
    – uhoh
    Jun 23 at 3:15
  • 3
    It's a little unclear what you're asking. Are you asking what the ballot might look like, given that there are so many possible combinations? Remember there doesn't need to be a separate box for each combination, there could just be a grid with a line for each candidate and five columns for first through fifth choice. Jun 23 at 3:18
  • 1
    rather than posting code, maybe post a sample ballot? Jun 23 at 3:21
  • 7
    Ranked-Choice Voting (RCV) can refer to various voting systems, though in the USA I think it usually means Instant-Runoff Voting (IRV) — is that what's meant here?
    – gidds
    Jun 23 at 11:38
37

How ranked choice voting ballots can be counted by hand

I think the counting can be done by hand (using several 'passes' if necessary). For example, in Canada, according to CBC.ca (on ranked voting in Canada):

"They're really simple. They're as easy as one, two three. You rank your choices in order — so who do I want to be mayor, who's my first choice, who's my second choice, and who's my third choice.

In the first round, we just add up the first choices, and if anyone has a majority, it's over. They win. But if nobody has a majority — let's say the person with the most votes only has 30 per cent — then obviously they shouldn't be the mayor necessarily.

So you eliminate the candidate with the fewest votes, and you just transfer those ballots to the second choice on each ballot until somebody has a majority.

Counting this by hand doesn't seem so difficult, you wouldn't need to account for all the possible ballot combinations in the counting process.

As the quote says, you start by dividing the ballots by first choice. If you have 14 candidates, then you have 14 piles of ballots. If there's no winner based on first choices, then you eliminate the candidate with the fewest (first choice) votes and start looking at the second choice on the ballots from that pile. Then you have only 13 candidates left in the running. this process continues until you have a winner.

This is also how NPR describes the counting process for the New York City mayoral election:

  1. If someone gets 50% plus one after all the first-choice votes are counted, then the election is over and that candidate wins.

  2. But if no one gets 50% plus one, it's on to Round 2.

  3. The person with the lowest number of first-place votes is eliminated, and that candidate's voters' second choices get redistributed as votes for other candidates.

  4. This reallocation of votes goes on until someone reaches 50% plus one.

New York's implementation

In New York's election though, the votes will be counted by machine. As CBS News reported on May 25th 2021:

New Yorkers can expect to find out who won the city's upcoming Democratic mayoral primary more quickly than they would have if the New York State Board of Elections hadn't acted Tuesday to approve software for tabulating ranked-choice voting results. The decision means the city will now avoid a lengthy hand count of the ballots cast in the race next month.

Nevertheless, results probably won't be available right away, from that same CBS News article:

Despite the software approval, it'll still be days, if not weeks, before New Yorkers know who won the June 22 primary. Unofficial results of the first-choice votes are expected to be released on primary night to show first-choice votes, but the city Board of Elections says that officials won't be able to start calculating results until at least the following week.

As for the specific implementation, that's already been covered in-depth by Zach Lipton's answer.

13
  • 19
    @endolith you don't need to take them all to a single location, you can carry out the count once per district and call in the counts to a central location. Then recount the ballots where the first choice was for the lowest-ranked, and continue. What you do have to do, of course, is wait for all districts to report their results so you know who's last at any given stage
    – Chris H
    Jun 23 at 11:58
  • 1
    @MichaelRichardson - That could be a really interesting new question to ask. But if you vote for one of the top candidates, why would it matter who else you wanted if they didn't get the job?
    – Bobson
    Jun 23 at 15:30
  • 6
    @Bobson Suppose there are two really popular but controversial candidates, A and B, who split most of the #1 votes between them, but voters for each of them really hate the other one. There is also a well regarded compromise candidate C that everybody likes, but in most cases not as their #1 pick. C takes an overwhelming majority of the #2 votes. C seems the obvious best option, with by far the broadest support if you check #2 votes, but C gets eliminated for having only 5% of the #1 votes, and you end up with a winner who half the voters like somewhat more than C but the other half hate.
    – Douglas
    Jun 23 at 16:00
  • 11
    @Douglas: IRV is not perfect. What you describe is a great example of IRV failing to satisfy the Condorcet criterion (anyone who would win every pairwise election should win the whole election).
    – Kevin
    Jun 23 at 16:07
  • 3
    The counting could be done by hand, but that's not an answer to the question, which is "how will NYC" count the votes. The ballots are computer scannable, so the obvious intention is to have the computer count the votes, not people.
    – phoog
    Jun 24 at 1:46
20

New York City did tabulate some ranked choice ballots by hand in special elections earlier this year, where the number of ballots and candidates was comparatively small and hand counting was more feasible.

However, for the Mayoral election, the state Board of Elections certified software for the counting process: The RCV Universal Tabulator, an open source package produced by a non-profit group called The Ranked Choice Resource Center.

The software is open source and can be viewed on GitHub. I imagine the physical ballots will be scanned using typical certified voting tabulation equipment to produce the input for the RCV software. If you're able to read Java, the core tabulation loop looks pretty straightforward (the software supports multiple winners, though that's clearly not being used in this election):

// At each iteration, we'll either a) identify one or more
// winners and transfer their votes to the remaining candidates (if we still need to find more
// winners), or b) eliminate one or more candidates and gradually transfer votes to the
// remaining candidates.

They'll eventually release the full cast vote record as well, which will allow anyone to perform their own version of the algorithm if they wish.

5
  • 5
    Of the three current answers only this one directly addresses "How will New York City physically implement the ranked choice voting algorithm..." Ballots will be scanned and the data processed by software X which has been certified by board Y and here are the supporting sources. We won't be seeing fourteen piles of hand sorted votes after each pass.
    – uhoh
    Jun 23 at 22:38
  • update: now some others do as well.
    – uhoh
    Jun 24 at 22:14
  • "They'll eventually release the full cast vote record as well" Can you provide a source for this?
    – endolith
    Jul 9 at 21:15
  • 1
    @endolith The source is the Gothamist article linked under "certified software," which says: "So far, the city BOE said it will not release what’s called the “cast-vote record” until after the primary results are certified, which could be several weeks after the primary. The cast-vote record shows the results based on how voters ranked all their choices and it is what’s used when compiling the ranked-choice voting results." Jul 9 at 22:52
  • And just to follow up, here is the cast vote record, which has been posted online following the primary. Oct 5 at 21:53
12

I think you're misunderstanding how the ranked choice voting works. If, as was the case, no candidate crosses 50% of the vote, the last-place candidate is eliminated. Their ballots are now all allocated to the second-choice candidates from their voters. So the only votes that need to be re-counted are the last-place candidate's.

We then go back to the beginning and pretend that those recategorized votes have the second-choice candidate as their first-choice candidate, third-choice as second-choice etc. and again look to see if anyone has crossed 50%. If not, we repeat the process with the new last-place candidate. Note that it's possible that the threshold for 50% will go down as the process continues if anyone doesn't pick a second- or third- etc. candidate.

The process is described here: https://vote.nyc/page/ranked-choice-voting

I'd add also, that (a) they're not going to start the process until next week and (2) some of the early round reallocations will go really fast since there are very small numbers for the most minor candidates.

14
  • 13
    @uhoh you describe a process that doesn't correspond to how ranked-choice voting works. I answered the question of how, but also pointed out that your question was flawed because the voting doesn't work the way you think it does.
    – Don Hosek
    Jun 23 at 3:19
  • 19
    You talk about how many possible ballot combinations there could be (and write a Python program to something that could be calculated with high school mathematics and a calculator—and got the wrong answer to boot. The number of ranked choices of 5 out of 14 candidates if ₅*P*₁₄ = 14!/5! = 726,485,760). You don't need algorithms, you need stacks of ballots. I used to teach this material. I know it and I can tell when someone doesn't understand it.
    – Don Hosek
    Jun 23 at 3:33
  • 9
    And my exact words were, "I think you're misunderstanding how ranked-choice voting works" Nothing you've said has done anything than persuade me that you don't.
    – Don Hosek
    Jun 23 at 3:34
  • 6
    D''oh! It's been so long since I had to calculate a permutation I got the denominator wrong. Most of the time, the calculation is the permutation which has a denominator of (m-n)!n! and I dropped the wrong denominator. It is 15 years since I was last teaching. But regardless, that number doesn't come into play in ranked choice voting. The same class where I taught permutations also covered voting algorithms and we did a mock election (of ice cream flavors) with multiple voting algorithms. Even with 40 students it was a quick job to count votes in class for each of the algorithms.
    – Don Hosek
    Jun 23 at 3:59
  • 10
    In retrospect, I should have had an election on vote-counting algorithms.
    – Don Hosek
    Jun 23 at 3:59
5

I'm curious how New York City will physically and computationally implement ranked-choice vote counting.

Physically, voters received a tabular ballot (see this NYC government page) enter image description here where rows are candidates and columns are order of preference, and the ballots are scanned to obtain varying length records (the voter can express 1÷5 choices) containing the voted candidates in order of preference.

Computationally, NYC has a more fail-safe version of this (relatively) simple Python script

from random import seed, shuffle
from timeit import default_timer as dt
seed(20210622)
n_candidates, n_choices, n_ballots = 14, 5, 10**6    
# ##### generate the ballots
start_generation = dt()
candidates = list(range(n_candidates))+[0] # introducing a bias for candidate 0
ballots = [candidates[:n_choices] for _ in range(n_ballots)
           if not shuffle(candidates)]
print("\nGeneration of %d ballots required %.2f s"%(
        n_ballots, dt()-start_generation))

# ##### process the ballots
start_count = dt()
while True:
    counts = {candidate:0 for candidate in candidates}
    # count 1st choices
    for ballot in ballots: counts[ballot[0]] += 1
    # sort candidates according to 1st choices
    ranks = sorted(list(counts.items()), key=lambda t:t[1])
    # max no. of 1st choices
    max_1st = ranks[-1][1]
    # if there is a winner, stop counting
    if max_1st > len(ballots)//2: break
    
    # who is the loser?
    loser = ranks[0][0]
    
    # remove loser from ballots and from list of candidates
    for ballot in ballots:
        if loser in ballot: ballot.remove(loser)
    candidates.remove(loser)

    # remove any empty ballot from list of ballots
    # (copying not empty ballots is WAY FASTER than deleting void ballots)
    ballots = [ballot for ballot in ballots if ballot]

# we have a winner
print(*reversed(ranks), sep='\n')
print("Counting %d ballots required %.2f s"%(
        n_ballots, dt()-start_count))

When I ran it on my old, low end notebook I got the following output

Generation of 1000000 ballots required 9.29 s
(0, 490711)
(12, 245897)
Counting 1000000 ballots required 6.08 s

Even in this simulation it is apparent that the real problem is preparing the data in a format that is suitable for counting, then it's a matter of seconds…


As a foot note, initially I thought I had to optimize the script using vector math libraries but it turned out it is not necessary.

4
  • comments are not for +1 so I'll +n! instead, but I'm wondering if detection and handling of missing rankings (e.g. 2nd, 3rd and 5th only) or repetitions (e.g. 1st: "X", 2nd: "Y", 3rd: "X") is an important part of the process? I didn't specifically ask about that, but since you've posted an example algorithm it should somehow represent each of the critical elements.
    – uhoh
    Jun 24 at 13:22
  • 1
    Re missing rankings, the election committee has the last word, but I'd say "simply «shift left» the preferences: s/- 3 - 7 2/3 7 2 - -/." The same applies to repetitions, but here the page I linked says that repetitions are simply ignored, so it should be s/3 3 3 12 1/3 12 1 - -/. Finally, different record lengths are treated during processing, so I can say that different length records can be treated as well also in the first pass.
    – gboffi
    Jun 24 at 13:37
  • 3
    @uhoh This may be an oversimplification, but the NYC explainer linked in the answer partially addresses that. "If you rank your preferred candidate more than once, for example as your 1st, 2nd, 3rd, 4th, and 5th choice, then only your first ranking will count": this suggests that repeated votes for the same candidate are simply ignored instead of invalidating the ballot. "If you ranked that candidate first, your vote will go to the next highest ranked candidate on your ballot" suggests that missing levels are skipped
    – divibisan
    Jun 24 at 15:56
  • It might be more important to know what happens if (by mistake) someone ranks two candidates on the same place, e. g. X and Y as first, then Z as third etc. However, dealing with invalid ballots is not specific to this kind of scheme. Jun 27 at 15:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .