formatting, text

master v0.1
Martin Lackner 2022-02-16 14:58:22 +01:00
rodzic 0a1a742b72
commit 03673bf679
3 zmienionych plików z 71 dodań i 16 usunięć

Wyświetl plik

@ -15,7 +15,7 @@ The following apportionment methods are implemented:
- Adams
* the quota method [1]
This module supports 3.7+.
This module supports Python 3.7+.
## How-to

Wyświetl plik

@ -0,0 +1,20 @@
import apportionment.methods as app
"""
Dominik's remark:
It is actually not without loss of generality to focus just on ties that still appear in the end.
Here is an example: votes = [720, 720, 120, 120], house size h = 8. Then the quota method selects
exactly the following: 3 seats go to each of the big parties, and then choose 1 big party and 1
small party and give those a seat each. This last structure can't be captured by ties just at the
end. (In contrast, for divisor methods, the ties are always of the form "assign necessary seats
(say there are t of them), and then choose an arbitrary subset of size h - t from a specified
set S of parties".)
"""
votes = [720, 720, 120, 120]
seats = 8
print("votes: ", votes)
print(seats, "seats")
result = app.compute("quota", votes, seats, verbose=True)

Wyświetl plik

@ -1,4 +1,6 @@
# Apportionment methods
"""
Apportionment methods
"""
from fractions import Fraction
import math
@ -29,13 +31,15 @@ def compute(
parties=string.ascii_letters,
threshold=None,
tiesallowed=True,
verbose=True
verbose=True,
):
filtered_votes = apply_threshold(votes, threshold)
if method == "quota":
return quota(filtered_votes, seats, fractions, parties, tiesallowed, verbose)
elif method in ["lrm", "hamilton", "largest_remainder"]:
return largest_remainder(filtered_votes, seats, fractions, parties, tiesallowed, verbose)
return largest_remainder(
filtered_votes, seats, fractions, parties, tiesallowed, verbose
)
elif method in [
"dhondt",
"jefferson",
@ -52,7 +56,9 @@ def compute(
"majorfractions",
"greatestdivisors",
]:
return divisor(filtered_votes, seats, method, fractions, parties, tiesallowed, verbose)
return divisor(
filtered_votes, seats, method, fractions, parties, tiesallowed, verbose
)
else:
raise NotImplementedError("apportionment method " + method + " not known")
@ -117,7 +123,12 @@ def within_quota(votes, representatives, parties=string.ascii_letters, verbose=T
# Largest remainder method (Hamilton method)
def largest_remainder(
votes, seats, fractions=False, parties=string.ascii_letters, tiesallowed=True, verbose=True
votes,
seats,
fractions=False,
parties=string.ascii_letters,
tiesallowed=True,
verbose=True,
):
# votes = np.array(votes)
if verbose:
@ -125,7 +136,9 @@ def largest_remainder(
if fractions:
q = Fraction(int(sum(votes)), seats)
quotas = [Fraction(int(p), q) for p in votes]
representatives = np.array([int(qu.numerator // qu.denominator) for qu in quotas])
representatives = np.array(
[int(qu.numerator // qu.denominator) for qu in quotas]
)
else:
votes = np.array(votes)
quotas = (votes * seats) / np.sum(votes)
@ -167,7 +180,13 @@ def largest_remainder(
# Divisor methods
def divisor(
votes, seats, method, fractions=False, parties=string.ascii_letters, tiesallowed=True, verbose=True
votes,
seats,
method,
fractions=False,
parties=string.ascii_letters,
tiesallowed=True,
verbose=True,
):
votes = np.array(votes)
representatives = np.zeros(len(votes), dtype=int)
@ -214,18 +233,25 @@ def divisor(
else:
representatives = np.array([1 if p > 0 else 0 for p in votes])
if fractions:
divisors = np.array([
Fraction(2 * (i + 1) * (i + 2), 2 * (i + 1) + 1) for i in range(seats)
])
divisors = np.array(
[
Fraction(2 * (i + 1) * (i + 2), 2 * (i + 1) + 1)
for i in range(seats)
]
)
else:
divisors = np.arange(seats)
divisors = (2 * (divisors + 1) * (divisors + 2)) / (2 * (divisors + 1) + 1)
divisors = (2 * (divisors + 1) * (divisors + 2)) / (
2 * (divisors + 1) + 1
)
else:
raise NotImplementedError("divisor method " + method + " not known")
# assigning representatives
if seats > np.sum(representatives):
if fractions and method not in ["huntington", "hill", "modified_saintelague"]:
weights = np.array([[Fraction(int(p), d) for d in divisors.tolist()] for p in votes])
weights = np.array(
[[Fraction(int(p), d) for d in divisors.tolist()] for p in votes]
)
flatweights = sorted([w for l in weights for w in l])
else:
weights = np.array([p / divisors for p in votes])
@ -296,7 +322,14 @@ def __divzero_fewerseatsthanparties(votes, seats, parties, tiesallowed, verbose)
return representatives
def quota(votes, seats, fractions=False, parties=string.ascii_letters, tiesallowed=True, verbose=True):
def quota(
votes,
seats,
fractions=False,
parties=string.ascii_letters,
tiesallowed=True,
verbose=True,
):
"""The quota method
see Balinski, M. L., & Young, H. P. (1975).
The quota method of apportionment.
@ -316,8 +349,10 @@ def quota(votes, seats, fractions=False, parties=string.ascii_letters, tiesallow
while np.sum(representatives) < seats:
if fractions:
quotas = [Fraction(int(votes[i]), int(representatives[i]) + 1)
for i in range(len(votes))]
quotas = [
Fraction(int(votes[i]), int(representatives[i]) + 1)
for i in range(len(votes))
]
else:
quotas = votes / (representatives + 1)
# check if upper quota is violated