Allocated Score: Difference between revisions

Added python code to be super clear
No edit summary
(Added python code to be super clear)
Line 14:
 
'''Fractional Surplus Handling to break ties''': when calculating which ballots belong to a candidate's quota so they should be allocated to them, if for a particular score, including voters that gave that candidate that score in the quota would make the quota to large and excluding it would make it to small, then exhaust a portion of those vote's ballot weights such that the total weight of the exhausted ballots still equals the hare quota. The reason why [[Fractional Surplus Handling]] is preferred is that it preserves the [[Independence of irrelevant alternatives]] and [[Monotonicity]] criteria.
 
==Python Implementation==
 
Given a Pandas dataframe '''S''' with columns representing candidates and rows representing voters the entries would encode the score of all the ballots. For a max score of '''K''' and a desired number of winners '''W'''.
 
<source lang="python">
import pandas as pd
import numpy as np
 
def Allocated_Score(K, W, S):
 
#Normalize score matrix
ballots = pd.DataFrame(S.values/K, columns=S.columns)
#Find number of voters and quota size
V = ballots.shape[0]
quota = V/W
ballot_weight = pd.Series(np.ones(V),name='weights')
#Populate winners in a loop
winner_list = []
while len(winner_list) < W:
 
#Select winner
w = ballots.multiply(ballot_weight, axis="index").sum().idxmax()
#Add winner to list
winner_list.append(w)
#Create lists for manipulation
cand_df = pd.concat([ballot_weight,ballots[w]], axis=1).copy()
cand_df_sort = cand_df.sort_values(by=[w], ascending=False).copy()
#find the score where a quota is filled
split_point = cand_df_sort[cand_df_sort['weights'].cumsum() < quota][w].min()
#Amount of ballot for voters who voted more than the split point
spent_above = cand_df[cand_df > split_point]['weights'].sum()
#Exhaust all ballots above split point
if spent_above>0:
cand_df.loc[cand_df[w] > split_point, 'weights'] = 0.0
#Amount of ballot for voters who gave a score on the split point
weight_on_split = cand_df[cand_df[w] == split_point]['weights'].sum()
 
#Fraction of ballot on split needed to be spent
if weight_on_split>0:
spent_value = (quota - spent_above)/weight_on_split
#Take the spent value from the voters on the threshold evenly
cand_df.loc[cand_df[w] == split_point, 'weights'] = cand_df.loc[cand_df[w] == split_point, 'weights'] * (1 - spent_value)
ballot_weight = cand_df['weights']
 
return winner_list
 
</source>
 
==Variants==
763

edits