Example #1
0
def __monroe_bruteforce(profile, committeesize, resolute):
    """Brute-force computation of Monroe's rule"""
    opt_committees = []
    opt_monroescore = -1
    for comm in combinations(list(range(profile.num_cand)), committeesize):
        score = scores.monroescore(profile, comm)
        if score > opt_monroescore:
            opt_committees = [comm]
            opt_monroescore = score
        elif scores.monroescore(profile, comm) == opt_monroescore:
            opt_committees.append(comm)

    committees = sort_committees(opt_committees)
    if resolute:
        committees = [committees[0]]

    return committees
Example #2
0
def compute_monroe(profile, committeesize, algorithm="brute-force",
                   resolute=False, verbose=0):
    """Monroe's rule"""
    enough_approved_candidates(profile, committeesize)

    # optional output
    if verbose:
        print(header(rules["monroe"].longname))
        if resolute:
            print("Computing only one winning committee (resolute=True)\n")
    if verbose >= 3:
        if algorithm == "gurobi":
            print("Using the Gurobi ILP solver\n")
        if algorithm == "brute-force":
            print("Using a brute-force algorithm\n")
    # end of optional output

    if not profile.has_unit_weights():
        raise ValueError(rules["monroe"].shortname +
                         " is only defined for unit weights (weight=1)")

    if algorithm == "gurobi":
        committees = abcrules_gurobi.__gurobi_monroe(
            profile, committeesize, resolute)
        committees = sort_committees(committees)
    elif algorithm == "brute-force":
        committees = __monroe_bruteforce(
            profile, committeesize, resolute)
    else:
        raise NotImplementedError(
            "Algorithm " + str(algorithm)
            + " not specified for compute_monroe")

    # optional output
    if verbose:
        print("Optimal Monroe score: "
              + str(scores.monroescore(profile, committees[0])) + "\n")

        print(str_committees_header(committees, winning=True))
        print(str_candsets(committees, names=profile.names))
    # end of optional output

    return committees
Example #3
0
"""Example 7 (Greedy Monroe)
from the survey: "Approval-Based Multi-Winner Voting:
Axioms, Algorithms, and Applications"
by Martin Lackner and Piotr Skowron
"""

from __future__ import print_function
import sys
sys.path.insert(0, '..')
from abcvoting import abcrules
from survey import example01 as ex1
from abcvoting.scores import monroescore
from abcvoting import misc

print(misc.header("Example 7", "*"))

print(misc.header("Input (election instance from Example 1):"))
print(ex1.profile.str_compact())

committees = abcrules.compute_greedy_monroe(ex1.profile, 4, verbose=2)

# verify correctness
a, b, c, d, e, f, g = list(range(7))  # a = 0, b = 1, c = 2, ...
assert committees == [[a, c, d, f]]
assert monroescore(ex1.profile, committees[0]) == 10
Example #4
0
    {a, b},
    {a, c},
    {a, c},
    {a, c},
    {a, d},
    {a, d},
    {b, c, f},
    {e},
    {f},
    {g},
]
profile = Profile(num_cand, cand_names="abcdefgh")
profile.add_voters(approval_sets)
committeesize = 4
#

print(misc.header("Example 7", "*"))

print(misc.header("Input (election instance from Example 1):"))
print(profile.str_compact())

committees = abcrules.compute_monroe(profile, 4)

# verify correctness
a, b, c, d, e, f, g = range(7)  # a = 0, b = 1, c = 2, ...
assert len(committees) == 6
# Monroe-score of all committees is the same
score = monroescore(profile, committees[0])
for committee in committees:
    assert score == monroescore(profile, committee)
Example #5
0
def compute_greedy_monroe(profile, committeesize,
                          algorithm="standard", resolute=True, verbose=0):
    """"Greedy Monroe"""
    enough_approved_candidates(profile, committeesize)
    if not profile.has_unit_weights():
        raise ValueError(rules["greedy-monroe"].shortname +
                         " is only defined for unit weights (weight=1)")

    if not resolute:
        raise NotImplementedError(
            "compute_greedy_monroe does not support resolute=False.")

    if algorithm != "standard":
        raise NotImplementedError(
            "Algorithm " + str(algorithm)
            + " not specified for compute_greedy_monroe")

    num_voters = len(profile)
    committee = []

    # remaining voters
    remaining_voters = list(range(num_voters))
    remaining_cands = set(range(profile.num_cand))

    assignment = []
    for t in range(committeesize):
        maxapprovals = -1
        selected = None
        for c in remaining_cands:
            approvals = len([i for i in remaining_voters
                             if c in profile[i]])
            if approvals > maxapprovals:
                maxapprovals = approvals
                selected = c

        # determine how many voters are removed (at most)
        if t < num_voters - committeesize * (num_voters // committeesize):
            num_remove = num_voters // committeesize + 1
        else:
            num_remove = num_voters // committeesize

        # only voters that approve the chosen candidate
        # are removed
        to_remove = [i for i in remaining_voters
                     if selected in profile[i]]
        if len(to_remove) > num_remove:
            to_remove = to_remove[:num_remove]
        assignment.append((selected, to_remove))
        remaining_voters = [i for i in remaining_voters
                            if i not in to_remove]
        committee.append(selected)
        remaining_cands.remove(selected)

    committees = sort_committees([committee])

    # optional output
    if verbose:
        print(header(rules["greedy-monroe"].longname))

    if verbose >= 2:
        score1 = scores.monroescore(profile, committees[0])

        score2 = len(profile) - len(remaining_voters)
        print("The Monroe assignment computed by Greedy Monroe")
        print("has a Monroe score of " + str(score2) + ".")

        if score1 > score2:
            print("Monroe assignment found by Greedy Monroe is not "
                  + "optimal for the winning committee,")
            print("i.e., by redistributing voters to candidates a higher "
                  + "satisfaction is possible "
                  + "(without changing the committee).")
            print("Optimal Monroe score of the winning committee is "
                  + str(score1) + ".")

        # build actual Monroe assignment for winning committee
        for t, district in enumerate(assignment):
            cand, voters = district
            if t < num_voters - committeesize * (num_voters // committeesize):
                missing = num_voters // committeesize + 1 - len(voters)
            else:
                missing = num_voters // committeesize - len(voters)
            for _ in range(missing):
                v = remaining_voters.pop()
                voters.append(v)

        print("Assignment (unsatisfatied voters marked with *):\n")
        for cand, voters in assignment:
            print(" candidate " + profile.names[cand]
                  + " assigned to: ", end="")
            output = ""
            for v in sorted(voters):
                output += str(v)
                if cand not in profile[v].approved:
                    output += "*"
                output += ", "
            print(output[:-2])
        print()

    if verbose:
        print(str_committees_header(committees, winning=True))
        print(str_candsets(committees, names=profile.names))
    # end of optional output

    return committees