Example #1
0
    def calculate_new_outcome(self, new_voter_preference, voter):

        new_preference = self.preferences.copy()
        new_preference[voter] = new_voter_preference

        new_voting_scheme = VotingScheme(new_preference,
                                         len(new_preference[0]))
        new_voting_scheme.execute_voting(self.voting_scheme_option)

        new_outcome = new_voting_scheme.get_outcome()

        return new_outcome, new_voting_scheme
Example #2
0
    def __init__(self, preferences, voting_scheme_option):

        self.preferences = preferences
        self.voting_scheme_option = voting_scheme_option

        self.voting_scheme = VotingScheme(preferences, len(preferences[0]))
        self.points_outcome = self.voting_scheme.execute_voting(
            voting_scheme_option)
        self.outcome = self.voting_scheme.get_outcome()
        self.happiness = self.voting_scheme.calc_happiness(self.outcome)
        self.overall_happiness = self.voting_scheme.calc_overall_happiness(
            self.outcome)
Example #3
0
    def __init__(self, preferences, voting_scheme):

        self.preferences = preferences
        self.voting_scheme = voting_scheme

        self.vs = VotingScheme(preferences, len(preferences[0]))
        self.outcome = self.vs.execute_voting(voting_scheme)
        self.winner_list = self.vs.get_outcome()
        self.happiness = self.vs.calc_happiness()
        self.hate = self.calculate_hate()
        self.hate_list = self.calculate_hated_candidates()
        # self.calculate()
        self.change_voter_votes_borda(1)
Example #4
0
class VotingSchemeShould(unittest.TestCase):

    def setUp(self):
        self.nCandidates = 5
        self.preferences = {0: ['A', 'D', 'E', 'B', 'C'], 1: ['C', 'B', 'E', 'A', 'D'], 2: ['E', 'D', 'A', 'B', 'C'],
                       3: ['C', 'E', 'A', 'D', 'B'], 4: ['E', 'C', 'D', 'A', 'B']}
        self.voting = VotingScheme(self.preferences, self.nCandidates)

    def test_plurality_voting(self):
        expected_outcome = {'A': 1, 'B': 0, 'C': 2, 'D': 0, 'E': 2}

        actual_outcome = self.voting.plurality_voting()

        self.assertEqual(expected_outcome, actual_outcome)

    def test_voting_for_two(self):
        expected_outcome = {'A': 1, 'B': 1, 'C': 3, 'D': 2, 'E': 3}

        actual_outcome = self.voting.voting_for_two()

        self.assertEqual(expected_outcome, actual_outcome)

    def test_anti_plurality_voting(self):
        expected_outcome = {'A': 5, 'B': 3, 'C': 3, 'D': 4, 'E': 5}

        actual_outcome = self.voting.anti_plurality_voting()

        self.assertEqual(expected_outcome, actual_outcome)

    def test_borda_voting(self):
        expected_outcome = {'A': 10, 'B': 5, 'C': 11, 'D': 9, 'E': 15}

        actual_outcome = self.voting.borda_voting()

        self.assertEqual(expected_outcome, actual_outcome)

    def test_get_outcome(self):
        expected_outcome = ['C', 'E', 'A', 'B', 'D']

        self.voting.plurality_voting()
        actual_outcome = self.voting.get_outcome()

        self.assertEqual(expected_outcome, actual_outcome)
