On 07/28/2013 04:37 PM, Vidar Wahlberg wrote:
On Tue, Jul 23, 2013 at 09:29:25PM +0200, Vidar Wahlberg wrote:
Implementing it is no easy task. It may be that my sources, mainly the
Wikipedia entry and Olli Salmi's page[2] are a bit short on the topic,
but one hindrance I've faced is figuring out what the divisor values
should be during the correction stages. Neither sources elaborate well
on how they decided the divisor values, and Salmi writes "I have just
fiddled with the divisor until the total number of seats assigned is
correct", but that's no good when implementing the algorithm.

An update on this. This mail will be very long, sorry about that.

I gave up on using the article on Wikipedia and Salmi's page, instead I
came across a PDF where the method was explained well, although using
multiplicators rather than divisors. Arguably this only makes the method
easier to explain and produce the same result, so it probably is a
better solution.
The PDF I've used for reference can be found here:
http://www.math.uni-augsburg.de/stochastik/pukelsheim/2008f.pdf

Here's a shot at explaining my implementation (as of this writing I've
not yet implemented preferential election, which I intend to do later).
The code (rough, only intended as "proof of concept") can be found here:
https://github.com/canidae/voting/blob/master/pbpa.d

Upper apportionment:
- Party seats are apportioned using unmodified Sainte-Laguë based on
   national votes. If desirable the first divisor may be modified, or a
   election threshold may be set to prevent fragmentation, but I've not
   done this.

Apportionment according to divisor methods can be done in two ways: either explicitly (like Sainte-Laguë) or by a round-and-adjust method (like Webster). If I understand you correctly, your biproportional program uses the Webster method, i.e. you pick x so that
SUM k=1...n round(support[k] * x)
equals the desired number of seats.

I don't know how to turn a given explicit divisor method into a given rounding method, so how would you implement modified Sainte-Laguë this way?

- District seats are determined externally and thus not apportioned in
   this implementation.

A similar trick could be used to implement a threshold if desired. It would be complicated, though, something like:

1. Do a county-by-county count.
2. Parties below the threshold have their number of seats fixed to the number of seats they got "directly". 3. Fixing these parties' number of seats, determine the number of seats for the other parties by national Sainte-Laguë: each party gets a seat as in Sainte-Laguë, but when a party below the threshold have got all their seats according to 2., remove that party from the count.
4. Use the result as the target for the number of party seats.

I'd still rather use an absolute but lower threshold, though; or none at all, like you're doing.

The PDF I used as reference says you should use the maximum multiplier
when you're to increase the number of seats, and the minimum multiplier
when you're to decrease the number of seats. I'm not entirely sure why
this is recommended, if someone have insight on this then please share.

I would guess this makes the method converge more quickly, but I'm not sure. Perhaps try and see if it does?

On the other hand, one could argue that one should use the minimal multiplier when increasing and the maximal when decreasing. Say there's a somewhat sophisticated opponent that objects by saying "You got the current outcome by multiplying the votes by certain adjustment factors. Well, I can make Rødt get every single seat with the right adjustment factors, too, so this is not democratic". Against an objection like that, the closer the factors are to 1, the better; and so, when increasing the strength of a party (or district) to increase the number of seats, one should increase it by as little as possible that gets the job done, and similarly when decreasing.

Salmi on the other hand mentions using the average of these two
multipliers (or divisors in his case), and this also more or less solves
the problem with multipliers being a fraction of the optimal value, so
for now I'm using the average of the minimum and maximum multipliers.

I seem to recall seeing somewhere that this avoids certain tricky tie situations where it would otherwise fail to converge. I don't remember where I read that, however.

In this code I've not weighted up votes from districts which in the
current system are weighted up, and I've kept the amount of seats in
each district. This means that there's a theoretical possibility (as
I've discussed earlier) that you can end up with an unresolvable
election, but it should be noted that this possibility is very low.
If there are too many parties/districts and/or there are very small
differences in votes for parties then you may also have a problem with
too low accuracy of floating numbers. This can be solved by using
floating numbers with higher precision if it should become a problem.

The method itself will partly make votes unequal by weighting them to match the district totals you have already specified. However, it will not be quite as biased as just preweighting all the vote counts, since the party axis is based on the unweighted votes.

That is, it will give certain districts more than its "fair" share of MPs according to population alone. But it won't give parties disproportionate numbers of MPs like it does districts, because the party target is provided by national Sainte-Laguë.

That's an interesting tension. To see how it works, consider an extreme: Finnmark gets every seat but one, but the party target is based on a national count. Then almost every MP would come from Finnmark (contrary to relative party support there), but even if most Finnmark voters voted for Rødt, Rødt would still only get two Finnmark MPs.

So I expect that the districts with "too many" seats would see greater adjustment of their party factors than would districts with the right number of seats.

---

Floating point problems can also be solved by using a rational number type, for instance the one provided by the GNU multiprecision library. I think I read about an implementation of the Meek STV method doing just that - the Meek method can also run into problems with floating point precision in certain cases. Rational number types are much slower than floating point, but they are exact.

