Example #1
0
    def sqrt(x):
        p = x.rational_part
        s, t = p.numerator, p.denominator
        if p == 0:
            return Quadratic()
        elif p < 0:
            raise NotImplementedError
        elif x.quadratic_power == 0:
            if is_square(s) and is_square(t):
                return Quadratic(Fraction(isqrt(s), isqrt(t)))

        r = Fraction(1, t)
        p = s * t
        prime_power_list = []
        for prime, x_power in zip(primes, x.quadratic_part
                                  or (0, ) * len(primes)):
            power = 0
            while p % prime == 0:
                p //= prime
                power += 1
            r *= prime**(power >> 1)
            prime_power_list.append(((power & 1) << x.quadratic_power)
                                    | x_power)
        if not is_square(p):
            return
        return Quadratic(r * isqrt(p), x.quadratic_power + 1,
                         tuple(prime_power_list))
Example #2
0
def __lp_av_score_fct(i, ell):
    # l-th root of i
    # l=1 ... Approval Voting
    # l=\infty ... Chamberlin-Courant
    if i == 1:
        return 1
    else:
        return i**Fraction(1, ell) - (i - 1)**Fraction(1, ell)
Example #3
0
def quota(votes,
          seats,
          parties=string.ascii_letters,
          tiesallowed=True,
          verbose=True):
    if verbose:
        print("\nQuota method")
    representatives = [0] * len(votes)
    while sum(representatives) < seats:
        quotas = [
            Fraction(votes[i], representatives[i] + 1)
            for i in range(len(votes))
        ]
        # check if upper quota is violated
        for i in range(len(votes)):
            upperquota = int(
                math.ceil(
                    float(votes[i]) * (sum(representatives) + 1) / sum(votes)))
            if representatives[i] >= upperquota:
                quotas[i] = 0

        maxquotas = [i for i in range(len(votes)) if quotas[i] == max(quotas)]

        nextrep = maxquotas[0]
        representatives[nextrep] += 1

    if len(maxquotas) > 1 and not tiesallowed:
        raise TiesException("Tie occurred")

    # print tiebreaking information
    if verbose and len(maxquotas) > 1:
        quotas_now = [
            Fraction(votes[i], representatives[i] + 1)
            for i in range(len(votes))
        ]
        tiebreaking_message = ("  tiebreaking in order of: " +
                               str(parties[:len(votes)]) +
                               "\n  ties broken in favor of: ")
        ties_favor = [
            i for i in range(len(votes))
            if quotas_now[i] == quotas_now[nextrep]
        ]
        for i in ties_favor:
            tiebreaking_message += str(parties[i]) + ", "
        tiebreaking_message = (tiebreaking_message[:-2] +
                               "\n  to the disadvantage of: ")
        for i in maxquotas[1:]:
            tiebreaking_message += str(parties[i]) + ", "
        print(tiebreaking_message[:-2])

    if verbose:
        __print_results(representatives, parties)

    return representatives
Example #4
0
 def __new__(cls,
             rational_part=Fraction(),
             quadratic_power=0,
             quadratic_part=None):
     self = super(Quadratic, cls).__new__(cls)
     if type(rational_part) is str:
         rational_part = Fraction(rational_part)
     if isinstance(rational_part, (int, mpz_type, mpq_type)):
         self.rational_part = Fraction(rational_part)
         self.quadratic_power = quadratic_power
         self.quadratic_part = quadratic_part
         return self
     elif isinstance(rational_part, Quadratic):
         return rational_part
     else:
         raise NotImplementedError
