Components API¶
Quotas¶
Quota functions used in largest-remainder proportional voting systems.
Quotas can however be used as a component in many other voting systems, such as transferable vote or open list evaluators.
A quota function takes the total number of votes and the number of seats to allocate and returns the number of votes required to reach a seat. The unrounded quota functions return fractions to retain exact values.
All supported quota functions are assembled in the QUOTAS dictionary keyed by their name. get() retrieves from this dictionary by string key; construct() also accepts callables and passes them through.
- votelib.component.quota.droop(votes, seats)¶
Droop quota, the most widely used one.
This it is the smallest integer quota guaranteeing the number of passing candidates will not be higher than the number of seats.
- Return type
int
- votelib.component.quota.hagenbach_bischoff(votes, seats)¶
Hagenbach-Bischoff quota.
This is the unrounded variant, giving the exact fraction.
- Return type
Fraction
- votelib.component.quota.hagenbach_bischoff_ceil(votes, seats)¶
Hagenbach-Bischoff quota, rounding up.
This is the rounded variant that is identical to the Droop quota in most cases.
- Return type
int
- votelib.component.quota.hagenbach_bischoff_rounded(votes, seats)¶
Hagenbach-Bischoff quota, rounding mathematically (round-to-even).
This is the rounded variant that is used in some rare cases, e.g. old Slovak regional apportionment of parliamentary seats. Half is rounded up.
- Return type
int
- votelib.component.quota.hare(votes, seats)¶
Hare quota, the most basic one.
This is the unrounded variant, giving the exact fraction.
- Return type
Fraction
- votelib.component.quota.hare_rounded(votes, seats)¶
Hare quota, the most basic one.
This is the rounded variant, which is used more often. Half is rounded up.
- Return type
int
- votelib.component.quota.imperiali(votes, seats)¶
Imperiali quota.
Imperiali quota can produce more candidates than seats to be filled in some cases; the results then usually need to be recalculated using a different quota.
- Return type
Fraction
Divisors¶
Divisor functions used in highest-averages proportional voting systems.
This provides arguments for the
votelib.evaluate.proportional.HighestAverages
evaluator. However,
divisors can be used as a component in many other voting systems,
such as biproportional allocation.
A divisor function takes the order number (usually equal to the number of seats allocated so far) and returns the divisor by which to divide the number of votes for the given party or candidate. The party or candidate with the largest result then gets the next seat.
Some systems use a mathematically defined divisor but artificially change the
result for parties with no seats so far (order == 0) to make it harder for
parties to get their seats. Use modified_first_coef()
for that.
All supported divisor functions are assembled in the DIVISORS dictionary keyed by their name. get() retrieves from this dictionary by string key; construct() also accepts callables and passes them through.
- votelib.component.divisor.d_hondt(order)¶
D’Hondt divisor, the most commonly used divisor.
Forms a simple sequence 1, 2, 3… In the United States, this is known as the Jefferson divisor that was used for congressional apportionment 1792-1842.
Known to slightly favor larger parties.
- Return type
int
- votelib.component.divisor.danish(order)¶
Danish divisor.
Forms a sequence 1, 4, 7…
Extremely favors smaller parties.
- Return type
int
- votelib.component.divisor.huntington_hill(order)¶
Huntington-Hill divisor.
The divisors are defined by sqrt(n*(n+1)). This means the divisor is invalid for the zeroth order (passing a zero gives a divisor of zero, which raises an error in the subsequent division) and can thus only be used in cases where the first seat is already guaranteed (use the prev_gains argument for that).
Used for United States congressional apportionment as of 2020.
- Return type
Decimal
- votelib.component.divisor.imperiali(order)¶
Imperiali divisor. Not to be confused with the Imperiali quota.
Forms a sequence 1, 1.5, 2…
Known to favor large parties greatly.
- Return type
Fraction
- votelib.component.divisor.macau(order)¶
Macau modified D’Hondt divisor.
This uses order counts as exponents (1, 2, 4, 8…), and therefore favors smaller parties.
- Return type
int
- votelib.component.divisor.modified_first_coef(divisor_fx, first_coef=Decimal('1.4'))¶
Modify the divisor for the zeroth order to an apriori coefficient.
This can be used to raise the threshold for parties that have not yet obtained a seat. This is the case in the Czech regional election (Koudelka coefficient 1.42), Nepal, Norway, and Sweden.
- Parameters
divisor_fx (
Callable
[[int
],Number
]) – The ordinary divisor function to be wrapped and used for the first order and subsequent ones.first_coef (
Decimal
) – The coefficient to be used when order == 0.
- Return type
Callable
[[int
],Number
]
- votelib.component.divisor.sainte_lague(order)¶
Sainte-Laguë (Webster, Schepers) divisor, a commonly used divisor.
Forms a sequence 1, 3, 5…
Known to favor mid-sized parties.
- Return type
int
Pairwise win scorers¶
Functions to score magnitudes of wins between pairs of candidates.
These are used in some Condorcet methods to determine ranking priority.
- votelib.component.pairwin_scorer.margins(counts)¶
Margins pairwise win scorer. Takes the difference from reverse option.
Also called margin of victory or defeat strength. Assigns the number of votes ranking the pair in the given order minus the number of votes doing the reverse as the win strength (which is thus negative for pairwise losses).
- Parameters
counts (
Dict
[Tuple
[Union
[str
,CandidateObject
],Union
[str
,CandidateObject
]],Number
]) – Condorcet votes (counts of pairwise preferences).- Return type
Dict
[Tuple
[Union
[str
,CandidateObject
],Union
[str
,CandidateObject
]],Number
]
- votelib.component.pairwin_scorer.pairwise_opposition(counts)¶
Pairwise opposition win scorer. Returns the win counts unchanged.
This gives the number of votes ranking the pair in the given order directly as the measure of pairwise win, regardless of the number of votes preferring the opposite pairwise ranking.
- Parameters
counts (
Dict
[Tuple
[Union
[str
,CandidateObject
],Union
[str
,CandidateObject
]],Number
]) – Condorcet votes (counts of pairwise preferences).- Return type
Dict
[Tuple
[Union
[str
,CandidateObject
],Union
[str
,CandidateObject
]],Number
]
- votelib.component.pairwin_scorer.winning_votes(counts)¶
Winning votes pairwise win scorer. Counts wins fully, zero otherwise.
This is the most common pairwise win scorer. When the number of votes for the pair ranked in one direction is larger than the other direction, assigns all those votes as the pairwise win strength.
- Parameters
counts (
Dict
[Tuple
[Union
[str
,CandidateObject
],Union
[str
,CandidateObject
]],Number
]) – Condorcet votes (counts of pairwise preferences).- Return type
Dict
[Tuple
[Union
[str
,CandidateObject
],Union
[str
,CandidateObject
]],Number
]
Rank scorers¶
Objects to assign scores to ranks in ranked voting systems such as Borda.
A rank scorer returns a list of numerical scores to be assigned to ranks given by voters. This is the essence of Borda count system, and rank scorers capture most of the variations there are in that system.
- class votelib.component.rankscore.Borda(base=1)¶
Borda rank scorer, corresponding to the original Borda count variant.
Assigns the base score to the candidate ranked last, and one point more for each higher rank.
This rank scorer needs to be initialized by the
set_n_candidates()
before callingscores()
.- Parameters
base (
int
) – The score to assign to the candidate ranked last. For the truly original Borda, this equals to 1; some variants set it to zero, and thus set the score for the first rank to the number of candidates minus one.
- scores(n_ranked)¶
Return the scores for the first n_ranked ranks.
This gives (number of candidates + base - 1 - rank) for ranks running from 0 (best rank) to n_ranked.
- Parameters
n_ranked (
int
) – Number of ranks to be returned. Equal to the length of the output list.- Raises
RuntimeError – If the scorer has not been initialized first by calling
set_n_candidates()
.- Return type
List
[int
]
- set_n_candidates(n_candidates)¶
Set the total number of candidates that could be ranked.
This helps to account for rankings that do not rank all candidates.
- Parameters
n_candidates (
int
) – The total number of candidates that could be ranked on any ballot (i.e. the number of candidates participating in the election in the particular constituency).- Return type
None
- class votelib.component.rankscore.Dowdall¶
Dowdall (Nauru) rank scorer.
Assigns the numbers of the harmonic series (1, 1/2, 1/3…) to progressively lower ranks.
- scores(n_ranked)¶
Return the scores for the first n_ranked ranks.
This gives 1 / (rank + 1) for ranks running from 0 (best rank) to n_ranked.
- Parameters
n_ranked (
int
) – Number of ranks to be returned. Equal to the length of the output list.- Return type
List
[Fraction
]
- class votelib.component.rankscore.FixedTop(top)¶
A rank scorer with fixed score for the top rank.
Assigns scores progressively decreased by one until hitting zero.
- Parameters
top (
int
) – The score for the top (best) ranked candidate on the ballot.
- scores(n_ranked)¶
Return the scores for the first n_ranked ranks.
This gives max(top - rank, 0) for ranks running from 0 (best rank) to n_ranked.
- Parameters
n_ranked (
int
) – Number of ranks to be returned. Equal to the length of the output list.- Return type
List
[int
]
- class votelib.component.rankscore.Geometric(base=2)¶
A geometric progression rank scorer.
Assigns the numbers of a chosen inverse geometric progression (e.g. 1, 1/2, 1/4… for 2) to progressively lower ranks.
- Parameters
base (
int
) – Base of the geometric progression.
- scores(n_ranked)¶
Return the scores for the first n_ranked ranks.
This gives 1 / (2 ** rank) for ranks running from 0 (best rank) to n_ranked.
- Parameters
n_ranked (
int
) – Number of ranks to be returned. Equal to the length of the output list.- Return type
List
[Fraction
]
- class votelib.component.rankscore.ModifiedBorda¶
Modified Borda count rank scorer.
In this system, the score for the highest rank is not constant (as is the case for the vanilla Borda count), but is equal to the number of ranked candidates; therefore, it encourages voters to rank many candidates.
- scores(n_ranked)¶
Return the scores for the first n_ranked ranks.
This gives n_ranked - rank for ranks running from 0 (best rank) to n_ranked.
- Parameters
n_ranked (
int
) – Number of ranks to be returned. Equal to the length of the output list.- Return type
List
[int
]
- class votelib.component.rankscore.RankScorer¶
An abstract base class for rank scorers.
Rank scorers must provide a scores() method that returns a list of scores based on the number of ranks given. They may also provide a set_n_candidates() method that sets the total number of candidates participating in the election, which might be relevant for computing the rank scores. If this method is defined, it must be called before the scores() method is called first.
- class votelib.component.rankscore.SequenceBased(sequence)¶
A rank scorer with a predetermined sequence of scores.
This is used in many competitions (Eurovision, Formula One, etc.)
Assigns scores according to the given sequence until hitting zero, and zero scores afterwards.
- Parameters
sequence (
List
[Number
]) – The scores for the top candidates on the ballot.
- scores(n_ranked)¶
Return the scores for the first n_ranked ranks.
This gives values from the initial sequence, then zeros.
- Parameters
n_ranked (
int
) – Number of ranks to be returned. Equal to the length of the output list.- Return type
List
[Number
]
- votelib.component.rankscore.select_padded(sequence, n, pad_with=0)¶
Select n leading elements from sequence, padding with pad_with.
Padding with pad_with is used when sequence is not long enough to select n elements.
- Return type
List
[Any
]
Vote transferers for STV¶
Objects to transfer votes between candidates for transferable vote systems.
Transfers of votes from eliminated and elected candidates to candidates staying
in the contest are an essential part of any transferable vote system,
such as the one of
votelib.evaluate.sequential.TransferableVoteSelector
.
There are many variants how to achieve this, some are implemented here.
NOTE: The VoteTransferer
interface is provisional and may be changed
in the future, chiefly to accommodate a wider range of transfer methods (Meek,
Wright…)
- class votelib.component.transfer.Gregory¶
Gregory (fractional) vote transferer.
The variant used is the Weighted Inclusive Gregory Method (WIGM) used e.g. in Scottish local government elections.
When a candidate is elected by quota, the fraction corresponding to the quota divided by total votes for the candidate is used to multiply (lower) each vote allocated to that candidate; the votes are then transferred to next candidates on the ballots.
In case of shared ranks, the votes are evenly distributed between the candidates sharing the rank.
The implementation produces exact fractional votes. Rounding rules are not implemented yet.
- subtract(allocation, elected)¶
Remove votes from elected candidates according to the quota.
- Parameters
allocation (
Dict
[Union
[str
,CandidateObject
,None
],Dict
[Tuple
[Union
[str
,CandidateObject
,FrozenSet
[Union
[str
,CandidateObject
]]], …],Number
]]) – Current allocation of ranked votes to candidates. The votes allocated to elected candidates will be lowered by the amount corresponding to the quota for their election.elected (
Dict
[Union
[str
,CandidateObject
],int
]) – Elected candidates, mapped to the quota with which they were elected (or multiples thereof, if they were awarded multiple seats). These quotas should be removed from the candidates’ votes (because so many votes were used).
- Return type
Dict
[Union
[str
,CandidateObject
,None
],Dict
[Tuple
[Union
[str
,CandidateObject
,FrozenSet
[Union
[str
,CandidateObject
]]], …],Number
]]
- transfer(allocation, candidates)¶
Transfer votes from eliminated or fully elected candidates.
- Parameters
allocation (
Dict
[Union
[str
,CandidateObject
,None
],Dict
[Tuple
[Union
[str
,CandidateObject
,FrozenSet
[Union
[str
,CandidateObject
]]], …],Number
]]) – Current allocation of ranked votes to candidates. The votes allocated to specified candidates will be reallocated to other candidates that are present in the allocation, or reassigned to the None key as exhausted ballots.candidates (
List
[Union
[str
,CandidateObject
]]) – Candidates to be removed from the allocation.
- Return type
Dict
[Union
[str
,CandidateObject
,None
],Dict
[Tuple
[Union
[str
,CandidateObject
,FrozenSet
[Union
[str
,CandidateObject
]]], …],Number
]]
- class votelib.component.transfer.Hare(seed=None)¶
Hare (random ballot selection) vote transferer.
This is the variant used (AFAIK) in Irish lower house legislative elections (Dáil Éireann).
When a candidate is elected by quota, the number of ballots corresponding to the quota is randomly selected and discarded, the rest is fully transferred to their next preferences.
In case of shared ranks, the votes are randomly distributed between the candidates sharing the rank.
- Parameters
seed (
Optional
[int
]) – Seed for the random generator.
- subtract(allocation, elected)¶
Remove votes from elected candidates according to the quota.
- Parameters
allocation (
Dict
[Union
[str
,CandidateObject
,None
],Dict
[Tuple
[Union
[str
,CandidateObject
,FrozenSet
[Union
[str
,CandidateObject
]]], …],Number
]]) – Current allocation of ranked votes to candidates. The votes allocated to elected candidates will be lowered by the amount corresponding to the quota for their election.elected (
Dict
[Union
[str
,CandidateObject
],int
]) – Elected candidates, mapped to the quota with which they were elected (or multiples thereof, if they were awarded multiple seats). These quotas should be removed from the candidates’ votes (because so many votes were used).
- Return type
Dict
[Union
[str
,CandidateObject
,None
],Dict
[Tuple
[Union
[str
,CandidateObject
,FrozenSet
[Union
[str
,CandidateObject
]]], …],Number
]]
- transfer(allocation, candidates)¶
Transfer votes from eliminated or fully elected candidates.
- Parameters
allocation (
Dict
[Union
[str
,CandidateObject
,None
],Dict
[Tuple
[Union
[str
,CandidateObject
,FrozenSet
[Union
[str
,CandidateObject
]]], …],Number
]]) – Current allocation of ranked votes to candidates. The votes allocated to specified candidates will be reallocated to other candidates that are present in the allocation, or reassigned to the None key as exhausted ballots.candidates (
List
[Union
[str
,CandidateObject
]]) – Candidates to be removed from the allocation.
- Return type
Dict
[Union
[str
,CandidateObject
,None
],Dict
[Tuple
[Union
[str
,CandidateObject
,FrozenSet
[Union
[str
,CandidateObject
]]], …],Number
]]