Evaluators API

Evaluate the results of the elections.

There are two basic election types - selections and distributions. In selections, each candidate (usually a physical person) is either elected or not elected. In distributions, some candidates (usually parties) are allocated a positive number of seats (seats are distributied among the parties), while other parties get none and do not appear in the result.

Selection evaluators return a list of candidates. If some of them are tied, a core.Tie object will appear in the list. The tie object will contain all candidates tied for the seats and will be repeated the number of times equal to the number of tied seats.

Distribution evaluators return a dictionary mapping candidates to the number of seats (or other tokens they should be allocated). In case of a tie, the core.Tie object will appear as one of the keys, with the number of tied seats as its associated value.

There are some other election concepts, for example asset voting, where the candidates bargain with each other with the votes they have received; these understandably cannot be implemented within the current scope of Votelib. 1

None of the evaluators validate vote correctness; use the tools in the vote module for that, potentially wrapped in convert.InvalidVoteEliminator.

1

“Asset voting”, Range voting.org. https://rangevoting.org/Asset.html

Plurality evaluator

class votelib.evaluate.core.Plurality

Plurality voting / maximum score evaluator. Elects a list of candidates.

This encompasses the following voting systems:

  • First-past-the-post (simple plurality, FPTP) for a single seat and one vote per person.

  • Single non-transferable vote (SNTV) for multiple seats and one vote per voter.

  • Plurality-at-large (multiple non-transferable vote) for multiple seats and number of votes equal the number of seats.

  • Limited voting for multiple seats and number of votes per voter fixed and less than the number of seats.

  • Cumulative voting, a very similar variant where the number of available votes per voter is not tied to the number of candidates or seats.

  • Approval voting (AV) for number of available votes per voter equal to the number of candidates (but not the more advanced variants of approval voting such as proportional approval voting - see the approval for that). A multiwinner variant of approval voting is sometimes called block approval voting and exhibits very different properties. Use votelib.convert.ApprovalToSimpleVotes to convert approval votes to simple votes accepted by this evaluator.

  • Satisfaction approval voting (SAV), with one arbitrarily splittable vote per voter. Use votelib.convert.ApprovalToSimpleVotes to convert approval votes to simple votes accepted by this evaluator.

  • Score voting after the votes are aggregated by a score vote aggregator such as votelib.convert.ScoreToSimpleVotes (votelib.evaluate.cardinal.ScoreVoting can be used instead).

These voting systems all use this evaluator together with some vote conversion or validation criteria.

evaluate(votes, n_seats=1)

Select candidates by plurality voting.

In case of a tie, returns Tie objects at the end of the list of elected candidates. There will be as many ties as the number of tied seats; each tie will group the tied candidates.

Parameters
  • votes (Dict[Union[str, CandidateObject], Number]) – Simple votes (mapping the candidates to a quantity, the more the better).

  • n_seats (int) – Number of candidates to select.

Return type

List[Union[str, CandidateObject]]

Returns

A list of elected candidates, sorted in descending order by the input votes.

Proportional distribution evaluators

Distribution evaluators that are usually called proportional.

This contains the most common distribution evaluators used in party-list elections that at least aim to be proportional (although some parameter setups might make the result very nonproportional, such as the Imperiali divisor) and also some similar, simpler distribution evaluators that aim for strict proportionality while relaxing some of the constraints of a distribution evaluator.

class votelib.evaluate.proportional.BiproportionalEvaluator(divisor_function='d_hondt', apportioner=None, signpost_q=None)

Allocate seats biproportionally to parties and constituencies.

Biproportional apportionment is a method to provide proportional election results in two dimensions - constituencies and parties (candidates). It works by computing the proportional result using a highest averages method along one dimension (here: parties) and then iteratively updating it until proportionality is also reached for constituencies, in a process that somehow resembles iterative proportional fitting (IPF) but for integer values.

There are two main biproportional apportionment algorithms - alternate scaling (AS), which is known to be faster in initial stages but also to stall in some corner cases, and tie-and-transfer (TT), which is slower but robust. Here, tie-and-transfer (TT) is implemented as described in 2.

So far, the only studied variant of biproportional apportionment uses highest averages methods, but usually in an alternative specification by rounding rules (also called signpost sequences). These rounding rules have only been found for D’Hondt and Sainte-Laguë divisors; for other divisors, the implementation is missing yet.

Parameters
  • divisor_function (Union[str, Callable[[int], Number]]) – A callable producing the divisor from the number of seats awarded to the contestant so far, in the same form accepted by HighestAverages.

  • apportioner (Union[Distributor, Dict[Constituency, int], int, None]) – An optional distribution evaluator to allocate seats to constituencies according to the total numbers of votes cast in each. Can also be an integer stating the uniformly valid number of seats for each constituency, or a dictionary giving the numbers per constituency. If None, the number of seats must be specified to evaluate(), or the highest averages evaluator defined by divisor_function is used.

  • signpost_q (Union[int, Fraction, None]) – The signpost function subtraction constant, which defines the rounding. For D’Hondt and Sainte-Laguë divisors, this is automatically determined; for other divisors, it must be specified manually.

2

“Chapter 15. Double-Proportional Divisor Methods: Technicalities”, F. Pukelsheim. In: Proportional Representation, DOI 10.1007/978-3-319-64707-4_15.

evaluate(votes, n_seats)

Distribute seats biproportionally.

Parameters
  • votes (Dict[Constituency, Dict[Union[str, CandidateObject], int]]) – Simple votes per constituency to be evaluated.

  • n_seats (Union[int, Dict[Constituency, int]]) – Number of seats to be filled, either in total or by constituency.

Return type

Dict[Constituency, Dict[Union[str, CandidateObject], int]]

class votelib.evaluate.proportional.HighestAverages(divisor_function='d_hondt')

Distribute seats proportionally by ordering divided vote counts.

Divides the vote count for each party by an increasing sequence of divisors (usually small integers), sorts these quotients and awards a seat for each of the first n_seats quotients.

This includes some popular proportional party-list systems like D’Hondt or Sainte-Laguë/Webster. The result is usually quite close to proportionality and avoids the Alabama paradox of largest remainder systems. However, it usually favors either large or smaller parties, depending on the choice of the divisor function.

Parameters

divisor_function (Union[str, Callable[[int], Number]]) – A callable producing the divisor from the number of seats awarded to the contestant so far. For example, the D’Hondt divisor (which uses the natural numbers sequence) would always return the number of currently held seats raised by one. The common divisor functions can be referenced by string name from the votelib.component.divisor module.

evaluate(votes, n_seats, prev_gains={}, max_seats={})

Distribute seats proportionally by highest averages.

Parameters
  • votes (Dict[Union[str, CandidateObject], int]) – Simple votes to be evaluated.

  • n_seats (int) – Number of seats to be filled.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds, to determine the starting divisor.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Dict[Union[str, CandidateObject], int]

class votelib.evaluate.proportional.LargestRemainder(quota_function, **kwargs)

Distribute seats proportionally, rounding by largest remainder.

Each contestant is awarded the number of seats according to the number of times their votes fill the provided quota, just like QuotaDistributor. In addition to that, the parties that have the largest remainder of votes after the quotas are subtracted get an extra seat until the number of seats is exhausted.

This includes some popular proportional party-list systems like Hare, Droop or Hagenbach-Bischoff. The result is usually very close to proportionality (closer than in highest averages systems) but might suffer from an Alabama paradox where adding proportionally distributed votes might cause one of the contestants to lose seats.

Parameters

quota_function (Union[str, Callable[[int, int], Number]]) – A callable producing the quota threshold from the total number of votes and number of seats. The common quota functions can be referenced by string name from the votelib.component.quota module.

All additional keyword arguments have the same meaning as in QuotaDistributor.

evaluate(votes, n_seats, prev_gains={}, max_seats={})

Distribute seats proportionally, rounding by largest remainder.

Parameters
  • votes (Dict[Union[str, CandidateObject], int]) – Simple votes to be evaluated.

  • n_seats (int) – Number of seats to be filled.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds to be subtracted from the proportional result awarded here.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Dict[Union[str, CandidateObject], int]