Example #5
0
def geometric_marginal_score_fct(i, base):
    """
    Geometric marginal score functions.

    This is the additional (marginal) score from a voter for the `i`-th approved candidate
    in the committee.

    For example, the 2-Geometric marginal scoring function (`base=2`) is

    .. math::

       f(i) = 1 / 2^{i-1}.

    For a mathematical description of Geometric score functions, see e.g.
    Martin Lackner and Piotr Skowron
    Utilitarian Welfare and Representation Guarantees of Approval-Based Multiwinner Rules
    In Artificial Intelligence, 288: 103366, 2020.
    https://arxiv.org/abs/1801.01527

    Parameters
    ----------
        i : int
            We are calculating the score for the `i`-th approved candidate in the committee.

        base : float or int or Fraction
            The base for the geometric function `1 / base ** (i-1)`.

    Returns
    -------
        Fraction
            The corresponding marginal score.
    """
    if i == 0:
        return 0
    return Fraction(1, base**(i - 1))
Example #6
0
def get_marginal_scorefct(scorefct_id, committeesize=None):
    """
    Return marginal score function (for a Thiele method) given its name.

    Parameters
    ----------
        scorefct_id : str
            A string identifying the score function.

        committeesize : int, optional
            Committee size.

            Some marginal score functions require fixing the size of committees.

    Returns
    -------
        function
            The corresponding marginal score function.
    """
    if scorefct_id == "pav":
        return pav_score_fct
    if scorefct_id == "slav":
        return slav_score_fct
    if scorefct_id == "cc":
        return cc_score_fct
    if scorefct_id == "av":
        return av_score_fct
    if scorefct_id[:4] == "geom":
        base = Fraction(scorefct_id[4:])
        return functools.partial(geometric_marginal_score_fct, base=base)
    if scorefct_id[:7] == "atleast":
        param = int(scorefct_id[7:])
        return functools.partial(at_least_ell_fct, ell=param)

    raise UnknownScoreFunctionError(scorefct_id)
def compute_av(profile, committeesize, resolute=False, sav=False):
    """Returns the list of winning committees according to Approval Voting"""
    enough_approved_candidates(profile, committeesize)

    appr_scores = [0] * profile.num_cand
    for pref in profile.preferences:
        for cand in pref.approved:
            if sav:
                # Satisfaction Approval Voting
                appr_scores[cand] += Fraction(pref.weight, len(pref.approved))
            else:
                # (Classic) Approval Voting
                appr_scores[cand] += pref.weight

    # smallest score to be in the committee
    cutoff = sorted(appr_scores)[-committeesize]

    certain_cand = [
        c for c in range(profile.num_cand) if appr_scores[c] > cutoff
    ]
    possible_cand = [
        c for c in range(profile.num_cand) if appr_scores[c] == cutoff
    ]
    missing = committeesize - len(certain_cand)
    if resolute:
        return sort_committees([(certain_cand + possible_cand[:missing])])
    else:
        return sort_committees([
            (certain_cand + list(selection))
            for selection in combinations(possible_cand, missing)
        ])
Example #8
0
    def elect_winners(self):
        eligible = self.candidates - self.elected - self.disqualified
        self.vote_weights = reweight_votes(self.vote_weights, eligible)
        if not self.vote_weights:
            raise Ambiguous()

        current_scores = {c: Fraction(0) for c in eligible}
        voters = defaultdict(lambda: [])

        for v, w in self.vote_weights.items():
            c = v[0]
            assert c in eligible
            voters[c].append(v)
            current_scores[c] += w

        n_winners = 0
        for candidate, score in current_scores.items():
            if score >= self.quota:
                n_winners += 1
                self.elected.add(candidate)
                excess = score - self.quota
                reweight = excess / score
                assert 0 <= reweight < 1
                for v in voters[candidate]:
                    self.vote_weights[v] *= reweight

        assert len(self.elected) * self.quota + sum(
            self.vote_weights.values()) == len(self.votes)
        return current_scores
