summaryrefslogtreecommitdiff
path: root/project/templates/stvcount.xhtml
blob: e47569286445d330498f62ed785bee694af347ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

{%- extends "base_plain.xhtml" -%}



{%- block title -%}Single Transferable Vote Counter{%- endblock -%}



{%- block style %}
    <link href="/css/stvcount.css" rel="stylesheet" />
{% endblock -%}



{%- block content %}
<h4>Single Transferable Vote Counter</h4>

<p>Git repository: <a href="/cgi-bin/cgit.cgi/stv-count">Link</a></p>

<h5>19/2/2017</h5>

<p>To give an incredibly brief summary of <a href="https://en.wikipedia.org/wiki/Parliament_of_Australia"
class="external">Australia's political system</a>, both the Federal Parliament and most of the State
Parliaments are bicameral. The lower houses are generally elected by Instant Runoff, while the upper
houses generally have half elections using Single Transferable Vote. There are exceptions and a
whole lot of differing details, but that's the overall pattern.</p>

<p>In 2016, however, the Federal Parliament underwent a Double Dissolution, causing the entirety of
both houses to go to an election. This had the outcome of 20 out of 76 seats going to third parties
in the upper house, a record number. Even more than the 18 there were prior. As the entire purpose
of a Double Dissolution is to break deadlocks in parliament, to have the outcome go in the
<a href="http://www.abc.net.au/news/2016-07-03/crabb-election-2016-is-lose-lose-for-malcolm-turnbull/7565840"
class="external">complete opposite direction</a> probably caused some dismay from Malcolm Turnbull
and his Liberal/National government.</p>

<p>This raises the question: Would they have been better off had a normal election happened instead?
</p>

<p>To calculate the likely outcome, the ballot preference data is needed. That's the easy part, as
the Australian Electoral Commission makes that available
<a href="http://results.aec.gov.au/20499/Website/SenateDownloadsMenu-20499-Csv.htm" class="external">
here</a> in the 'Formal preferences' section. Then, a program is needed to execute the STV
algorithm, which is as follows:</p>

<ol>
    <li>Set the quota of votes required for a candidate to win.</li>
    <li>Allocate the ballot papers according to first preference to each of the candidates for
        initial vote totals.</li>
    <li>Mark any candidate who has reached or exceeded the quota as elected.</li>
    <li>If any elected candidate has more votes than the quota, transfer the excess to the other
        candidates according to the next applicable preference.</li>
    <li>If no further candidates meet the quota, the candidate with the fewest votes is eliminated
        and their votes are transferred to the others according to next applicable preference.</li>
    <li>Repeat steps 3-5 until all seats are filled.</li>
</ol>

<p>Seems simple enough, right? Except not really. There is a surprising amount of complexity in
there, and most of it is to do with how to transfer votes around. So, in addition, there are the
specifics for the version used for the Australian Senate:</p>

<ul>
    <li>Voters are given the option of voting either "above the line" or "below the line". The
        latter is standard STV. The former used to be a group voting ticket, but for 2016 and later
        it is treated as a shorthand way of voting, as per instructions
        <a href="http://www.aec.gov.au/Voting/How_to_vote/Voting_Senate.htm" class="external">here</a>.</li>
    <li>There are <a href="http://www.aec.gov.au/Elections/candidates/files/ballot-paper-formality guidelines.pdf" class="external">specific guidelines</a> on what constitutes a correctly filled
        out ballot. This is important for parsing the formal preference data.</li>
    <li>The <a href="https://en.wikipedia.org/wiki/Droop_quota" class="external">Droop quota</a> is
        used.</li>
    <li>All votes are transferred from elected candidates at a fraction of their value, as per the
        <a href="https://en.wikipedia.org/wiki/Counting_single_transferable_votes#Gregory" class="external">
        Gregory Method</a>. This can result in fractions with surprisingly large numerators and
        denominators. This also results in occasional discarding of fractional votes during
        transfers.</li>
    <li>Should the next applicable preference of a ballot be a candidate who has already been
        elected, that preference is ignored and the ballot is transferred to the next preference.
        </li>
    <li>If the number of remaining candidates is equal to one more than the number of remaining
        vacancies, the candidates with the highest vote totals at that point are considered elected.
        </li>
</ul>

<p>My implementation also includes <a href="https://en.wikipedia.org/wiki/Counting_single_transferable_votes#Bulk_exclusions"
class="external">bulk exclusions</a> using applied breakpoints in order to increase speed slightly
and minimise superfluous logging.</p>

