def statistical_test(nr_candidates=10, nr_voters=1000):
    """
    Runs a statistical test of Shulze with nr_candidates and nr_voters.
    Each voter generates a set of choices (a vote) based on the chances of each candidate's
    randomly determined chance of winning.
    """
    candidates = list(range(nr_candidates))
    candidate_chances = [(random.random()/2, c) for c in candidates]
    candidate_chances.sort()
    candidate_chances.reverse()

    voters = list(range(nr_voters))
    votes = [generate_vote(candidate_chances) for _ in voters]

    # Create directed graph
    preference = schulze.rank_votes(votes, candidates)

    # Get the strongest paths of each candidate
    strongest_paths = schulze.compute_strongest_paths(preference, candidates)

    # Get final, ordered, results
    results = schulze.get_ordered_voting_results(strongest_paths)

    print candidate_chances
    print results

    # Assert every candidate is within 1 seats of expected statistical outcome
    for place, candidate in enumerate(candidate_chances):
        expected_place = candidate_chances.index(candidate)
        assert place in (expected_place, expected_place + 1, expected_place - 1)

        print "candidate", candidate[1], "had", candidate[0], "% chance of winning."
        other_candidates = 0 if results[candidate[1]] is None else len(results[candidate[1]]), "other candidates"
        print "candidate was ranked above {}".format(other_candidates)
Beispiel #2
0
    def get_ordered_candidates_from_votes(self):
        if self.deadline_joined_org:
            votes = ElectionVote.objects.select_related(
                'candidate__user').filter(
                    election=self,
                    user__userprofile__joined_org__lt=self.deadline_joined_org)
        else:
            votes = ElectionVote.objects.select_related(
                'candidate__user').filter(election=self)
        candidates = Candidate.objects.select_related('user').filter(
            election=self)
        votemap = {}
        for vote in votes:
            if not votemap.has_key(vote.user_id):
                votemap[vote.user_id] = []
            votemap[vote.user_id].append(vote)

        manger = []
        for user_id in votemap:
            manger.append([(v.value, v.candidate) for v in votemap[user_id]])

        preference = schulze.rank_votes(manger, candidates)
        strongest_paths = schulze.compute_strongest_paths(
            preference, candidates)

        ordered_candidates = schulze.get_ordered_voting_results(
            strongest_paths)
        return ordered_candidates
Beispiel #3
0
def test_3_candidates_3_votes_cyclical():

    candidates = ['x', 'y', 'z']
    votes = [
        [(1, 'x'), (2, 'y'), (3, 'z')],
        [(1, 'y'), (2, 'z'), (3, 'x')],
        [(1, 'z'), (2, 'x'), (3, 'y')]
    ]

    # Randomize the votes
    random.shuffle(votes)

    # Create directed graph
    preference = schulze.rank_votes(votes, candidates)

    # Get the strongest paths of each candidate
    strongest_paths = schulze.compute_strongest_paths(preference, candidates)

    # Get final, ordered, results
    results = schulze.get_ordered_voting_results(strongest_paths)

    # We should only get 3 results, even if this is cyclical tied vote.
    assert len(results) == 3

    # All path strengths should be equal, this is a tied vote!
    for sp in strongest_paths.itervalues():
        assert sum(sp.values()) == 4
Beispiel #4
0
def test_3_candidates_3_votes_cyclical():

    candidates = ['x', 'y', 'z']
    votes = [
        [(1, 'x'), (2, 'y'), (3, 'z')],
        [(1, 'y'), (2, 'z'), (3, 'x')],
        [(1, 'z'), (2, 'x'), (3, 'y')]
    ]

    # Randomize the votes
    random.shuffle(votes)

    # Create directed graph
    preference = schulze.rank_votes(votes, candidates)

    # Get the strongest paths of each candidate
    strongest_paths = schulze.compute_strongest_paths(preference, candidates)

    # Get final, ordered, results
    results = schulze.get_ordered_voting_results(strongest_paths)

    # We should only get 3 results, even if this is cyclical tied vote.
    assert len(results) == 3

    # All path strengths should be equal, this is a tied vote!
    for sp in strongest_paths.itervalues():
        assert sum(sp.values()) == 4
Beispiel #5
0
 def schulze_results_old(self):
     candidates = self.candidates
     preference = schulze.rank_votes(self.ballots, candidates)
     strongest_paths = schulze.compute_strongest_paths(
         preference, candidates)
     ordered_candidates = schulze.get_ordered_voting_results(
         strongest_paths)
     return [cand for cand in ordered_candidates]
Beispiel #6
0
    def get_context_data(self, *args, **kwargs):

        # Single variable for template to check which controls to enable
        voting_interface_enabled = self.get_object().polity.is_member(
            self.request.user) and self.get_object().is_voting

        if self.get_object().deadline_joined_org:
            votes = ElectionVote.objects.select_related(
                'candidate__user').filter(
                    election=self.get_object(),
                    user__userprofile__joined_org__lt=self.get_object(
                    ).deadline_joined_org)
        else:
            votes = ElectionVote.objects.select_related(
                'candidate__user').filter(election=self.get_object())
        candidates = Candidate.objects.select_related('user').filter(
            election=self.get_object())
        votemap = {}
        for vote in votes:
            if not votemap.has_key(vote.user_id):
                votemap[vote.user_id] = []

            votemap[vote.user_id].append(vote)

        manger = []
        for user_id in votemap:
            manger.append([(v.value, v.candidate) for v in votemap[user_id]])

        preference = schulze.rank_votes(manger, candidates)
        strongest_paths = schulze.compute_strongest_paths(
            preference, candidates)

        election_results = schulze.get_ordered_voting_results(strongest_paths)

        context_data = super(ElectionDetailView,
                             self).get_context_data(*args, **kwargs)
        context_data.update({
            'polity':
            self.polity,
            "now":
            datetime.now().strftime("%d/%m/%Y %H:%I"),
            'election_results':
            election_results,
            'voting_interface_enabled':
            voting_interface_enabled,
            'user_is_member':
            self.request.user in self.polity.members.all()
        })
        return context_data
Beispiel #7
0
    def get_ordered_candidates_from_votes(self):
        if self.deadline_joined_org:
            votes = ElectionVote.objects.select_related('candidate__user').filter(election=self, user__userprofile__joined_org__lt = self.deadline_joined_org)
        else:
            votes = ElectionVote.objects.select_related('candidate__user').filter(election=self)
        candidates = Candidate.objects.select_related('user').filter(election=self)
        votemap = {}
        for vote in votes:
            if not votemap.has_key(vote.user_id):
                votemap[vote.user_id] = []
            votemap[vote.user_id].append(vote)

        manger = []
        for user_id in votemap:
            manger.append([(v.value, v.candidate) for v in votemap[user_id]])

        preference = schulze.rank_votes(manger, candidates)
        strongest_paths = schulze.compute_strongest_paths(preference, candidates)

        ordered_candidates = schulze.get_ordered_voting_results(strongest_paths)
        return ordered_candidates
Beispiel #8
0
def statistical_test(nr_candidates=10, nr_voters=1000):
    """
    Runs a statistical test of Shulze with nr_candidates and nr_voters.
    Each voter generates a set of choices (a vote) based on the chances of each candidate's
    randomly determined chance of winning.
    """
    candidates = list(range(nr_candidates))
    candidate_chances = [(random.random() / 2, c) for c in candidates]
    candidate_chances.sort()
    candidate_chances.reverse()

    voters = list(range(nr_voters))
    votes = [generate_vote(candidate_chances) for _ in voters]

    # Create directed graph
    preference = schulze.rank_votes(votes, candidates)

    # Get the strongest paths of each candidate
    strongest_paths = schulze.compute_strongest_paths(preference, candidates)

    # Get final, ordered, results
    results = schulze.get_ordered_voting_results(strongest_paths)

    print candidate_chances
    print results

    # Assert every candidate is within 1 seats of expected statistical outcome
    for place, candidate in enumerate(candidate_chances):
        expected_place = candidate_chances.index(candidate)
        assert place in (expected_place, expected_place + 1,
                         expected_place - 1)

        print "candidate", candidate[1], "had", candidate[
            0], "% chance of winning."
        other_candidates = 0 if results[candidate[1]] is None else len(
            results[candidate[1]]), "other candidates"
        print "candidate was ranked above {}".format(other_candidates)
