Hello,
I was running property-based tests and it seems to have found a situation where the Droop quota violated the quota rule. As a largest remainder method, I thought the Droop quota will always satisfy the quota rule. I don't think it is my code being buggy because I reached the same results when calculating by hand. You can also use this unrelated calculator and it gives the same results. In fact, its code uses my algorithm. I found another project which I didn't manage to compile, but the code should also give the same results.
I am aware of the mathematical proofs behind the method and the quota rule, so I hope all three of us made a mistake!
Consider this election with 4 parties contesting 360 seats, with the following vote counts
p1, p2, p3, p4 = 885292, 50089, 1536, 87859
house_size = 360
sum == 1024776
Calculate the droop quota
quota = 1 + floor(sum / (1 + house_size))
quota == 2839
Divide each party's votes by the quota
p1 / quota = 311.83233532934133
p2 / quota = 17.643184219795703
p3 / quota = 0.5410355759070095
p4 / quota = 30.94716449454033
Give each party their automatic seats based on the floor of the above:
party |
seats |
1 |
311 |
2 |
17 |
3 |
0 |
4 |
30 |
total |
358 |
There are 2 seats remaining, so give one seat to the two parties with the largest remainder - they are party #3 (0.94716449454033) and party #1 (0.83233532934133)
The election result is thus:
party |
seats |
1 |
312 |
2 |
17 |
3 |
0 |
4 |
31 |
total |
360 |
The problem with this result is that party #1's seats violated the quota rule. The lower and upper quotas are the vote percentages times the house size:
expr |
result |
lower quota |
upper quota |
p1 / sum * house_size |
310.99978922223 |
310 |
311 |
p2 / sum * house_size |
17.596079533478534 |
17 |
18 |
p3 / sum * house_size |
0.5395910911262558 |
0 |
1 |
p4 / sum * house_size |
30.86454015316518 |
30 |
31 |
Party #1 received 312 seats, which violates the quota rule. The additional seat could be awarded to party #2 or #3 without violating the quota rule. Notably, party #1 was automatically allocated its upper quota, and gained another one due to its large remainder.
I'm following the rules on the Wikipedia page for the largest remainder method -- as do the two other implementations. You can see my code here. Please do leave a comment if you have an insight. Thank you.
PS: I'd post this to the proportional representation category but there was no new topic button
Edit: here are some other parameters that appear to violate quota:
house_size = 72, p1 = 80183, p2 = 34027, p3 = 403586, p4 = 30472
house_size = 144, p1 = 80183, p2 = 34027, p3 = 803270, p4 = 7888
house_size = 216, p1 = 35570, p2 = 24675, p3 = 798357, p4 = 30291
house_size = 288, p1 = 80183, p2 = 34027, p3 = 705602, p4 = 23398
They all appear to share some common characteristics: the largest party has over 80% of the vote; their vote share has a large remainder, and the floor of their vote share is their upper quota. In other words, to construct this scenario, find p
such that floor(p) == upper_quota(p)
and remainder(p)
is one of the largest compared to the other parties.