<p>At this point I'm fairly sure my program provides an accurate count. However, my numbers still
differ slightly from the ones provided by the AEC's official distribution of preferences.
Investigations into the exact cause are ongoing.</p>

<h4>Results</h4>

<p>Calculations were done for each state using the formal preference data with vacancies set to 6
instead of 12, and the results were added to the Senators elected in 2013 to find the probable
outcome. The results for ACT and NT were taken as-is, because the few Senators elected from the
territories are not part of the half election cadence anyway.</p>

<p>Computational resources required varied from approximately 50 seconds using 46MB of memory for
Tasmania, to nearly 30 minutes using 1452MB memory for NSW. The vast majority of that time was spent
parsing preference data, and the program is single threaded, so there is still room for improvement.
All counts were run on a Core 2 Quad Q9500.</p>

<table>
    <caption>Probable non-DD results by state</caption>
    <tr>
        <th colspan="2" style="width:10em;">NSW</th>
        <th colspan="2" style="width:10em;">VIC</th>
        <th colspan="2" style="width:10em;">QLD</th>
        <th colspan="2" style="width:10em;">SA</th>
        <th colspan="2" style="width:10em;">WA</th>
        <th colspan="2" style="width:10em;">TAS</th>
    </tr>
    <tr>
        <td style="background-color:#080CAB; width:8px">&#160;</td><td>Liberal</td>
        <td style="background-color:#080CAB; width:8px;">&#160;</td><td>Liberal</td>
        <td style="background-color:#1456F1; width:8px;">&#160;</td><td>Liberal National</td>
        <td style="background-color:#080CAB; width:8px;">&#160;</td><td>Liberal</td>
        <td style="background-color:#080CAB; width:8px;">&#160;</td><td>Liberal</td>
        <td style="background-color:#080CAB; width:8px;">&#160;</td><td>Liberal</td>
    </tr>
    <tr>
        <td style="background-color:#F00011; width:8px">&#160;</td><td>Labor</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
    </tr>
    <tr>
        <td style="background-color:#080CAB; width:8px">&#160;</td><td>Liberal</td>
        <td style="background-color:green; width:8px;">&#160;</td><td>National</td>
        <td style="background-color:#1456F1; width:8px;">&#160;</td><td>Liberal National</td>
        <td style="background-color:#FF6300; width:8px;">&#160;</td><td>Xenophon</td>
        <td style="background-color:#080CAB; width:8px;">&#160;</td><td>Liberal</td>
        <td style="background-color:#080CAB; width:8px;">&#160;</td><td>Liberal</td>
    </tr>
    <tr>
        <td style="background-color:#F00011; width:8px">&#160;</td><td>Labor</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
        <td style="background-color:#080CAB; width:8px;">&#160;</td><td>Liberal</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
    </tr>
    <tr>
        <td style="background-color:green; width:8px">&#160;</td><td>National</td>
        <td style="background-color:#10C25B; width:8px;">&#160;</td><td>Green</td>
        <td style="background-color:#F8F16F; width:8px;">&#160;</td><td>One Nation</td>
        <td style="background-color:#F00011; width:8px;">&#160;</td><td>Labor</td>
        <td style="background-color:#10C25B; width:8px;">&#160;</td><td>Green</td>
        <td style="background-color:#E36137; width:8px;">&#160;</td><td>Jacqui Lambie</td>
    </tr>
    <tr>
        <td style="background-color:#10C25B; width:8px">&#160;</td><td>Green</td>
        <td style="background-color:#002F5D; width:8px;">&#160;</td><td>Derryn Hinch</td>
        <td style="background-color:#1456F1; width:8px;">&#160;</td><td>Liberal National</td>
        <td style="background-color:#FF6300; width:8px;">&#160;</td><td>Xenophon</td>
        <td style="background-color:#080CAB; width:8px;">&#160;</td><td>Liberal</td>
        <td style="background-color:#10C25B; width:8px;">&#160;</td><td>Green</td>
    </tr>
</table>