class votelib.evaluate.proportional.PureProportionality

Distribute seats among candidates strictly proportionally (no rounding).

This evaluator is mostly auxiliary since it gives fractional seat counts.

evaluate(votes, n_seats, prev_gains={}, max_seats={})

Distribute seats exactly proportionally, giving fractional seats.

Parameters
  • votes (Dict[Union[str, CandidateObject], int]) – Simple votes to be evaluated.

  • n_seats (int) – Number of seats to be filled.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds to be subtracted from the proportional result awarded here.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Dict[Union[str, CandidateObject], Fraction]

class votelib.evaluate.proportional.QuotaDistributor(quota_function='droop', accept_equal=True, on_overaward='error')

Distribute seats proportionally, according to multiples of quota filled.

Each contestant is awarded the number of seats according to the number of times their votes fill the provided quota. (This essentially means the numbers of votes are divided by the quota and rounded down to get the numbers of seats.)

This is usually not a self-standing evaluator because it (except for very rare cases) does not award the full number of seats; it is, however, used in initial stages of some proportional systems, such as the Czech Chamber of Deputies election.

Parameters
  • quota_function (Union[str, Callable[[int, int], Number]]) – A callable producing the quota threshold from the total number of votes and number of seats. The common quota functions can be referenced by string name from the votelib.component.quota module.

  • accept_equal (bool) – Whether to consider the candidate elected when their votes exactly equal the quota.

  • on_overaward (str) –

    Some ill-conditioned but still used quotas, such as Imperiali, may distribute more seats than the allocated total since they are low. In that case, do the following:

    • 'ignore' - return the result regardless,

    • 'error' - raise a VotingSystemError,

    • 'subtract' - subtract seats from the candidates with the smallest remainder after the quota division (those that exceed the quota by a lowest margin) until the total seat count is met.

evaluate(votes, n_seats, prev_gains={}, max_seats={})

Distribute seats proportionally by multiples of quota filled.

Parameters
  • votes (Dict[Union[str, CandidateObject], int]) – Simple votes to be evaluated.

  • n_seats (int) – Number of seats to be filled.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds to be subtracted from the proportional result awarded here.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Dict[Union[str, CandidateObject], int]

class votelib.evaluate.proportional.VotesPerSeat(votes_per_seat, rounding='ROUND_DOWN', accept_equal=True)

Award seats for each N votes cast for each candidate.

This is an old and simple system that was used e.g. in pre-war Germany 3. It divides the number of votes by a pre-specified constant and rounds to give the appropriate number of seats. It is also used as an auxiliary evaluator in some other systems with fixed quota.

Parameters
  • votes_per_seat (int) – Number of votes required for the candidate to obtain a single seat.

  • rounding (str) – A rounding mode from the decimal Python library. The default option is to round down, which is the most frequent case, but this evaluator allows to specify a different method as well.

  • accept_equal (bool) – If False, whenever the number of votes is exactly divisible by votes_per_seat, award one less seat.

3

“Reichstag (Weimarer Republik): Wahlsystem”, Wikipedia. https://de.wikipedia.org/wiki/Reichstag_(Weimarer_Republik)#Wahlsystem

Condorcet selection evaluators

Condorcet selection evaluators.

These evaluators work by examining pairwise orderings between candidates (how many voters prefer one candidate to another), which is also the form of votes they take in; if you have ranked vote input, use votelib.convert.RankedToCondorcetVotes to convert it first and account for possible shared rankings and unranked candidates.

All of the methods in this module reliably select a Condorcet winner when there is one in the input.

These evaluators are considered more advanced in terms of satisfied criteria than transferable vote systems but still cannot defy some impossibility theorems such as Arrow’s or Gibbard’s.

These evaluators only take few parameters; therefore, a dictionary of their instances with different setups is provided in the EVALUATORS module variable.

class votelib.evaluate.condorcet.CondorcetWinner

Condorcet winner selector.

Selects a candidate that pairwise beats all other candidates, if there is one, or an empty list otherwise.

evaluate(votes)

Select the Condorcet winner.

Parameters

votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.condorcet.Copeland(second_order=True)

Copeland (count of pairwise wins) Condorcet selection evaluator.

Calculates the pairwise wins, constructs the Copeland score by taking number_of_pairwise_wins - number_of_pairwise_losses for each candidate, and uses this score to rank candidates. This often produces ties, which can be used by second order tiebreaking - by preferring the candidates who have pairwise beaten the candidates with the highest total Copeland score.

Parameters

second_order (bool) – Whether to use second-order Copeland tiebreaking.

evaluate(votes, n_seats=1)

Select candidates using the Copeland method.

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

  • n_seats (int) – Number of candidates to select.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.condorcet.KemenyYoung

Kemeny-Young Condorcet selection evaluator.

Kemeny-Young orders the candidates based on their pairwise comparison by constructing an objective function that measures the quality of any ordering, evaluating it for all permutations of the candidate set, and selecting the ordering with the maximum score.

The objective function is given as the number of satisfied pairwise orderings of candidates as given by the voters.

WARNING: Due to the enumeration of all candidate set permutations, this method is highly computationally expensive (O(n!) in the number of candidates) and infeasible on common machines for more than a handful of candidates.

evaluate(votes, n_seats=1)

Select candidates by the Kemeny-Young Condorcet method.

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

  • n_seats (int) – Number of candidates to select.

Return type

List[Union[str, CandidateObject]]

static score(variant, votes)

Compute the Kemeny-Young ordering score (objective function value).

Parameters
  • variant (Collection[Union[str, CandidateObject]]) – The ordering of candidates to evaluate.

  • votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

Return type

int

class votelib.evaluate.condorcet.MinimaxCondorcet(pairwin_scoring='winning_votes')

Minimax Condorcet selection evaluator.

Also known as successive reversal or Simpson-Kramer method. Selects as the winner the candidate whose greatest pairwise defeat is smaller than the greatest pairwise defeat of any other candidate.

The magnitude of the pairwise defeat can be measured in different ways according to the pairwise win scorer provided.

Parameters

pairwin_scoring (Union[str, Callable]) – A pairwise win scorer callable. Most common variants are found in the votelib.component.pairwin_scorer module and can be referred to by their names.

evaluate(votes, n_seats=1)

Select candidates by the Minimax Condorcet method.

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

  • n_seats (int) – Number of candidates to select.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.condorcet.RankedPairs(pairwin_scoring='winning_votes')

Tideman’s ranked pairs Condorcet selection evaluator.

Ranks pairwise wins by their magnitude and sequentially locks pairs of who beats whom in descending order into a ranking, discarding pairs that would contradict previously established rankings (i.e. create a cycle).

The magnitude of the pairwise win can be measured in different ways according to the pairwise win scorer provided.

Parameters

pairwin_scoring (Union[str, Callable]) – A pairwise win scorer callable. Most common variants are found in the votelib.component.pairwin_scorer module and can be referred to by their names.

evaluate(votes, n_seats=1)

Select candidates by the ranked pairs method.

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

  • n_seats (int) – Number of candidates to select.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.condorcet.Schulze

Schulze (beatpath) Condorcet selection evaluator.

Also called Schwartz Sequential dropping or path voting. Finds paths between pairs of candidates in which each candidate pairwise beats the next and then selects the candidates with strongest such paths.

evaluate(votes, n_seats=1)

Select candidates using the Schulze method.

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

  • n_seats (int) – Number of candidates to select.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.condorcet.SchwartzSet

Schwartz set selector.

The Schwartz set is the smallest possible non-empty set whose candidates are pairwise unbeaten by all other candidates.

evaluate(votes)

Select the Schwartz set.

Parameters

votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.condorcet.SmithSet

Smith set selector.

The Smith set is the smallest possible non-empty set whose candidates beat all other candidates in pairwise preference comparisons.

evaluate(votes)

Select the Smith set.

Parameters

votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

Return type

List[Union[str, CandidateObject]]

votelib.evaluate.condorcet.beat_counts(votes)

Count the number of candidates a given candidate beats pairwise.

Parameters

votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

Return type

Dict[Union[str, CandidateObject], int]