Example #9
0
def prm(ctx):
    """
    Parser based on CHP and PRM files. CHP file contains contest meta-info and candidate code maps.
    PRM file contains ballot info. PRM files may appear separated out by precinct.
    """
    # get candidate code map
    name_map = chp_names(ctx)
    # get prm file list
    prm_filepaths = chp_order(ctx)

    ballots = []
    for prm_filepath in prm_filepaths:
        with open(prm_filepath, 'r', encoding='utf8') as f:
            for i in f:
                if any(map(str.isalnum, i)) and i.strip()[0] != '#':
                    b = []
                    s = i.split()
                    choices = [] if len(s) == 1 else s[1].split(',')
                    for choice in filter(None, choices):
                        can, rank = choice.split(']')[0].split('[')
                        b.extend([SKIPPEDRANK] * (int(rank) - len(b) - 1))
                        b.append(OVERVOTE if '=' in choice else name_map[can])
                    ballots.append(b)

    # add in tail skipped ranks
    maxlen = max(map(len, ballots))
    for b in ballots:
        b.extend([SKIPPEDRANK] * (maxlen - len(b)))

    return {'ranks': ballots, 'weight': [Fraction(1) for b in ballots]}
Example #10
0
def slav_score_fct(i):
    """
    SLAV (Sainte-Lague Approval Voting) marginal score function.

    This is the additional (marginal) score from a voter for the `i`-th approved candidate
    in the committee.

    For a mathematical description of this score function, see e.g.
    Martin Lackner and Piotr Skowron
    Utilitarian Welfare and Representation Guarantees of Approval-Based Multiwinner Rules
    In Artificial Intelligence, 288: 103366, 2020.
    https://arxiv.org/abs/1801.01527

    Parameters
    ----------
        i : int
            We are calculating the score for the `i`-th approved candidate in the committee.

    Returns
    -------
        Fraction
            The corresponding marginal score.
    """
    if i == 0:
        return 0
    return Fraction(1, 2 * i - 1)
Example #11
0
def compute_seqphragmen(profile, committeesize, resolute=False):
    """Returns the list of winning committees
    according to sequential Phragmen"""
    enough_approved_candidates(profile, committeesize)

    load = {v: 0 for v in profile.preferences}
    comm_loads = {(): load}

    approvers_weight = {}
    for c in range(profile.num_cand):
        approvers_weight[c] = sum(v.weight for v in profile.preferences
                                  if c in v.approved)

    # build committees starting with the empty set
    for _ in range(0, committeesize):
        comm_loads_next = {}
        for committee, load in comm_loads.items():
            approvers_load = {}
            for c in range(profile.num_cand):
                approvers_load[c] = sum(v.weight * load[v]
                                        for v in profile.preferences
                                        if c in v.approved)
            new_maxload = [
                Fraction(approvers_load[c] + 1, approvers_weight[c])
                if approvers_weight[c] > 0 else committeesize + 1
                for c in range(profile.num_cand)
            ]
            for c in range(profile.num_cand):
                if c in committee:
                    new_maxload[c] = sys.maxsize
            for c in range(profile.num_cand):
                if new_maxload[c] <= min(new_maxload):
                    new_load = {}
                    for v in profile.preferences:
                        if c in v.approved:
                            new_load[v] = new_maxload[c]
                        else:
                            new_load[v] = load[v]
                    comm_loads_next[tuple(sorted(committee +
                                                 (c, )))] = new_load
        # remove suboptimal committees
        comm_loads = {}
        cutoff = min([max(load.values()) for load in comm_loads_next.values()])
        for com, load in comm_loads_next.items():
            if max(load.values()) <= cutoff:
                comm_loads[com] = load
        if resolute:
            committees = sort_committees(list(comm_loads.keys()))
            comm = tuple(committees[0])
            comm_loads = {comm: comm_loads[comm]}

    committees = sort_committees(list(comm_loads.keys()))
    if resolute:
        return [committees[0]]
    else:
        return committees