<table>
    <caption>Probable non-DD Senate composition</caption>
    <tr>
        <th colspan="2" style="width:24em">Party</th>
        <th style="width:9em">Seats Won</th>
        <th style="width:9em">Continuing Senators</th>
        <th style="width:9em">Total Seats</th>
        <th style="width:9em">Difference From Actual</th>
    </tr>
    <tr>
        <td style="background-color:#080CAB; width:8px;">&#160;</td>
        <td class="left">Liberal/National Coalition</td>
        <td>17</td>
        <td>15</td>
        <td>32</td>
        <td>+2</td>
    </tr>
    <tr>
        <td style="background-color:#F00011; width:8px;">&#160;</td>
        <td class="left">Australian Labor Party</td>
        <td>14</td>
        <td>10</td>
        <td>24</td>
        <td>-2</td>
    </tr>
    <tr>
        <td style="background-color:#10C25B; width:8px;">&#160;</td>
        <td class="left">Australian Greens</td>
        <td>4</td>
        <td>4</td>
        <td>8</td>
        <td>-1</td>
    </tr>
    <tr>
        <td style="background-color:#FF6300; width:8px;">&#160;</td>
        <td class="left">Xenophon Group</td>
        <td>2</td>
        <td>1</td>
        <td>3</td>
        <td>Nil</td>
    </tr>
    <tr>
        <td style="background-color:#E36137; width:8px;">&#160;</td>
        <td class="left">Jacqui Lambie Network*</td>
        <td>1</td>
        <td>1</td>
        <td>2</td>
        <td>+1</td>
    </tr>
    <tr>
        <td style="background-color:#F9E518; width:8px;">&#160;</td>
        <td class="left">Liberal Democratic Party</td>
        <td>0</td>
        <td>1</td>
        <td>1</td>
        <td>Nil</td>
    </tr>
    <tr>
        <td style="background-color:#00CCFF; width:8px;">&#160;</td>
        <td class="left">Family First Party</td>
        <td>0</td>
        <td>1</td>
        <td>1</td>
        <td>Nil</td>
    </tr>
    <tr>
        <td style="background-color:#FFED00; width:8px;">&#160;</td>
        <td class="left">Palmer United Party*</td>
        <td>0</td>
        <td>1</td>
        <td>1</td>
        <td>+1</td>
    </tr>
    <tr>
        <td style="background-color:gray; width:8px;">&#160;</td>
        <td class="left">Glenn Lazarus Team*</td>
        <td>0</td>
        <td>1</td>
        <td>1</td>
        <td>+1</td>
    </tr>
    <tr>
        <td style="background-color:#191970; width:8px;">&#160;</td>
        <td class="left">Australian Motoring Enthusiast Party</td>
        <td>0</td>
        <td>1</td>
        <td>1</td>
        <td>+1</td>
    </tr>
    <tr>
        <td style="background-color:#F8F16F; width:8px;">&#160;</td>
        <td class="left">One Nation</td>
        <td>1</td>
        <td>0</td>
        <td>1</td>
        <td>-3</td>
    </tr>
    <tr>
        <td style="background-color:#002F5D; width:8px;">&#160;</td>
        <td class="left">Derryn Hinch's Justice Party</td>
        <td>1</td>
        <td>0</td>
        <td>1</td>
        <td>Nil</td>
    </tr>
</table>

<p>* These three parties were all part of the Palmer United Party at the 2013/2014 election, but
split up mid term.</p>

<p>Surprisingly, these projected results <em>still</em> have 20 out of 76 seats held by third party
candidates, despite the half election putting them at a disadvantage. The number of third party
groups the Liberal/Nationals have to negotiate with to pass legislation (assuming Labor and Greens
attempt to block) equally remains unchanged.</p>

<p>The Greens manage to do slightly worse, even though their usual position of winning the 5th or
6th seat in most states often allows them to obtain more representation than their primary vote
would otherwise support. This can't even be attributed to a bad 2013 result, as their primary vote
both then and in 2016 was nearly identical.</p>

<p>One Nation's much reduced number of seats can be attributed to the inherent geographic bias that
any system involving electing candidates across many independent divisions has. If like-minded
voters are all in one place, they receive representation, but when the same number of voters are
spread out, they get nothing. When this effect is intentionally exploited it's called
gerrymandering, but here it's merely an artifact of electing Senators from each state separately.
One Nation's support is strongest in Queensland but is relatively diffuse. Any claims of Pauline
Hanson being <a href="http://junkee.com/malcolm-turnbull-will-probably-need-pauline-hansons-support-to-pass-any-laws/82138" class="external">one of the most powerful politicians in Australia</a> are thus
overblown.</p>

<p>The Xenophon Group, by contrast, has the vast majority of their support concentrated in South
Australia. So the result for them remains unchanged.</p>

<p>The most noteworthy outcomes for the question though, are that the Liberal/Nationals would have
obtained more seats, and Labor would have been in a more difficult position to block the passage of
legislation. Meaning that yes, the Liberal/National government would definitely have been better off
with a normal election.</p>

<p>Nice job screwing over your own party, Malcolm.</p>
{% endblock -%}