File Coverage

blib/lib/Vote/Count/Method/CondorcetIRV.pm
Criterion Covered Total %
statement 41 41 100.0
branch 4 4 100.0
condition n/a
subroutine 9 9 100.0
pod 1 1 100.0
total 55 55 100.0


line stmt bran cond sub pod time code
1 3     3   607 use strict;
  3         8  
  3         102  
2 3     3   19 use warnings;
  3         8  
  3         88  
3 3     3   62 use 5.024;
  3         11  
4 3     3   20 use feature qw /postderef signatures/;
  3         6  
  3         342  
5              
6             package Vote::Count::Method::CondorcetIRV;
7 3     3   22 use namespace::autoclean;
  3         7  
  3         33  
8 3     3   377 use Moose;
  3         20  
  3         37  
9             extends 'Vote::Count';
10             with 'Vote::Count::BottomRunOff';
11              
12             our $VERSION='2.00';
13              
14             =head1 NAME
15              
16             Vote::Count::Method::CondorcetIRV
17              
18             =head1 VERSION 2.00
19              
20             =cut
21              
22             # ABSTRACT: Simple Condorcet IRV Methods.
23              
24             =pod
25              
26             =head1 SYNOPSIS
27              
28             use Vote::Count::Method::CondorcetIRV ;
29              
30             my $Election = Vote::Count::Method::CondorcetIRV->new(
31             'BallotSet' => $someballotset,
32             'TieBreakMethod' => 'precedence', # defaults to all
33             );
34             my $result = $Election->SmithSetIRV() ;
35             say "Winner is: " . $result->{'winner'};
36             say $Election->logv();
37              
38             =head1 Description
39              
40             Provides Common Basic Condorcet-IRV Methods. These methods are simple and beat other Condorcet Methods on Later Harm.
41              
42             =head1 Method Common Names: Smith Set IRV, Smith-IRV
43              
44             Identifies the Smith Set and runs IRV on it.
45              
46             =head2 Function Name: SmithSetIRV
47              
48             SmithSetIRV is exported and requires a Vote::Count object, an optional second argument is an IRV tiebreaker rule name (see IRV module). It will return a hashref similar to RunIRV, in the event of a tie the Vote::Count Object's Active Set will also be the tied choices (available for any later tie breakers you would implement). Events will be logged to the Vote::Count Object.
49              
50             =head2 Criteria
51              
52             =head3 Simplicity
53              
54             SmithSet IRV is easy to understand but requires a full matrix and thus is harder to handcount than Benham or BTR IRV. If it desired to handcount, an aggressive Floor Rule like TCA (see Floor module) is recommended, or an Approval or Top Count Floor of up to 15%. 15% Top Count permits at most 6 choices, but 6 choices still require 15 pairings to complete the Matrix.
55              
56             =head3 Later Harm
57              
58             When there is no Condorcet Winner this method is Later Harm Sufficient. There might be edge cases where IRV's sensitivity to dropping order creates a Later Harm effect, but they should be pretty rare. When there is a Condorcet Winner the effect is the normal one for a Condorcet Method.
59              
60             The easiest way to imagine a case where a choice not in the Smith Set changed the outcome is by cloning the winner, such that there is a choice defeating them in early Top Count but not defeating them. The negative impact of the clone is an established weakness of IRV. It would appear that any possible Later Harm issue in addition to being very much at the edge is more than offset by consistency improvement.
61              
62             Smith Set IRV still inherits the Later Harm failure of requiring a Condorcet Winner, but it has the lowest possible Later Harm effect for a Smith compliant Method. Woodhull and restricting Pairwise Opposition to the Smith Set have equal Later Harm effect to Smith Set IRV.
63              
64             =head3 Condorcet Criteria
65              
66             Meets Condorcer Winner, Condorcet Loser, and Smith.
67              
68             =head3 Consistency
69              
70             By meeting the three Condorcet Criteria a level of consistency is guaranteed. When there is no Condorcet Winner the resolution has all of the weaknesses of IRV, as discussed in the Later Harm topic above restricting IRV to the Smith Set would appear to provide a consistency gain over basic IRV.
71              
72             Smith Set IRV is therefore substantially more consistent than basic IRV, but less consistent than Condorcet methods like SSD that focus on Consistency.
73              
74             =head1 Smith Set Restricted MinMax (Currently Unimplemented, See Vote::Count::Method::MinMax)
75              
76             MinMax methods do not meet the Smith Criteria nor the Condorcet Loser Criteria, two do meet the Condorcet Winner Criteria, and one meets Later Harm. Restricting MinMax to the Smith Set will make all of the sub-methods meet all three Condorcet Criteria; "Opposition" will match the Later Harm protection of Smith Set IRV.
77              
78             =head1 Method Common Name: Woodhull Method (Currently Unimplemented)
79              
80             The Woodhull method is similar to Smith Set IRV. The difference is: instead of eliminating the choices outside the Smith Set, Woodhull does not permit them to win. Since, it has to deal with the situation where an ineligible choice wins via IRV, it becomes slightly more complex. In addition, group elimination of unwinnable choices improves consistency, which is another advantage to Smith Set IRV. As for possible differences in Later Harm effect, the Later Harm comes from the restriction of the victor to the Smith Set, which is the same effect for both methods.
81              
82             The argument in favor of Woodhull over Smith would be that: Anything which alters the dropping order can alter the outcome of IRV, and Woodhull preserves the IRV dropping order. Since, a dropping order change has an equal possiblity of helping or hurting one's preferred choice, this side-effect is a random flaw. Removing the least consequential choices is preventing them from impacting the election (in a random manner), thus this author sees it as an advantage for Smith Set IRV.
83              
84             =head1 Method Common Name: Bottom Two Runoff IRV, BTR IRV (Implementation Soon)
85              
86             This is the simplest modification to IRV which meets the Condorcet Winner Criteria. Instead of eliminating the low choice, the lowest two choices enter a virtual runoff, eliminating the loser. This is the easiest Hand Count Condorcet method, there will always be fewer pairings than choices. This method fails LNH, when there is no Condorcet Winner the LNH impact may substantial since it can come into play for each runoff. BTR IRV will only eliminate a member of the Smith Set when both members of the runoff are in it, it can never eliminate the final member of the Smith Set. BTR IRV meets both Condorcet Criteria and the Smith Criteria.
87              
88             =head1 Method Common Names: Benham, Benham IRV
89              
90             This method modifies IRV by checking for a Condorcet Winner each round, and then drops the low choice as regular IRV. It is probably the most widely used Condorcet Method for Hand Counting because it does not require a full matrix. For each choice it is only required to determine if they lose to any of the other active choices.
91              
92             This method is implemented by L<Vote::Count::Method::CondorcetDropping|Vote::Count::Method::CondorcetDropping/Benham>.
93              
94             =cut
95              
96 3     3   22952 no warnings 'experimental';
  3         8  
  3         175  