votelib.evaluate.condorcet.pairwise_wins(votes, include_ties=False)

Select pairs of candidates where the first is preferred to the second.

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]], int]) – Condorcet votes (counts of candidate pairs as they appear in the voter rankings); use votelib.convert.RankedToCondorcetVotes to produce them from ranked votes.

  • include_ties (bool) – Whether to include pairs of candidates that are tied. Such a pair will be included in both directions.

Return type

List[Tuple[Union[str, CandidateObject], Union[str, CandidateObject]]]

Returns

Ordered pairs from the input that are generally preferred to the opposite ranking (i.e. listed in this order by more voters).

Sequential (vote addition) selection evaluators

Evaluators that operate sequentially on ranked votes.

This hosts mainly the transferable vote evaluator (TransferableVoteSelector) but also its less known relative, PreferenceAddition.

class votelib.evaluate.sequential.Benham

Benham sequential Condorcet selector. 5

Selects a Condorcet winner. If one does not exist, eliminates one candidate using transferable vote (instant-runoff) and re-runs.

class votelib.evaluate.sequential.PreferenceAddition(coefficients=[1], split_equal_rankings=True)

Evaluates ranked votes by stepwise addition of lower preferences.

Each candidate starts with their first-preference votes and lower-preference votes are added to them until a sufficient amount of candidates achieve a majority. This includes the following voting systems:

  • Bucklin voting where the lower preferences are added without change.

  • Oklahoma system where the lower preferences are added divided by the order of preference, thus yielding the row of coefficients 1, 1/2, 1/3, 1/4… (Use Fraction to maintain exact values.)

Parameters
  • coefficients (Union[List[Number], Callable[[int], Number]]) – Coefficients to multiply the lower preferences with before they are added to the vote totals (the default adds them simply, which creates Bucklin voting).

  • split_equal_rankings (bool) – Whether to split votes having multiple alternatives at the same rank, or to add the whole amount to each of these alternatives.

evaluate(votes, n_seats=1)

Select candidates by sequential preference addition.

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject, FrozenSet[Union[str, CandidateObject]]], …], int]) – Ranked votes.

  • n_seats (int) – Number of candidates to be elected.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.sequential.TidemanAlternative(set_selector=<votelib.evaluate.condorcet.SmithSet object>)

Tideman alternative selector (Alternative Smith/Schwartz). 4

Uses a Smith or Schwartz set selector; if the set has multiple members, eliminates one candidate by transferable vote (instant-runoff) and reruns. For election of multiple candidates, it runs in multiple tiers where previous winners are eliminated from all following tiers. 5

Parameters

set_selector (SeatlessSelector) – The Smith/Schwartz set selector. Any seatless selector that accepts the Condorcet (pairwise preference) vote format.

4

“Tideman alternative method”, Wikipedia. https://en.wikipedia.org/wiki/Tideman_alternative_method

5(1,2)

Green-Armytage, James. “Four Condorcet-Hare Hybrid Methods for Single-Winner Elections”, Voting Matters. http://www.votingmatters.org.uk/ISSUE29/I29P1.pdf

class votelib.evaluate.sequential.TransferableVoteDistributor(transferer=<votelib.component.transfer.Gregory object>, retainer=None, eliminate_step=-1, quota_function='droop', accept_quota_equal=True, mandatory_quota=False)

Select candidates by eliminating and transfering votes among them.

This is the evaluator for transferable vote selection (since the evaluator does not concern itself with restrictions on allowed votes, it covers not only single transferable vote systems - STV -, but also potential multiple transferable vote systems). Its single-winner variant is also called instant-runoff voting (IRV).

First, this evaluator looks at first-preference votes. If any of the candidates has at least a specified quota of votes, they are awarded the number of seats according to how many times the quota fits into their number of votes. If they hit their maximum achievable number of seats (if there is one), their votes over the quota are redistributed (reallocated) to other candidates according to the next stated preference.

If no candidate has the quota, the candidate with the fewest currently allocated votes is eliminated and their votes transferred according to their next stated preference. Votes that have no further stated preferences are called exhausted and are removed from consideration.

The current version does not use elimination breakpoints.

Parameters
  • transferer (Union[str, VoteTransferer]) – An instance determining how much votes for eliminated candidates to transfer and to whom. It must provide the votelib.component.transfer.VoteTransferer interface (experimental, stability not guaranteed). The basic vote transfer variants are implemented in the votelib.component.transfer module and can be referred to by their names as strings.

  • retainer (Optional[Selector]) – A selector determining which candidates to retain when elimination is to be performed (it may accept a number of seats, which will correspond to the number of candidates to retain). If not given, the candidates with the lowest amounts of currently allocated votes will be eliminated one by one.

  • eliminate_step (Optional[int]) – Determines how many candidates to eliminate whenever elimination is to be performed. If a negative integer, determines how many candidates to eliminate at each step (the default eliminates one candidate at a time). If a positive integer, determines how many candidates to retain after elimination - this essentially allows only a single elimination and might cause an infinite loop if not used properly.

  • quota_function (Union[str, Callable[[int, int], Number], None]) – A callable producing the quota threshold from the total number of votes and number of seats. The common quota functions can be referenced by string name from the votelib.component.quota module. If None, no election by quota takes place - the candidates are just eliminated until the desired number remains. (Not specifying the quota only works when the maximum numbers of seats per candidate are specified.)

  • accept_quota_equal (bool) – Whether to use non-strict comparison for the number of votes against the quota.

  • mandatory_quota (bool) – If True, the candidates must reach the quota to be elected, i.e. they cannot be merely the last to be eliminated. If False, as soon as the number of unallocated seats equals the number of remaining candidates, these are all elected regardless of reaching the quota.

evaluate(votes, n_seats, prev_gains={}, max_seats={})

Allocate seats to candidates by transferable vote.

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject, FrozenSet[Union[str, CandidateObject]]], …], int]) – Ranked votes. Equal rankings are allowed.

  • n_seats (int) – Number of seats to allocate to candidates.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds to be subtracted from the result awarded here.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Dict[Union[str, CandidateObject], int]

next_count(allocation, n_seats, total_n_votes, prev_gains={}, max_seats={})

Advance the transferable voting process by one iteration (count).

Parameters
  • allocation (Dict[Union[str, CandidateObject, None], Dict[Tuple[Union[str, CandidateObject, FrozenSet[Union[str, CandidateObject]]], …], Number]]) – Current allocation of ranked votes to candidates still contesting the remaining seats. Eliminated candidates are not present in the dictionary keys. Exhausted votes are keyed by None.

  • n_seats (int) – Total number of seats to award.

  • total_n_votes (int) – Total number of votes. Used to compute the election quota.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Numbers of seats the candidates gained in the previous counts of the election.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Tuple[Dict[Union[str, CandidateObject, None], Dict[Tuple[Union[str, CandidateObject, FrozenSet[Union[str, CandidateObject]]], …], Number]], Dict[Union[str, CandidateObject], int]]

Returns

A 2-tuple containing the new allocation of votes and a mapping of candidates to newly assigned seats (might be empty if no seats were awarded on this count).

nth_count(votes, n_seats=1, count_number=1, prev_gains={}, max_seats={})

Get the intermediate counting state at a given iteration (count).

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject, FrozenSet[Union[str, CandidateObject]]], …], Number]) – Ranked votes. Equal rankings are allowed.

  • n_seats (int) – Number of candidates to select.

  • count_number (int) – 1-indexed count number.

Return type

Tuple[Dict[Union[str, CandidateObject, None], Dict[Tuple[Union[str, CandidateObject, FrozenSet[Union[str, CandidateObject]]], …], Number]], Dict[Union[str, CandidateObject], int]]

Returns

A 2-tuple containing the allocation of votes after the given count and a list of elected candidates so far (might be empty).

votelib.evaluate.sequential.initial_allocation(votes, transferer=<votelib.component.transfer.Gregory object>)

Allocate votes by first preference.

Parameters
  • votes (Dict[Tuple[Union[str, CandidateObject, FrozenSet[Union[str, CandidateObject]]], …], Number]) – Ranked votes.

  • transferer (VoteTransferer) – A votelib.component.transfer.VoteTransferer to transfer votes from shared first ranks among their candidates.

Return type

Dict[Union[str, CandidateObject, None], Dict[Tuple[Union[str, CandidateObject, FrozenSet[Union[str, CandidateObject]]], …], Number]]

Returns

The votes dictionary separated into subdictionaries keyed by candidate to whom the votes are allocated. A candidate with no first preference votes will be assigned to an empty dictionary.

Approval voting selection evaluators

Advanced approval voting methods.

This module contains approval voting evaluators that cannot be reduced to a plurality evaluation by aggregating the scores. Use votelib.convert.ApprovalToSimpleVotes in conjunction with votelib.evaluate.Plurality to evaluate simple approval voting (AV) or satisfaction approval voting (SAV).

class votelib.evaluate.approval.ProportionalApproval

Proportional Approval Voting (PAV) evaluator. 6

This method uses approval votes (voters select one or more permissible candidates) and evaluates the satisfaction of voters with each of the combinations of elected candidates. The satisfaction for each voter is given as the sum of reciprocals from 1 to N, where N is the number of elected candidates that the voter approved of.

WARNING: Due to the enumeration of all candidate set combinations, this method is highly computationally expensive (O(n!) in the number of candidates) and infeasible on common machines for more than a handful of candidates.

Tie breaking not implemented - the method itself does not provide a way to do it, a dedicated tie breaker will probably be necessary.

6

“Proportional approval voting”, Wikipedia. https://en.wikipedia.org/wiki/Proportional_approval_voting

evaluate(votes, n_seats)

Select candidates by proportional approval.

Parameters
  • votes (Dict[FrozenSet[Union[str, CandidateObject]], int]) – Approval votes.

  • n_seats (int) – Number of candidates to be elected.

Return type

List[Union[str, CandidateObject]]

Returns

Selected candidates in decreasing order measured by drop in satisfaction when the given candidate is excluded from the selected set.

class votelib.evaluate.approval.QuotaSelector(quota_function='droop', accept_equal=True, on_more_over_quota='error')

Quota threshold (plurality) selector.

Elects candidates with more (or also equally many, depending on accept_equal) votes than the specified quota. This often gives fewer candidates than the number of seats, and thus usually needs to be accompanied by an another evaluation step. In very rare cases, it might select more candidates than the number of seats.

This is a component in the following systems:

  • Two-round runoff (usually with the Droop quota and a single seat) where it gives the first-round winner if they have a majority of votes, and no one otherwise.

It can also serve as a threshold evaluator (eliminator) in proportional systems that restrict the first party seat from being a remainder seat, or a kickstart for Huntington-Hill related methods that are not defined for zero-seat parties.

Parameters
  • quota_function (Union[str, Callable[[int, int], Number]]) – A callable producing the quota threshold from the total number of votes and number of seats.

  • accept_equal (bool) – Whether to elect candidates that only just reach the quota threshold (this is known to produce some instabilities).

  • on_more_over_quota (str) –

    How to handle the case when more candidates fulfill the quota that there is seats:

class votelib.evaluate.approval.SequentialProportionalApproval

Sequential Proportional Approval Voting (SPAV) evaluator. 7

This method uses approval votes (voters select one or more permissible candidates) but evaluates them iteratively, unlike proportional approval voting. In each iteration, the best candidate is selected and all ballots that approve of them are reduced in value to 1/n, where n is the number of the candidates on that ballot already elected plus one (the value of those votes thus decreases to a half after one of the marked candidates is elected, to a third if a second one is elected, and so on).

Tie breaking not yet implemented.

7

“Sequential proportional approval voting”, Wikipedia. https://en.wikipedia.org/wiki/Sequential_proportional_approval_voting

evaluate(votes, n_seats)

Select candidates by sequential proportional approval.

Parameters
  • votes (Dict[FrozenSet[Union[str, CandidateObject]], int]) – Approval votes.

  • n_seats (int) – Number of candidates to be elected.

Return type

List[Union[str, CandidateObject]]

Returns

Selected candidates ordered as they were selected in the successive iterations.

Auxiliary evaluators

Open list evaluators

Open party list selection evaluators.

Many party-list proportional systems feature open lists - that is, voters get to cast preferential votes for the candidates on that list, and the order of those candidates might then be altered by these preferences. These evaluators serve to select the candidates from the party list that actually get one of the seats allocated to it.

The evaluators in this module accept an extra argument to their evaluate() methods, namely the original ordering of the candidates on the party list. Many methods only alter this ordering (allow jumps) if the lower candidates have significantly more votes than those above them; almost all of them rely on this ordering to break ties.

For the most common open list evaluation case, ThresholdOpenList (allowing jumps when the candidate gets at least a given fraction of the total votes for the list or at least a quota of the votes based on the number of seats) is provided. ListOrderTieBreaker provides a wrapper for any selection evaluator and uses the list ordering to break ties.

class votelib.evaluate.openlist.ListOrderTieBreaker(evaluator)

A wrapper for any selector for open-list candidate selection.

The candidates that the provided evaluator returns with the given votes are provided as the result of the open list. If there is a tie, it is broken by the ordering on the party list.

Parameters

evaluator (Selector) – Any selection evaluator.

evaluate(votes, n_seats, candidate_list)

Select candidates from an open party list.

Parameters
  • votes (Dict[Any, Number]) – Preferential votes for candidates on the list. Must be of the type that is accepted by the underlying evaluator.

  • n_seats (int) – Number of seats to be awarded to the list - the number of candidates to elect.

  • candidate_list (List[Union[str, CandidateObject]]) – The original (party-determined) list ordering.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.openlist.ThresholdOpenList(jump_fraction=None, quota_function=None, quota_fraction=1, take_higher=False, accept_equal=False, list_precedence=False)

A threshold-based open list evaluator.

Allows candidates that got at least a given number of votes for the list as preferential votes to jump over all other candidates. These jumping candidates are selected first, ordered by their number of votes; the rest of the seats is filled by other candidates on the list in its original order.

The number of votes required for the jump is determined relative to the total number of votes received by the list (jump_fraction) or to a quota computed from this total and the number of seats to award to the list (quota_function and quota_fraction).

Parameters
  • jump_fraction (Optional[Fraction]) – The fraction of total votes for the list that the candidate must obtain to jump ahead in the rankings.

  • quota_function (Union[str, Callable[[int, int], Number], None]) – A callable producing the quota threshold (number of votes required to jump) from the total number of votes and number of seats. The common quota functions can be referenced by string name from the votelib.component.quota module. The Hare quota ('hare') is used most frequently.

  • quota_fraction (Fraction) – A number to multiply the calculated quota with, to allow e.g. all candidates that got at least half of the quota to jump.

  • take_higher (bool) – If both the jump fraction and quota are specified, this determines whether to take the higher of the thresholds (amounting to an AND function) or the lower one (amounting to an OR function, the default).

  • accept_equal (bool) – Whether to use non-strict comparison for the number of votes against the quota or jump fraction.

  • list_precedence (bool) – Whether the original list ordering takes precedence when more candidates are allowed to jump than the number of seats. If True, the candidates lowest on the list are eliminated; if False, the candidates with the least votes are eliminated.

evaluate(votes, n_seats, candidate_list)

Select candidates from an open party list.

Parameters
  • votes (Dict[Union[str, CandidateObject], Number]) – Preferential votes (simple) for candidates on the list.

  • n_seats (int) – Number of seats to be awarded to the list - the number of candidates to elect.

  • candidate_list (List[Union[str, CandidateObject]]) – The original (party-determined) list ordering.

Return type

List[Union[str, CandidateObject]]

Electoral threshold evaluators

Electoral threshold evaluators and other seatless selectors.

These evaluators mainly serve as auxiliary components (usually preconditions) in proportional or similar voting systems. They are seatless selectors, which means they return a list of elected candidates without being given the number of them to select; that number is determined by other means.

class votelib.evaluate.threshold.AbsoluteThreshold(threshold, accept_equal=True)

Absolute threshold seatless selector.

Selects all candidates with more (or equally many) votes than the specified absolute number. Does not accept a number of seats as an argument to the evaluate() method.

