interregnum package

Algorithms for comuting electoral systems.

Methods (methods)

Methods allocate seats given a set of votes.

Implemented methods are grouped by their required input:

Districts (district)

This subpackage allows the seats allocation through multiple hierarchical districts.

Collections

Collections map functions to string identifiers. Additionally, new custom functions can be registered as the user needs.

Bibliography

[Gallagher:1992] (1,2,3,4,5,6,7,8,9,10,11,12)

Gallagher, M. (1992). Comparing proportional representation electoral systems: Quotas, thresholds, paradoxes and majorities. British Journal of Political Science, 22(4), 469–496.

@article{Gallagher:1992,
    author = {Gallagher, Michael},
    journal = {British Journal of Political Science},
    number = {4},
    pages = {469--496},
    publisher = {Cambridge University Press},
    title = {{Comparing proportional representation electoral systems: Quotas, thresholds,
              paradoxes and majorities}},
    volume = {22},
    year = {1992}
}
[Denmark:2011] (1,2)

Elklit, J., Pade, A. B., & Miller, N. N. (Eds.). (2011). The Parliamentary Electoral System in Denmark. Guide to the Danish electoral system [Techreport]. Ministry of the Interior.

@techreport{ElklitPadeMiller:2011,
    editor = {Elklit, J{\o}rgen and Pade, Anne Birte and Miller, Nicoline Nyholm},
    institution = {Ministry of the Interior and Health and The Danish Parliament},
    isbn = {978-87-7982-116-3},
    title = {{The Parliamentary Electoral System in Denmark.
              Guide to the Danish electoral system}},
    year = {2011}
}
[Norway:2023] (1,2)

Lov om valg til Stortinget, fylkesting og kommunestyrer (valgloven). (2023). [Techreport].

