Refactor/clean up (un)weighted inclusive Gregory handling
This commit is contained in:
parent
f73e2eaa53
commit
5f4d6aa7ca
@ -31,6 +31,8 @@ class BaseSTVCounter:
|
|||||||
def __init__(self, election, options=None):
|
def __init__(self, election, options=None):
|
||||||
self.election = election
|
self.election = election
|
||||||
|
|
||||||
|
self.cls_ballot_value = Num # Need to use Rational in unweighted inclusive Gregory
|
||||||
|
|
||||||
# Default options
|
# Default options
|
||||||
self.options = {
|
self.options = {
|
||||||
'prog_quota': False, # Progressively reducing quota?
|
'prog_quota': False, # Progressively reducing quota?
|
||||||
@ -60,9 +62,35 @@ class BaseSTVCounter:
|
|||||||
"""
|
"""
|
||||||
Public function:
|
Public function:
|
||||||
Reset the count and perform the first step
|
Reset the count and perform the first step
|
||||||
Subclasses must override this function
|
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError('Method not implemented')
|
|
||||||
|
# Distribute first preferences
|
||||||
|
for ballot in self.election.ballots:
|
||||||
|
__pragma__('opov')
|
||||||
|
candidate = next((c for c in ballot.preferences if self.candidates[c].state == CandidateState.HOPEFUL), None)
|
||||||
|
|
||||||
|
if candidate is not None:
|
||||||
|
self.candidates[candidate].transfers += ballot.value
|
||||||
|
self.candidates[candidate].ballots.append((ballot, self.cls_ballot_value(ballot.value)))
|
||||||
|
else:
|
||||||
|
self.exhausted.transfers += ballot.value
|
||||||
|
self.exhausted.ballots.append((ballot, self.cls_ballot_value(ballot.value)))
|
||||||
|
__pragma__('noopov')
|
||||||
|
|
||||||
|
self.quota = None
|
||||||
|
self.compute_quota()
|
||||||
|
self.elect_meeting_quota()
|
||||||
|
|
||||||
|
__pragma__('opov')
|
||||||
|
return CountStepResult(
|
||||||
|
'First preferences',
|
||||||
|
self.candidates,
|
||||||
|
self.exhausted,
|
||||||
|
self.loss_fraction,
|
||||||
|
self.total + self.exhausted.votes + self.loss_fraction.votes,
|
||||||
|
self.quota
|
||||||
|
)
|
||||||
|
__pragma__('noopov')
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
"""
|
"""
|
||||||
@ -295,35 +323,6 @@ class BaseWIGSTVCounter(BaseSTVCounter):
|
|||||||
Basic weighted inclusive Gregory STV counter
|
Basic weighted inclusive Gregory STV counter
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
# Distribute first preferences
|
|
||||||
for ballot in self.election.ballots:
|
|
||||||
__pragma__('opov')
|
|
||||||
candidate = next((c for c in ballot.preferences if self.candidates[c].state == CandidateState.HOPEFUL), None)
|
|
||||||
|
|
||||||
if candidate is not None:
|
|
||||||
self.candidates[candidate].transfers += ballot.value
|
|
||||||
self.candidates[candidate].ballots.append((ballot, ballot.value))
|
|
||||||
else:
|
|
||||||
self.exhausted.transfers += ballot.value
|
|
||||||
self.exhausted.ballots.append((ballot, ballot.value))
|
|
||||||
__pragma__('noopov')
|
|
||||||
|
|
||||||
self.quota = None
|
|
||||||
self.compute_quota()
|
|
||||||
self.elect_meeting_quota()
|
|
||||||
|
|
||||||
__pragma__('opov')
|
|
||||||
return CountStepResult(
|
|
||||||
'First preferences',
|
|
||||||
self.candidates,
|
|
||||||
self.exhausted,
|
|
||||||
self.loss_fraction,
|
|
||||||
self.total + self.exhausted.votes + self.loss_fraction.votes,
|
|
||||||
self.quota
|
|
||||||
)
|
|
||||||
__pragma__('noopov')
|
|
||||||
|
|
||||||
def do_surplus(self, candidate_surplus, count_card, surplus):
|
def do_surplus(self, candidate_surplus, count_card, surplus):
|
||||||
for ballot, ballot_value in count_card.ballots:
|
for ballot, ballot_value in count_card.ballots:
|
||||||
__pragma__('opov')
|
__pragma__('opov')
|
||||||
@ -357,34 +356,10 @@ class BaseUIGSTVCounter(BaseSTVCounter):
|
|||||||
Basic unweighted inclusive Gregory STV counter
|
Basic unweighted inclusive Gregory STV counter
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def reset(self):
|
def __init__(self, *args, **kwargs):
|
||||||
# Distribute first preferences
|
BaseSTVCounter.__init__(self, *args, **kwargs)
|
||||||
for ballot in self.election.ballots:
|
# Need to use Rational for ballot value internally, as Num may be set to integers only
|
||||||
__pragma__('opov')
|
self.cls_ballot_value = Rational
|
||||||
candidate = next((c for c in ballot.preferences if self.candidates[c].state == CandidateState.HOPEFUL), None)
|
|
||||||
|
|
||||||
if candidate is not None:
|
|
||||||
self.candidates[candidate].transfers += ballot.value
|
|
||||||
self.candidates[candidate].ballots.append((ballot, Rational(ballot.value.pp(0))))
|
|
||||||
else:
|
|
||||||
self.exhausted.transfers += ballot.value
|
|
||||||
self.exhausted.ballots.append((ballot, Rational(ballot.value.pp(0))))
|
|
||||||
__pragma__('noopov')
|
|
||||||
|
|
||||||
self.quota = None
|
|
||||||
self.compute_quota()
|
|
||||||
self.elect_meeting_quota()
|
|
||||||
|
|
||||||
__pragma__('opov')
|
|
||||||
return CountStepResult(
|
|
||||||
'First preferences',
|
|
||||||
self.candidates,
|
|
||||||
self.exhausted,
|
|
||||||
self.loss_fraction,
|
|
||||||
self.total + self.exhausted.votes + self.loss_fraction.votes,
|
|
||||||
self.quota
|
|
||||||
)
|
|
||||||
__pragma__('noopov')
|
|
||||||
|
|
||||||
def do_surplus(self, candidate_surplus, count_card, surplus):
|
def do_surplus(self, candidate_surplus, count_card, surplus):
|
||||||
# FIXME: Is it okay to use native int's here?
|
# FIXME: Is it okay to use native int's here?
|
||||||
|
@ -25,7 +25,10 @@ class Fixed:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.impl = Big(val)
|
if isinstance(val, Fixed):
|
||||||
|
self.impl = val.impl
|
||||||
|
else:
|
||||||
|
self.impl = Big(val)
|
||||||
|
|
||||||
def pp(self, dp):
|
def pp(self, dp):
|
||||||
"""Pretty print to specified number of decimal places"""
|
"""Pretty print to specified number of decimal places"""
|
||||||
|
@ -20,7 +20,10 @@ class NativeInt:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.impl = Math.floor(parseFloat(val))
|
if isinstance(val, NativeInt):
|
||||||
|
self.impl = val.impl
|
||||||
|
else:
|
||||||
|
self.impl = Math.floor(parseFloat(val))
|
||||||
|
|
||||||
def pp(self, dp):
|
def pp(self, dp):
|
||||||
"""Pretty print to specified number of decimal places"""
|
"""Pretty print to specified number of decimal places"""
|
||||||
|
@ -20,7 +20,10 @@ class Native:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.impl = parseFloat(val)
|
if isinstance(val, Native):
|
||||||
|
self.impl = val.impl
|
||||||
|
else:
|
||||||
|
self.impl = parseFloat(val)
|
||||||
|
|
||||||
def pp(self, dp):
|
def pp(self, dp):
|
||||||
"""Pretty print to specified number of decimal places"""
|
"""Pretty print to specified number of decimal places"""
|
||||||
|
@ -20,7 +20,10 @@ class Rational:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.impl = bigRat(val)
|
if isinstance(val, Rational):
|
||||||
|
self.impl = val.impl
|
||||||
|
else:
|
||||||
|
self.impl = bigRat(val)
|
||||||
|
|
||||||
def pp(self, dp):
|
def pp(self, dp):
|
||||||
"""
|
"""
|
||||||
|
Reference in New Issue
Block a user