Parameters
  • threshold (Number) – The absolute threshold as a number of votes.

  • accept_equal (bool) – Whether to elect candidates that only just reach the threshold.

evaluate(votes)

Select candidates by a given absolute threshold of votes.

Parameters

votes (Dict[Union[str, CandidateObject], Number]) – Simple votes.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.threshold.AlternativeThresholds(partials)

An OR function for threshold evaluators.

Wraps multiple seatless selectors and selects a candidate that is selected by any single one of them.

Parameters

partials (List[SeatlessSelector]) – The selectors to wrap.

evaluate(votes, prev_gains={})

Select candidates by dispatching to partial selectors and ORing.

Parameters

votes (Dict[Union[str, CandidateObject], Number]) – Simple votes.

Return type

List[Union[str, CandidateObject]]

Returns

A list of candidates that were selected by any single one of the internal partial selectors. They are ordered by mean rank in those partial selections.

class votelib.evaluate.threshold.CoalitionMemberBracketer(evaluators, default)

Dispatch to different seatless selectors for coalitions.

In many proportional systems the threshold to exclude smaller parties is raised for coalitions depending on the number of their members, to prevent the fragmentation of the resulting elected body.

Parameters
  • evaluators (Dict[int, SeatlessSelector]) – A dictionary mapping the number of coalition members to the corresponding seatless selector such as RelativeThreshold. Atomic parties (non-coalitions) will be dispatched to 1.

  • default (SeatlessSelector) – A default seatless selector for coalitions that do not have the corresponding count in evaluators. This is useful for clauses like “four and more party coalitions”.

evaluate(votes)

Select parties by dispatching to partial selectors.

Parameters

votes (Dict[ElectionParty, Number]) – Simple votes for parties. The keys in the dictionary must provide an is_coalition property and if its value is truthy, a get_n_coalition_members() method that returns the number of coalition members as an integer.

Return type

List[ElectionParty]

class votelib.evaluate.threshold.PreviousGainThreshold(selector)

A threshold on gained seats in previous election rounds.

In some multi-round systems (especially mixed-member proportional ones), an alternative to clearing a national-level vote fraction threshold is to gain a specific minimum number of seats in the first round (e.g. in Germany a party may qualify for list seats if they gain three or more district seats).

This evaluator passes the prev_gains argument of ordinary distribution evaluators to the votes argument of a given seatless selector, allowing one to specify a threshold based on previously gained seats.

Parameters

selector (SeatlessSelector) – The selector to evaluate the threshold on previous gains; AbsoluteThreshold would be the most typical choice.

evaluate(votes, prev_gains)

Select candidates by previous gain according to the inner selector.

Parameters
  • votes (Dict[Any, int]) – Will be disregarded.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds. Will be passed as votes to the inner selector.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.threshold.PropertyBracketer(property, evaluators, default=None)

Dispatch to different seatless selectors for some types of parties.

In many proportional systems the threshold to exclude smaller parties is lowered or nonexistent for parties with a special designation, such as parties of regional minorities. This wrapper class allows to provide special seatless selectors for such special cases.

Parameters
  • property (str) – The property (attribute) of the candidate to get as the key to distinguish which evaluator to use. To get the property, if the candidate object has a properties attribute, it is used, otherwise, getattr() is used on the candidate object directly.

  • evaluators (Dict[Any, Optional[SeatlessSelector]]) – A dictionary mapping the values of the property to the corresponding seatless selector such as RelativeThreshold.

  • default (Optional[SeatlessSelector]) – A default seatless selector for candidates that do not define the specified property or whose property value is outside the set of keys of the evaluators dictionary.

evaluate(votes)

Select candidates by dispatching to partial selectors.

Parameters

votes (Dict[Union[str, CandidateObject], Number]) – Simple votes. The keys in the dictionary (i.e. candidate objects) should provide the property name specified at the setup of this elector; if they do not, the default evaluator is used for them.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.threshold.RelativeThreshold(threshold, accept_equal=True)

Relative threshold seatless selector.

Selects all candidates with more (or equally many) votes than the specified fraction of total votes. Does not accept a number of seats as an argument to the evaluate() method.

This is a common component in proportional systems that excludes very small parties to increase stability of the resulting elected body.

Parameters
  • threshold (Number) – The relative threshold as a fraction of total votes.

  • accept_equal (bool) – Whether to elect candidates that only just reach the threshold.

evaluate(votes)

Select candidates by a given threshold of fraction of total votes.

Parameters

votes (Dict[Union[str, CandidateObject], Number]) – Simple votes.

Return type

List[Union[str, CandidateObject]]

Other auxiliary evaluators

Evaluators for special partial purposes, especially tiebreaking.

These evaluators should not be used as the main component of an election system (except for obscure ones). Many of them choose the winners randomly, so they are useful for tiebreaking, but that is about it.

You can make the random evaluators outputs stable if you give them a seed for the random generator, but be careful with that in a real-world setting.

class votelib.evaluate.auxiliary.CandidateNumberRanker

Select first N candidates with lowest candidate number.

This is useful for tiebreaking with an externally determined sort order.

evaluate(votes, n_seats=1)

Select the first candidates that appear in the votes dictionary.

Parameters
  • votes (Dict[Union[str, CandidateObject], Any]) – Simple votes. The quantities of votes are disregarded.

  • n_seats (int) – Number of candidates to be selected.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.auxiliary.InputOrderSelector

Select first N candidates as they appear in the vote counts.

This is useful for tiebreaking with an externally determined sort order, e.g. by ballot numbers or pre-generated random numbers. It takes advantage of dictionaries in Python 3.7+ maintaining insertion order.

evaluate(votes, n_seats=1)

Select the first candidates that appear in the votes dictionary.

Parameters
  • votes (Dict[Union[str, CandidateObject], Any]) – Simple votes. The quantities of votes are disregarded.

  • n_seats (int) – Number of candidates to be selected.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.auxiliary.RFC3797Selector(sources)

Select candidates randomly by the algorithm from RFC 3797.

This is a well-defined random selection method using external sources of randomness, that are to be provided as numbers or lists thereof. Once the sources of randomness are fixed in the constructor, the selection is deterministic with regard to the input order of candidates (candidate names or votes are disregarded).

Parameters

sources (List[Union[Number, Collection[Number]]]) – Sources of randomness (seeds). For detailed recommendations on where to take them from, see the RFC. The list should contain an item per source. The list items may contain a number, a string (which will be stripped of accents and anything besides ASCII alphanumeric characters and uppercased) or a list of numbers. Strings and floats are STRONGLY not recommended.

8

“RFC 3797: Publicly Verifiable Nominations Committee (NomCom) Random Selection”, D. Eastlake 3rd. https://tools.ietf.org/html/rfc3797

evaluate(votes, n_seats=1)

Select the candidates by the algorithm from RFC 3797.

Parameters
  • votes (Dict[Union[str, CandidateObject], Any]) – Simple votes. The quantities of votes are disregarded.

  • n_seats (int) – Number of candidates to be selected.

Return type

List[Union[str, CandidateObject]]

classmethod source_bytestring(sources)

Create the base randomness string from given randomness sources.

Follows the procedure as given by Section 4 of the RFC.

Return type

bytes

class votelib.evaluate.auxiliary.RandomUnrankedBallotSelector(seed=None)

Select candidates by drawing random simple ballots from the tally.

Useful for tiebreaking. Can also be used to evaluate random approval voting if the approval votes are converted to simple first.

Parameters

seed (Optional[int]) – Seed for the random generator that performs the sampling.

evaluate(votes, n_seats=1)

Select candidates by drawing random ballots.

Parameters
  • votes (Dict[Union[str, CandidateObject], Number]) – Simple votes.

  • n_seats (int) – Number of candidates (ballots) to be selected.

Return type

List[Union[str, CandidateObject]]

class votelib.evaluate.auxiliary.Sortitor(seed=None)

Perform sortition (random sampling) among the candidates.

This selects the candidates purely randomly, with equal probabilities for each of them. Useful for tiebreaking and some obscure protocols such as Venetian doge election.

Parameters

