Example #1
0
    def test_mwrules_correct_simple(self):
        from preferences import Profile
        import rules_approval

        self.longMessage = True

        profile = Profile(4)
        profile.add_preferences([[0], [1], [2], [3]])
        committeesize = 2

        for rule in rules_approval.MWRULES.keys():
            if rule == "greedy-monroe":  # always returns one committee
                continue
            self.assertEqual(len(
                rules_approval.compute_rule(rule, profile, committeesize)),
                             6,
                             msg=rule + " failed")

        for rule in rules_approval.MWRULES.keys():
            self.assertEqual(len(
                rules_approval.compute_rule(rule,
                                            profile,
                                            committeesize,
                                            resolute=True)),
                             1,
                             msg=rule + " failed with resolute=True")
Example #2
0
    def test_mwrules_correct_advanced_3(self):

        from preferences import Profile
        self.longMessage = True

        # and a third profile
        profile = Profile(6)
        committeesize = 4
        preflist = [[0, 3, 4, 5], [1, 2], [0, 2, 5], [2], [0, 1, 2, 3, 4],
                    [0, 3, 4], [0, 2, 4], [0, 1]]
        profile.add_preferences(preflist)

        tests3 = {
            "seqpav": [[0, 1, 2, 4]],
            "av": [[0, 1, 2, 4], [0, 2, 3, 4]],
            "sav": [[0, 1, 2, 4]],
            "pav-ilp": [[0, 1, 2, 4]],
            "pav-noilp": [[0, 1, 2, 4]],
            "revseqpav": [[0, 1, 2, 4]],
            "minimaxav-noilp": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 2, 3, 4],
                                [0, 2, 3, 5], [0, 2, 4, 5]],
            "minimaxav-ilp": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 2, 3, 4],
                              [0, 2, 3, 5], [0, 2, 4, 5]],
            "phrag": [[0, 1, 2, 4]],
            "optphrag":
            [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 2, 3, 4],
             [0, 2, 3, 5], [0, 2, 4, 5], [1, 2, 3, 4], [1, 2, 3, 5],
             [1, 2, 4, 5]],
            "cc-ilp": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 2, 3, 4],
                       [0, 2, 3, 5], [0, 2, 4, 5], [1, 2, 3, 4], [1, 2, 3, 5],
                       [1, 2, 4, 5]],
            "cc-noilp":
            [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 2, 3, 4],
             [0, 2, 3, 5], [0, 2, 4, 5], [1, 2, 3, 4], [1, 2, 3, 5],
             [1, 2, 4, 5]],
            "seqcc": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 2, 3, 4],
                      [0, 2, 3, 5], [0, 2, 4, 5]],
            "revseqcc": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2,
                                                      5], [0, 2, 3, 4],
                         [0, 2, 3, 5], [0, 2, 4, 5], [1, 2, 3, 4],
                         [1, 2, 3, 5], [1, 2, 4, 5]],
            "monroe-ilp": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5],
                           [0, 2, 3, 4], [0, 2, 3, 5], [0, 2, 4, 5],
                           [1, 2, 3, 4], [1, 2, 3, 5], [1, 2, 4, 5]],
            "monroe-noilp": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5],
                             [0, 2, 3, 4], [0, 2, 3, 5], [0, 2, 4, 5],
                             [1, 2, 3, 4], [1, 2, 3, 5], [1, 2, 4, 5]],
            "greedy-monroe": [[0, 1, 2, 3]],
            "seqslav": [[0, 1, 2, 4]],
            "slav-ilp": [[0, 1, 2, 4]],
            "slav-noilp": [[0, 1, 2, 4]],
            "rule-x": [[0, 1, 2, 4]],
            "phragmen-enestroem": [[0, 1, 2, 4]],
        }

        run_test_instance(self, profile, committeesize, tests3)
Example #3
0
def compute(rankings, cand_count):
    profile = Profile(cand_count)
    profile.add_preferences(rankings)
    print("Computing a committee of size", committeesize, end=' ')
    print("with the Proportional Approval Voting (PAV) rule")
    print("given a", profile)
    print("Output:")
    output = rules_approval.compute_pav(profile, committeesize, ilp=ilp)
    committees.print_committees(output)

    print("****************************************")
Example #4
0
    def test_mwrules__toofewcandidates(self):
        from preferences import Profile
        import rules_approval
        profile = Profile(5)
        committeesize = 4
        preflist = [[0, 1, 2], [1], [1, 2], [0]]
        profile.add_preferences(preflist)

        for rule in rules_approval.MWRULES.keys():
            with self.assertRaises(Exception):
                rules_approval.compute_rule(rule, profile, committeesize)
            with self.assertRaises(Exception):
                rules_approval.compute_rule(rule,
                                            profile,
                                            committeesize,
                                            resolute=True)
