Exemplo n.º 1
0
    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")
Exemplo n.º 2
0
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()
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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")
Exemplo n.º 6
0
    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")
Exemplo n.º 7
0
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)
Exemplo n.º 8
0
    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
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
        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()
Exemplo n.º 11
0
    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")
Exemplo n.º 12
0
        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)
Exemplo n.º 13
0
        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)