Skip to content

weighted voting #22

@antviro

Description

@antviro

I introduced a function for weighted voting with a St. Lagüe weight function given by 1/(1+2(n-1))
http://www.uv.es/~pla/sistelec/propabga.htm

ponderado.py:
from abstract_classes import MultipleWinnerVotingSystem
from common_functions import matching_keys
import types
import copy

class ponderado(MultipleWinnerVotingSystem):

def __init__(self, ballots, tie_breaker=None, required_winners=1):
    super(Ponderado, self).__init__(ballots, tie_breaker=tie_breaker, required_winners=required_winners)

def calculate_results(self):

    # Standardize the ballot format and extract the candidates
    self.candidates = set()
    for ballot in self.ballots:

        # Convert single candidate ballots into ballot lists
        if not isinstance(ballot["ballot"], types.ListType):
            ballot["ballot"] = [ballot["ballot"]]

        # Ensure no ballot has an excess of votes
        if len(ballot["ballot"]) > self.required_winners:
            raise Exception("A ballot contained too many candidates")

        # Add all candidates on the ballot to the set
        self.candidates.update(set(ballot["ballot"]))

    # Sum up all votes for each candidate with weight!!
    self.tallies = dict.fromkeys(self.candidates, 0)
    for ballot in self.ballots:
        for icand in range(0,len(ballot["ballot"])):
            candidate = ballot["ballot"][icand]
            peso = 1./(1+2*icand)
            self.tallies[candidate] += ballot["count"]*peso
    tallies = copy.deepcopy(self.tallies)

    # Determine which candidates win
    winning_candidates = set()
    while len(winning_candidates) < self.required_winners:

        # Find the remaining candidates with the most votes
        largest_tally = max(tallies.values())
        top_candidates = matching_keys(tallies, largest_tally)

        # Reduce the found candidates if there are too many
        if len(top_candidates | winning_candidates) > self.required_winners:
            self.tied_winners = top_candidates.copy()
            while len(top_candidates | winning_candidates) > self.required_winners:
                top_candidates.remove(self.break_ties(top_candidates, True))

        # Move the top candidates into the winning pile
        winning_candidates |= top_candidates
        for candidate in top_candidates:
            del tallies[candidate]

    self.winners = winning_candidates

def as_dict(self):
    data = super(Ponderado, self).as_dict()
    data["tallies"] = self.tallies
    return data

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions