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)
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
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
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]
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
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
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)
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]
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"
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