Example #12
0
def common_csv(ctx, path=None):

    # if no path passed, get from ctx
    if path is None:
        path = ctx['path']

    # assume contest-specific filename, otherwise revert to default name
    cvr_path = path + '/' + ctx['dop'] + '.csv'
    if os.path.isfile(cvr_path) is False:
        cvr_path = path + '/cvr.csv'

    df = pd.read_csv(cvr_path)

    # find rank columns
    rank_col = [col for col in df.columns if 'rank' in col.lower()]

    # ensure rank columns are strings
    df[rank_col] = df[rank_col].astype(str)

    # if candidate codes file exist, swap in names
    candidate_codes_fpath = path + '/candidate_codes.csv'
    if os.path.isfile(candidate_codes_fpath):

        cand_codes = pd.read_csv(candidate_codes_fpath)

        cand_codes_dict = {str(code): cand for code, cand in zip(cand_codes['code'], cand_codes['candidate'])}
        replace_dict = {col: cand_codes_dict for col in rank_col}

        df = df.replace(replace_dict)

    # replace skipped ranks and overvotes with constants
    df = df.replace({col: {'under': SKIPPEDRANK, 'skipped': SKIPPEDRANK, 'undervote': SKIPPEDRANK,
                           'over': OVERVOTE, 'overvote': OVERVOTE} for col in rank_col})

    # pull out rank lists
    rank_col_list = [df[col].tolist() for col in rank_col]
    rank_lists = [list(rank_tuple) for rank_tuple in list(zip(*rank_col_list))]

    # double check
    if not all([len(i) == len(rank_lists[0]) for i in rank_lists]):
        print('not all rank lists are same length. debug')
        raise RuntimeError

    # assemble dict
    dct = {'ranks': rank_lists}

    # add in non-rank columns
    for col in df.columns:
        if col not in rank_col:
            dct[col] = df[col].tolist()

    # add weight if not present in csv
    if 'weight' not in dct:
        dct['weight'] = [Fraction(1) for b in dct['ranks']]

    return dct
Example #13
0
def largest_remainder(votes,
                      seats,
                      parties=string.ascii_letters,
                      tiesallowed=True,
                      verbose=True):
    if verbose:
        print("\nLargest remainder method with Hare quota (Hamilton)")
    q = Fraction(sum(votes), seats)
    quotas = [Fraction(p, q) for p in votes]
    representatives = [
        int(qu.numerator) // int(qu.denominator) for qu in quotas
    ]

    ties = False
    if sum(representatives) < seats:
        remainders = [a - b for a, b in zip(quotas, representatives)]
        cutoff = sorted(remainders,
                        reverse=True)[seats - sum(representatives) - 1]
        tiebreaking_message = ("  tiebreaking in order of: " +
                               str(parties[:len(votes)]) +
                               "\n  ties broken in favor of: ")
        for i in range(len(votes)):
            if sum(representatives) == seats and remainders[i] >= cutoff:
                if not ties:
                    tiebreaking_message = tiebreaking_message[:-2]
                    tiebreaking_message += "\n  to the disadvantage of: "
                    ties = True
                tiebreaking_message += parties[i] + ", "
            elif sum(representatives) < seats and remainders[i] > cutoff:
                representatives[i] += 1
            elif sum(representatives) < seats and remainders[i] == cutoff:
                tiebreaking_message += parties[i] + ", "
                representatives[i] += 1
        if ties and verbose:
            print(tiebreaking_message[:-2])

    if ties and not tiesallowed:
        raise TiesException("Tie occurred")

    if verbose:
        __print_results(representatives, parties)

    return representatives
Example #14
0
def get_scorefct(scorefct_str, committeesize):
    if scorefct_str == 'pav':
        return __pav_score_fct
    elif scorefct_str == 'cc':
        return __cc_score_fct
    elif scorefct_str == 'av':
        return __av_score_fct
    elif scorefct_str[:4] == 'geom':
        base = Fraction(scorefct_str[4:])
        return functools.partial(__geom_score_fct, base=base)
    elif scorefct_str.startswith('generalizedcc'):
        param = Fraction(scorefct_str[13:])
        return functools.partial(__generalizedcc_score_fct,
                                 ell=param,
                                 committeesize=committeesize)
    elif scorefct_str.startswith('lp-av'):
        param = Fraction(scorefct_str[5:])
        return functools.partial(__lp_av_score_fct, ell=param)
    else:
        raise Exception("Scoring function", scorefct_str, "does not exist.")