Example #5
0
    def test_experiment_borda_voting_voter_5(self):
        # Initiate experiment variables
        number_of_candidates = 4
        voting_scheme = VotingSchemeOption.BORDA

        # Preferences Matrix
        preferences = {
            0: ["C", "A", "D", "B"],
            1: ["B", "D", "C", "A"],
            2: ["C", "D", "A", "B"],
            3: ["B", "D", "C", "A"],
            4: ["B", "C", "D", "A"]
        }

        voting = VotingScheme(preferences, number_of_candidates)
        voting.execute_voting(voting_scheme)

        model = Model(preferences, voting_scheme)
        results = model.calculate(False)

        # true outcome should be
        self.assertEqual(["C", "B", "D", "A"], results[0])

        # Voter 5 (index:4) should bury C
        self.assertEqual('This candidate was buried', results[2][4][3]["C"])
        # and the new outcome should be, making B win instead of C
        self.assertEqual(["B", "C", "D", "A"], results[2][4][1])
        # and his new preferences should be
        self.assertEqual(["B", "D", "C", "A"], results[2][4][0])

        # In the slides example the voter actually swapped C and A candidates instead of
        # B, C, D, A he voted B, A, D, C
        # In our software his new preferences where B, D, C, A

        # The overall happiness is reduced
        new_overall_happiness, old_overall_happiness = results[2][4][
            2], results[1]
        self.assertTrue(new_overall_happiness < old_overall_happiness)

        # Happiness of voter 5 should be increased
        old_happiness_of_5 = voting.get_happiness_by_voter(4)
        new_happiness_of_5 = voting.get_new_happiness_by_voter(
            4, ["B", "C", "D", "A"])
        self.assertTrue(new_happiness_of_5 > old_happiness_of_5)
Example #6
0
 def setUp(self):
     self.nCandidates = 5
     self.preferences = {0: ['A', 'D', 'E', 'B', 'C'], 1: ['C', 'B', 'E', 'A', 'D'], 2: ['E', 'D', 'A', 'B', 'C'],
                    3: ['C', 'E', 'A', 'D', 'B'], 4: ['E', 'C', 'D', 'A', 'B']}
     self.voting = VotingScheme(self.preferences, self.nCandidates)
Example #7
0
 def change_voter_vote(self, voter, vote):
     new_preferences = self.preferences.copy()
     possible_strategy = []
     true_preferred_cand = self.preferences[voter][0]
     opponent = self.vs.get_opponent(true_preferred_cand)
     for candidate in self.hate_list:
         voter_preferences = self.preferences[voter].copy()
         if candidate is voter_preferences[0]:
             # It does not make sense making win someone less hated than the person we would like that wins
             break
         # print()
         # Change the preferred voted
         c_index_v_pref = voter_preferences.index(candidate)
         help = voter_preferences[c_index_v_pref]
         voter_preferences[c_index_v_pref] = true_preferred_cand
         # print("The voter", voter, "was voting for", voter_preferences[0], "and is gonna try to vote for", help)
         voter_preferences[vote] = help
         new_preferences[voter] = voter_preferences
         # Create a new voting scheme with the new preferences
         new_vs = VotingScheme(new_preferences, len(new_preferences[0]))
         # Vote a first time with the new preferences
         new_vs.execute_voting(self.voting_scheme)
         first_outcome = new_vs.get_outcome()
         new_opponent = new_vs.get_opponent(true_preferred_cand)
         # If the outcome of applying the voting manipulation is the same one then it is not a good manipulation
         if collections.Counter(first_outcome[:2]) == collections.Counter(
                 self.winner_list[:2]):
             continue
         elif self.hate_list.index(new_opponent) >= self.hate_list.index(
                 opponent):
             continue
         # print("The result of the first round is", help_outcome)  # Vote a first time
         new_vs.second_round(self.preferences)
         second_outcome = new_vs.get_outcome()
         # If after the second round the winner is the desired one then it is an acceptable way of strategic voting
         if new_vs.get_outcome()[0] is self.preferences[voter][0]:
             print("For the voter", voter, "that was voting for",
                   self.preferences[voter][0],
                   "a new possible strategies is voting for", help)
             print("The new outcome in first round would be", first_outcome,
                   "and in the second", new_vs.get_outcome())
             possible_strategy.append(help)
         # If the two first candidates are not the same as previously
         # and the preferred candidate of the voter is still in top 2
     if len(possible_strategy) > 0:
         print("For the voter", voter,
               "the possible strategies are voting for", possible_strategy)
