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):
|
||||
self.election = election
|
||||
|
||||
self.cls_ballot_value = Num # Need to use Rational in unweighted inclusive Gregory
|
||||
|
||||
# Default options
|
||||
self.options = {
|
||||
'prog_quota': False, # Progressively reducing quota?
|
||||
@ -60,9 +62,35 @@ class BaseSTVCounter:
|
||||
"""
|
||||
Public function:
|
||||
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):
|
||||
"""
|
||||
@ -295,35 +323,6 @@ class BaseWIGSTVCounter(BaseSTVCounter):
|
||||
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):
|
||||
for ballot, ballot_value in count_card.ballots:
|
||||
__pragma__('opov')
|
||||
@ -357,34 +356,10 @@ class BaseUIGSTVCounter(BaseSTVCounter):
|
||||
Basic unweighted 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, 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 __init__(self, *args, **kwargs):
|
||||
BaseSTVCounter.__init__(self, *args, **kwargs)
|
||||
# Need to use Rational for ballot value internally, as Num may be set to integers only
|
||||
self.cls_ballot_value = Rational
|
||||
|
||||
def do_surplus(self, candidate_surplus, count_card, surplus):
|
||||
# FIXME: Is it okay to use native int's here?
|
||||
|
@ -25,7 +25,10 @@ class Fixed:
|
||||
"""
|
||||
|
||||
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):
|
||||
"""Pretty print to specified number of decimal places"""
|
||||
|
@ -20,7 +20,10 @@ class NativeInt:
|
||||
"""
|
||||
|
||||
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):
|
||||
"""Pretty print to specified number of decimal places"""
|
||||
|
@ -20,7 +20,10 @@ class Native:
|
||||
"""
|
||||
|
||||
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):
|
||||
"""Pretty print to specified number of decimal places"""
|
||||
|
@ -20,7 +20,10 @@ class Rational:
|
||||
"""
|
||||
|
||||
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):
|
||||
"""
|
||||
|
Reference in New Issue
Block a user