Example #15
0
def geometric_score_fct(i, base):
    """Geometric score functions.

    For a mathematical description of Geomtric score functions, see e.g.
    Martin Lackner and Piotr Skowron
    Utilitarian Welfare and Representation Guarantees of Approval-Based Multiwinner Rules
    In Artificial Intelligence, 288: 103366, 2020.
    https://arxiv.org/abs/1801.01527
    """
    if i == 0:
        return 0
    else:
        return Fraction(1, base**(i - 1))
Example #16
0
def slav_score_fct(i):
    """SLAV (Sainte-Lague Approval Voting) score function.

    For a mathematical description of this score function, see e.g.
    Martin Lackner and Piotr Skowron
    Utilitarian Welfare and Representation Guarantees of Approval-Based Multiwinner Rules
    In Artificial Intelligence, 288: 103366, 2020.
    https://arxiv.org/abs/1801.01527
    """
    if i == 0:
        return 0
    else:
        return Fraction(1, 2 * i - 1)
Example #17
0
def get_scorefct(scorefct_str, committeesize):
    if scorefct_str == 'pav':
        return __pav_score_fct
    elif scorefct_str == 'slav':
        return __slav_score_fct
    elif scorefct_str == 'cc':
        return __cc_score_fct
    elif scorefct_str == 'av':
        return __av_score_fct
    elif scorefct_str[:4] == 'geom':
        base = Fraction(scorefct_str[4:])
        return functools.partial(__geom_score_fct, base=base)
    else:
        raise Exception("Score function", scorefct_str, "does not exist.")
Example #18
0
def get_scorefct(scorefct_id, committeesize=None):
    """Return score function (for a Thiele method) given its name."""
    if scorefct_id == "pav":
        return pav_score_fct
    elif scorefct_id == "slav":
        return slav_score_fct
    elif scorefct_id == "cc":
        return cc_score_fct
    elif scorefct_id == "av":
        return av_score_fct
    elif scorefct_id[:4] == "geom":
        base = Fraction(scorefct_id[4:])
        return functools.partial(geometric_score_fct, base=base)
    else:
        raise UnknownScoreFunctionError(scorefct_id)
Example #19
0
def __seqphragmen_irresolute(profile, committeesize,
                             start_load=None, partial_committee=None):
    """Algorithm for computing irresolute seq-Phragmen (>=1 winning committees)
    """
    approvers_weight = {}
    for c in range(profile.num_cand):
        approvers_weight[c] = sum(pref.weight for pref in profile if c in pref)

    load = start_load
    if load is None:
        load = {v: 0 for v, _ in enumerate(profile)}

    if partial_committee is None:
        partial_committee = []  # build committees starting with the empty set
    comm_loads = {tuple(partial_committee): load}

    for _ in range(len(partial_committee), committeesize):
        comm_loads_next = {}
        for committee, load in comm_loads.items():
            approvers_load = {}
            for c in range(profile.num_cand):
                approvers_load[c] = sum(pref.weight * load[v]
                                        for v, pref in enumerate(profile)
                                        if c in pref)
            new_maxload = [
                Fraction(approvers_load[c] + 1, approvers_weight[c])
                if approvers_weight[c] > 0 else committeesize + 1
                for c in range(profile.num_cand)]
            # exclude committees already in the committee
            for c in range(profile.num_cand):
                if c in committee:
                    new_maxload[c] = sys.maxsize
            # compute new loads
            # and add new committees
            for c in range(profile.num_cand):
                if new_maxload[c] <= min(new_maxload):
                    new_load = {}
                    for v, pref in enumerate(profile):
                        if c in pref:
                            new_load[v] = new_maxload[c]
                        else:
                            new_load[v] = load[v]
                    new_comm = tuple(sorted(committee + (c,)))
                    comm_loads_next[new_comm] = new_load
        comm_loads = comm_loads_next

    committees = sort_committees(list(comm_loads.keys()))
    return committees, comm_loads