That said, this looks like a very solid system for an optimal
biproportional apportionment. Since there are multiplicators for each
party and each district it will also be more resistant to two parties
receiving the exact same amount of votes in the same district.
That each vote is worth equally much regardless of which district the
vote was given is also an appealing thought.

I agree.

So here's the result using data from the Norwegian 2009 election. No
election threshold cause 3 new parties to enter the parliament:

Upper apportionment:

Parties (2009 result in parentheses):
Rødt                     :  2 ( 0)
Sosialistisk Venstreparti: 11 (11)
Arbeiderpartiet          : 60 (64)
Senterpartiet            : 10 (11)
Kristelig Folkeparti     :  9 (10)
Venstre                  :  7 ( 2)
Høyre                    : 29 (30)
Fremskrittspartiet       : 39 (41)
Miljøpartiet de Grønne   :  1 ( 0)
Kystpartiet              :  0 ( 0)
Pensjonistpartiet        :  1 ( 0)

The Loosemore-Hanby index for the 2009 result is 5.4%. The Loosemore-Hanby index for the biproportional result is 1.3%, so by that measure, the biproportional result is indeed more proportional. And that is not very strange, since for this election, the biproportional apportionment method managed to completely satisfy the nationwide Sainte-Laguë result: each party got as many seats as it should have had were there just one district.

(The greatest contribution to disproportionality in the 2009 election, according to the Loosemore-Hanby index, was due to the number of seats given to Venstre. Second-place finisher was Arbeiderpartiet. The former party got too few seats and the latter too many. According to the Sainte-Laguë index, Venstre was still the most disproportionately represented party, but Rødt came in second.)

After this it went back to adjust parties again, then districts, and so
on. It needed to adjust parties 13 times and districts 13 times before
it found a final result:

Modifying multipliers for districts:
Multiplier for Buskerud        : 1.00021 (1.00003/1.00039)
Multiplier for Telemark        : 0.999337 (0.998849/0.999826)

                   |    Rodt | Sosiali | Arbeide | Senterp | Kristel | Venstre 
|   Hoyre | Fremskr | Miljopa | Kystpar | Pensjon |   Total
------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------
          Akershus |       0 |       1 |       5 |       0 |       1 |       1 
|       4 |       4 |       0 |       0 |       0 |  16/ 16
        Aust-Agder |       0 |       0 |       1 |       0 |       1 |       0 
|       1 |       1 |       0 |       0 |       0 |   4/  4
          Buskerud |       0 |       0 |       3 |       1 |       0 |       0 
|       2 |       3 |       0 |       0 |       0 |   9/  9
          Finnmark |       0 |       1 |       2 |       0 |       0 |       0 
|       1 |       1 |       0 |       0 |       0 |   5/  5
           Hedmark |       0 |       1 |       3 |       1 |       0 |       0 
|       1 |       1 |       0 |       0 |       1 |   8/  8
         Hordaland |       1 |       1 |       4 |       1 |       1 |       1 
|       3 |       3 |       0 |       0 |       0 |  15/ 15
   More og Romsdal |       0 |       0 |       3 |       1 |       1 |       1 
|       1 |       2 |       0 |       0 |       0 |   9/  9
          Nordland |       0 |       1 |       4 |       1 |       0 |       0 
|       1 |       3 |       0 |       0 |       0 |  10/ 10
    Nord-Trondelag |       0 |       0 |       3 |       1 |       0 |       0 
|       1 |       1 |       0 |       0 |       0 |   6/  6
           Oppland |       0 |       0 |       4 |       1 |       0 |       0 
|       1 |       1 |       0 |       0 |       0 |   7/  7
              Oslo |       1 |       2 |       5 |       0 |       0 |       2 
|       3 |       3 |       1 |       0 |       0 |  17/ 17
          Rogaland |       0 |       1 |       3 |       1 |       2 |       1 
|       2 |       3 |       0 |       0 |       0 |  13/ 13
  Sogn og Fjordane |       0 |       0 |       2 |       1 |       0 |       0 
|       1 |       1 |       0 |       0 |       0 |   5/  5
     Sor-Trondelag |       0 |       1 |       4 |       1 |       0 |       1 
|       1 |       2 |       0 |       0 |       0 |  10/ 10
          Telemark |       0 |       0 |       3 |       0 |       1 |       0 
|       1 |       1 |       0 |       0 |       0 |   6/  6
             Troms |       0 |       1 |       3 |       0 |       0 |       0 
|       1 |       2 |       0 |       0 |       0 |   7/  7
        Vest-Agder |       0 |       0 |       2 |       0 |       1 |       0 
|       1 |       2 |       0 |       0 |       0 |   6/  6
          Vestfold |       0 |       1 |       2 |       0 |       0 |       0 
|       2 |       2 |       0 |       0 |       0 |   7/  7
           Ostfold |       0 |       0 |       4 |       0 |       1 |       0 
|       1 |       3 |       0 |       0 |       0 |   9/  9
------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------
             Total |   2/  2 |  11/ 11 |  60/ 60 |  10/ 10 |   9/  9 |   7/  7 
|  29/ 29 |  39/ 39 |   1/  1 |   0/  0 |   1/  1 | 169/169

What did the factors end up being for the parties and districts?


----
Election-Methods mailing list - see http://electorama.com/em for list info

Reply via email to