Example #5
0
    def test_monroescore(self):
        from preferences import Profile
        from score_functions import monroescore_flowbased, monroescore_matching
        self.longMessage = True

        # and a third profile
        profile = Profile(6)
        preflist = [[0, 1], [1], [1, 3], [4], [2], [1, 5, 3]]
        profile.add_preferences(preflist)

        self.assertEqual(monroescore_flowbased(profile, [1, 3, 2]), 5)
        self.assertEqual(monroescore_matching(profile, [1, 3, 2]), 5)
        self.assertEqual(monroescore_flowbased(profile, [2, 1, 5]), 4)
        self.assertEqual(monroescore_matching(profile, [2, 1, 5]), 4)
        self.assertEqual(monroescore_flowbased(profile, [2, 4, 5]), 3)
        self.assertEqual(monroescore_matching(profile, [2, 5, 4]), 3)
Example #6
0
    def test_optphrag_notiebreaking(self):
        from preferences import Profile
        from rules_approval import compute_rule

        self.longMessage = True

        profile = Profile(6)
        profile.add_preferences([[0], [0], [1, 3], [1, 3], [1, 4], [2, 4],
                                 [2, 5], [2, 5]])
        committeesize = 3

        self.assertEqual(
            len(
                compute_rule("optphrag",
                             profile,
                             committeesize,
                             resolute=False)), 12)
Example #7
0
    def test_monroe_indivisible(self):
        from preferences import Profile
        import rules_approval

        self.longMessage = True

        profile = Profile(4)
        profile.add_preferences([[0], [0], [0], [1, 2], [1, 2], [1], [3]])
        committeesize = 3

        for ilp in [True, False]:
            # max Monroe score is 6 (even for committee [0, 1, 3])
            self.assertEqual(
                rules_approval.compute_monroe(profile,
                                              committeesize,
                                              ilp=ilp,
                                              resolute=False),
                [[0, 1, 2], [0, 1, 3], [0, 2, 3]])
Example #8
0
    def test_mwrules_weightsconsidered(self):
        from preferences import Profile
        from preferences import DichotomousPreferences
        import rules_approval

        self.longMessage = True

        profile = Profile(3)
        profile.add_preferences(DichotomousPreferences([0], 3))
        profile.add_preferences(DichotomousPreferences([1], 3))
        profile.add_preferences(DichotomousPreferences([0]))
        committeesize = 2

        for rule in rules_approval.MWRULES.keys():
            if rule[:6] == "monroe":
                continue  # Monroe only works with unit weights
            self.assertEqual(rules_approval.compute_rule(
                rule, profile, committeesize), [[0, 1]],
                             msg=rule + " failed")
Example #9
0
    def test_mwrules_weightsconsidered(self):
        from preferences import Profile
        from preferences import DichotomousPreferences
        import rules_approval

        self.longMessage = True

        profile = Profile(3)
        profile.add_preferences(DichotomousPreferences([0]))
        profile.add_preferences(DichotomousPreferences([0]))
        profile.add_preferences(DichotomousPreferences([1], 5))
        profile.add_preferences(DichotomousPreferences([0]))
        committeesize = 1

        for rule in rules_approval.MWRULES.keys():
            if "monroe" in rule or "rule-x" in rule:
                # Monroe and rule x only work with unit weights:
                continue
            result = rules_approval.compute_rule(rule, profile, committeesize)
            self.assertTrue([1] in result, msg=rule + " failed" + str(result))
