def test_simple_stv(self): stay = Candidate("Stay") soft = Candidate("Soft Brexit") hard = Candidate("Hard Brexit") candidates = [stay, soft, hard] ballots = [ Ballot(ranked_candidates=[soft, stay]), Ballot(ranked_candidates=[stay, soft]), Ballot(ranked_candidates=[stay, soft]), Ballot(ranked_candidates=[hard, soft]), Ballot(ranked_candidates=[hard, stay, soft]), ] election_result = pyrankvote.single_transferable_vote( candidates, ballots, number_of_seats=1) winners = election_result.get_winners() self.assertEqual(1, len(winners), "Function should return a list with one item") winner = winners[0] self.assertEqual(stay, winner, "Winner should be Soft")
def calculateElectionResults(election): for i in election.questions: q = Question.query.filter_by(id=i).first() if q.voteType == "FPTP": winnerVote = {"first": {"description": "", "count": 0}} ties = list() for name, details in q.votes["answers"].items(): if details["count"] > winnerVote[next(iter(winnerVote))]["count"]: winnerVote = {name: details} ties = [] elif details["count"] == winnerVote[next(iter(winnerVote))]["count"]: ties += [{name: details}] q.votes["results"] = [winnerVote] + ties audit = f"Answer {next(iter(winnerVote))} won by having highest number of votes, {winnerVote[next(iter(winnerVote))]['count']}." if len(ties) == 0: audit += " There were no ties." else: audit += f" There were ties as well: " for tie in ties: audit += ( ", ".join([next(iter(tie)), str(tie[next(iter(tie))]["count"])]) + "; " ) q.votes["audit"] = audit flag_modified(q, "votes") db.session.add(q) db.session.flush() elif q.voteType == "STV": candidates = list(map(lambda x: Candidate(x["name"]), q.votes["answers"])) fullBallots = ballotify(q.votes["ballots"], candidates) results = pyrankvote.single_transferable_vote( candidates, fullBallots, number_of_seats=1 ) winner = results.get_winners() print(f"Winner for STV question: {winner}") print(f"Audit for STV question:\n{results}") winnerDetails = list( filter(lambda x: x["name"] == str(winner[0]), q.votes["answers"]) ) print(winnerDetails) q.votes["results"] = winnerDetails q.votes["audit"] = str(results) flag_modified(q, "votes") db.session.add(q) db.session.flush() db.session.commit()
def test_case2(self): per = Candidate("Per") paal = Candidate("Pål") maria = Candidate("Maria") ingrid = Candidate("Ingrid") candidates = [per, paal, maria, ingrid] # Quote = 3.33 with 10 votes and 2 seat ballots = [ Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[maria, ingrid]), Ballot(ranked_candidates=[ingrid, maria]), Ballot(ranked_candidates=[ingrid, maria]), ] # 1. round: Per: 7, Ingrid: 2, Maria: 1, Pål: 0 # --> Per is elected and 3.67 votes are transferred to Pål # Final round: Per: 3.33, Pål: 3.67, Ingrid: 2, Maria: 1 # --> Paal is elected. Since all seats filled, Ingrid and Maria are rejected. election_result = pyrankvote.single_transferable_vote( candidates, ballots, number_of_seats=2) winners = election_result.get_winners() self.assertEqual(2, len(winners), "Function should return a list with two items") self.assertListEqual([per, paal], winners, "Winners should be Per and Pål") round = 0 votes_round = [ candidate_vc.number_of_votes for candidate_vc in election_result.rounds[round].candidate_results ] assert_list_almost_equal(self, votes_round, [7, 2, 1, 0], 0.02) round = 1 votes_round = [ candidate_vc.number_of_votes for candidate_vc in election_result.rounds[round].candidate_results ] assert_list_almost_equal(self, votes_round, [3.33, 3.67, 2, 1], 0.02)
def get_election_res(pred_df, id_orig, n_ans): df = pred_df[pred_df.id.str.startswith(id_orig)] candidates = [Candidate(el) for el in df.answers.unique()] ballots = [ Ballot(ranked_candidates=[ Candidate(vote) for vote in df[df.id == id_].answers ]) for id_ in df.id.unique() ] if len(candidates) <= n_ans: return list(df.answers) if args['voting'] == 'pbv': election_result = pyrankvote.preferential_block_voting( candidates, ballots, min(n_ans, len(candidates))) else: election_result = pyrankvote.single_transferable_vote( candidates, ballots, min(n_ans, len(candidates))) return election_result
def test_case3(self): per = Candidate("Per") paal = Candidate("Pål") maria = Candidate("Maria") ingrid = Candidate("Ingrid") candidates = [per, paal, maria, ingrid] # Quote = 4.67 with 11 votes and 2 seat ballots = [ Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[maria, ingrid]), Ballot(ranked_candidates=[ingrid, maria]), Ballot(ranked_candidates=[ingrid, maria]), ] # 1. round: Per: 7, Ingrid: 2, Maria: 1, Pål: 0 # --> Per is elected and 3.33 votes are transfered to Pål # 2. round: Pål: 3.33, Ingrid: 2, Maria: 1 # --> Maria is excluded and her one vote is transfered to Ingrid # 3. round: Pål: 3.33, Ingrid: 3 # --> Pål is elected election_result = pyrankvote.single_transferable_vote( candidates, ballots, number_of_seats=2) winners = election_result.get_winners() self.assertEqual(2, len(winners), "Function should return a list with two items") self.assertListEqual([per, paal], winners, "Winners should be Per and Pål")
def test_simple_stv2(self): per = Candidate("Per") paal = Candidate("Pål") askeladden = Candidate("Askeladden") candidates = [per, paal, askeladden] ballots = [ Ballot(ranked_candidates=[askeladden, per]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[per, paal]), Ballot(ranked_candidates=[paal, per]), Ballot(ranked_candidates=[paal, per, askeladden]), ] election_result = pyrankvote.single_transferable_vote( candidates, ballots, number_of_seats=1) winners = election_result.get_winners() self.assertEqual(1, len(winners), "Function should return a list with one item") self.assertListEqual([per], winners, "Winners should be Per")
def main(): gc = gspread.authorize(get_creds()) wb = gc.open_by_key(os.environ['gsheet_id']) worksheet = wb.get_worksheet(0) candidates = {} for candidate in [CANDIDATE_REGEX.search(c).group(1) for c in worksheet.row_values(1) if CANDIDATE_REGEX.search(c)]: candidates[candidate] = pyrankvote.Candidate(candidate) raw_ballots = worksheet.get_all_records() ballots = [] for raw_ballot in raw_ballots: ballot = sorted({candidates[CANDIDATE_REGEX.search(c).group(1)]: r for (c, r) in raw_ballot.items() if CANDIDATE_REGEX.search(c)}.items(), key=lambda x: x[1]) ballots.append(pyrankvote.Ballot(ranked_candidates=[c for c, r in ballot])) # print(ballot) election_result = pyrankvote.single_transferable_vote(candidates=candidates.values(), ballots=ballots, number_of_seats=SEATS) winners = election_result.get_winners() with open('output/results.txt', 'w+') as f: f.write(str(election_result)) print(election_result)
Ballot(ranked_candidates=[popular_moderate, moderate2, moderate3, far_left]), Ballot(ranked_candidates=[popular_moderate, moderate3, moderate2, far_left]), Ballot(ranked_candidates=[popular_moderate, moderate3, moderate2, far_left]), Ballot(ranked_candidates=[moderate2, popular_moderate, moderate3, far_left]), Ballot(ranked_candidates=[moderate2, popular_moderate, moderate3, far_left]), Ballot(ranked_candidates=[far_left, popular_moderate, moderate2, moderate3]), Ballot(ranked_candidates=[far_left, popular_moderate, moderate2, moderate3]), Ballot(ranked_candidates=[far_left, moderate2, popular_moderate, moderate3]), Ballot(ranked_candidates=[far_left, moderate2, popular_moderate, moderate3]), ] # SINGLE TRANSFERABLE VOTE election_result = pyrankvote.single_transferable_vote(candidates, ballots, number_of_seats=2) # Elects: William, popular moderate; and Thomas, far-left print(election_result) # Prints: """ FINAL RESULT Candidate Votes Status ------------------------- ------- -------- William, popular moderate 4 Elected Thomas, far-left 4 Elected John, moderate 2 Rejected Charles, moderate 0 Rejected """ # PREFERENTIAL BLOCK VOTING
def main(): # where are we now? frame = inspect.currentframe().f_code.co_name # how many "seats" are being selected? n_seats = 2 # load the data into a dataframe ballots = [] candidates = [] # make the ballots utils.print_message(frame, "Making ballots.") # there are a couple of ways to arrange the data # 1. ranked columns have a format of # voter1 voter2 voter 3 # candidate1 1 1 2 # candidate2 3 2 1 # candidate3 2 3 3 # etc. # # use the functions in matrix_votes to construct ballots and candidate lists # - matrix_votes.make_candidate_list() # - matrix_votes.make_ballots() # df = read_ranked_columns("./matrix_data.xlsx") df = read_ranked_columns("./cerc2.xlsx") candidate_names = [] candidates, candidate_names = mv.make_candidate_list(df) ballots = mv.make_ballots(df, candidate_names, ['voter1', 'voter2', 'voter3','voter4','voter5','voter6'], top_N) print("The ranked voting data:") print(df) # 2. MS Forms "arrange in preferred order" data # - it contains a column with a list each respondent's ranking # - items in the ranking column are separated by a semi-colon # - and must end with a semicolon too! # # voter1 candidate1;candidate2;candidate3; # voter2 candidate2;candidate1;candidate3; # etc. # use the code below # # df = read_forms_data("./forms_data.xlsx").values.tolist() # for item in df: # # ranked list is in column 5 (with 0-based index) # b = item[5].split(';') # # drop the last empty item # # TODO: probably other ways to do this to, with an iterator maybe # b = b[:(len(b)-1)] # ballots.append(Ballot(ranked_candidates=[Candidate(x) for x in b])) # if VERBOSE: # print(ballots) # # make the list of candidates # utils.print_message(frame, "Making list of candidate names.") # # use the last ballot, sorted, to get the list of candidate names # # this is an easy way to do it and just re-uses the last ballot # for the_candidate in sorted(b): # candidates.append(Candidate(the_candidate)) # # show the list of Candidate objects # if VERBOSE: # print(candidates) # run the STV vote utils.print_message(frame, "Executing STV selection.") stv_election_result = pyrankvote.single_transferable_vote( candidates, ballots, number_of_seats=n_seats ) stv_winner = stv_election_result.get_winners() utils.print_message(frame, "STV Selected: {0}".format(stv_winner)) if VERBOSE: utils.print_message(frame, "STV Selection Result.") print(stv_election_result)
ranked_vote != ranked_vote ) # True where there are NaNs (candidates that didn't get a ranking) ranked_vote[NaNs] = len( candidates ) + 1 # If the voter didn't rank this candidate, they are disregarded (placed last, so the next line will cut them out) # Create a sorted list of Candidate objects based on this voter's rankings candidate_indices = np.argsort(ranked_vote)[:( len(candidates) - sum(NaNs) )] # Returns indices of candidates in sorted order, removing candidates that this voter didn't rank ranked_candidates = candidates[ candidate_indices] # Candidate objects corresponding to the sorted indices # Create ballot! ballot = Ballot(ranked_candidates=ranked_candidates) ballots.append(ballot) # print ("Vote is {}".format(ballot)) ## Run single transferable vote election ## # Note that in case of first-choice tie, the library uses second-choice for tiebreaks. election = pyrankvote.single_transferable_vote(candidates, ballots, number_of_seats=args.n_seats) print(election) with open(args.output, 'w') as f: f.write(str(election)) print('Saved to file ' + args.output) # breakpoint()
def test_example(self): popular_moderate = Candidate("William, popular moderate") moderate2 = Candidate("John, moderate") moderate3 = Candidate("Charles, moderate") far_left = Candidate("Thomas, far-left") candidates = [popular_moderate, moderate2, moderate3, far_left] ballots = [ Ballot(ranked_candidates=[ popular_moderate, moderate2, moderate3, far_left ]), Ballot(ranked_candidates=[ popular_moderate, moderate2, moderate3, far_left ]), Ballot(ranked_candidates=[ popular_moderate, moderate3, moderate2, far_left ]), Ballot(ranked_candidates=[ popular_moderate, moderate3, moderate2, far_left ]), Ballot(ranked_candidates=[ moderate2, popular_moderate, moderate3, far_left ]), Ballot(ranked_candidates=[ moderate2, popular_moderate, moderate3, far_left ]), Ballot(ranked_candidates=[ far_left, popular_moderate, moderate2, moderate3 ]), Ballot(ranked_candidates=[ far_left, popular_moderate, moderate2, moderate3 ]), Ballot(ranked_candidates=[ far_left, moderate2, popular_moderate, moderate3 ]), Ballot(ranked_candidates=[ far_left, moderate2, popular_moderate, moderate3 ]), ] election_result = pyrankvote.single_transferable_vote( candidates, ballots, number_of_seats=2) round_nr = 0 candidates_results_in_round = election_result.rounds[ round_nr].candidate_results ranking_in_round = [ candidate_result.candidate for candidate_result in candidates_results_in_round ] votes_in_round = [ candidate_result.number_of_votes for candidate_result in candidates_results_in_round ] self.assertEqual(4, len(ranking_in_round), "All four candidates should be list.") self.assertListEqual( [popular_moderate, far_left, moderate2, moderate3], ranking_in_round) assert_list_almost_equal(self, [4, 4, 2, 0], votes_in_round) self.assertEqual(1, len(election_result.rounds), "Should be only one round") winners = election_result.get_winners() self.assertEqual(2, len(winners), "Should be two winners") self.assertIn(popular_moderate, winners, "William should be a winner") self.assertIn(far_left, winners, "John should be a winner")
else: continue return names votes = get_votes(path) for vote in votes: names = get_names(vote) ballot = [] for name in names: name = name[0].upper() + name[1:] if name not in candidates: candidates[name] = prv.Candidate(name) ballot.append(candidates[name]) ballots.append(prv.Ballot(ranked_candidates=ballot)) Candidates = [candidates[i] for i in candidates] election = prv.single_transferable_vote(Candidates, ballots, spots) if "show_all" in sys.argv: print(election) elif "show_last" in sys.argv: print(f"Final result, last of {len(election.rounds) + 1} rounds") print(election.rounds[-1]) else: winners = election.get_winners() for winner in winners: print(winner)
reader = csv.reader(f) first_row = True for row in reader: if first_row: first_row = False continue # Skip timestamp and user. ballots.append(row[2:]) # Create Candidate objects for every proposal. proposals = {} for ballot in ballots: for proposal in ballot: if proposal not in proposals: proposals[proposal] = Candidate(proposal) # Create Ballot objects for every ballot. processed_ballots = [] for ballot in ballots: ranked = [] for proposal in ballot: ranked.append(proposals[proposal]) processed_ballots.append(Ballot(ranked_candidates=ranked)) # Print election results. election_result = pyrankvote.single_transferable_vote( proposals.values(), processed_ballots, number_of_seats=NUMBER_OF_WINNERS) print(election_result)