@techreport{lovdata2023,
    address = {https://lovdata.no/dokument/NL/lov/2023-06-16-62},
    title = {{Lov om valg til Stortinget, fylkesting og kommunestyrer (valgloven)}},
    year = {2023}
}
[KohlerZeh:2012] (1,2,3)

Kohler, U., & Zeh, J. (2012). Apportionment methods. The Stata Journal, 12(3), 375–392.

@article{KohlerZeh:2012,
    author = {Kohler, Ulrich and Zeh, Janina},
    journal = {The Stata Journal},
    number = {3},
    pages = {375--392},
    publisher = {SAGE Publications Sage CA: Los Angeles, CA},
    title = {{Apportionment methods}},
    volume = {12},
    year = {2012}
}
[Reitzig:2014] (1,2,3,4,5,6,7)

Reitzig, R., & Wild, S. (2015). A practical and worst-case efficient algorithm for divisor methods of apportionment. ArXiv Preprint ArXiv:1504.06475.

@article{ReitzigWild:2015,
    author = {Reitzig, Raphael and Wild, Sebastian},
    journal = {arXiv preprint arXiv:1504.06475},
    title = {{A practical and worst-case efficient algorithm for divisor methods of
              apportionment}},
    year = {2015}
}
[DorfleitnerKlein:1997] (1,2,3)

Dorfleitner, Gregor and Klein, Thomas (1997). Rounding with multiplier methods: An efficient algorithm and applications in statistics. Statistical Papers 40, 143-157 (1999)

@article{DorfleitnerKlein:1999,
    author = {Dorfleitner, Gregor and Klein, Thomas},
    journal = {Statistical Papers},
    pages = {143--157},
    publisher = {Springer},
    title = {{Rounding with multiplier methods: An efficient algorithm and applications in
              statistics}},
    volume = {40},
    year = {1999}
}
[Zachariasen:2006] (1,2)

Zachariasen, Martin (2006). Algorithmic Aspects of Divisor-Based Biproportional Rounding. ISSN 0107-8283

@article{Zachariasen:2006,
    author = {Zachariasen, Martin},
    journal = {Typescript, April},
    title = {{Algorithmic aspects of divisor-based biproportional rounding}},
    year = {2006}
}
[Loreg:1985]

Ley Orgánica 5/1985, de 19 de junio, del Régimen Electoral General. (No. 147; Boletı́n Oficial Del Estado). (1985). Jefatura del Estado (España).

@techreport{Loreg:1985,
    month = jun,
    number = {147},
    publisher = {Jefatura del Estado (Espa{\~n}a)},
    series = {{Bolet{\'\i}n Oficial del Estado}},
    title = {{Ley Org{\'a}nica 5/1985, de 19 de junio, del R{\'e}gimen Electoral General.}},
    year = {1985}
}
[Schulze:2011]

Schulze, M. (2011). A new monotonic, clone-independent, reversal symmetric, and condorcet-consistent single-winner election method. Social Choice and Welfare, 36(2), 267–303. http://dblp.uni-trier.de/db/journals/scw/scw36.html#Schulze11;%20http://dx.doi.org/10.1007/s00355-010-0475-4;%20https://www.bibsonomy.org/bibtex/2bf639adac1ce14c4a937a7b13ee640ba/dblp

@article{journals/scw/Schulze11,
    author = {Schulze, Markus},
    journal = {Social Choice and Welfare},
    number = 2,
    pages = {267--303},
    timestamp = {2012-03-27T11:34:04.000+0200},
    title = {{A new monotonic, clone-independent, reversal symmetric, and condorcet-consistent
              single-winner election method.}},
    url = {http://dblp.uni-trier.de/db/journals/scw/scw36.html#Schulze11;
           http://dx.doi.org/10.1007/s00355-010-0475-4; https://www.bibsonomy.org/bibtex/2bf639adac1ce14c4a937a7b13ee640ba/dblp},
    volume = 36,
    year = 2011
}
[EireSTV]

A Guide to Ireland’s PR-STV Voting System. (n.d.). Department of Housing, Planning & Local Government. Rialtas na hÉireann.

@booklet{STVEire,
    address = {https://assets.gov.ie/111110/03f591cc-6312-4b21-8193-d4150169480e.pdf},
    institution = {Department of Housing, Planning \& Local Government.
                   Rialtas na h{\'E}ireann},
    title = {{A Guide to Ireland{\rq}s PR-STV Voting System}}
}
[AusProp]

Proportional Representation Voting Systems of Australia’s Parliaments. (n.d.). Electoral Council of Australia.

@booklet{AusProp,
    address = {https://www.ecanz.gov.au/electoral-systems/proportional},
    institution = {Electoral Council of Australia},
    title = {{Proportional Representation Voting Systems of Australia's Parliaments}}
}
[Miragliotta2002]

Miragliotta, N. (2002). Determining the result: Transferring Surplus Votes in the Western Australian Legislative Council [Techreport]. Western Australian Electoral Commission.

@techreport{Miragliotta2002,
    address = {0-7307-5809-5},
    author = {Miragliotta, Narelle},
    institution = {Western Australian Electoral Commission},
    location = {Perth Western Australia},
    title = {{Determining the result: Transferring Surplus Votes in the Western Australian
              Legislative Council}},
    year = {2002}
}
[Iceland:2013]

Helgason, T. (2013). Apportionment of Seats to Althingi, the Icelandic Parliament: Analysis of the Elections on May 10, 2003, May 12, 2007, April 25, 2009 and April 27, 2013 [Techreport]. The National Electoral Commission of Iceland.

@techreport{Helgason:2013,
    author = {Helgason, Thorkell},
    institution = {The National Electoral Commission of Iceland},
    title = {{Apportionment of Seats to Althingi, the Icelandic Parliament: Analysis of the
              Elections on May 10, 2003, May 12, 2007, April 25, 2009 and April 27, 2013}},
    year = {2013}
}
[Scotland:2024]

Scottish Parliament electoral system (SPICe Fact Sheet). (2024). [Techreport]. Scottish Parliament Information Centre. https://www.parliament.scot/-/media/files/spice/factsheets/parliamentary-business/scottish-parliament-electoral-system-12-may-2021.pdf

@techreport{Scotland:2024,
    publisher = {Scottish Parliament Information Centre},
    series = {{SPICe Fact Sheet}},
    title = {{Scottish Parliament electoral system}},
    url = {https://www.parliament.scot/-/media/files/spice/factsheets/parliamentary-business/scottish-parliament-electoral-system-12-may-2021.pdf},
    year = {2024}
}
[Germany:2025]

Wahl zum 21. Deutschen Bundestag am 23. Februar 2025. (2025). [Techreport]. Die Bundeswahlleiterin. https://www.bundeswahlleiterin.de/dam/jcr/5316c01c-8a1e-44d0-8075-eab495f466b6/btw25_heft3.pdf

@techreport{bundeswahlleiterin2025,
    publisher = {Die Bundeswahlleiterin},
    title = {{Wahl zum 21. Deutschen Bundestag am 23. Februar 2025}},
    url = {https://www.bundeswahlleiterin.de/dam/jcr/5316c01c-8a1e-44d0-8075-eab495f466b6/btw25_heft3.pdf},
    year = {2025}
}
[Pukelsheim:2013]

Pukelsheim, F., & others. (2013). The ABC of Apportionment Numeracy: The Augsburg Bazi Pseudo-Code [Version 2013.07]. Bazi Team.

@misc{Pukelsheim:2013,
    author = {Pukelsheim, Friedrich and others},
    institution = {Universit{\"a}t Augsburg},
    organization = {Bazi Team},
    title = {{The ABC of Apportionment Numeracy: The Augsburg Bazi Pseudo-Code
              [Version 2013.07]}},
    year = {2013}
}
[Oelbermann:2016]

Oelbermann, K.-F. (2016). Alternate Scaling algorithm for biproportional divisor methods. Math. Soc. Sci., 80, 25–32. http://dblp.uni-trier.de/db/journals/mss/mss80.html#Oelbermann16;%20https://doi.org/10.1016/j.mathsocsci.2016.02.003;%20https://www.bibsonomy.org/bibtex/25eedf3fe678e4d47cdd9ef6eaf52809c/dblp

@article{journals/mss/Oelbermann16,
    address = {http://dblp.uni-trier.de/db/journals/mss/mss80.html\#Oelbermann16},
    author = {Oelbermann, Kai-Friederike},
    journal = {Math. Soc. Sci.},
    pages = {25--32},
    timestamp = {2020-02-25T13:14:02.000+0100},
    title = {{Alternate Scaling algorithm for biproportional divisor methods}},
    url = {http://dblp.uni-trier.de/db/journals/mss/mss80.html#Oelbermann16;
           https://doi.org/10.1016/j.mathsocsci.2016.02.003; https://www.bibsonomy.org/bibtex/25eedf3fe678e4d47cdd9ef6eaf52809c/dblp},
    volume = 80,
    year = 2016
}

Subpackages

Submodules

interregnum.bisect module

Quota bisection process.

class interregnum.bisect.QuotaBisect(quota, votes, seats, step=1)

Bases: object

Find the best quota using binary search.

Start with a quota calculated for votes and seats.

step defines the quota increment at each step.

Parameters:
  • quota (int | Fraction) – initial quota

  • votes (int | Fraction) – number of votes

  • seats (int) – number of seats

  • step (int | Fraction) – move the quota by using this step

bad()

Mark current quota as a bad quota.

A bad quota will allocate more seats than the allowed amount.

Return type:

None

good()

Mark current quota as a good quota.

A good quota will allocate the allowed amount or seats, or less.

Return type:

None

guess()

Get current tentative quota.

Return type:

int | Fraction

has_more()

Return True if there are values yet to explore.

Return type:

bool

interregnum.collections module

Function collections.

class interregnum.collections.AnyCallable

Any type for callables

alias of TypeVar(‘AnyCallable’, bound=Callable[[…], Any])

class interregnum.collections.FunctionCollection(transform_f=None)

Bases: Generic[AnyCallable]

Collection of named functions.

It allows to register or retrieve function by names.

A registered function can have more than one associated name.

Create a collection.

Parameters:

transform_f (Callable[[str], str] | None)

__contains__(key)

Return True if key is in this collection.

Parameters:

key (str)

Return type:

bool

__getitem__(key)

Get a function identified by some key.

Parameters:

key (str)

Return type:

AnyCallable

add(key, item)

Add a new function identified by key.

Parameters:
Return type:

None

get(key_or_function)

Get a function associated to a key.

If a function is provided, return the same function

Parameters:

key_or_function (str | AnyCallable)

Return type:

AnyCallable

register(*keys)

Register a new function identified by the given keys.

Decorator for adding functions to the collection.

Parameters:

keys (str)

Return type:

Callable[[Callable[[~_Args], _Ret]], Callable[[~_Args], _Ret]]

interregnum.collections.key_normalizer(key)

Transform a key to a canonical form.

Parameters:

key (str)

Return type:

str

interregnum.dfs module

Depth First Search.

exception interregnum.dfs.CycleDetectedError

Bases: Exception

Raised when a depth first search has found a cycle.

Depth first search algorithm for acyclic directed graphs.

Parameters:
  • edges (Callable[[_Node], Iterator[_Node]]) – function that returns all reachable nodes from one node.

  • action (Callable[[_Node], Any]) – action to perform for a node

  • root (_Node) – node where the search begins

Raises:

CycleDetectedError – when a cycle is found

Return type:

None

interregnum.divisors module

Divisors for Highest-Averages method.

References


class interregnum.divisors.AdamsDivisorIterator

Bases: DivisorIterator[int]

Iterator for the Adams divisor.

divisor_iterators collection keys:

  • adams

Create an Adams divisor iterator.

class interregnum.divisors.BelgianImperialiDivisorIterator

Bases: DivisorIterator[Fraction]

Iterator for the Imperiali divisor.

divisor_iterators collection keys:

  • imperiali

Create a Belgian Imperiali divisor iterator.

class interregnum.divisors.DanishDivisorIterator

Bases: DivisorIterator[int]

Iterator for Danish divisor.

divisor_iterators collection keys:

  • danish

Create a Danish divisor iterator.

class interregnum.divisors.DhondtDivisorIterator

Bases: DivisorIterator[int]

Iterator for the d’Hondt divisor.

divisor_iterators collection keys:

  • dhondt

  • d’hondt

  • jefferson

Create a D’Hondt divisor iterator.

class interregnum.divisors.DivisorIterator(divisor_f)

Bases: Generic[_Divisor]

A wrapper for a divisor sequence iterator.

Create this iterator from divisor_f.

Parameters:

divisor_f (Callable[[int], _Divisor])

__call__(seats, *args, **kwargs)

Return a divisor iterator.

Parameters:
  • seats (int)

  • args (Any)

  • kwargs (Any)

Return type:

Iterator[_Divisor]

divisor(seats=0)

Return a divisor after seats have been assigned to candidate.

Raises:

PreconditionError – When seats is less than 0.

Parameters:

seats (int)

Return type:

_Divisor

sequence(seats=0)

Return a divisor iterator starting from seats.

Raises:

PreconditionError – When seats is less than 0.

Parameters:

seats (int)

Return type:

Iterator[_Divisor]

class interregnum.divisors.ImperialiDivisorIterator

Bases: DivisorIterator[int]

Iterator for the Imperiali divisor.

divisor_iterators collection keys:

  • imperiali

Create an Imperiali divisor iterator.

class interregnum.divisors.SainteLague14DivisorIterator

Bases: DivisorIterator[int | Fraction]

Iterator for the Sainte-Laguë 1.4 divisor.

divisor_iterators collection keys:

  • sainte_lague_1.4

  • sainte-lague-1.4

  • sainte_laguë_1.4

  • sainte-laguë-1.4

Create a Sainte-Laguë divisor iterator with 1.4 as first divisor.

class interregnum.divisors.SainteLagueDivisorIterator

Bases: DivisorIterator[int]

Iterator for the Sainte-Laguë divisor.

divisor_iterators collection keys:

  • sainte_lague

  • sainte-lague

  • sainte_laguë

  • sainte-laguë

  • webster

Create a Sainte-Laguë divisor iterator.

interregnum.divisors.adams_divisor(seats)

Adams divisor / Smallest divisors.

\(d(seats) = seats\)

Sequence: 0, 1, 2, 3, 4, … for \(seats \in \{0, 1, 2, 3, 4, \dots\}\)

See [Gallagher:1992]

divisors collection keys:

  • adams

  • smallest-divisors

  • smallest_divisors

Parameters:

seats (int)

Return type:

int

interregnum.divisors.belgian_imperiali_divisor(seats)

Belgian Imperiali divisor.

\(d(seats) = \frac{seats + 1}{2}\)

Sequence: 1, 1.5, 2, 2.5, … for \(seats \in \{0, 1, 2, 3, \dots\}\)

See [Gallagher:1992]

Parameters:

seats (int) – assigned seats

Returns:

divisor for the next unassigned seat

Return type:

Fraction

divisors collection keys:

  • belgian-imperiali

  • belgian_imperiali

interregnum.divisors.danish_divisor(seats)

Danish divisor.

\(d(seats) = 3 seats + 1\)

Sequence: 1, 4, 7, 10, 13, … for \(seats \in \{0, 1, 2, 3, \dots\}\)

See [Denmark:2011], [Gallagher:1992] and [Reitzig:2014]

Parameters:

seats (int) – assigned seats

Returns:

divisor for the next unassigned seat

Return type:

int

divisors collection keys:

  • danish

interregnum.divisors.dean_divisor(seats)

Dean divisor.

\(d(seats) = \frac{2 seats (seats + 1)}{2 seats + 1}\)

See [KohlerZeh:2012] and [Reitzig:2014]

Parameters:

seats (int) – assigned seats

Returns:

divisor for the next unassigned seat

Return type:

Fraction

divisors collection keys:

  • dean

  • harmonic-mean

  • harmonic_mean

interregnum.divisors.dhondt_divisor(seats)

D’Hondt / Jefferson divisor / Greatest divisors.

\(d(seats) = seats + 1\)

Sequence: 1, 2, 3, 4, … for \(seats \in \{0, 1, 2, 3, \dots\}\)

See [Gallagher:1992] and [Reitzig:2014]

Parameters:

seats (int) – assigned seats

Returns:

divisor for the next unassigned seat

Return type:

int

divisors collection keys:

  • dhondt

  • d’hondt

  • jefferson

  • greatest_divisors

  • greatest-divisors

interregnum.divisors.huntington_hill_1_divisor(seats)

Huntington-Hill + 1 / Equal proportions + 1.

This version starts at 1.414.

\(d(seats) = \sqrt{(seats + 1) (seats + 2)}\)

Sequence: 1.414, 2.449, 3.464, 4.472, … for \(seats \in \{0, 1, 2, 3, \dots\}\)

Parameters:

seats (int) – assigned seats

Returns:

divisor for the next unassigned seat

Return type:

float

divisors collection keys:

  • huntington_hill1

  • huntington-hill1

interregnum.divisors.huntington_hill_divisor(seats)

Huntington-Hill / Equal proportions.

\(d(seats) = \sqrt{seats (seats + 1)}\)

Sequence: 0, 1.414, 2.449, 3.464, 4.472, … for \(seats \in \{0, 1, 2, 3, 4, \dots\}\)

See [KohlerZeh:2012], [Gallagher:1992] and [Reitzig:2014]

Parameters:

seats (int) – assigned seats

Returns:

divisor for the next unassigned seat

Return type:

float

divisors collection keys:

  • huntington_hill

  • huntington-hill

  • equal-proportions

  • equal_proportions

interregnum.divisors.imperiali_divisor(seats)

Imperiali divisor.

\(d(seats) = seats + 2\)

Sequence: 2, 3, 4, 5, … for \(seats \in \{0, 1, 2, 3, \dots\}\)

See [Reitzig:2014]

Parameters:

seats (int) – assigned seats

Returns:

divisor for the next unassigned seat

Return type:

int

divisors collection keys:

  • imperiali

interregnum.divisors.modified_sainte_lague_divisor(seats)

Return a modified Sainte-Laguë divisor.

\(d(0) = 1\)

\(d(seats) = \frac{10(seats + 1) - 5}{7}\) for \(seats > 0\)

Sequence: 1, 2.14, 3.57, 5, 6.43 for \(seats \in \{0, 1, 2, 3, 4, \dots\}\)

See [Gallagher:1992]

divisors collection keys:

  • modified-sainte-laguë

  • modified_sainte_laguë

  • modified-sainte-lague

  • modified_sainte_lague

Parameters:

seats (int)

Return type:

Fraction

interregnum.divisors.sainte_lague_14_divisor(seats)

Sainte-Laguë divisor with 1.4 for the first seat.

\(d(0) = 1.4\)

\(d(seats) = 2 seats + 1\) for \(seats > 0\)

Sequence: 1.4, 3, 5, 7, … for \(seats \in \{0, 1, 2, 3, \dots\}\)

See [Norway:2023] and [Reitzig:2014]

Parameters:

seats (int) – assigned seats

Returns:

divisor for the next unassigned seat

Return type:

int | Fraction

divisors collection keys:

  • sainte_lague_1.4

  • sainte-lague-1.4

  • sainte_laguë_1.4

  • sainte-laguë-1.4

interregnum.divisors.sainte_lague_divisor(seats)

Sainte-Laguë / Webster divisor.

\(d(seats) = 2 seats + 1\)

Sequence: 1, 3, 5, 7, … for \(seats \in \{0, 1, 2, 3, \dots\}\)

See [Gallagher:1992]

Parameters:

seats (int) – assigned seats

Returns:

divisor for the next unassigned seat

Return type:

int

divisors collection keys:

  • sainte_lague

  • sainte-lague

  • sainte_laguë

  • sainte-laguë

  • webster

interregnum.divisors.CallDivisorIterator

A function that returns a divisor iterator

alias of Callable[[], DivisorIterator[int | float | Fraction]]

interregnum.divisors.Divisor

Allowed types for divisors

alias of int | float | Fraction

interregnum.divisors.DivisorFunction

Functions that return a divisor for a number of seats

alias of Callable[[int], int | float | Fraction]

interregnum.divisors.divisor_iterators: FunctionCollection[Callable[[], DivisorIterator[int | float | Fraction]]] = <interregnum.collections.FunctionCollection object>

Collection of divisor iterators

interregnum.divisors.divisors: FunctionCollection[Callable[[int], int | float | Fraction]] = <interregnum.collections.FunctionCollection object>

Collection of divisor functions

interregnum.exceptions module

Custom exception.

exception interregnum.exceptions.PreconditionError

Bases: Exception

Raised when an operation can not be computed for not meeting all the pre-conditions.

exception interregnum.exceptions.PreconditionWarning

Bases: UserWarning

Emitted when a pre-condition failed by the process continues.

exception interregnum.exceptions.UnsolvableError

Bases: Exception

Raised when an allocator can’t resolve the allocation.

interregnum.graphs module

Weighted and unweighted directed graphs.

class interregnum.graphs.UnweightedGraph(nodes=None, *, loops=False)

Bases: Generic[_Key]

Unweighted directed graph.

Create a graph with this set of nodes.

If loops is False, trying to create a loop will raise a ValueError exception.

Parameters:
  • nodes (Iterable[_Key] | None)

  • loops (bool)

__contains__(idx)

Return True if the edge idx is in this graph.

Parameters:

idx (tuple[_Key, _Key])

Return type:

bool

__getitem__(idx)

Return True if there is an edge from idx[0] to idx[1].

Parameters:

idx (tuple[_Key, _Key])

Return type:

bool

__str__()

Return printable().

Return type:

str

all_nodes()

Set of all known nodes.

Return type:

frozenset[_Key]

connect(tail, head)

Set an arc from tail to head.

Parameters:
  • tail (_Key)

  • head (_Key)

Return type:

None

existing_nodes()

Return the subset of nodes with arcs.

Return type:

frozenset[_Key]

heads()

Return nodes in the heads set.

Return type:

Iterator[_Key]

heads_for(tail)

Iterate heads for connections given a ‘tail’.

Parameters:

tail (_Key)

Return type:

Iterator[_Key]

printable(all_nodes=None)

Return a printable representation.

Parameters:

all_nodes (Iterable[_Key] | None)

Return type:

str

reachable(node_x, node_y, closure=False)

Return True if there is a path from node_x to node_y.

If closure is True, transitive arcs are created. That is, if a path is discovered from node_x to m, and a path is discovered from m to node_y, a new arc (node_x, node_y) is created.

Parameters:
  • node_x (_Key)

  • node_y (_Key)

  • closure (bool)

Return type:

bool

sinks()

Return set of sink keys.

>>> t = PairwiseTable()
>>> t.connect('Alice', 'Bob')
>>> t.connect('Bob', 'Alice')
>>> t.connect('Bob', 'Charles')
>>> t.connect('Alex', 'Zoe')
>>> # ['Charles', 'Zoe']
>>> t.sink()
Return type:

frozenset[_Key]

sources()

Return set of source keys.

>>> t = PairwiseTable()
>>> t.connect('Alice', 'Bob')
>>> t.connect('Bob', 'Alice')
>>> t.connect('Bob', 'Charles')
>>> t.connect('Alex', 'Zoe')
>>> # ['Alex']
>>> t.source()
Return type:

frozenset[_Key]

tails()

Return nodes in the tails set.

Return type:

KeysView[_Key]

transitive_closure(all_nodes=None)

Compute in-site the transitive closure of this graph.

Parameters:

all_nodes (Iterable[_Key] | None)

Return type:

None

class interregnum.graphs.WeightedGraph(nodes, default)

Bases: SparseTable[_Key, _Key, AnyValue], Generic[_Key, AnyValue]

A weighted directed graph.

Create a graph with this set of nodes and use a default weight for edges.

Parameters:
  • nodes (Iterable[_Key])

  • default (AnyValue)

__str__()

Return str(self).

Return type:

str

keys()

Return node set.

Return type:

Iterator[_Key]

printable(all_nodes=None)

Return a printable representation.

Parameters:

all_nodes (Iterable[_Key] | None)

Return type:

str

reachable(cand_from, cand_to)

Return True if cand_to is reachable from cand_from.

>>> t = PairwiseTable(["Alice", "Alex", "Bob", "Charles", "Zoe"], 0)
>>> t['Alice', 'Bob'] = 5
>>> t['Bob', 'Alice'] = 7
>>> t['Bob', 'Charles'] = 3
>>> t['Alex', 'Zoe'] = 1
>>> # True
>>> t.reachable('Alice', 'Charles')
>>> # False
>>> t.reachable('Alice', 'Zoe')
Parameters:
  • cand_from (_Key)

  • cand_to (_Key)

Return type:

bool

sink()

Return set of sink nodes.

>>> t = PairwiseTable(["Alice", "Alex", "Bob", "Charles", "Zoe"], 0)
>>> t['Alice', 'Bob'] = 5
>>> t['Bob', 'Alice'] = 7
>>> t['Bob', 'Charles'] = 3
>>> t['Alex', 'Zoe'] = 1
>>> # ['Charles', 'Zoe']
>>> t.sink()
Return type:

frozenset[_Key]

source()

Return set of source nodes.

>>> t = PairwiseTable(["Alice", "Alex", "Bob", "Charles", "Zoe"], 0)
>>> t['Alice', 'Bob'] = 5
>>> t['Bob', 'Alice'] = 7
>>> t['Bob', 'Charles'] = 3
>>> t['Alex', 'Zoe'] = 1
>>> # ['Alex']
>>> t.source()
Return type:

frozenset[_Key]

interregnum.logging module

Package common logger.

interregnum.logging.logger = <Logger interregnum (WARNING)>

Default logger object

interregnum.quotas module

Utils for the calculation of votes/seats quotas.

References


class interregnum.quotas.Comparison(operator, reference)

Bases: object

An inequality operator and a reference value.

<operator> reference

Parameters:
  • operator (Inequality)

  • reference (int | Fraction)

__contains__(value)

Return True if value evaluates to True.

Parameters:

value (int | Fraction | float)

Return type:

bool

reached(value)

Return True if ‘value’ <op> <reference>.

Parameters:

value (int | Fraction | float)

Return type:

bool

operator: Inequality

An inequality operator

reference: int | Fraction

A reference value (right side of the operator)

class interregnum.quotas.Inequality(*values)

Bases: Enum

Represents an (in)equality relation.

classmethod parse(text)

Parse inequality from string.

Raises:

ValueError – When text could not be parsed.

Parameters:

text (str)

Return type:

Inequality

__call__(first, second)

Evaluate this inequality: first <op> second.

Parameters:
  • first (int | Fraction | float)

  • second (int | Fraction | float)

Return type:

bool

__invert__()

Negate this inequality.

Return type:

Inequality

__str__()

Human representation for the operator.

Return type:

str

check(first, second)

Check if first <self> second.

Parameters:
  • first (int | Fraction | float)

  • second (int | Fraction | float)

Return type:

bool

negate()

Return the negated inequality.

Return type:

Inequality

EQ = 1

(\(=\)) equal

FALSE = 8

Always False

GE = 5

(\(\geq\)) greater or equal

GT = 4

(\(>\)) greater than

LE = 3

(\(\leq\)) less or equal

LT = 2

(\(<\)) less than

NE = 6

(\(\neq\)) not equal

TRUE = 7

Always True

interregnum.quotas.Quota

A quota comparator

class interregnum.quotas.QuotaResolver(strategy='midpoint', nice_quota=True)

Bases: object

Find a representative for a quota range.

Create a resolve using a strategy.

If nice_quota is True, find a value with the least number of digits as possible.

Parameters:
static nice(quota, min_quota, max_quota)

Try to get a nice quota number.

Parameters:
  • quota (int | Fraction | float)

  • min_quota (int | Fraction | float)

  • max_quota (int | Fraction | float)

Return type:

int | Fraction | float

find(min_quota, max_quota, status)

Get a quota using the resolver strategy.

Parameters:
  • min_quota (int | Fraction | float)

  • max_quota (int | Fraction | float)

  • status (QuotaStatus)

Return type:

int | Fraction | float

quota_extreme(min_quota, max_quota, status)

Get a quota at the range boundary.

Parameters:
  • min_quota (int | Fraction | float)

  • max_quota (int | Fraction | float)

  • status (QuotaStatus)

Return type:

int | Fraction | float

quota_midpoint(min_quota, max_quota)

Get a quota in the middle of the range.

Parameters:
  • min_quota (int | Fraction | float)

  • max_quota (int | Fraction | float)

Return type:

int | Fraction | float

class interregnum.quotas.QuotaResolverType(*values)

Bases: Enum

Type of quota resolver.

classmethod parse(key)

Parse enum from a string.

Parameters:

key (str)

Return type:

QuotaResolverType

EXTREME = 1

find a quota at the range boundary

MIDPOINT = 2

find a quota in the middle of the range

class interregnum.quotas.QuotaStatus(*values)

Bases: Enum

Validity status for a quota.

EXACT = 2
OVER = 1
UNDER = 3
interregnum.quotas.droop_quota(votes, seats)

Droop quota.

\(q=[\geq]1 + \lfloor \frac{votes}{seats + 1} \rfloor\)

See [Gallagher:1992]

Collection keys:

  • droop

Parameters:
  • votes (int | Fraction)

  • seats (int | Fraction)

Return type:

Comparison

interregnum.quotas.hagenbach_bischoff_quota(votes, seats)

Hagenbach Bischoff quota (Droop fractional).

\(q=[>]\frac{votes}{seats + 1}\)

Collection keys:

  • hagenbach_bischoff

  • hagenbach-bischoff

  • droop_fractional

Parameters:
  • votes (int | Fraction)

  • seats (int | Fraction)

Return type:

Comparison

interregnum.quotas.hare_quota(votes, seats)

Hare quota comparison.

\(q=[>]\frac{votes}{seats}\)

See [Gallagher:1992]

Collection keys:

  • hare

Parameters:
  • votes (int | Fraction)

  • seats (int | Fraction)

Return type:

Comparison

interregnum.quotas.imperiali_3_quota(votes, seats)

Reinforced Imperiali quota.

\(q=[>]\frac{votes}{seats + 3}\)

Collection keys:

  • imperiali3

  • imperiali_3

Parameters:
  • votes (int | Fraction)

  • seats (int | Fraction)

Return type:

Comparison

interregnum.quotas.imperiali_quota(votes, seats)

Imperali quota.

\(q=[>]\frac{votes}{seats + 2}\)

See [Gallagher:1992]

Collection keys:

  • imperiali

Parameters:
  • votes (int | Fraction)

  • seats (int | Fraction)

Return type:

Comparison

interregnum.quotas.infinity(_votes, _seats)

Return a contradiction, impossible to satisfy.

(for testing)

Collection keys:

  • infinity

Parameters:
  • _votes (int | Fraction)

  • _seats (int | Fraction)

Return type:

Comparison

interregnum.quotas.majority_quota(votes, *_args)

Absolute Majority quota.

\(q=[>]\frac{votes}{2}\)

Collection keys:

  • majority

Parameters:
  • votes (int | Fraction)

  • _args (Any)

Return type:

Comparison

interregnum.quotas.proportional_quota(pct, votes, *_args)

Proportional quota.

pct

a percent value (N%)

\(q = votes\frac{pct}{100}\)

Parameters:
  • pct (int | Fraction)

  • votes (int | Fraction)

  • _args (Any)

Return type:

Fraction

interregnum.quotas.QuotaFunction

A function that returns a quota comparator

alias of Callable[[int | Fraction, int | Fraction], Comparison]

interregnum.quotas.quotas: FunctionCollection[Callable[[int | Fraction, int | Fraction], Comparison]] = <interregnum.collections.FunctionCollection object>

Collection for quota comparators

interregnum.random module

Utils for random numbers operations.

class interregnum.random.Dice(rng=None)

Bases: object

Wrapper for a random number generator.

It keeps a usage counter.

Create a dice from rng.

Parameters:

rng (RandomSeed | None) – A random seed. When None, a random number generator with a randomly chosen seed is used.

__call__()

Increment the randomg generator usage and return it.

Return type:

Random

state()

Return a serializable state.

Return type:

dict[str, Any]

property deterministic: bool

Return True if the dice has not been used.

interregnum.random.RandomSeed

Type for random generators’ seeds

alias of int | Random

interregnum.ranks module

Functions for ranked ballots.

interregnum.ranks.rank_n(ballot_size, pos)

Borda ranking.

\(rank(ballotsize, pos) = ballotsize - pos\)

>>> [rank_n(10, n) for n in range(10)]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Parameters:
  • ballot_size (int)

  • pos (int)

Return type:

int

interregnum.ranks.rank_n_1(ballot_size, pos)

Tournament ranking.

\(rank(ballotsize, pos) = ballotsize - pos - 1\)

>>> [rank_n_1(10, n) for n in range(10)]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Parameters:
  • ballot_size (int)

  • pos (int)

Return type:

int

interregnum.ranks.rank_nauru(_ballot_size, pos)

Dowdall ranking, used in Nauru’s electoral system.

\(rank(ballotsize, pos) = \frac{1}{pos + 1}\)

>>> [float(rank_nauru(10, n)) for n in range(10)]
[1.0, 0.5, 0.3333333333333333, 0.25, 0.2, 0.16666666666666666,
    0.14285714285714285, 0.125, 0.1111111111111111, 0.1]
Parameters:
  • _ballot_size (int)

  • pos (int)

Return type:

Fraction

interregnum.ranks.RankFunction

A function for ranking. Return a score from a position and a ballot size

alias of Callable[[int, int], int | Fraction]

interregnum.ranks.ranks: FunctionCollection[Callable[[int, int], int | Fraction]] = <interregnum.collections.FunctionCollection object>

Collection for ranking functions.

interregnum.rounding module

Rounding and signpost sequence functions.

References


class interregnum.rounding.ArithmeticMeanRoundingFunction(q)

Bases: RoundingWithSignpost

Arithmetic-mean rounding methods.

See [DorfleitnerKlein:1997]:

\[s^{(q)}_k = (1-q)k+q(k+1) = k+q\]

for \(q \in [0, 1]\) and \(k \in \mathbb{N}_0\).

Parameters:

q (Fraction)

__call__(x)

Convert x into a rounded integer value.

Parameters:

x (int | Fraction)

Return type:

int

signpost(k)

Bounded signpost sequence \(s_k\).

\(s_k = 0\) for \(k \leq 0\)

Parameters:

k (int)

Return type:

int | Fraction

unbounded_signpost(k)

Unbounded signpost sequence \(s_k\).

Parameters:

k (int)

Return type:

int | Fraction

class interregnum.rounding.RoundingWithSignpost

Bases: object

Rounding function with associated signpost sequence.

See [DorfleitnerKlein:1997] and [Zachariasen:2006]:

Rounding function: \(R(x)=k\) for \(x \in [s_{k-1}, s_k)\) and \(k \in \mathbb{N}_0\) and a signpost sequence \(s_k \in [k, k+1]\).

__call__(x)

Convert x into a rounded integer value.

Parameters:

x (int | Fraction)

Return type:

int

decrementation(k, w)

Decrementation criterion.

\[D(k, w) \rightarrow \frac{s_{k-1}}{w}\]
Parameters:
  • k (int)

  • w (int | Fraction)

Return type:

int | Fraction | None

incrementation(k, w)

Incrementation criterion.

\[I(k, w) \rightarrow \frac{s_k}{w}\]
Parameters:
  • k (int)

  • w (int | Fraction)

Return type:

int | Fraction | None

signpost(k)

Bounded signpost sequence \(s_k\).

\(s_k = 0\) for \(k \leq 0\)

Parameters:

k (int)

Return type:

int | Fraction

unbounded_signpost(k)

Unbounded signpost sequence \(s_k\).

Parameters:

k (int)

Return type:

int | Fraction

interregnum.rounding.as_fraction(numerator, denominator)

Convert numerator and denominator into a fraction.

Division by zero will return Infinity (FRAC_INFTY)

Parameters:
  • numerator (int | Fraction)

  • denominator (int | Fraction)

Return type:

int | Fraction | None

interregnum.rounding.is_finite(x)

Return True if x is finite.

Parameters:

x (int | Fraction | None)

Return type:

TypeIs[int | Fraction]

interregnum.rounding.noop(score)

Return the same score.

Parameters:

score (int | Fraction)

Return type:

int | Fraction

interregnum.rounding.FRAC_INFTY: Final[Literal[None]] = None

Infinity value for Fraction represented as None

interregnum.rounding.FRAC_ZERO: Final[Fraction] = Fraction(0, 1)

Zero value as Fraction.

interregnum.rounding.RoundingFunction

Any function that makes a rounding operation.

alias of Callable[[int | Fraction], int | Fraction]

interregnum.rounding.ScoreWithInf = int | fractions.Fraction | None

A score with infinity values

interregnum.rounding.roundings: FunctionCollection[Callable[[int | Fraction], int | Fraction]] = <interregnum.collections.FunctionCollection object>

Collection of rounding functions.

interregnum.rounding.signposts: FunctionCollection[RoundingWithSignpost] = <interregnum.collections.FunctionCollection object>

Collection for rounding functions with signposts

interregnum.tabulate module

Utils for showing tabulated data.

interregnum.tabulate.tabulate(rows, colsep=' ', rowsep='\n', headersep=None)

Return a displayable representation of bidimensional data.

Useful for debugging.

Parameters:
  • rows (Sequence[Sequence[str]]) – bidimensional data

  • colsep (str) – columns separator

  • rowsep (str) – rows separator

  • headersep (str | None) – if this separator exists, will be printed after the first row.

Return type:

str

interregnum.types module

General types.

class interregnum.types.SortHash(*args, **kwargs)

Bases: Hashable, Protocol

Sortable and hashable type.

interregnum.types.as_score(val)

Convert a FScore to a Score.

Parameters:

val (int | Fraction | float)

Return type:

int | Fraction

interregnum.types.division(num: int | Fraction, den: int | Fraction) int | Fraction
interregnum.types.division(num: float, den: int | Fraction | float) int | float
interregnum.types.division(num: int | Fraction | float, den: float) int | float

Make a fraction or a float division.

Parameters:
  • num (int | Fraction | float)

  • den (int | Fraction | float)

Return type:

int | Fraction | float

interregnum.types.enum_from_string(value)

Convert a string to a canonical form for an enum attribute name.

Parameters:

value (str)

Return type:

str

interregnum.types.flag_from_string(value, sep)

Convert a string to a canonical form for a flag attribute name.

Parameters:
  • value (str)

  • sep (str)

Return type:

str

interregnum.types.ifnone(value, default)

Return a non optional value from an optional value.

Parameters:
  • value (_T | None)

  • default (_T)

Return type:

_T

interregnum.types.parse_enum(cls, value, canon=True)

Parse an attribute name for a Enum type.

Parameters:
  • cls (Type[_Enum])

  • value (str)

  • canon (bool)

Return type:

_Enum

interregnum.types.parse_flag(cls, text, canon=True, sep='+')

Parse an attribute name for a Flag type.

Parameters:
  • cls (Type[_Flag])

  • text (str)

  • canon (bool)

  • sep (str)

Return type:

_Flag | None

interregnum.types.FScore = int | fractions.Fraction | float

A numerical type for integer, fractional or floating point.

interregnum.types.Score = int | fractions.Fraction

A numerical type without precision loss.