Example #20
0
def __rule_x_get_min_q(profile, budget, cand):
    rich = set([v for v, pref in enumerate(profile)
                if cand in pref])
    poor = set()

    while len(rich) > 0:
        poor_budget = sum(budget[v] for v in poor)
        q = Fraction(1 - poor_budget, len(rich))
        new_poor = set([v for v in rich
                        if budget[v] < q])
        if len(new_poor) == 0:
            return q
        rich -= new_poor
        poor.update(new_poor)

    return None  # not sufficient budget available
Example #21
0
def minneapolis(ctx):
    choice_map = {}
    default = None
    if ctx['year'] == '2009':
        with open('/'.join(ctx['path'].split('/')[:-1] + ['convert.csv']),
                  encoding='utf8') as f:
            for i in f:
                split = i.strip().split('\t')
                if len(split) >= 3 and split[0] == ctx['office']:
                    choice_map[split[2]] = split[1]
        if choice_map == {}:
            print(
                'No candidates found. Ensure "office" field in contest_set matches CVR.'
            )
            raise RuntimeError
        choice_map['XXX'] = SKIPPEDRANK
        default = WRITEIN
    else:
        choice_map = {
            'UWI': WRITEIN,
            'undervote': SKIPPEDRANK,
            'overvote': OVERVOTE
        }
    path = ctx['path']
    precincts = []
    ballots = []
    with open(path, "r", encoding='utf8') as f:
        f.readline()
        for line in csv.reader(f):
            choices = [
                choice_map.get(i.strip(), i if default is None else default)
                for i in line[1:-1]
            ]
            if choices != ['', '', '']:
                ballots.extend([choices] * int(float(line[-1])))
            for p in range(int(float(line[-1]))):
                precincts.append(line[0])

    bs = {
        'ranks': ballots,
        'weight': [Fraction(1) for b in ballots],
        'precinct': precincts
    }

    return bs
Example #22
0
def pav_score_fct(i):
    """
    PAV marginal score function.

    This is the additional (marginal) score from a voter for the `i`-th approved candidate
    in the committee.

    Parameters
    ----------
        i : int
            We are calculating the score for the `i`-th approved candidate in the committee.

    Returns
    -------
        Fraction
            The corresponding marginal score.
    """
    if i == 0:
        return 0
    return Fraction(1, i)
Example #23
0
def lsb_leak_attack(lsb_oracle, n, e, c):
    """RSA LSB Leak Attack

    Given a cryptosystem such that:
    - Using the "textbook" RSA (RSA without pading)
    - We can give any ciphertexts to decrypt and can get the least significant bit of decrypted plaintext.
    - We can try to decrypt ciphertexts without limit
    we can break the ciphertext with LSB Leak Attack(We should make name more cool)

    Usage:
        plain = padding_oracle(lsb_oracle, N, e, C)

    The function lsb_oracle must return LSB (1 or 0).
    """
    logger = getLogger(__name__)

    L = n.bit_length()
    t = L // 100
    left, right = 0, n
    c2 = c
    i = 0
    while right - left > 1:
        m = Fraction(left + right, 2)
        c2 = (c2 * pow(2, e, n)) % n
        oracle = lsb_oracle(c2)
        if oracle == 1:
            left = m
        elif oracle == 0:
            right = m
        else:
            raise ValueError("The function `lsb_oracle` must return 1 or 0")
        i += 1
        if i % t == 0:
            logger.info("LSB Leak Attack {}/{}".format(i, L))
        assert (i <= L)
    return int(ceil(left))