97              
98 3     3   19 use Carp;
  3         7  
  3         1196  
99              
100 6     6 1 60 sub SmithSetIRV ( $E, $tiebreaker = 'all' ) {
  6         18  
  6         16  
  6         10  
101 6         189 my $matrix = $E->PairMatrix();
102 6         34 $E->logt('SmithSetIRV');
103 6         28 my $winner = $matrix->CondorcetWinner();
104 6 100       27 if ($winner) {
105 2         17 $E->logv("Condorcet Winner: $winner");
106             return {
107 2         17 'winner' => $winner,
108             'tied' => 0
109             };
110             }
111             else {
112 4         23 my $Smith = $matrix->SmithSet();
113 4         52 $E->logv( "Smith Set: " . join( ',', sort( keys $Smith->%* ) ) );
114 4         37 my $IRV = $E->RunIRV( $Smith, $tiebreaker );
115 4 100       24 unless ( $IRV->{'winner'} ) {
116 1         3 $winner = '';
117 1         5 $E->SetActive( { map { $_ => 1 } ( $IRV->{'tied'}->@* ) } );
  2         14  
118             }
119 4         26 return $IRV;
120             }
121             }
122              
123             # sub BTRIRV ( $E ) {
124              
125             # }
126              
127             # sub RunIRV ( $self, $active = undef, $tiebreaker = undef ) {
128             # # external $active should not be changed.
129             # if ( defined $active ) { $active = dclone $active }
130             # # Object's active is altered by IRV.
131             # else { $active = dclone $self->Active() }
132             # unless ( defined $tiebreaker ) {
133             # if ( defined $self->TieBreakMethod() ) {
134             # $tiebreaker = $self->TieBreakMethod();
135             # }
136             # else {
137             # $tiebreaker = 'all';
138             # }
139             # }
140             # my $roundctr = 0;
141             # my $maxround = scalar( keys %{$active} );
142             # $self->logt( "Instant Runoff Voting",
143             # 'Choices: ', join( ', ', ( sort keys %{$active} ) ) );
144             # # forever loop normally ends with return from $majority
145             # # a tie should be detected and also generate a
146             # # return from the else loop.
147             # # if something goes wrong roundcountr/maxround
148             # # will generate exception.
149             # IRVLOOP:
150             # until (0) {
151             # $roundctr++;
152             # die "IRVLOOP infinite stopped at $roundctr" if $roundctr > $maxround;
153             # my $round = $self->TopCount($active);
154             # $self->logv( '---', "IRV Round $roundctr", $round->RankTable() );
155             # my $majority = $self->EvaluateTopCountMajority($round);
156             # if ( defined $majority->{'winner'} ) {
157             # return $majority;
158             # }
159             # else {
160             # my @bottom =
161             # $self->_ResolveTie( $active, $tiebreaker, $round->ArrayBottom()->@* );
162             # if ( scalar(@bottom) == scalar( keys %{$active} ) ) {
163             # # if there is a tie at the end, the finalists should
164             # # be both top and bottom and the active set.
165             # $self->logt( "Tied: " . join( ', ', @bottom ) );
166             # return { tie => 1, tied => \@bottom, winner => 0 };
167             # }
168             # $self->logv( "Eliminating: " . join( ', ', @bottom ) );
169             # for my $b (@bottom) {
170             # delete $active->{$b};
171             # }
172             # }
173             # }
174             # }
175              
176             1;
177              
178             #FOOTER
179              
180             =pod
181              
182             BUG TRACKER
183              
184             L<https://github.com/brainbuz/Vote-Count/issues>
185              
186             AUTHOR
187              
188             John Karr (BRAINBUZ) brainbuz@cpan.org
189              
190             CONTRIBUTORS
191              
192             Copyright 2019-2021 by John Karr (BRAINBUZ) brainbuz@cpan.org.
193              
194             LICENSE
195              
196             This module is released under the GNU Public License Version 3. See license file for details. For more information on this license visit L<http://fsf.org>.
197              
198             SUPPORT
199              
200             This software is provided as is, per the terms of the GNU Public License. Professional support and customisation services are available from the author.
201              
202             =cut
203