interregnum.methods.singlevote package¶
Single votes allocators.
A single vote allocator needs an input
candidates.
- class interregnum.methods.singlevote.HighestAveragesAllocator(divisor_f, skip_initial_seats=False)¶
Bases:
NonDeterministicAllocator[AnyName,HAResultData]Highest averages allocator ([Gallagher:1992], [KohlerZeh:2012]).
Implementation based on divisor series which allocates one seat at a time.
Tie-breaking follows the rules defined by the Spanish law from 1985 ([Loreg:1985]).
allocatorscollection keys:highest_averages
highest-averages
Create a highest averages allocator using a divisor function or a divisor sequence.
- Parameters:
divisor_f (str | DivisorFunction | DivisorIterator[Divisor]) – A divisor function, a divisor iterator or a key in the
divisorscollection.skip_initial_seats (bool)
Examples
>>> # use the d'Hondt divisor >>> dhondt = HighestAveragesAllocator("dhondt")
- calc(candidates, seats, random_seed=None, filter_f=None, initial_seats=None, skip_initial_seats=None)¶
Allocate candidates to seats.
If a candidate has initial seats, the initial divisor will be adjusted considering those seats at a starting point ([Denmark:2011]).
Distributed seats will be logged by a
QuotaWinnerEvent.- Parameters:
candidates (Iterable[tuple[AnyName, int | Fraction] | tuple[AnyName, int | Fraction, int] | Candidate[AnyName]]) – list of candidates with votes. Only candidates in this list will be considered.
seats (int) – seats that will be computed, in addition to the initial seats
random_seed (int | Random | None) – used to break ties
filter_f (CandidateFilter[AnyName, Event] | None) – restrict allocation to filtered candidates
initial_seats (Iterable[tuple[AnyName, int]] | None) – seats already allocated to candidates
skip_initial_seats (bool | None) – add initial seats to results. If None, the value from the constructor will be used
- Return type:
- class interregnum.methods.singlevote.IterativeDivisorAllocator(signpost_f)¶
Bases:
Allocator[AnyName,IDResultData[AnyName]]Iterative divisor method.
See [DorfleitnerKlein:1997] and [Zachariasen:2006]
allocatorscollection keys:iterative_divisor
iterative-divisor
Create an iterative divisor allocator.
- Parameters:
signpost_f (str | RoundingWithSignpost) – round function with signpost (collection
signposts).
- calc(candidates, seats, exclude_candidates=None)¶
Allocate candidates to seats.
Initial candidate seats are ignored. All won seats will be logged by
SeatsEvent.- Parameters:
- Return type:
Examples
>>> # use the Jefferson method >>> jefferson = IterativeDivisorAllocator("jefferson")
- class interregnum.methods.singlevote.LargestRemainderAllocator(quota_f, fix_overflow=True, bisect_step=1, skip_initial_seats=False)¶
Bases:
NonDeterministicAllocator[AnyName,LRResultData]Largest remainder method.
See [Gallagher:1992], [KohlerZeh:2012] and https://en.wikipedia.org/wiki/Largest_remainder_method
allocatorscollection keys:largest_remainder
largest-remainder
Create a largest remainder method using quota_f as the quota function.
While the calculated quota allocates more than the avalaible seats and fix_overflow is True, the quota will be incremented by bisect_step. The remaining seats will be assigned to the candidates with the largest remainders.
- Parameters:
quota_f (str | QuotaFunction) – quota function or key in
quotasfix_overflow (bool) – adjust the quota if more seats than the required amount were allocated
bisect_step (int) – step used at the quota adjustment process
skip_initial_seats (bool)
Examples
>>> # Hare quota >>> hare = LargestRemainderAllocator("hare")
>>> # Reinforced Imperiali quota, adjusting quota >>> # if the allocated seats are greater than required >>> imp3 = LargestRemainderAllocator("imperiali3")
>>> # Reinforced Imperiali quota, do not adjust quota >>> imp3 = LargestRemainderAllocator("imperiali3", fix_overflow=False)
- calc(candidates, seats, random_seed=None, total_votes=None, exclude_candidates=None, initial_seats=None, skip_initial_seats=None)¶
Allocates candidates to seats.
If a candidate already has initial seats, the votes used for those seats are subtracted before the allocation.
Distributed seats will be logged by
QuotaWinnerEvent(seats by quota) andSeatsEvent(seats by remainders).If a quota is discarded because of overflow, a
NewQuotaEventwill be logged.- Parameters:
candidates (Iterable[tuple[AnyName, int | Fraction] | tuple[AnyName, int | Fraction, int] | Candidate[AnyName]]) – list of candidates
seats (int) – seats that will be computed, in addition to the initial seats
random_seed (int | Random | None) – used to break ties
total_votes (int | Fraction | None) – votes for the quota calculation, in the case it is greater than the sum of the candidates’ votes
initial_seats (Iterable[tuple[AnyName, int]] | None) – seats already allocated to candidates
skip_initial_seats (bool | None) – add initial seats to results. If None, the value from the constructor will be used
exclude_candidates (Iterable[AnyName] | None)
- Return type:
- class interregnum.methods.singlevote.LimitedVotingAllocator¶
Bases:
MultiWinnerAdapter[AnyName,MultiWinnerResultData,Sequence[Candidate[AnyName]],Iterable[tuple[AnyName,int|Fraction] |tuple[AnyName,int|Fraction,int] |Candidate[AnyName]]]Limited voting / Partial block voting.
Given that there are N available seats, the N most voted candidates win a seat each one.
Used in the election to the Spanish Senate.
See [Loreg:1985] and https://en.wikipedia.org/wiki/Limited_voting
allocatorscollection keys:limited_voting
partial_block_voting
Create a limited voting allocator.
Examples
>>> limited_voting = LimitedVotingAllocator()
- calc(candidates, seats, random_seed=None, filter_f=None, **ranking_args)¶
Allocate candidates to seats.
Initial seats will be ignored.
- Parameters:
candidates (Iterable[tuple[AnyName, int | Fraction] | tuple[AnyName, int | Fraction, int] | Candidate[AnyName]]) – list of candidates
seats (int) – number of expected winners
random_seed (int | Random | None) – used to break ties
filter_f (CandidateFilter[AnyName, Event] | None) – restrict to filtered candidates
ranking_args (Any)
- Return type:
- class interregnum.methods.singlevote.WinnerTakesAllAllocator¶
Bases:
WinnerTakesAllAdapter[AnyName,MultiWinnerResultData,Sequence[Candidate[AnyName]],Iterable[tuple[AnyName,int|Fraction] |tuple[AnyName,int|Fraction,int] |Candidate[AnyName]]]Winner-Takes-All / First past the post.
Each seat will be assigned to the most voted candidate in different rounds.
The winner will take all the seats.
allocatorscollection keys:winner_takes_all
first_past_the_post
Create a First Past The Post allocator.
Examples
>>> wta = WinnerTakesAllAllocator()
- calc(candidates, seats=1, random_seed=None, **kwargs)¶
Allocate candidates to seats.
- Parameters:
- Return type:
Submodules¶
interregnum.methods.singlevote.highest_averages module¶
Highest averages method for proportional apportionments.
References¶
- class interregnum.methods.singlevote.highest_averages.CandidateState(candidate, divisor, quotient, last_tie_victory=-1)¶
Bases:
Generic[AnyName]Candidate internal state.
- Parameters:
- classmethod init(candidate, div_f)¶
Init a candidate state.
- Parameters:
div_f (DivisorIterator[int | float | Fraction])
- Return type:
- tie_state()¶
Get a candidate with the same votes and the last tie victory.
- update()¶
Update quotient and divisor.
- Return type:
None
- divisor: Iterator[int | float | Fraction]¶
- last_tie_victory: int¶
- quotient: int | float | Fraction¶
- class interregnum.methods.singlevote.highest_averages.HAResultData(log=<factory>, max_quota=-inf, min_quota=inf, remaining_seats=0)¶
Bases:
EventLogAdditional result data for highest averages methods.
- Parameters:
log (list[Event])
max_quota (int | float | Fraction)
min_quota (int | float | Fraction)
remaining_seats (int)
- new_seat(criterion, winner)¶
Log new seat allocated to winner by criterion.
- Parameters:
criterion (str)
winner (CandidateState[Any])
- Return type:
None
- max_quota: int | float | Fraction = -inf¶
Maximum allowed quota
- min_quota: int | float | Fraction = inf¶
Minimum allowed quota
- remaining_seats: int = 0¶
Seats not allocated yet
- class interregnum.methods.singlevote.highest_averages.HAState(data=<factory>, *, random_seed)¶
Bases:
NonDeterministicStateCalculation state for Highest Average Allocator.
- Parameters:
data (HAResultData)
random_seed (dataclasses.InitVar[Union[int, random.Random, NoneType]])
- break_tie(candidates)¶
Resolve a tie affecting candidates.
Three strategies are applied in the following order ([Loreg:1985]):
tie_break_most_voted Choose the candidate with most votes.
tie_break_older_random_winner Choose the candidate the older non deterministic tie-winning candidate.
tie_break_random Choose a candidate randomly.
- Parameters:
candidates (Sequence[CandidateState[AnyName]]) – tied candidates
- Returns:
Winners grouped by criterion.
- Return type:
dict[str, list[CandidateState[AnyName]]]
- break_tie_ttl(candidates, limit=1)¶
Resolve a tie based on the less recent victory.
The candidates that won a random tie-breaking more time ago than the others will have priority.
If not possible, fall back to random tie-break.
Return winners grouped by criterion
- data: HAResultData¶
- class interregnum.methods.singlevote.highest_averages.HighestAveragesAllocator(divisor_f, skip_initial_seats=False)¶
Bases:
NonDeterministicAllocator[AnyName,HAResultData]Highest averages allocator ([Gallagher:1992], [KohlerZeh:2012]).
Implementation based on divisor series which allocates one seat at a time.
Tie-breaking follows the rules defined by the Spanish law from 1985 ([Loreg:1985]).
allocatorscollection keys:highest_averages
highest-averages
Create a highest averages allocator using a divisor function or a divisor sequence.
- Parameters:
divisor_f (str | DivisorFunction | DivisorIterator[Divisor]) – A divisor function, a divisor iterator or a key in the
divisorscollection.skip_initial_seats (bool)
Examples
>>> # use the d'Hondt divisor >>> dhondt = HighestAveragesAllocator("dhondt")
- calc(candidates, seats, random_seed=None, filter_f=None, initial_seats=None, skip_initial_seats=None)¶
Allocate candidates to seats.
If a candidate has initial seats, the initial divisor will be adjusted considering those seats at a starting point ([Denmark:2011]).
Distributed seats will be logged by a
QuotaWinnerEvent.- Parameters:
candidates (Iterable[tuple[AnyName, int | Fraction] | tuple[AnyName, int | Fraction, int] | Candidate[AnyName]]) – list of candidates with votes. Only candidates in this list will be considered.
seats (int) – seats that will be computed, in addition to the initial seats
random_seed (int | Random | None) – used to break ties
filter_f (CandidateFilter[AnyName, Event] | None) – restrict allocation to filtered candidates
initial_seats (Iterable[tuple[AnyName, int]] | None) – seats already allocated to candidates
skip_initial_seats (bool | None) – add initial seats to results. If None, the value from the constructor will be used
- Return type:
interregnum.methods.singlevote.iterative_divisor module¶
Iterative divisor allocator, based on [DorfleitnerKlein:1997].
References¶
- class interregnum.methods.singlevote.iterative_divisor.Discrepancy(*values)¶
Bases:
IntEnumMark for seats discrepancies.
- DECREMENTABLE = -1¶
A candidate can lose one seat
- EXACT = 0¶
A candidate can not lose or wine seats
- INCREMENTABLE = 1¶
A candidate can win one more seat
- class interregnum.methods.singlevote.iterative_divisor.IDResultData(log=<factory>, max_quota=-inf, min_quota=inf, remaining_seats=0, ties=<factory>)¶
Bases:
HAResultData,Generic[AnyName]Result data for Iterative Divisor Allocator.
- Parameters:
log (list[Event])
max_quota (int | float | Fraction)
min_quota (int | float | Fraction)
remaining_seats (int)
ties (dict[AnyName, Discrepancy])
- ties: dict[AnyName, Discrepancy]¶
Candidates with ties (incrementable or decrementable)
- class interregnum.methods.singlevote.iterative_divisor.IterativeDivisorAllocator(signpost_f)¶
Bases:
Allocator[AnyName,IDResultData[AnyName]]Iterative divisor method.
See [DorfleitnerKlein:1997] and [Zachariasen:2006]
allocatorscollection keys:iterative_divisor
iterative-divisor
Create an iterative divisor allocator.
- Parameters:
signpost_f (str | RoundingWithSignpost) – round function with signpost (collection
signposts).
- calc(candidates, seats, exclude_candidates=None)¶
Allocate candidates to seats.
Initial candidate seats are ignored. All won seats will be logged by
SeatsEvent.- Parameters:
- Return type:
Examples
>>> # use the Jefferson method >>> jefferson = IterativeDivisorAllocator("jefferson")
- interregnum.methods.singlevote.iterative_divisor.or_inf(val)¶
Return val if is finite, otherwise return Infinity.
- Parameters:
val (int | Fraction | None)
- Return type:
int | Fraction | float
- interregnum.methods.singlevote.iterative_divisor.priority_dec(round_f, cand)¶
Priority for decrementation.
- Parameters:
round_f (RoundingWithSignpost)
- Return type:
tuple[int | Fraction | float, int | Fraction, AnyName]
- interregnum.methods.singlevote.iterative_divisor.priority_inc(round_f, cand)¶
Priority for incrementation.
- Parameters:
round_f (RoundingWithSignpost)
- Return type:
tuple[int | Fraction | float, int | Fraction, AnyName]
interregnum.methods.singlevote.largest_remainder module¶
Largest remainder method.
References¶
- class interregnum.methods.singlevote.largest_remainder.CandidateState(candidate, remainder=None)¶
Bases:
Generic[AnyName]Candidate internal state.
- remainder: int | Fraction | None¶
Votes remainder after applying quota
- class interregnum.methods.singlevote.largest_remainder.LRResultData(log=<factory>, quota=0, remaining_seats=0)¶
Bases:
EventLogAdditional result data for largest remainder methods.
- Parameters:
log (list[Event])
quota (int | Fraction)
remaining_seats (int)
- first_quota: int | Fraction¶
Initial quota before adjustment
- quota: int | Fraction = 0¶
Current quota
- remaining_seats: int = 0¶
Seats not allocated
- class interregnum.methods.singlevote.largest_remainder.LRState(data=<factory>, total_votes=0, eligible=<factory>, *, random_seed)¶
Bases:
NonDeterministicState,Generic[AnyName]A calculation state for Largest Remainder Allocator.
- Parameters:
data (LRResultData)
total_votes (int | Fraction)
random_seed (dataclasses.InitVar[Union[int, random.Random, NoneType]])
- break_tie(candidates, limit)¶
Resolve a tie choosing limit candidates.
Strategies are applied in the following order:
tie_break_most_voted Choose the candidate with most votes.
tie_break_random Choose a candidate randomly.
- Parameters:
candidates (Sequence[CandidateState[AnyName]])
limit (int)
- Return type:
dict[str, list[CandidateState[AnyName]]]
- remove_used_votes(quota_f, seats)¶
Remove votes used for initial seats.
- Parameters:
quota_f (Callable[[int | Fraction, int | Fraction], Comparison])
seats (int)
- Return type:
None
- resolve_tie_most_voted(candidates)¶
Choose the most voted candidate.
- Parameters:
candidates (Sequence[CandidateState[AnyName]])
- Return type:
Sequence[CandidateState[AnyName]]
- seats_by_quota(seats, fix_overflow, bisect_step)¶
Allocate seats by quota.
- Parameters:
seats (int)
fix_overflow (bool)
bisect_step (int)
- Return type:
list[CandidateState[AnyName]]
- seats_by_remainders(remainders)¶
Allocate seats by largest remainders.
- Parameters:
remainders (Sequence[CandidateState[AnyName]])
- Return type:
Sequence[CandidateState[AnyName]]
- data: LRResultData¶
Result data
- total_votes: int | Fraction = 0¶
Total number of votes
- class interregnum.methods.singlevote.largest_remainder.LargestRemainderAllocator(quota_f, fix_overflow=True, bisect_step=1, skip_initial_seats=False)¶
Bases:
NonDeterministicAllocator[AnyName,LRResultData]Largest remainder method.
See [Gallagher:1992], [KohlerZeh:2012] and https://en.wikipedia.org/wiki/Largest_remainder_method
allocatorscollection keys:largest_remainder
largest-remainder
Create a largest remainder method using quota_f as the quota function.
While the calculated quota allocates more than the avalaible seats and fix_overflow is True, the quota will be incremented by bisect_step. The remaining seats will be assigned to the candidates with the largest remainders.
- Parameters:
quota_f (str | QuotaFunction) – quota function or key in
quotasfix_overflow (bool) – adjust the quota if more seats than the required amount were allocated
bisect_step (int) – step used at the quota adjustment process
skip_initial_seats (bool)
Examples
>>> # Hare quota >>> hare = LargestRemainderAllocator("hare")
>>> # Reinforced Imperiali quota, adjusting quota >>> # if the allocated seats are greater than required >>> imp3 = LargestRemainderAllocator("imperiali3")
>>> # Reinforced Imperiali quota, do not adjust quota >>> imp3 = LargestRemainderAllocator("imperiali3", fix_overflow=False)
- calc(candidates, seats, random_seed=None, total_votes=None, exclude_candidates=None, initial_seats=None, skip_initial_seats=None)¶
Allocates candidates to seats.
If a candidate already has initial seats, the votes used for those seats are subtracted before the allocation.
Distributed seats will be logged by
QuotaWinnerEvent(seats by quota) andSeatsEvent(seats by remainders).If a quota is discarded because of overflow, a
NewQuotaEventwill be logged.- Parameters:
candidates (Iterable[tuple[AnyName, int | Fraction] | tuple[AnyName, int | Fraction, int] | Candidate[AnyName]]) – list of candidates
seats (int) – seats that will be computed, in addition to the initial seats
random_seed (int | Random | None) – used to break ties
total_votes (int | Fraction | None) – votes for the quota calculation, in the case it is greater than the sum of the candidates’ votes
initial_seats (Iterable[tuple[AnyName, int]] | None) – seats already allocated to candidates
skip_initial_seats (bool | None) – add initial seats to results. If None, the value from the constructor will be used
exclude_candidates (Iterable[AnyName] | None)
- Return type:
- class interregnum.methods.singlevote.largest_remainder.NewQuotaEvent(quota, criterion, old_quota=None, data=None)¶
Bases:
EventA computed quota has changed.
- Parameters:
quota (int | Fraction)
criterion (str)
old_quota (int | Fraction | None)
data (Any | None)
- EVENT: ClassVar[str] = 'new quota'¶
Event type
- criterion: str¶
criterion for choosing the quota
- data: Any | None = None¶
additional data
- old_quota: int | Fraction | None = None¶
previous quota
- quota: int | Fraction¶
current quota
- interregnum.methods.singlevote.largest_remainder.apply_quota(seats, data, quota)¶
Apply quota to candidates.
- Parameters:
- Returns:
(remaining seats, remainders, log)
- Return type:
tuple[int, list[CandidateState[AnyName]], list[Event]]
interregnum.methods.singlevote.limited_voting module¶
Limited voting / Partial block voting.
References¶
- class interregnum.methods.singlevote.limited_voting.LimitedVotingAllocator¶
Bases:
MultiWinnerAdapter[AnyName,MultiWinnerResultData,Sequence[Candidate[AnyName]],Iterable[tuple[AnyName,int|Fraction] |tuple[AnyName,int|Fraction,int] |Candidate[AnyName]]]Limited voting / Partial block voting.
Given that there are N available seats, the N most voted candidates win a seat each one.
Used in the election to the Spanish Senate.
See [Loreg:1985] and https://en.wikipedia.org/wiki/Limited_voting
allocatorscollection keys:limited_voting
partial_block_voting
Create a limited voting allocator.
Examples
>>> limited_voting = LimitedVotingAllocator()
- calc(candidates, seats, random_seed=None, filter_f=None, **ranking_args)¶
Allocate candidates to seats.
Initial seats will be ignored.
- Parameters:
candidates (Iterable[tuple[AnyName, int | Fraction] | tuple[AnyName, int | Fraction, int] | Candidate[AnyName]]) – list of candidates
seats (int) – number of expected winners
random_seed (int | Random | None) – used to break ties
filter_f (CandidateFilter[AnyName, Event] | None) – restrict to filtered candidates
ranking_args (Any)
- Return type:
- class interregnum.methods.singlevote.limited_voting.MostVotedRanking(scores)¶
Bases:
RankingList[AnyName]Ranking based on votes.
Create a ranking list from a list of candidates.
interregnum.methods.singlevote.winner_takes_all module¶
First past the post.
- class interregnum.methods.singlevote.winner_takes_all.WinnerTakesAllAllocator¶
Bases:
WinnerTakesAllAdapter[AnyName,MultiWinnerResultData,Sequence[Candidate[AnyName]],Iterable[tuple[AnyName,int|Fraction] |tuple[AnyName,int|Fraction,int] |Candidate[AnyName]]]Winner-Takes-All / First past the post.
Each seat will be assigned to the most voted candidate in different rounds.
The winner will take all the seats.
allocatorscollection keys:winner_takes_all
first_past_the_post
Create a First Past The Post allocator.
Examples
>>> wta = WinnerTakesAllAllocator()
- calc(candidates, seats=1, random_seed=None, **kwargs)¶
Allocate candidates to seats.
- Parameters:
- Return type: