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()">
|
<select id="selPreset" onchange="changePreset()">
|
||||||
<option value="scottish" selected>Scottish STV</option>
|
<option value="scottish" selected>Scottish STV</option>
|
||||||
<option value="stvc">pyRCV STV-C</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="wright">Wright STV</option>
|
||||||
<option value="prsa77">PRSA 1977</option>
|
<option value="prsa77">PRSA 1977</option>
|
||||||
</select>
|
</select>
|
||||||
@ -119,7 +119,7 @@
|
|||||||
<select id="selExclusion">
|
<select id="selExclusion">
|
||||||
<option value="one_round" selected>Exclude in one round</option>
|
<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_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>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<br>
|
<br>
|
||||||
|
@ -20,6 +20,8 @@ from pyRCV2.model import CandidateState, CountCard, CountCompleted, CountStepRes
|
|||||||
from pyRCV2.numbers import Num, Rational
|
from pyRCV2.numbers import Num, Rational
|
||||||
from pyRCV2.safedict import SafeDict
|
from pyRCV2.safedict import SafeDict
|
||||||
|
|
||||||
|
import itertools
|
||||||
|
|
||||||
class STVException(Exception):
|
class STVException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -535,11 +537,28 @@ class WIGSTVCounter(BaseSTVCounter):
|
|||||||
|
|
||||||
def do_exclusion(self, candidate_excluded, count_card):
|
def do_exclusion(self, candidate_excluded, count_card):
|
||||||
if self.options['exclusion'] == 'parcels_by_order':
|
if self.options['exclusion'] == 'parcels_by_order':
|
||||||
parcel = count_card.parcels[0]
|
if len(count_card.parcels) > 0:
|
||||||
next_preferences, total_ballots, total_votes, next_exhausted, exhausted_ballots, exhausted_votes = self.next_preferences([parcel])
|
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)
|
count_card.parcels.remove(parcel)
|
||||||
elif self.options['exclusion'] == 'parcels_by_value':
|
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
|
else: # one_round
|
||||||
next_preferences, total_ballots, total_votes, next_exhausted, exhausted_ballots, exhausted_votes = self.next_preferences(count_card.parcels)
|
next_preferences, total_ballots, total_votes, next_exhausted, exhausted_ballots, exhausted_votes = self.next_preferences(count_card.parcels)
|
||||||
count_card.parcels = []
|
count_card.parcels = []
|
||||||
@ -573,6 +592,9 @@ class WIGSTVCounter(BaseSTVCounter):
|
|||||||
__pragma__('noopov')
|
__pragma__('noopov')
|
||||||
|
|
||||||
if len(count_card.parcels) == 0:
|
if len(count_card.parcels) == 0:
|
||||||
|
__pragma__('opov')
|
||||||
|
count_card.transfers -= count_card.votes
|
||||||
|
__pragma__('noopov')
|
||||||
count_card.state = CandidateState.EXCLUDED
|
count_card.state = CandidateState.EXCLUDED
|
||||||
|
|
||||||
class UIGSTVCounter(WIGSTVCounter):
|
class UIGSTVCounter(WIGSTVCounter):
|
||||||
@ -590,14 +612,14 @@ class UIGSTVCounter(WIGSTVCounter):
|
|||||||
|
|
||||||
if self.options['papers'] == 'transferable':
|
if self.options['papers'] == 'transferable':
|
||||||
__pragma__('opov')
|
__pragma__('opov')
|
||||||
transferable_ballots = total_ballots - exhausted_ballots
|
transferable_ballots = total_ballots - exhausted_ballots # Num
|
||||||
transferable_votes = total_votes.to_num() - exhausted_votes.to_num()
|
transferable_votes = total_votes - exhausted_votes # Rational
|
||||||
__pragma__('noopov')
|
__pragma__('noopov')
|
||||||
|
|
||||||
for candidate, x in next_preferences.items():
|
for candidate, x in next_preferences.items():
|
||||||
cand_ballots = x[0]
|
cand_ballots = x[0]
|
||||||
num_ballots = x[1]
|
num_ballots = x[1] # Num
|
||||||
num_votes = x[2]
|
num_votes = x[2] # Rational
|
||||||
|
|
||||||
new_parcel = []
|
new_parcel = []
|
||||||
if len(cand_ballots) > 0:
|
if len(cand_ballots) > 0:
|
||||||
@ -619,11 +641,11 @@ class UIGSTVCounter(WIGSTVCounter):
|
|||||||
__pragma__('opov')
|
__pragma__('opov')
|
||||||
if self.options['papers'] == 'transferable':
|
if self.options['papers'] == 'transferable':
|
||||||
if transferable_votes > surplus:
|
if transferable_votes > surplus:
|
||||||
new_value = (ballot.value * surplus) / transferable_ballots
|
new_value = (ballot.value * surplus).to_rational() / transferable_ballots.to_rational()
|
||||||
else:
|
else:
|
||||||
new_value = ballot_value
|
new_value = ballot_value
|
||||||
else:
|
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))
|
new_parcel.append((ballot, new_value))
|
||||||
__pragma__('noopov')
|
__pragma__('noopov')
|
||||||
|
Reference in New Issue
Block a user