Example #8
0
class PushOver:
    """
    Voting a Candidate that is easy to beat insincerely high in the first round so that the second round is easy to win
    """
    def __init__(self, preferences, voting_scheme):

        self.preferences = preferences
        self.voting_scheme = voting_scheme

        self.vs = VotingScheme(preferences, len(preferences[0]))
        self.outcome = self.vs.execute_voting(voting_scheme)
        self.winner_list = self.vs.get_outcome()
        self.happiness = self.vs.calc_happiness()
        self.hate = self.calculate_hate()
        self.hate_list = self.calculate_hated_candidates()
        # self.calculate()
        self.change_voter_votes_borda(1)

    def calculate(self):
        print("Outcome", self.outcome)
        print("Winner list", self.winner_list)

        # for candidate in self.winner_list:
        #     print("Candidate", candidate, "has", self.outcome[candidate], " votes")
        print("Hated list", self.hate_list)
        for voter, voter_preferences in self.preferences.items():
            # If the preferred candidate of the voter would win without doing anything
            # if voter_preferences[0] is self.winner_list[0] or voter_preferences[0] is self.winner_list[1]:
            # Maybe it is interesting to vote for someone else that other voters
            # do not like so that the second round is easier
            # print()
            # print("Voter", voter, "is very HAPPY")
            # print(self.preferences[voter])
            self.change_voter_votes_plurality(voter)

    """
    In plurality voting only one candidate can be voted and it is therefore the only that should be changed.
    """

    def change_voter_votes_plurality(self, voter):
        self.change_voter_vote(voter, 0)

    """
    In voting for two, only the two first candidates in the preference list get a point. Since both of them get a point
    it is not important which one is the first or second in the manipulation.
    """

    def change_voter_votes_for_two(self, voter):
        self.change_voter_vote(voter, 0)
        self.change_voter_vote(voter, 1)

    """
    In anti-plurality voting, only the least preferred candidate in the preference list does not get a point.
    Therefore, only changing the least preferred candidate could affect the outcome of the voting
    """

    def change_voter_votes_anti_plurality(self, voter):
        self.change_voter_vote(voter, len(self.preferences[voter]))

    """
    In borda voting every preference gets a point and the higher it is in the preference list, the more points it gets. 
    Therefore, all possible combinations of preferences have to be checked
    """

    def change_voter_votes_borda(self, voter):
        # TODO
        i = 0
        for possible in itertools.permutations(self.preferences[voter]):
            print("A new possibility is", possible)
            i += 1
        print(i)

        # self.change_voter_vote(voter, len(self.preferences[voter]))
        return

    def change_voter_vote(self, voter, vote):
        new_preferences = self.preferences.copy()
        possible_strategy = []
        true_preferred_cand = self.preferences[voter][0]
        opponent = self.vs.get_opponent(true_preferred_cand)
        for candidate in self.hate_list:
            voter_preferences = self.preferences[voter].copy()
            if candidate is voter_preferences[0]:
                # It does not make sense making win someone less hated than the person we would like that wins
                break
            # print()
            # Change the preferred voted
            c_index_v_pref = voter_preferences.index(candidate)
            help = voter_preferences[c_index_v_pref]
            voter_preferences[c_index_v_pref] = true_preferred_cand
            # print("The voter", voter, "was voting for", voter_preferences[0], "and is gonna try to vote for", help)
            voter_preferences[vote] = help
            new_preferences[voter] = voter_preferences
            # Create a new voting scheme with the new preferences
            new_vs = VotingScheme(new_preferences, len(new_preferences[0]))
            # Vote a first time with the new preferences
            new_vs.execute_voting(self.voting_scheme)
            first_outcome = new_vs.get_outcome()
            new_opponent = new_vs.get_opponent(true_preferred_cand)
            # If the outcome of applying the voting manipulation is the same one then it is not a good manipulation
            if collections.Counter(first_outcome[:2]) == collections.Counter(
                    self.winner_list[:2]):
                continue
            elif self.hate_list.index(new_opponent) >= self.hate_list.index(
                    opponent):
                continue
            # print("The result of the first round is", help_outcome)  # Vote a first time
            new_vs.second_round(self.preferences)
            second_outcome = new_vs.get_outcome()
            # If after the second round the winner is the desired one then it is an acceptable way of strategic voting
            if new_vs.get_outcome()[0] is self.preferences[voter][0]:
                print("For the voter", voter, "that was voting for",
                      self.preferences[voter][0],
                      "a new possible strategies is voting for", help)
                print("The new outcome in first round would be", first_outcome,
                      "and in the second", new_vs.get_outcome())
                possible_strategy.append(help)
            # If the two first candidates are not the same as previously
            # and the preferred candidate of the voter is still in top 2
        if len(possible_strategy) > 0:
            print("For the voter", voter,
                  "the possible strategies are voting for", possible_strategy)

    def calculate_hate(self):
        hate = {}
        for voter, voter_preferences in self.preferences.items():
            # Since the preferences are order being the most preferred in the position zero and the less liked
            # in the position n, it can also be understood as a measure of not liking or dislike
            for dislike, candidate in enumerate(voter_preferences):
                try:
                    hate[candidate] += dislike
                except:
                    hate[candidate] = dislike
        return hate

    def calculate_hated_candidates(self):
        return sorted(self.hate, key=self.hate.get, reverse=True)
