diff --git a/html/index.html b/html/index.html index 3629a9e..b459932 100644 --- a/html/index.html +++ b/html/index.html @@ -40,7 +40,7 @@ @@ -119,7 +119,7 @@
diff --git a/pyRCV2/method/base_stv.py b/pyRCV2/method/base_stv.py index 6bf866b..089306e 100644 --- a/pyRCV2/method/base_stv.py +++ b/pyRCV2/method/base_stv.py @@ -20,6 +20,8 @@ from pyRCV2.model import CandidateState, CountCard, CountCompleted, CountStepRes from pyRCV2.numbers import Num, Rational from pyRCV2.safedict import SafeDict +import itertools + class STVException(Exception): pass @@ -535,11 +537,28 @@ class WIGSTVCounter(BaseSTVCounter): def do_exclusion(self, candidate_excluded, count_card): if self.options['exclusion'] == 'parcels_by_order': - parcel = count_card.parcels[0] - next_preferences, total_ballots, total_votes, next_exhausted, exhausted_ballots, exhausted_votes = self.next_preferences([parcel]) + if len(count_card.parcels) > 0: + parcel = count_card.parcels[0] + next_preferences, total_ballots, total_votes, next_exhausted, exhausted_ballots, exhausted_votes = self.next_preferences([parcel]) + else: + # TODO: Skip this entirely if this is the case + parcel = [] count_card.parcels.remove(parcel) elif self.options['exclusion'] == 'parcels_by_value': - raise Exception('Not implemented') + # Sort the parcels by value + ballots = [(b, bv) for p in count_card.parcels for b, bv in p] + __pragma__('opov') + ballots.sort(key=lambda x: x[1] / x[0].value.to_rational(), reverse=True) + count_card.parcels = [list(g) for k, g in itertools.groupby(ballots, lambda x: x[1] / x[0].value.to_rational())] + __pragma__('noopov') + + if len(count_card.parcels) > 0: + parcel = count_card.parcels[0] + count_card.parcels.remove(parcel) + else: + parcel = [] + + next_preferences, total_ballots, total_votes, next_exhausted, exhausted_ballots, exhausted_votes = self.next_preferences([parcel]) else: # one_round next_preferences, total_ballots, total_votes, next_exhausted, exhausted_ballots, exhausted_votes = self.next_preferences(count_card.parcels) count_card.parcels = [] @@ -573,6 +592,9 @@ class WIGSTVCounter(BaseSTVCounter): __pragma__('noopov') if len(count_card.parcels) == 0: + __pragma__('opov') + count_card.transfers -= count_card.votes + __pragma__('noopov') count_card.state = CandidateState.EXCLUDED class UIGSTVCounter(WIGSTVCounter): @@ -590,14 +612,14 @@ class UIGSTVCounter(WIGSTVCounter): if self.options['papers'] == 'transferable': __pragma__('opov') - transferable_ballots = total_ballots - exhausted_ballots - transferable_votes = total_votes.to_num() - exhausted_votes.to_num() + transferable_ballots = total_ballots - exhausted_ballots # Num + transferable_votes = total_votes - exhausted_votes # Rational __pragma__('noopov') for candidate, x in next_preferences.items(): cand_ballots = x[0] - num_ballots = x[1] - num_votes = x[2] + num_ballots = x[1] # Num + num_votes = x[2] # Rational new_parcel = [] if len(cand_ballots) > 0: @@ -619,11 +641,11 @@ class UIGSTVCounter(WIGSTVCounter): __pragma__('opov') if self.options['papers'] == 'transferable': if transferable_votes > surplus: - new_value = (ballot.value * surplus) / transferable_ballots + new_value = (ballot.value * surplus).to_rational() / transferable_ballots.to_rational() else: new_value = ballot_value else: - new_value = (ballot.value * surplus) / total_ballots + new_value = (ballot.value * surplus).to_rational() / total_ballots.to_rational() new_parcel.append((ballot, new_value)) __pragma__('noopov')