From 781d40da5cf41034debb17d3b7f4f62d5665a97e Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 21 Aug 2016 17:51:59 +0100 Subject: [PATCH] compute-scottish-stv: wip, test produces undefs Signed-off-by: Ian Jackson --- compute-scottish-stv | 55 +++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/compute-scottish-stv b/compute-scottish-stv index 1684103..e3d5d77 100755 --- a/compute-scottish-stv +++ b/compute-scottish-stv @@ -22,6 +22,9 @@ use bigrat; our $seats=0; +our @allvotes; +our @non_transferable; +our %cands; our $stage=0; our $quota; our %tie; @@ -57,11 +60,11 @@ for (;;) { $cands{$cand}{Desc} = $desc; } elsif (m/^(\w*) :\s*(.*)\s*\|(.*)/) { my ($voter,$prefs,$opts) = ($1,$2,$3); - $v = { Voter => $voter }; + my $v = { Voter => $voter }; push @{ $v->{Prefs} }, [ $_ =~ m/\w+/g ] foreach split /\s+/, $prefs; foreach $_ (split / /, $opts) { - if (m/^_?[Ww]eight=(\d+)/(\d+)$/) { + if (m/^_?[Ww]eight=(\d+)\/(\d+)$/) { $v->{Weight} = $1 / $2; } elsif (m/^_?[Ww]eight=([0-9.]+)$/) { $v->{Weight} = new Math::BigRat $1; @@ -77,7 +80,12 @@ for (;;) { } } -$cands{$_}{Cand} = $_foreach keys %cands; +$cands{$_}{Cand} = $_ foreach keys %cands; + +sub votelog ($$) { + my ($vote,$m) = @_; + push @{ $vote->{Log} }, "stage $stage: $m"; +} sub sortballots (@) { # Takes each argument, which should be a ballot, sorts @@ -89,31 +97,31 @@ sub sortballots (@) { my $firstprefs = shift @{ $v->{Prefs} }; my $w = $v->{Weight}; if (!$firstprefs || !@$firstprefs) { - vlog $v, "no more preferences, non transferable"; + votelog $v, "no more preferences, non transferable"; push @non_transferable, $v; next; } if (@$firstprefs > 1) { - vlog $v, "splitting due to several equal first preferences"; + votelog $v, "splitting due to several equal first preferences"; foreach my $fpref (@$firstprefs) { my $v2 = { %$v, Weight => $w / @$firstprefs, Prefs => [ [ $fpref ], @{ $v->{Prefs} } ], }; - vlog $v, "split for $fpref"; + votelog $v, "split for $fpref"; } next; } - my $fp = $firstprefs[0]; + my $fp = $firstprefs->[0]; my $c = $cands{$fp}; my $noncont = $c->{NonCont}; if ($noncont) { - vlog $v, "dropping pref $fp, $noncont"; + votelog $v, "dropping pref $fp, $noncont"; sortvallots $v; next; } - vlog $v, "sorted into pile for candidate $fp weight $w"; + votelog $v, "sorted into pile for candidate $fp weight $w"; push @{ $c->{Votes} }, $v; } } @@ -124,13 +132,11 @@ sub prf { } sub countballots () { - foreach my $c (values %cand) { + foreach my $cand (sort keys %cands) { + my $c = $cands{$cand}; + next if $c->{NonCont}; $c->{Total} = 0; $c->{Total} += $_->{Weight} foreach @{ $c->{Voters} }; - } - foreach my $cand (sort keys %cand) { - $c = $cands{$cand}; - next if $c->{NonCont}; prf "cand %s: %s votes\n", $stage, $cand, $c->{Total}; $c->{History}[$stage-1] = $c->{Total}; } @@ -148,9 +154,9 @@ sub total_history_cmp () { foreach my $s (reverse 1 .. $stage) { my $d = $ha->[$s] <=> $hb->[$s]; next unless $d; - print DEBUG "history cmp $a->{Cand} $b->[Cand}" - ." => $d (#$s $ha->[$s] $hb->[$s])\n"; - return $e; + print DEBUG "history cmp $a->{Cand} $b->{Cand}". + " => $d (#$s $ha->[$s] $hb->[$s])\n"; + return $d; } return 0; } @@ -170,7 +176,7 @@ sub select_best_worst ($$$$) { # If it returns 0 we return alphabetically first CAND. Otherwise # we tie break. - my @maybe = grep { $wantcand->($_) } @continuing; + my @maybe = grep { $wantcand->($_) } continuing(); @maybe = sort total_history_cmp @maybe; @maybe = reverse @maybe if $signum > 0; @@ -184,7 +190,8 @@ sub select_best_worst ($$$$) { # Only interested in those who compare equal according to the # history (SLGEO 49(2)); NB our history includes the current # round. - last if $signum*(total_history_cmp $maybe[0], $nextc) > 0; + + last if $signum*($a = $maybe[0], $b = $nextc, total_history_cmp) > 0; $nextc++; } @@ -197,18 +204,18 @@ sub select_best_worst ($$$$) { my $selectcand; if ($nequal > 1) { - my @all = map { $_->{Cand} } @maybe_elect[0 .. $nelect-1]; + my @all = map { $_->{Cand} } @maybe[0 .. $nequal-1]; my $tiekey = $signum > 0 ? 'Win' : 'Lose'; my $win = $tie{"@all"}{$tiekey}; die "need tie break, want $tiekey from @all" unless defined $win; prf "$what %s due to tie break amongst %s\n", - $eslectcand, "@all"; + $selectcand, "@all"; } else { $selectcand = $maybe[0]; prf "$what %s\n"; } - return $cands{$electcand}; + return $cands{$selectcand}; } sub elect_core ($) { @@ -256,7 +263,7 @@ for (;;) { foreach my $v (@{ $c->{Votes} }) { my $A = $surplus * $v->{Weight}; my $F = 100000; - my $xfervalue = floor(($A * $F) / $B) / $f; + my $xfervalue = floor(($A * $F) / $B) / $F; # SLGEO 48(3): we do arithmetic to 5 d3ecimal places, # but always rounding down votelog $v, "transferring with value $xfervalue (A=$A B=$B)"; @@ -268,7 +275,7 @@ for (;;) { } # No-one to elect, must eliminate - my $c = select_best_worst + $c = select_best_worst sub { 1; }, sub { 1; }, -1, 'eliminating'; -- 2.30.2