Example #24
0
    def elect_winners(self):
        vote_retention = {
            c: Fraction(0) if c in self.disqualified else Fraction(1)
            for c in self.candidates
        }

        for _ in range(MEEK_ITERATIONS):
            excess = Fraction(0)
            candidate_scores = {
                c: Fraction(0) for c in self.candidates
            }
            for v in self.votes:
                remaining = Fraction(1)
                for c in v:
                    capture = vote_retention[c]
                    assert 0 <= capture <= 1
                    candidate_scores[c] += capture * remaining
                    remaining *= (1 - capture)
                assert remaining == 0

            quota = self.quota_type(len(self.votes) - excess, self.winners)
            precision = 0
            for v in candidate_scores.values():
                assert v >= 0
            assert sum(candidate_scores.values()) + excess == len(self.votes)

            for e in self.elected:
                score = candidate_scores[e]
                if score == 0:
                    reweight = 1
                else:
                    reweight = quota / score
                vote_retention[e] = min(
                    Fraction(1), vote_retention[e] * reweight)
                precision = max(precision, abs(1 - reweight))
            for e in self.disqualified:
                assert candidate_scores[e] == 0
            if precision <= MEEK_PRECISION:
                for candidate, score in candidate_scores.items():
                    if score >= quota:
                        self.elected.add(candidate)
                return candidate_scores
        assert False
Example #25
0
from functools import reduce
from gmpy2 import mpz, mpq as Fraction, is_square, isqrt

__all__ = ["Quadratic"]

primes = (2, 3, 5, 7)


def exp2(n):
    return {1: 0, 3: 1, 7: 2, 15: 3}[n ^ (n - 1)]


_PyHASH_MODULUS = sys.hash_info.modulus

mpz_type = type(mpz())
mpq_type = type(Fraction())


class Quadratic(numbers.Real):
    __slots__ = ("rational_part", "quadratic_power", "quadratic_part")

    def __new__(cls,
                rational_part=Fraction(),
                quadratic_power=0,
                quadratic_part=None):
        self = super(Quadratic, cls).__new__(cls)
        if type(rational_part) is str:
            rational_part = Fraction(rational_part)
        if isinstance(rational_part, (int, mpz_type, mpq_type)):
            self.rational_part = Fraction(rational_part)
            self.quadratic_power = quadratic_power
Example #26
0
 def sqrt(self, x, digits):
     if is_square(x.numerator) and is_square(x.denominator):
         y = isqrt(x.numerator)
         z = isqrt(x.denominator)
         self.check(Fraction(y, z), digits, Expression.sqrt(x))
Example #27
0
@pytest.mark.parametrize("committee,score", [([1, 3, 2], 5), ([2, 1, 5], 4),
                                             ([2, 5, 4], 3),
                                             ([0, 1, 2, 3, 4, 5], 6)])
@pytest.mark.parametrize("num_cand", [6, 7, 8])
def test_monroescore_matching(committee, score, num_cand):
    profile = Profile(num_cand)
    approval_sets = [[0, 1], [1], [1, 3], [4], [2], [1, 5, 3]]
    profile.add_voters(approval_sets)

    assert monroescore_matching(profile, committee) == score


@pytest.mark.parametrize(
    "scorefct_id,score",
    [
        ("pav", Fraction(119, 12)),
        ("av", 14),
        ("slav", Fraction(932, 105)),
        ("cc", 7),
        ("geom2", Fraction(77, 8)),
    ],
)
@pytest.mark.parametrize("num_cand", [8, 9])
def test_thiele_scores(scorefct_id, score, num_cand):
    profile = Profile(num_cand)
    approval_sets = [[0, 1], [1], [1, 3], [4], [1, 2, 3, 4, 5], [1, 5, 3],
                     [0, 1, 2, 4, 5]]
    profile.add_voters(approval_sets)
    committee = [6, 7]
    assert scores.thiele_score(scorefct_id, profile, committee) == 0
    committee = [1, 2, 3, 4]
Example #28
0
def to_number(string):
    number = Fraction(string)
    if number.denominator == 1:
        number = int(number)
    return number
Example #29
0
def __slav_score_fct(i):
    if i == 0:
        return 0
    else:
        return Fraction(1, 2 * i - 1)
Example #30
0
def __pav_score_fct(i):
    if i == 0:
        return 0
    else:
        return Fraction(1, i)