Example #10
0
    def test_mwrules_correct_advanced(self):
        def runmwtests(tests, committeesize):
            for rule in tests.keys():
                output = rules_approval.compute_rule(rule,
                                                     profile,
                                                     committeesize,
                                                     resolute=False)
                self.assertEqual(output, tests[rule], msg=rule + " failed")
                output = rules_approval.compute_rule(rule,
                                                     profile,
                                                     committeesize,
                                                     resolute=True)
                self.assertEqual(len(output),
                                 1,
                                 msg=rule + " failed with resolute=True")
                self.assertTrue(output[0] in tests[rule],
                                msg=rule + " failed with resolute=True")

        from preferences import Profile
        import rules_approval
        self.longMessage = True

        tests1 = {
            "seqpav": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 4, 5],
                       [1, 3, 4, 5], [2, 3, 4, 5]],
            "av": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 4, 5],
                   [1, 3, 4, 5], [2, 3, 4, 5]],
            "sav": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 3, 4],
                    [0, 1, 3, 5], [0, 1, 4, 5], [0, 2, 3, 4], [0, 2, 3, 5],
                    [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 5],
                    [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
            "pav-ilp": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 4, 5],
                        [1, 3, 4, 5], [2, 3, 4, 5]],
            "pav-noilp": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5],
                          [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
            "revseqpav": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5],
                          [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
            "mav-noilp":
            [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 3, 4],
             [0, 1, 3, 5], [0, 1, 4, 5], [0, 2, 3, 4], [0, 2, 3, 5],
             [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 5],
             [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
            "phrag": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 4, 5],
                      [1, 3, 4, 5], [2, 3, 4, 5]],
            "cc-ilp": [[0, 1, 2, 3]],
            "cc-noilp": [[0, 1, 2, 3]],
            "seqcc": [[0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 3, 4], [0, 1, 3, 5],
                      [0, 2, 3, 4], [0, 2, 3, 5], [1, 2, 3, 4], [1, 2, 3, 5]],
            "revseqcc": [[0, 1, 2, 3]],
            "monroe-ilp": [[0, 1, 2, 3]],
            "monroe-noilp": [[0, 1, 2, 3]],
        }

        profile = Profile(6)
        committeesize = 4
        preflist = [[0, 4, 5], [0], [1, 4, 5], [1], [2, 4, 5], [2], [3, 4, 5],
                    [3]]
        profile.add_preferences(preflist)

        runmwtests(tests1, committeesize)

        # and now with reversed preflist
        preflist.reverse()
        for p in preflist:
            p.reverse()
        profile = Profile(6)
        profile.add_preferences(preflist)
        runmwtests(tests1, committeesize)

        # and another profile
        profile = Profile(5)
        committeesize = 3
        preflist = [[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2],
                    [0, 1], [3, 4], [3, 4], [3]]
        profile.add_preferences(preflist)

        tests2 = {
            "seqpav": [[0, 1, 3]],
            "av": [[0, 1, 2]],
            "sav": [[0, 1, 3]],
            "pav-ilp": [[0, 1, 3]],
            "pav-noilp": [[0, 1, 3]],
            "revseqpav": [[0, 1, 3]],
            "mav-noilp": [[0, 1, 3], [0, 2, 3], [1, 2, 3]],
            "phrag": [[0, 1, 3]],
            "cc-ilp": [[0, 1, 3], [0, 2, 3], [0, 3, 4], [1, 2, 3], [1, 3, 4]],
            "cc-noilp": [[0, 1, 3], [0, 2, 3], [0, 3, 4], [1, 2, 3], [1, 3,
                                                                      4]],
            "seqcc": [[0, 1, 3], [0, 2, 3], [0, 3, 4], [1, 2, 3], [1, 3, 4]],
            "revseqcc": [[0, 1, 3], [0, 2, 3], [0, 3, 4], [1, 2, 3], [1, 3,
                                                                      4]],
            "monroe-ilp": [[0, 1, 3], [0, 2, 3], [1, 2, 3]],
            "monroe-noilp": [[0, 1, 3], [0, 2, 3], [1, 2, 3]],
        }

        runmwtests(tests2, committeesize)
Example #11
0
 def test_createprofiles(self):
     from preferences import Profile
     from preferences import DichotomousPreferences
     num_cand = 7
     prof = Profile(num_cand)
     self.assertEqual(
         prof.add_preferences(DichotomousPreferences([0, 4, 5])), None)
     with self.assertRaises(Exception):
         prof.add_preferences(DichotomousPreferences([num_cand]))
     with self.assertRaises(Exception):
         prof.add_preferences(DichotomousPreferences([-1]))
     self.assertEqual(prof.add_preferences([0, 4, 5]), None)
     with self.assertRaises(Exception):
         prof.add_preferences([0, 4, 5, "1"])
     with self.assertRaises(Exception):
         prof.add_preferences(["1", 0, 4, 5])
     p1 = DichotomousPreferences([0, 4, 5])
     p2 = DichotomousPreferences([1, 2])
     self.assertEqual(prof.add_preferences([p1, p2]), None)
     self.assertTrue(prof.has_unit_weights())
     prof.add_preferences(DichotomousPreferences([0, 4, 5], 2.4))
     self.assertFalse(prof.has_unit_weights())
     self.assertEqual(prof.totalweight(), 6.4)
Example #12
0
    def test_mwrules_correct_advanced_1(self):

        from preferences import Profile
        self.longMessage = True
        committeesize = 4

        profile = Profile(6)
        preflist = [[0, 4, 5], [0], [1, 4, 5], [1], [2, 4, 5], [2], [3, 4, 5],
                    [3]]
        profile.add_preferences(preflist)

        tests1 = {
            "seqpav": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 4, 5],
                       [1, 3, 4, 5], [2, 3, 4, 5]],
            "av": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 4, 5],
                   [1, 3, 4, 5], [2, 3, 4, 5]],
            "sav": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 3, 4],
                    [0, 1, 3, 5], [0, 1, 4, 5], [0, 2, 3, 4], [0, 2, 3, 5],
                    [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 5],
                    [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
            "pav-ilp": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 4, 5],
                        [1, 3, 4, 5], [2, 3, 4, 5]],
            "pav-noilp": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5],
                          [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
            "revseqpav": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5],
                          [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
            "minimaxav-noilp": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5],
                                [0, 1, 3, 4], [0, 1, 3, 5], [0, 1, 4, 5],
                                [0, 2, 3, 4], [0, 2, 3, 5], [0, 2, 4, 5],
                                [0, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 5],
                                [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
            "minimaxav-ilp": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5],
                              [0, 1, 3, 4], [0, 1, 3, 5], [0, 1, 4, 5],
                              [0, 2, 3, 4], [0, 2, 3, 5], [0, 2, 4, 5],
                              [0, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 5],
                              [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
            "phrag": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 4, 5],
                      [1, 3, 4, 5], [2, 3, 4, 5]],
            "optphrag": [[0, 1, 2, 3]],
            "cc-ilp": [[0, 1, 2, 3]],
            "cc-noilp": [[0, 1, 2, 3]],
            "seqcc": [[0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 3, 4], [0, 1, 3, 5],
                      [0, 2, 3, 4], [0, 2, 3, 5], [1, 2, 3, 4], [1, 2, 3, 5]],
            "revseqcc": [[0, 1, 2, 3]],
            "monroe-ilp": [[0, 1, 2, 3]],
            "monroe-noilp": [[0, 1, 2, 3]],
            "greedy-monroe": [[0, 2, 3, 4]],
            "slav-ilp":
            [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 3, 4],
             [0, 1, 3, 5], [0, 2, 3, 4], [0, 2, 3, 5], [1, 2, 3, 4],
             [1, 2, 3, 5]],
            "slav-noilp": [[0, 1, 2, 3], [0, 1, 2, 4], [0, 1, 2, 5],
                           [0, 1, 3, 4], [0, 1, 3, 5], [0, 2, 3, 4],
                           [0, 2, 3, 5], [1, 2, 3, 4], [1, 2, 3, 5]],
            "seqslav": [[0, 1, 2, 4], [0, 1, 2, 5], [0, 1, 3, 4], [0, 1, 3, 5],
                        [0, 2, 3, 4], [0, 2, 3, 5], [1, 2, 3, 4], [1, 2, 3,
                                                                   5]],
            "rule-x": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5], [1, 2, 4, 5],
                       [1, 3, 4, 5], [2, 3, 4, 5]],
            "phragmen-enestroem": [[0, 1, 4, 5], [0, 2, 4, 5], [0, 3, 4, 5],
                                   [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]],
        }

        run_test_instance(self, profile, committeesize, tests1)

        # and now with reversed preflist
        preflist.reverse()
        for p in preflist:
            p.reverse()
        profile = Profile(6)
        profile.add_preferences(preflist)

        run_test_instance(self, profile, committeesize, tests1)
ilp = True
try:
    import gurobipy  # pylint: disable=unused-import
except ImportError:
    ilp = False
    print "ILP solver Gurobi not available (import gurobipy failed)."
    print

print "****************************************"

# Compute PAV with our without Gurobi

num_cand = 5
profile = Profile(num_cand)
profile.add_preferences([[0, 1, 2], [0, 1], [0, 1], [1, 2], [3, 4], [3, 4]])
committeesize = 3
print "Computing a committe of size", committeesize,
print "with the Proportional Approval Voting (PAV) rule"
print "given a", profile
print "Output:"
output = rules_approval.compute_pav(profile, committeesize, ilp=ilp)
committees.print_committees(output)

print "****************************************"

# Compute all implemented multiwinner rules

num_cand = 6
profile = Profile(num_cand)
profile.add_preferences([[0, 4, 5], [0], [1, 4, 5], [1], [2, 4, 5], [2],