Proportional representation with droop quota and quota rule
-
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 thatfloor(p) == upper_quota(p)
andremainder(p)
is one of the largest compared to the other parties. -
@akazukin5151 said in Proportional representation with droop quota and quota rule:
The lower and upper quotas are the vote percentages times the house size:
If you are using Droop quotas to compute the seats then you must also use the Droop quota to compute the upper/lower quotas. What you have done is use the Hare quota to define the upper/lower quotas but then use the Droop quota to fill the seats.
-
Also Droop Quota isn't a method. You can have e.g. largest remainder or highest averages methods that use the Droop quota.
-
@andy-dienes Oh, that makes sense. How do I use the droop quota to calculate the lower and upper quota though? I can sort of see the similarities between
p1 / sum
and the hare quota (total_votes/total_seats
). But if I substitutep1
intototal_votes
andsum
(of all votes) intototal_seats
for droop, I get1 + floor(p1 / (1 + sum))
, which will always be greater than 1. Even if the1+
andfloor
is dropped, I still get 311 for party #1's upper quota. Thank you so much for your help! -
floor( vote / droop_quota )
is the lower quota,ceil( votes / droop_quota )
is the upper quota.