Example #9
0
class Model:
    COMPROMISE = "Compromised in favor of this candidate"
    BURYING = "This candidate was buried"
    BULLET_VOTING = "There was bulet voting in favor of this candidate"
    """
        Voting a Candidate that is easy to beat insincerely high in the first round so that the second round is easy to win
        """
    def __init__(self, preferences, voting_scheme_option):

        self.preferences = preferences
        self.voting_scheme_option = voting_scheme_option

        self.voting_scheme = VotingScheme(preferences, len(preferences[0]))
        self.points_outcome = self.voting_scheme.execute_voting(
            voting_scheme_option)
        self.outcome = self.voting_scheme.get_outcome()
        self.happiness = self.voting_scheme.calc_happiness(self.outcome)
        self.overall_happiness = self.voting_scheme.calc_overall_happiness(
            self.outcome)

    """
    Calculates for every voter the possible strategic-voting result
    
    output possibly empty strategic-voting option 
    """

    def calculate(self, bullet_voting_allowed):

        strategic_voting_option = []
        self.n_strategic_options = 0
        for voter in range(len(self.preferences)):
            voter_max_hap = self.voting_scheme.calc_happiness(
                self.outcome)[voter]
            voter_original_hap = voter_max_hap
            voter_strategic_votes = {}

            candidates = self.preferences[voter]

            if self.voting_scheme_option != VotingSchemeOption.PLURALITY_VOTING and bullet_voting_allowed:
                self.calculate_bullet_voting(candidates, voter, voter_max_hap,
                                             voter_strategic_votes,
                                             voter_original_hap)
            elif self.voting_scheme_option == VotingSchemeOption.PLURALITY_VOTING:
                self.calculate_compromising_and_burying_plurality(
                    voter, voter_max_hap, voter_strategic_votes,
                    voter_original_hap)
            else:
                self.calculate_compromising_and_burying(
                    voter, voter_max_hap, voter_strategic_votes,
                    voter_original_hap)

            strategic_voting_option.append(
                self.evaluate_outcome(voter, voter_strategic_votes))

        risk = self.n_strategic_options / len(self.preferences)

        return self.outcome, self.overall_happiness, strategic_voting_option, risk

    def calculate_compromising_and_burying_plurality(self, voter,
                                                     voter_max_hap,
                                                     voter_strategic_votes,
                                                     voter_original_hap):

        for index, candidate in enumerate(self.preferences[voter]):
            new_voter = voter
            new_voter_preferences = self.preferences[voter].copy()

            # Change the preferred voted
            new_voter_preferences[index] = new_voter_preferences[0]
            new_voter_preferences[0] = candidate
            # print("The voter", voter, "was voting for", voter_preferences[0], "and is gonna try to vote for", help)

            new_outcome, new_voting_scheme = self.calculate_new_outcome(
                new_voter_preferences, voter)

            if new_outcome[0] is self.outcome[0]:
                continue

            new_happiness = self.voting_scheme.get_new_happiness_by_voter(
                voter, new_outcome)

            if new_happiness > voter_original_hap:
                self.n_strategic_options += 1

            if new_happiness <= voter_max_hap:
                continue

            voter_max_hap = new_happiness
            voter_strategic_votes[new_voting_scheme] = new_outcome

    def calculate_compromising_and_burying(self, voter, voter_max_hap,
                                           voter_strategic_votes,
                                           voter_original_hap):
        for new_voter_preference in itertools.permutations(
                self.preferences[voter]):

            new_voter_preference = list(new_voter_preference)

            new_outcome, new_voting_scheme = self.calculate_new_outcome(
                new_voter_preference, voter)

            if new_outcome[0] is self.outcome[0]:
                continue

            new_happiness = self.voting_scheme.get_new_happiness_by_voter(
                voter, new_outcome)

            if new_happiness > voter_original_hap:
                self.n_strategic_options += 1

            if new_happiness <= voter_max_hap:
                continue

            voter_max_hap = new_happiness
            voter_strategic_votes[new_voting_scheme] = new_outcome

    def calculate_bullet_voting(self, candidates, voter, voter_max_hap,
                                voter_strategic_votes, voter_original_hap):
        # to perform bullet voting as strategic voting we have to generate the preference with only the first one
        for candidate in candidates:

            new_voter_preference = ["" for i in candidates]
            new_voter_preference[0] = candidate

            new_outcome, new_voting_scheme = self.calculate_new_outcome(
                new_voter_preference, voter)

            if new_outcome[0] is self.outcome[0]:
                continue

            new_happiness = self.voting_scheme.get_new_happiness_by_voter(
                voter, new_outcome)

            if new_happiness > voter_original_hap:
                self.n_strategic_options += 1

            if new_happiness <= voter_max_hap:
                continue

            voter_strategic_votes[new_voting_scheme] = new_outcome

    """
    Evaluate the input strategic vote for the input voter and return the kind of strategic vote applied and to which candidate.
    input @voter 
    input @voter_strategic_votes 
    
    output (dict/list/array?) changes
    
    """

    def evaluate_outcome(self, voter, voter_strategic_votes):

        best_happiness = self.voting_scheme.get_new_happiness_by_voter(
            voter, self.outcome)
        changes = {}

        # for bullet prove change the preference in the array with ""
        # before checking if the position is greater/smaller than the original check if the position is ""
        new_preferences = []
        new_final_outcome = []
        new_overall_happiness = 0

        for new_voting_scheme, new_outcome in voter_strategic_votes.items():

            if self.voting_scheme.get_new_happiness_by_voter(
                    voter, new_outcome) <= best_happiness:
                continue

            best_happiness = self.voting_scheme.get_new_happiness_by_voter(
                voter, new_outcome)

            changes = {}

            if new_voting_scheme.preferences[voter][1] is "":
                candidate = new_voting_scheme.preferences[voter][0]
                changes[candidate] = self.BULLET_VOTING
                new_preferences = new_voting_scheme.preferences[voter]
                new_final_outcome = new_outcome
                new_overall_happiness = self.voting_scheme.calc_overall_happiness(
                    new_outcome)
                continue

            # Position is the index in the array and candidate the value
            for old_position, candidate in enumerate(self.outcome):

                if new_outcome.index(candidate) < old_position:
                    # Compromising
                    changes[candidate] = self.COMPROMISE
                elif new_outcome.index(candidate) > old_position:
                    # Burying
                    changes[candidate] = self.BURYING

            new_preferences = new_voting_scheme.preferences[voter]
            new_final_outcome = new_outcome
            new_overall_happiness = self.voting_scheme.calc_overall_happiness(
                new_outcome)

        return new_preferences, new_final_outcome, new_overall_happiness, changes

    def calculate_new_outcome(self, new_voter_preference, voter):

        new_preference = self.preferences.copy()
        new_preference[voter] = new_voter_preference

        new_voting_scheme = VotingScheme(new_preference,
                                         len(new_preference[0]))
        new_voting_scheme.execute_voting(self.voting_scheme_option)

        new_outcome = new_voting_scheme.get_outcome()

        return new_outcome, new_voting_scheme