seed (Optional[int]) – Seed for the random generator that performs the sampling.

evaluate(votes, n_seats=1)

Select candidates randomly.

Parameters
  • votes (Dict[Union[str, CandidateObject], Any]) – Simple votes. The quantities of votes are disregarded.

  • n_seats (int) – Number of candidates to be selected.

Return type

List[Union[str, CandidateObject]]

Base classes and composition objects

General voting system evaluator machinery.

Common evaluation objects

class votelib.evaluate.core.Tie

Candidates tied for a seat.

This object, a subclass of frozenset, is produced by evaluators that do not resolve all evaluation ties - for example, a plurality evaluator when two or more candidates have an equal number of votes and only some of them fit into the number of seats to fill. It can either be presented in the result (such as in the case when the given voting system has no tiebreaking mechanism) or caught by a tiebreaking evaluator - use TieBreaking for this.

This object also provides some special static and class methods to handle ties in some basic ways.

static any(result)

Return True if there is any tie in the list, False otherwise.

Return type

bool

classmethod break_by_list(elected, breaker)

Break ties in the elected list according to ordering in breaker.

Return type

List[Union[str, CandidateObject]]

classmethod reconcile(elected)

Reconcile multiply tied candidates.

A placeholder implementation to account for the situation where e.g. partial evaluations gave ties but their multiple occurrence in the overall result means the ties can be unambiguously resolved.

Parameters

elected (List[Union[str, CandidateObject, Tie]]) – Selection result - a list of candidates or ties.

Return type

List[Union[str, CandidateObject]]

static tie_rankings(rankings)

Form a single ranking out of a list of rankings.

Produces ties where the rankings do not agree.

Return type

List[Union[str, CandidateObject, Tie]]

class votelib.evaluate.core.VotingSystemError

A voting system with a valid setup ended up in an unresolvable state.

Abstract base classes for evaluators

class votelib.evaluate.core.Evaluator

Evaluate votes for candidates and allocate seats to them.

A root abstract base class for all evaluators.

abstract evaluate(votes, *args, **kwargs)

Evaluate votes for candidates and allocate seats to them.

Return type

Union[List[Union[str, CandidateObject]], Dict[Union[str, CandidateObject], int]]

class votelib.evaluate.core.Selector

Elect a given number of candidates.

Requires a number of seats to determine the number of candidates to elect.

abstract evaluate(votes, n_seats, *args, **kwargs)

Elect n_seats candidates as a list.

Parameters
  • votes – Votes of any type.

  • n_seats – Number of candidates to elect.

Return type

List[Union[str, CandidateObject]]

Returns

A list of candidates elected, ordered by magnitude of victory (winner first).

class votelib.evaluate.core.SeatlessSelector

Elect some candidates.

Does not allow to pass a number of seats to determine the number of candidates to elect; it arises naturally from the votes and other selector settings.

abstract evaluate(votes, *args, **kwargs)

Elect a list of candidates without a guaranteed count.

Parameters

votes – Votes of any type.

Return type

List[Union[str, CandidateObject]]

Returns

A list of candidates elected, ordered by magnitude of victory (winner first).

class votelib.evaluate.core.Distributor

Allocate seats to candidates based on collective preference.

abstract evaluate(votes, n_seats, prev_gains={}, max_seats={})

Allocate n_seats to candidates as a dictionary.

Parameters
  • votes (Dict[Any, int]) – Votes of any type.

  • n_seats (int) – Number of seats to allocate to candidates.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Dict[Union[str, CandidateObject], int]

Returns

Numbers of seats allocated to respective candidates. Candidates with no allocated seats do not appear in the dictionary. The ordering of the dictionary is unspecified.

class votelib.evaluate.core.SeatCountCalculator

Composite evaluators

class votelib.evaluate.core.FixedSeatCount(evaluator, n_seats)

An evaluator wrapper that provides a fixed seat count.

Useful when the seat count for a given system is predefined and constant. Then, you do not need to specify it each time you call the evaluator, just provide the votes.

Parameters
  • evaluator (Evaluator) – The evaluator to wrap. Must accept number of seats into its evaluate method.

  • n_seats (int) – The fixed number of seats to provide to the evaluator at each call.

evaluate(votes, **kwargs)

Run the inner evaluator with the predefined number of seats.

All other keyword parameters are passed through to the wrapped evaluator.

Parameters

votes (Dict[Any, int]) – Votes of the type accepted by the wrapped evaluator.

Return type

Union[List[Union[str, CandidateObject]], Dict[Union[str, CandidateObject], int]]

class votelib.evaluate.core.TieBreaking(main, tiebreaker, subsetter=<votelib.vote.SimpleSubsetter object>)

Break ties from the main evaluation through a dedicated tiebreaker.

Runs the main evaluator on the input, and if ties are present in its output, runs them through a separately specified selector with the original votes subsetted to just those concerning the tied candidates.

Tiebreakers can be nested if there are more tiebreaking methods with different priority. To do so, wrap the core evaluator with the highest priority tiebreaker first, and then supply the result as the main evaluator to another tiebreaker with lower priority.

Parameters
  • main (Evaluator) – The main evaluator; might be a selector or a distributor.

  • tiebreaker (Selector) – A selector to evaluate ties.

  • vote_subsetter – A subsetter to subset a vote to just concern the tied candidates.

evaluate(votes, *args, **kwargs)

Evaluate the election, breaking ties if they arise.

Any arguments besides the votes dictionary are passed unchanged to the main evaluator.

Parameters

votes – Votes for the election; will be used to feed the main evaluator (and the tiebreaker, after subsetting).

class votelib.evaluate.core.Conditioned(eliminator, evaluator, subsetter=None, depth=1)

An evaluator whose votes are pre-selected to exclude some variants.

Before passing the votes to the main evaluator, an eliminator is evaluated first, and only the candidates returned by it are allowed to proceed to the main evaluation. This is useful for implementing vote thresholds in proportional systems.

Parameters
  • evaluator (Evaluator) – The main evaluator to produce the results.

  • eliminator (SeatlessSelector) – A selector to determine which variants proceed to the main evaluator - only those that are returned by its evaluate method do so. It can accept previous gain counts but should not need the number of seats (it should be independent of it).

  • subsetter (Optional[SimpleSubsetter]) – A subsetter to subset a vote to just concern the candidates returned by the eliminator.

evaluate(votes, n_seats=None, prev_gains={}, **kwargs)

Evaluate the main evaluator for variants that passed the eliminator.

All other keyword arguments are passed through to the main evaluator.

Parameters
  • votes (Dict[Any, int]) – Votes to be passed to the main evaluator and eliminator.

  • n_seats (Optional[int]) – Number of seats to allocate by the main evaluator.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Numbers of seats previously gained by the candidates (e.g. in previous scrutinia). Will be passed to both the main evaluator and eliminator, if they accept them (as determined by the accepts_seats function).

Return type

Union[List[Union[str, CandidateObject]], Dict[Union[str, CandidateObject], int]]

class votelib.evaluate.core.PreConverted(converter, evaluator)

An evaluator whose votes are first run through a converter.

Useful when the evaluator accepts a different type of votes than the actual ballots, where the converter adapts them - e.g. when the votes are by constituency but the evaluation is nationwide, or when ranked votes are given but a part of the system runs on simple votes.

Parameters
  • evaluator – An evaluator to run.

  • converter – A converter to apply on the votes before passing them to the evaluator.

evaluate(votes, *args, **kwargs)

Convert the votes by and evaluate them through the evaluator.

All other arguments are passed through to the evaluator.

Parameters
  • votes – Votes to be passed to the converter.

  • n_seats – Number of seats to allocate by the evaluator.

class votelib.evaluate.core.PostConverted(evaluator, converter)

An evaluator whose results are run through a converter.

Useful when the evaluator is a part of a larger system and its output needs to be adapted to it, e.g. in multi-member proportional systems where first votes are received by candidates in a selection evaluation but the second votes are evaluated by distribution to parties.

Parameters
  • evaluator – An evaluator to run.

  • converter – A converter to apply on the results of the evaluator.

evaluate(votes, *args, **kwargs)

Run the evaluator and return its result, converted.

