From 673b5314751236208c18fc706708b551743a634c Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Sun, 3 Jan 2021 17:20:13 +1100 Subject: [PATCH] Optimisation: Do not re-sort already sorted parcels in exclusion by_value --- pyRCV2/method/base_stv.py | 20 +++++++++++++------- pyRCV2/model.py | 1 + 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/pyRCV2/method/base_stv.py b/pyRCV2/method/base_stv.py index f6751a2..97a8eb9 100644 --- a/pyRCV2/method/base_stv.py +++ b/pyRCV2/method/base_stv.py @@ -538,6 +538,7 @@ class WIGSTVCounter(BaseSTVCounter): if len(cand_ballots) > 0: __pragma__('opov') self.candidates[candidate].parcels.append(new_parcel) + self.candidates[candidate]._parcels_sorted = False __pragma__('noopov') __pragma__('opov') @@ -590,13 +591,15 @@ class WIGSTVCounter(BaseSTVCounter): count_card.parcels.remove(parcel) elif self.options['exclusion'] == 'by_value': # Sort the ballots 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, reverse=True) - # Round to 8 decimal places to consider equality - # FIXME: Work out a better way of doing this - count_card.parcels = groupby(ballots, lambda x: (x[1] / x[0].value).round(8, x[1].ROUND_DOWN)) - __pragma__('noopov') + if not count_card._parcels_sorted: + 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, reverse=True) + # Round to 8 decimal places to consider equality + # FIXME: Work out a better way of doing this + count_card.parcels = groupby(ballots, lambda x: (x[1] / x[0].value).round(8, x[1].ROUND_DOWN)) + count_card._parcels_sorted = True + __pragma__('noopov') if len(count_card.parcels) > 0: parcel = count_card.parcels[0] @@ -618,6 +621,7 @@ class WIGSTVCounter(BaseSTVCounter): if len(cand_ballots) > 0: __pragma__('opov') self.candidates[candidate].parcels.append(new_parcel) + self.candidates[candidate]._parcels_sorted = False __pragma__('noopov') __pragma__('opov') @@ -669,6 +673,7 @@ class UIGSTVCounter(WIGSTVCounter): if len(cand_ballots) > 0: __pragma__('opov') self.candidates[candidate].parcels.append(new_parcel) + self.candidates[candidate]._parcels_sorted = False __pragma__('noopov') __pragma__('opov') @@ -736,6 +741,7 @@ class EGSTVCounter(UIGSTVCounter): if len(cand_ballots) > 0: __pragma__('opov') self.candidates[candidate].parcels.append(new_parcel) + self.candidates[candidate]._parcels_sorted = False __pragma__('noopov') __pragma__('opov') diff --git a/pyRCV2/model.py b/pyRCV2/model.py index 520692f..b5b6980 100644 --- a/pyRCV2/model.py +++ b/pyRCV2/model.py @@ -71,6 +71,7 @@ class CountCard: # Parcel = List[Tuple[Ballot, Num]] # The exhausted/loss to fraction piles will have only one parcel self.parcels = [] + self._parcels_sorted = False # Optimisation to avoid re-sorting in exclusion by_value @property def votes(self):