Skip to content

Commit

Permalink
remove no-tiebreak configuration flag - ACR tiebreaking no longer opt…
Browse files Browse the repository at this point in the history
…ional
  • Loading branch information
ikluft committed Aug 30, 2024
1 parent dee514d commit 0fed3dd
Show file tree
Hide file tree
Showing 7 changed files with 14 additions and 44 deletions.
5 changes: 2 additions & 3 deletions src/perl/prefvote/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,8 @@ It only makes sense for tie-breaking, where becomes meaningful if everything els
For high-stakes elections, a runoff may be a more appropriate action.
For polls on approval of a proposal or measure, a tie should mean failure to achieve a majority.

_PrefVote::Core_ makes average choice rank (ACR) data available to subclasses which must use it for tie-breaking,
except when the _no-tiebreak_ configuration flag is set.
Ties should be extremely unlikely with ACR tie-breaking enabled.
_PrefVote::Core_ makes average choice rank (ACR) data available to subclasses which must use it for tie-breaking.
Ties are less likely due to ACR tie-breaking, but cannot be made impossible.

- result\_yaml()

Expand Down
8 changes: 0 additions & 8 deletions src/perl/prefvote/bin/vote-count
Original file line number Diff line number Diff line change
Expand Up @@ -266,14 +266,6 @@ Supported configuration settings:
=over 1
=item no-tiebreak
takes a boolean value, 1 for true or 0 for false.
This indicating PrefVote voting methods should disable the
normal tie-breaking by Average Choice Rank (ACR).
The default is false, which allows tie-breaking with ACR.
This setting is used by the STV, Schulze and RankedPairs voting methods.
=item input-ties
(for use in testing only)
Expand Down
6 changes: 0 additions & 6 deletions src/perl/prefvote/lib/PrefVote/Config.pm
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,6 @@ All configuration entries default to non-existent and undefined.
=over 1
=item no-tiebreak
If defined, this contains a boolean flag that inhibits the PrefVote system's use of L<PrefVote::Core>
"average choice rank" (ACR) data for tie-breaking. This is recognized by L<PrefVote::STV>, L<PrefVote::Schulze> and
L<PrefVote::RankedPairs>.
=item input-ties
(experimental)
Expand Down
5 changes: 2 additions & 3 deletions src/perl/prefvote/lib/PrefVote/Core.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1103,9 +1103,8 @@ For low-stakes polls, such as where to meet for dinner, a random selection such
For high-stakes elections, a runoff may be a more appropriate action.
For polls on approval of a proposal or measure, a tie should mean failure to achieve a majority.
I<PrefVote::Core> makes average choice rank (ACR) data available to subclasses which must use it for tie-breaking,
except when the I<no-tiebreak> configuration flag is set.
Ties should be extremely unlikely with ACR tie-breaking enabled.
I<PrefVote::Core> makes average choice rank (ACR) data available to subclasses which must use it for tie-breaking.
Ties are less likely with ACR tie-breaking, but cannot be made impossible.
=item result_yaml()
Expand Down
11 changes: 4 additions & 7 deletions src/perl/rankedpairs/lib/PrefVote/RankedPairs.pm
Original file line number Diff line number Diff line change
Expand Up @@ -408,13 +408,10 @@ sub cmp_choice
}

# 2nd comparison: choice/candidate's average ballot placement in ascending order
my $tiebreak_disabled = $self->config("no-tiebreak") // 0; # config flag to disable tie-breaking by avg rank
if ( not $tiebreak_disabled ) {
my $place1 = $self->average_ranking($cand1);
my $place2 = $self->average_ranking($cand2);
if ( not fp_equal( $place1, $place2 ) ) {
return fp_cmp( $place1, $place2 );
}
my $place1 = $self->average_ranking($cand1);
my $place2 = $self->average_ranking($cand2);
if ( not fp_equal( $place1, $place2 ) ) {
return fp_cmp( $place1, $place2 );
}

return 0;
Expand Down
4 changes: 0 additions & 4 deletions src/perl/schulze/lib/PrefVote/Schulze/Round.pm
Original file line number Diff line number Diff line change
Expand Up @@ -630,10 +630,6 @@ sub narrow_winners
my $self = shift;
my $schulze_ref = shift; # ref to PrefVote::Schulze object

# skip step if configuration flag disables PrefVotes's tie-breaking by average rank to strictly follow algorithm
my $tiebreak_disabled = $self->config("no-tiebreak") // 0; # config flag to disable tie-breaking by avg rank
return if $tiebreak_disabled;

# sort winners by average ballot placement order
my @winning_group =
sort { fp_cmp( $schulze_ref->average_ranking($a), $schulze_ref->average_ranking($b) ) } $self->win_flag_keys();
Expand Down
19 changes: 6 additions & 13 deletions src/perl/stv/lib/PrefVote/STV.pm
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,12 @@ sub process_winners
# quota exceeded - we have a winner!
my @round_winner;
my $place = $self->winners_count() + 1;
my $tiebreak_disabled = $self->config("no-tiebreak") // 0; # config flag to disable tie-breaking by avg rank
foreach my $curr_key (@round_candidate) {

# mark all the candidates over quota who are tied for first place as winners
if (
( $round->tally_get($curr_key)->votes() == $round->tally_get( $round_candidate[0] )->votes() )
and ( $tiebreak_disabled
or fp_equal( $self->average_ranking($curr_key), $self->average_ranking( $round_candidate[0] ) ) )
and fp_equal( $self->average_ranking($curr_key), $self->average_ranking( $round_candidate[0] ) )
)
{
my $c_votes = $round->tally_get($curr_key)->votes();
Expand Down Expand Up @@ -316,13 +314,11 @@ sub eliminate_losers

# mark candidates tied for last as eliminated
my @round_eliminated;
my $tiebreak_disabled = $self->config("no-tiebreak") // 0; # config flag to disable tie-breaking by avg rank
for ( $i = ( scalar @round_candidate ) - 1 ; $i > 0 ; $i-- ) {
my $indexed_cand = $round_candidate[$i];
if (
( $round->tally_get($last_cand)->votes() == $round->tally_get($indexed_cand)->votes() )
and ( $tiebreak_disabled
or fp_equal( $self->average_ranking($last_cand), $self->average_ranking($indexed_cand) ) )
and fp_equal( $self->average_ranking($last_cand), $self->average_ranking($indexed_cand) )
)
{
$round->tally_get($indexed_cand)->mark_as_eliminated();
Expand Down Expand Up @@ -370,7 +366,6 @@ sub count
}

# sort in descending order
my $tiebreak_disabled = $self->config("no-tiebreak") // 0; # config flag to disable tie-breaking by avg rank
my @round_candidate = $round->sort_candidates(
sub {
# 1st/primary comparison: votes for candidate in descending order
Expand All @@ -381,12 +376,10 @@ sub count
}

# 2nd comparison: average ballot-ranking position in ascending order
if ( not $tiebreak_disabled ) {
my $acr0 = $self->average_ranking( $_[0] );
my $acr1 = $self->average_ranking( $_[1] );
if ( not fp_equal( $acr0, $acr1 ) ) {
return fp_cmp( $acr0, $acr1 );
}
my $acr0 = $self->average_ranking( $_[0] );
my $acr1 = $self->average_ranking( $_[1] );
if ( not fp_equal( $acr0, $acr1 ) ) {
return fp_cmp( $acr0, $acr1 );
}

# 3rd comparison: alphabetical (so ties in testing keep consistent order)
Expand Down

0 comments on commit 0fed3dd

Please sign in to comment.