Generating Ranked Ballots

For most of the voting systems considered we need to generate ranked ballots. That’s easier said than done.

The problem boils down to:

Given v0 votes for candidate c0, a set of other candidates ci each with vi votes, and some polling data, how many of the c0 votes should go to each permutation of the other candidates?

An example: Given 1000 votes for c0 = Lib0 and the other candidates are Lib1, Con2, Con3, and NDP4, the following ranked ballots are all possibilities. How many of the 1,000 votes are assigned to each?

  • Lib0 Lib1 Con2 Con3 NDP4
  • Lib0 Lib1 Con2 NDP4 Con3
  • Lib0 Lib1 Con3 Con2 NDP4
  • Lib0 Lib1 Con3 NDP4 Con2
  • etc

Note that Lib0 is always the first preference.


We encode our assumptions as shown in the following configuration file. The specific values can be easily changed, of course.

The voteXferMap is data from Ekos and tells us that (according to the poll), a Liberal’s second choice candidate is a Conservative (on average) 10.6% of the time and an NDPer 28.6% of the time. Notice that the percentages for Liberals only add up to 65.8%. That’s because 34.2% have no second choice.

  "voteXfer": {
    "voteXferMap": [
      ["Lib", "Con", 10.6],
      ["Lib", "NDP", 28.6],
      ["Lib", "Grn", 22.4],
      ["Lib", "PPC", 1.0],
      ["Lib", "Bloc", 3.2],

      ["Con", "Lib", 8.2],
      ["Con", "NDP", 8.4],
      ["Con", "Grn", 8.5],
      ["Con", "PPC", 10.3],
      ["Con", "Bloc", 0.7],

      ["NDP", "Lib", 30.1],
      ["NDP", "Con", 5.8],
      ["NDP", "Grn", 33.1],
      ["NDP", "PPC", 0.8],
      ["NDP", "Bloc", 4.8],

# Additional parties omitted from example
    "maxPrefs": 10,
    "samePartyProbability": 80,
    "minVotingBlock": 10

In some simulations an STV riding may have tens of candidates. The maxPrefs value (10) says that we won’t compute additional preferences. Once a voter in the simulation gets to 10, the ballot is considered exhausted.

The Ekos poll assumes that there is only one candidate for a given party in the riding. That may not be true in other voting systems. This value is used as follows:

if (there are one or more candidates from the same party as the voter's first preference)
   split 80% of this candidate's votes between them
   split 20% of this candidate's votes between candidates from other parties 
   split all of this candidate's votes between candidates from other parties

As a matter of computational efficiency, any permutation of preferences with minVotingBlock votes will be considered exhausted as well.


Suppose we’re calculating the preferences for voters who initially voted for a candidate “Lib0”. There are two other Liberals in the race, two Conservatives, and an NDPer.

Lib0 got 1,000 votes.

80% of those will go to the other Liberals, in proportion to the first preference votes they earned. So if Lib1 got 3,000 votes and Lib2 got 1,000 votes, there will be 1,000 * 0.80 * 3/4 = 600 ballots with preferences start out Lib0 Lib1 and there will be 1,000 * 0.80 * 1/4 = 200 with preferences that start out Lib0 Lib2.

What happens to the remaining 20% of the 1,000 votes? 10.6% or 1,000 * 0.20 * .106 = 21 votes will be split between the two Conservatives, in proportion to their first preference votes. The NDP is treated similarly. The remaining votes will be exhausted.

At this point, we have the following ballots (assuming first preference votes for the two Conservatives were nearly equal):

  • 600 [Lib0 Lib1 …]
  • 200 [Lib0 Lib2 …]
  • 10 [Lib0 Con0 …]
  • 11 [Lib0 Con1 …]
  • 57 [Lib0 NDP0 …]
  • 122 [Lib0]

122 ballots were cast for Lib0 with no further preferences listed. The remaining ballots all need to have further preferences defined. Taking the 600 ballots cast for Lib0 with Lib1 as the next preference as an example:

  • 600 * .80 = 480 will have preferences [Lib0 Lib1 Lib2 …]
  • 600 * .20 * .106 = 13 will have preferences that start [Lib0 Lib1 Con0 …] or [Lib0 Lib1 Con1 …]
  • 600 * .20 * .286 = 34 will have preferences that start [Lib0 Lib1 NDP0 …]
  • The rest will be exhausted with preferences [Lib0 Lib1]

Each of these have additional preferences calculated until all ballots are exhausted.

At each step, the permutation with the least number of votes is adjusted so that the total number of votes is preserved.