LearnSTV

rweait's picture

The OpenStreetMap Foundation election to the Board is coming up soon, or so I hear. And will use Single Transferrable Vote (STV) for the first time. I'm not familliar with STV, not having lived in an STV jusrisdiction, and wanted to see what the proceess looked like. Dermot found some tools for use by the Board, and now I've made a tool to create example election results.

What are you doing now?

For the election, OSMF will use an on-line tool to handle the anonymity and email issues. We expect it to provide a result, but also an anonymized summary that includes every ballot from every anonymized voter. We should be able to feed that record into another tool to confirm the results.

One other tool for later analysis of election ballots is openSTV.

Install openSTV

aptitude install openstv

Easy. Now openstv can analyze any ballots that you have. My script creates example ballots to send to openSTV.

Install LearnSTV

cd bin
git clone git@github.com:rweait/learnSTV.git
cd learnSTV
chmod +x make-test-ballot.py

Use LearnSTV

The default settings are all built into the code, but should be easy enough to modify to your liking. The script uses a default output filename.
I've set an election of three from eight candidates. And I've set eight imaginary candidate names. Alter to suit your fancy.

The script creates several hundred voter ballots and each voter lists their favourite candidates in order. I made a naive attempt at randomizing the order of preference and the number of candidates per vote. The script adds some houskeeping details that are expected by openSTV, and can be read directly by openSTV.

LearnSTV output

Shortened output, with added comments

8 3 # 8 candidates, 3 seats available
1 8 4 2 3 5 1 6 0 # each voter ballot
1 1 6 2 0 # starts with a weight, in my case 1
1 0 # each ballot ends with 0 This one is empty
1 4 7 3 0 # This voter selected only three candidates
1 5 7 0 # using defaults will give hundreds of voter ballots
1 4 7 2 6 0
1 6 5 3 0
1 6 5 7 1 2 0
1 7 2 6 4 0
1 1 2 0
1 1 7 5 0
0 # a lone 0 ends the voter ballots 
"Alice" # the candidate names are listed one per line
"Bob" # change the voter names to give them character
"Claire"
"Dan"
"Eve"
"Fil"
"Gen"
"Hodor"
"fake-ballot-results" # and finally a name for the election

Use openSTV

openSTV GUI

Click the icon in the Launcher, or type openstv from the command line.

  1. Select File >> Run Election
  2. Select the ballot file name and election method, click Okay
  3. An Election information dialogue will open
    1. It tells you how many ballots it read
    2. Change the number of seats to elect if required
    3. Increase the display width if your candidates have long names
    4. Click OK
  4. A new tab will open in the main openSTV window with the results details.

openSTV from command line

openSTV comes with a script to run a single election from the command line. Enjoy all of the wonderful optional arguments. For now, try

python /usr/share/openstv/openstv/runElection.py -r TextReport ScottishSTV fake-results.blt

It generates a wall of text that explain the six rounds of the election.

OpenSTV version 1.6.1 (http://www.OpenSTV.org/)

Suggested donation for using OpenSTV for an election is $50.  Please go to 
http://www.OpenSTV.org/donate to donate via PayPal, Google Checkout, or
Amazon Payments.  

Certified election reports are also available.  Please go to 
http://www.openstv.org/certified-reports for more information.

Loading ballots from file fake-results.blt.
Ballot file contains 8 candidates and 11 ballots.
No candidates have withdrawn.
Ballot file contains 10 non-empty ballots.

Counting votes for fake-ballot-results using Scottish STV.
8 candidates running for 3 seats.

 R|Alice  |Bob    |Claire |Dan    |Eve    |Fil    |Gen    |Hodor  |Exhaust|Surplus|Thresho
  |       |       |       |       |       |       |       |       |ed     |       |ld     
==========================================================================================
 1|3.00000|0.00000|0.00000|2.00000|1.00000|2.00000|1.00000|1.00000|0.00000|0.00000|3.00000
  |---------------------------------------------------------------------------------------
  | Count of first choices. Candidate Alice has reached the threshold and is elected. No
  | candidates have surplus votes so candidates will be eliminated and their votes
  | transferred for the next round.
==========================================================================================
 2|3.00000|0.00000|       |2.00000|1.00000|2.00000|1.00000|1.00000|0.00000|0.00000|3.00000
  |---------------------------------------------------------------------------------------
  | Count after eliminating Claire and transferring votes. Candidates Bob and Claire were
  | tied when choosing candidates to eliminate. Candidate Claire was chosen by breaking
  | the tie randomly. No candidates have surplus votes so candidates will be eliminated
  | and their votes transferred for the next round.
==========================================================================================
 3|3.00000|       |       |2.00000|1.00000|2.00000|1.00000|1.00000|0.00000|0.00000|3.00000
  |---------------------------------------------------------------------------------------
  | Count after eliminating Bob and transferring votes. No candidates have surplus votes
  | so candidates will be eliminated and their votes transferred for the next round.
==========================================================================================
 4|3.00000|       |       |2.00000|       |2.00000|2.00000|1.00000|0.00000|0.00000|3.00000
  |---------------------------------------------------------------------------------------
  | Count after eliminating Eve and transferring votes. Candidates Eve, Gen, and Hodor
  | were tied when choosing candidates to eliminate. Candidate Eve was chosen by breaking
  | the tie randomly. No candidates have surplus votes so candidates will be eliminated
  | and their votes transferred for the next round.
==========================================================================================
 5|3.00000|       |       |3.00000|       |2.00000|2.00000|       |0.00000|0.00000|3.00000
  |---------------------------------------------------------------------------------------
  | Count after eliminating Hodor and transferring votes. Candidate Dan has reached the
  | threshold and is elected. No candidates have surplus votes so candidates will be
  | eliminated and their votes transferred for the next round.
==========================================================================================
 6|3.00000|       |       |3.00000|       |3.00000|       |       |1.00000|0.00000|3.00000
  |---------------------------------------------------------------------------------------
  | Count after eliminating Gen and transferring votes. Candidates Fil and Gen were tied
  | when choosing candidates to eliminate. Candidate Gen was chosen by breaking the tie at
  | round 3. Candidate Fil has reached the threshold and is elected.

Winners are Alice, Dan, and Fil.

Run more sample elections

for i in {1..5};
do
./make-test-ballot.py;
python /usr/share/openstv/openstv/runElection.py \
-r TextReport \
ScottishSTV \
fake-results.blt \
|tail -1;
done

Will run five elections for you and summarize the results with just the Winners line, like

Winners are Claire, Dan, and Hodor.
Winners are Bob, Claire, and Hodor.
Winners are Eve, Fil, and Gen.
Winners are Bob, Dan, and Eve.
Winners are Alice, Bob, and Hodor.

Have fun.

Now we should each be able to understand the election results, and confirm them from the anonymized summary.

See the code

https://github.com/rweait/learnSTV

Acquire and improve the code

git clone git@github.com:rweait/learnSTV.git

More?

The raw data from the election has been published

Photo credits

Vote photo by Marc Tarlock is licensed CC-By-SA

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.