All other arguments are passed through to the evaluator.

Parameters
  • votes – Votes for the evaluator.

  • n_seats – Number of seats to allocate by the evaluator.

class votelib.evaluate.core.ByConstituency(evaluator, apportioner=None, preselector=None, subsetter=<votelib.vote.SimpleSubsetter object>)

Perform constituency-wise evaluation of given system.

Evaluates and returns the results of the given system separately per each constituency it is given votes for. If desired, apportions the seats to constituencies according to the total numbers of votes cast in each.

The selector and vote subsetter perform what the Conditioned evaluator wrapper would do; however, they are only used after apportionment is performed, because that is often defined before candidates are excluded. If this is not desired, define the selector and vote subsetter on a Conditioned wrapper, with the selector wrapped in an additional PreConverted with votelib.convert.VoteTotals, and leave the selector undefined here.

Parameters
  • evaluator (Evaluator) – Evaluator to use on the constituency level.

  • apportioner (Union[Distributor, Dict[Constituency, int], int, None]) – An optional distribution evaluator to allocate seats to constituencies according to the total numbers of votes cast in each. Can also be an integer stating the uniformly valid number of seats for each constituency, or a dictionary giving the numbers per constituency. If None, the number of seats must be specified to evaluate().

  • preselector (Optional[Selector]) – An optional selection evaluator to select candidates eligible for constituency-wise evaluation. Votes for candidates that do not pass its selection will be removed for all constituencies before evaluation. If not given, no preselection will be applied.

  • subsetter (VoteSubsetter) – A subsetter to subset a vote to just concern the candidates returned by the selector. The default option needs to be modified if the votes are more deeply nested.

evaluate(votes, n_seats=None, prev_gains={}, max_seats={})

Return the election results evaluated by constituency.

Parameters
  • votes (Dict[Constituency, Dict[Any, int]]) – Votes in the format accepted by the inner evaluator.

  • n_seats (Union[int, Dict[Constituency, int], None]) –

    Number of seats to be allocated:

    • If None, the apportioner must be a distributor that does not accept seat count, and will be called with the total numbers of votes cast in each constituency to provide a seat count for each constituency.

    • If an integer and the apportioner is None, regarded as the uniform number of seats for each constituency.

    • If an integer and the apportioner is a distributor, the apportioner will be called with this integer as the total number of seats to distribute it to the constituencies.

    • If a dictionary, it will be regarded as the mapping of constituencies to their numbers of seats.

  • prev_gains (Dict[Constituency, Dict[Union[str, CandidateObject], int]]) – Seats gained by the candidate/party in previous election rounds in each constituency, to inform the underlying evaluator.

  • max_seats (Dict[Constituency, Dict[Union[str, CandidateObject], int]]) – Maximum number of seats that the given candidate/party can obtain in total per constituency (including previous gains).

Return type

Union[Dict[Constituency, Dict[Union[str, CandidateObject], int]], Dict[Constituency, List[Union[str, CandidateObject]]]]

Returns

Results of the evaluation by constituency.

class votelib.evaluate.core.PreApportioned(evaluator, apportioner)

Apportion seats to constituencies before the evaluation.

In some systems, apportionment is not fixed but is only done at the time of the election based on the number of votes cast in the constituencies. This component also allows to perform this.

Parameters
  • evaluator (Distributor) – The per-constituency election evaluator.

  • apportioner (Union[Distributor, Dict[Constituency, int], int]) –

    How to apportion the seats to constituencies:

    • If an integer, each constituency gets this many seats.

    • If a dictionary mapping constituencies to integers, each constituency gets the number of seats specified.

    • If a distribution evaluator, it is called on vote totals in each constituency to produce the number of seats. In this variant, n_seats must be passed to evaluate().

class votelib.evaluate.core.RemovedApportionment(evaluator)

Disregard previously computed apportionment for this evaluator.

In some systems, only a single (usually the “proportionality leveling”) component does not respect an otherwise valid apportionment; this wrapper sums the apportioned seats back up into a single number for it.

Parameters

evaluator (Distributor) – The wrapped evaluator that expects unapportioned seats (i.e. a single number).

class votelib.evaluate.core.ByParty(overall_evaluator, allocator=None, subsetter=<votelib.vote.SimpleSubsetter object>)

Distribute overall party results among its constituency lists.

This is an inverted variant of the ByConstituency evaluator. Here, the total seat counts for each party are determined by an overall evaluator on nationally aggregated votes and an allocation distributor is subsequently used to disaggregate the result of the party to constituencies.

Useful for some mixed-member proportional system such as the German Bundestag one, where this mechanism is used to distribute overhang leveling seats.

Parameters
  • overall_evaluator (Distributor) – Evaluator to use on the central (national) level.

  • allocator (Optional[Distributor]) – An optional distribution evaluator to allocate seats of the party to individual constituencies. If None, the overall evaluator is reused. In either case, the allocator must accept simple votes for constituencies as candidates.

  • subsetter (VoteSubsetter) – A subsetter according to the vote type used, to extract votes for any single party from the overall votes.

evaluate(votes, n_seats=None, prev_gains={}, max_seats={})

Return constituency-wise election results evaluated by party.

Parameters
  • votes (Dict[Constituency, Dict[Any, int]]) – Votes in the format accepted by the overall evaluator. They will be subsetted and aggregated to simple votes for constituencies for the allocator evaluation.

  • n_seats (Optional[int]) – Number of seats to be allocated. If None, the overall evaluator must be seatless.

  • prev_gains (Dict[Constituency, Dict[Union[str, CandidateObject], int]]) – Seats gained by the candidate/party in previous election rounds in each constituency, to inform the allocator. Not passed to the overall evaluator.

  • max_seats (Dict[Constituency, Dict[Union[str, CandidateObject], int]]) – Maximum number of seats that the given candidate/party can obtain in total per constituency (including previous gains). Not passed to the overall evaluator.

Return type

Dict[Constituency, Dict[Union[str, CandidateObject], int]]

Returns

Results of the evaluation by constituency.

class votelib.evaluate.core.MultistageDistributor(rounds, depth=1)

A distribution evaluator with several rounds of awarding seats.

Useful for several systems, e.g. multi-member proportional systems where the first round evaluates the constituencies and the second one evaluates the national level.

Parameters
  • rounds (List[Distributor]) – Partial distributors. Will be called one by one, with the subsequent distributors getting the results of the previous steps as previous gains.

  • depth (int) – Nesting depth of the results. Use numbers larger than 1 when the results from the rounds are nested by constituency levels (2 for one constituency level, etc.)

evaluate(votes, n_seats, prev_gains={}, max_seats={})

Evaluate all rounds of the distribution.

Parameters
  • votes (Union[Dict[Any, int], List[Dict[Any, int]]]) – Votes to be evaluated. Either a single set to be passed to all rounds, or separate sets of votes for each round.

  • n_seats (int) – Number of seats to be filled in total.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Dict[Union[str, CandidateObject], int]

class votelib.evaluate.core.UnusedVotesDistributor(rounds, quota_functions=None, depth=1)

Run several rounds of awarding seats, subtracting used votes.

In some elections, candidates who receive a seat have a certain quota of votes (usually the quota used to grant that seat) subtracted from their vote count, which then continues into subsequent rounds of evaluation. An example is the new (after 2021) Czech Parliament lower house election.

Parameters
  • rounds (List[Distributor]) – Partial distributors. Will be called one by one, with the subsequent distributors getting the results of the previous steps as previous gains and the votes progressively lowered according to corresponding subtracted quotas.

  • quota_functions (Optional[List[Union[str, Callable[[int, int], Number]]]]) – Quota functions to use for used vote subtraction. The length of this list should be one item smaller than the number of rounds (since after the last round, there is no meaningful subtraction).

  • depth (int) – Nesting depth of the results. Use numbers larger than 1 when the results from the rounds are nested by constituency levels (2 for one constituency level, etc.)

evaluate(votes, n_seats, prev_gains={}, max_seats={})

Evaluate all rounds of the distribution.