Beispiel #9
0
 def schulze_results_old(self):
     candidates = self.candidates
     preference = schulze.rank_votes(self.ballots, candidates)
     strongest_paths = schulze.compute_strongest_paths(preference, candidates)
     ordered_candidates = schulze.get_ordered_voting_results(strongest_paths)
     return [cand for cand in ordered_candidates]
Beispiel #10
0
def test_6_candidates_45_votes():
    # Candidate 'x' is someone no-one voted for but was eligible.
    # Otherwise, this test reflects the example on https://en.wikipedia.org/wiki/Schulze_method
    candidates = ['a', 'b', 'c', 'd', 'e', 'x']
    votes = [
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')], #5
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')],
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')],
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')],
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')],
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')], #5
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')], #8
        [(1, 'c'), (2, 'a'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'b'), (4, 'e'), (5, 'd')], #20
        [(1, 'c'), (2, 'a'), (3, 'b'), (4, 'e'), (5, 'd')], #3
        [(1, 'c'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'e')],
        [(1, 'c'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'e')], #2
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')], #30
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')], #7
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')], #40
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')] #8
    ]

    # Randomize the votes
    random.shuffle(votes)

    # Create directed graph
    preference = schulze.rank_votes(votes, candidates)

    # Get the strongest paths of each candidate
    strongest_paths = schulze.compute_strongest_paths(preference, candidates)

    # Get final, ordered, results
    results = schulze.get_ordered_voting_results(strongest_paths)

    assert ", ".join(results.keys()) == "e, a, c, b, d, x"
Beispiel #11
0
def test_6_candidates_45_votes():
    # Candidate 'x' is someone no-one voted for but was eligible.
    # Otherwise, this test reflects the example on https://en.wikipedia.org/wiki/Schulze_method
    candidates = ['a', 'b', 'c', 'd', 'e', 'x']
    votes = [
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'a'), (2, 'c'), (3, 'b'), (4, 'e'), (5, 'd')], #5
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')],
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')],
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')],
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')],
        [(1, 'a'), (2, 'd'), (3, 'e'), (4, 'c'), (5, 'b')], #5
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')],
        [(1, 'b'), (2, 'e'), (3, 'd'), (4, 'a'), (5, 'c')], #8
        [(1, 'c'), (2, 'a'), (3, 'b'), (4, 'e'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'b'), (4, 'e'), (5, 'd')], #20
        [(1, 'c'), (2, 'a'), (3, 'b'), (4, 'e'), (5, 'd')], #3
        [(1, 'c'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'e')],
        [(1, 'c'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'e')], #2
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')],
        [(1, 'd'), (2, 'c'), (3, 'e'), (4, 'b'), (5, 'a')], #30
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')],
        [(1, 'c'), (2, 'a'), (3, 'e'), (4, 'b'), (5, 'd')], #7
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')], #40
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')],
        [(1, 'e'), (2, 'b'), (3, 'a'), (4, 'd'), (5, 'c')] #8
    ]

    # Randomize the votes
    random.shuffle(votes)

    # Create directed graph
    preference = schulze.rank_votes(votes, candidates)

    # Get the strongest paths of each candidate
    strongest_paths = schulze.compute_strongest_paths(preference, candidates)

    # Get final, ordered, results
    results = schulze.get_ordered_voting_results(strongest_paths)

    assert ", ".join(results.keys()) == "e, a, c, b, d, x"

    return results