Implement exclusion of parcels by value + Senate STV
This commit is contained in:
parent
803941a53a
commit
61506f0082
@ -40,7 +40,7 @@
|
||||
<select id="selPreset" onchange="changePreset()">
|
||||
<option value="scottish" selected>Scottish STV</option>
|
||||
<option value="stvc">pyRCV STV-C</option>
|
||||
<!--<option value="senate">Australian Senate STV</option>-->
|
||||
<option value="senate">Australian Senate STV</option>
|
||||
<option value="wright">Wright STV</option>
|
||||
<option value="prsa77">PRSA 1977</option>
|
||||
</select>
|
||||
@ -119,7 +119,7 @@
|
||||
<select id="selExclusion">
|
||||
<option value="one_round" selected>Exclude in one round</option>
|
||||
<option value="parcels_by_order">Exclude by parcel (by order)</option>
|
||||
<!--<option value="parcels_by_value">Exclude by parcel (by value)</option>-->
|
||||
<option value="parcels_by_value">Exclude by parcel (by value)</option>
|
||||
</select>
|
||||
</label>
|
||||
<br>
|
||||
|
@ -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':
|
||||
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')
|
||||
|
Reference in New Issue
Block a user