Parameters
  • votes (Dict[Union[str, CandidateObject], int]) – Votes to be evaluated. Either a single set to be passed to all rounds, or separate sets of votes for each round.

  • n_seats (int) – Number of seats to be filled in total.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Dict[Union[str, CandidateObject], int]

class votelib.evaluate.core.AdjustedSeatCount(calculator, evaluator)

Distribute an adjusted total number of seats according to votes cast.

Useful in multi-member proportional systems where overhang seats are accounted for, e.g. by leveling.

Parameters
  • calculator (SeatCountCalculator) – A calculator determining how many seats to award. It is called with the evaluation parameters (votes, intended number of seats, previously gained seats…).

  • evaluator (Distributor) – A distribution evaluator producing the actual results with the adjusted number of seats.

evaluate(votes, n_seats, prev_gains, max_seats={})

Distribute an adjusted total number of seats.

Parameters
  • votes (Dict[Any, int]) – Votes to be evaluated, of any type accepted by the calculator and evaluator.

  • n_seats (int) – Intended (baseline) number of seats that would arise if no adjustment was necessary.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained by the candidate/party in previous election rounds.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total (including previous gains).

Return type

Dict[Union[str, CandidateObject], int]

class votelib.evaluate.core.PartyListEvaluator(party_eval, list_eval=None, list_votes_converter=None)

Evaluate which candidates are elected from party lists.

Useful to determine the actual representatives elected when the result is first evaluated by party. This wrapper evaluates the party-based result first, then uses a party list evaluator to determine which candidates from the given party lists actually get elected.

Parameters
  • party_eval (Distributor) – A distribution evaluator determining the party-based election result.

  • list_eval (Optional[OpenListEvaluator]) – An open list evaluator determining which candidates from the party list to elect, according to the preferential votes for the candidates. Look to the votelib.evaluate.openlist for some of these. If None, the party lists are considered closed and the elected candidates are taken from the top of each list, without considering the list votes.

  • list_votes_converter (Optional[Converter]) – A converter to apply to list votes before passing to the list evaluator. The converter should produce a result where the candidate votes are grouped by party (such as votelib.convert.GroupVotesByParty). If not given, the list votes are passed unchanged.

evaluate(votes, n_seats, *, party_lists, list_votes=None, **kwargs)

Return lists of candidates elected for each party.

All keyword arguments are passed to the party evaluator.

Parameters
  • votes (Dict[Any, Number]) – Votes in the format accepted by the party evaluator.

  • n_seats (int) – Number of seats to be allocated, to be passed to the party evaluator.

  • party_lists (Dict[ElectionParty, List[Union[str, CandidateObject]]]) – Lists of candidates for each party in the order they were submitted for election.

  • list_votes (Optional[Dict[ElectionParty, Dict[Any, Number]]]) – Votes for individual candidates on the party lists. If not given, the list evaluator must be None and the party lists are considered closed.

Raises

ValueError – If only one of list votes and a list evaluator is given.

Return type

Dict[ElectionParty, List[Person]]

Seat count adjustment calculators

class votelib.evaluate.core.AllowOverhang(evaluator)

Increase the total number of seats to allow keeping overhang seats.

Overhang seats arise in multi-member proportional systems when a party gains more seats in the first round (usually local and plurality-based) than its proportional share according to second round (national, proportional party-based) votes. This calculator increases the number of seats so that all parties keep their overhang seats while the number of seats awarded in the second round stays constant. This leads to parties that performed strong in the first round but weak in the second round gaining more representation than would be decided by the second round only.

This is the system used in New Zealand legislative elections.

Parameters

evaluator (Distributor) – A distribution evaluator producing the proportional results from the second round votes to determine which seats are overhang. Usually will be the same or very similar to the evaluator used in the second round directly.

calculate(votes, n_seats, prev_gains, max_seats={})

Return an adjustment to the total number of seats to allow overhang.

Parameters
  • votes (Dict[Any, int]) – Second round votes to produce the proportional result to determine overhang.

  • n_seats (int) – Intended (baseline) number of seats that would arise if no adjustment was necessary. This is passed to the internal evaluator to determine the proportional result.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained in the first round results.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total, including first round results.

Return type

int

Returns

Zero if no adjustment is necessary, a positive integer if it is, amounting to the number of overhang seats detected.

class votelib.evaluate.core.LevelOverhang(evaluator)

Increase the total number of seats to proportional, keeping overhang.

Overhang seats arise in multi-member proportional systems when a party gains more seats in the first round (usually local and plurality-based) than its proportional share according to second round (national, proportional party-based) votes. This calculator increases the number of seats so that all parties keep their overhang seats while the overall seat counts for parties remain proportional according to the second round votes. This means that even when the first round seats end up dominated by a single party which has a huge overhang, the other parties still get enough leveling seats on the national level to maintain a representation proportional to their second round votes.

Parameters

evaluator (Distributor) – A distribution evaluator producing the proportional results from the second round votes to determine which seats are overhang. Usually will be the same or very similar to the evaluator used in the second round directly.

calculate(votes, n_seats, prev_gains, max_seats={})

Return an adjustment to the total number of seats to level overhang.

Parameters
  • votes (Dict[Any, int]) – Second round votes to produce the proportional result to determine overhang.

  • n_seats (int) – Intended (baseline) number of seats that would arise if no adjustment was necessary. This is passed to the internal evaluator to determine the proportional result.

  • prev_gains (Dict[Union[str, CandidateObject], int]) – Seats gained in the first round results.

  • max_seats (Dict[Union[str, CandidateObject], int]) – Maximum number of seats that the given candidate/party can obtain in total, including first round results.

Return type

int

Returns

Zero if no adjustment is necessary, a positive integer if it is, amounting to the sum of overhang seats detected and leveling seats required.

class votelib.evaluate.core.LevelOverhangByConstituency(constituency_evaluator, overall_evaluator=None)

Increase the total number of seats to proportional in constituencies.

This is a variant LevelOverhang that works out overhang and leveling seats on a constituency level (such as Länder in Germany) while still maintaining nationwide proportionality. For a detailed description of the overhang leveling process, see that class. This variant detects overhang seats for each constituency separately and progressively increases the number of leveling seats until proportionality is satisfied on a national level.

This is the system used for the election to German Bundestag.

Parameters
  • constituency_evaluator (Distributor) – Evaluates the total party result per constituency.

  • overall_evaluator (Optional[Distributor]) – Evaluates the total party result nationwide; if not given, an aggregate of the constituency result is used instead.

calculate(votes, n_seats, prev_gains, max_seats={})

Adjust the seat count to level overhang by constituency.

Parameters
  • votes (Dict[Constituency, Dict[Any, int]]) – Second round votes to produce the proportional result to determine overhang, by constituency.

  • n_seats (int) – Intended (baseline) number of seats that would arise if no adjustment was necessary. This is passed to the internal evaluator to determine the proportional result.

  • prev_gains (Dict[Constituency, Dict[Union[str, CandidateObject], int]]) – Seats gained in the first round results by parties, by constituency.

  • max_seats (Dict[Constituency, Dict[Union[str, CandidateObject], int]]) – Maximum number of seats that the given candidate/party can obtain in total, including first round results, by constituency.

Return type

int

Returns

Zero if no adjustment is necessary, a positive integer if it is, amounting to the sum of overhang seats detected and leveling seats required for all constituencies.

Auxiliary evaluation functions

votelib.evaluate.core.get_n_best(votes, n_seats)

Return n_seats candidates with the highest number of votes.

Essentially a plurality selection function. Produces ties correctly so is useful as a component in many other systems that use selection by maximum somewhere in their process.

Parameters
  • votes (Dict[Union[str, CandidateObject], Number]) – Mapping of candidates to the number of votes obtained.

  • n_seats (int) – Number of seats to be filled.

Return type

List[Union[str, CandidateObject, Tie]]

Returns

A list of top n_seats candidates. If there is a tie, the last items will refer to a single Tie object containing the tied candidates.

votelib.evaluate.core.accepts_seats(evaluator)

Whether evaluator takes seat count as an argument to evaluate().

Return type

bool

votelib.evaluate.core.accepts_prev_gains(evaluator)

Whether evaluator takes previous gains as an argument to evaluate().

Return type

bool