X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=appendix-a6.git;a=blobdiff_plain;f=parse;h=13fe2f23395fabb16bb0a9b15d3bc6496f9454ea;hp=e176ecc250713bf4e03b34a4ab3f6007f93dc64d;hb=454c5cdcf27ce0ac28aa9f62585387139690c779;hpb=5dc538aedf489281785ce32f25dcaa18385ac6a5 diff --git a/parse b/parse index e176ecc..13fe2f2 100755 --- a/parse +++ b/parse @@ -1,13 +1,14 @@ #!/usr/bin/perl -w use strict; use utf8; +use autodie; use Data::Printer; use Graph::Directed; -binmode STDIN, 'encoding(UTF-8)' or die; -binmode STDOUT, 'encoding(UTF-8)' or die; -binmode STDERR, 'encoding(UTF-8)' or die; +binmode STDIN, 'encoding(UTF-8)'; +binmode STDOUT, 'encoding(UTF-8)'; +binmode STDERR, 'encoding(UTF-8)'; our @choices; our %choices; @@ -26,6 +27,7 @@ while (<>) { s/\s+$//; next if m/^\s*\#/; next unless m/\S/; + next if m/^\s/; if (m/^([A-Z]+)\s*\=\s*(\S.*)$/) { my ($choname, $desc) = ($1,$2); my $cho = addchoice($choname, Desc => $desc); @@ -56,6 +58,8 @@ our @vab; # Go through the voters and construct V(A,B) +print "\nPreference matrix\n"; + foreach my $iv (@invotes) { my ($votestr,$voter) = @$iv; eval { @@ -90,29 +94,29 @@ foreach my $iy (-2..$#ch) { foreach my $ix (-2..$#ch) { if ($iy==-1) { if ($ix==-1) { - printf "+" or die; + printf "+"; } else { - printf "------" or die; + printf "------"; } } elsif ($ix==-1) { - printf "|" or die; + printf "|"; } elsif ($ix==-2 && $iy==-2) { - printf "V(Y,X)" or die; + printf "V(Y,X)"; } elsif ($iy==-2) { - printf "%5s ", $choices[$ix] or die $!; + printf "%5s ", $choices[$ix]; } elsif ($ix==-2) { - printf "%5s ", $choices[$iy] or die $!; + printf "%5s ", $choices[$iy]; } else { my $v = \( $vab[$iy][$ix] ); $$v ||= [ ]; if (@$$v) { - printf "%5d ", (scalar @$$v) or die $!; + printf "%5d ", (scalar @$$v); } else { - printf "%5s ", "" or die $!; + printf "%5s ", ""; } } } - printf "\n" or die $!; + printf "\n"; } sub drop ($$) { @@ -121,7 +125,7 @@ sub drop ($$) { $ch[$i]{Dropped} = $why; } -print "# quorum A.6(2)\n" or die $!; +print "\nQuorum A.6(2) (quorum is $quorum)\n"; foreach my $i (0..$#choices) { next if $ch[$i]{Dropped}; @@ -131,7 +135,7 @@ foreach my $i (0..$#choices) { drop $i, "quorum ($v < $quorum)"; } -print "# maj. ratio A.6(3)\n" or die $!; +print "\nMajority ratio A.6(3)\n"; foreach my $i (0..$#choices) { next if $ch[$i]{Dropped}; @@ -144,56 +148,119 @@ foreach my $i (0..$#choices) { drop $i, "majority ratio ($vad * $majr->[1] <= $vda * $majr->[0])"; } -my $defeats = Graph::Directed->new; # A.6(4) +print "\nDefeats A.6(4)\n"; + +my $defeats = Graph::Directed->new; + +sub chremain () { + return grep { !$ch[$_]{Dropped} } (0..$#ch); +} -foreach my $ia (0..$#ch) { - foreach my $ib (0..$#ch) { - my $vab = $vab[$ia][$ib]; - my $vba = $vab[$ib][$ia]; +foreach my $ia (chremain()) { + $defeats->add_vertex($choices[$ia]); + foreach my $ib (chremain()) { + my $vab = scalar @{ $vab[$ia][$ib] }; + my $vba = scalar @{ $vab[$ib][$ia] }; next unless $vab > $vba; - print "defeat: $choices[$ia] beats $choices[$ib] ($vab > $vba)\n" - or die $!; - $defeats->add_vertex($ia,$ib); + my $diff = $vab - $vba; + print "defeat: $choices[$ia] beats $choices[$ib]", + " ($vab > $vba: $diff)\n"; + $defeats->add_edge($choices[$ia],$choices[$ib]); } } -print "# transitive closure A.6(5)\n" or die $!; +sub chvab ($$) { + my ($ca,$cb) = @_; + my $v = $vab[ $choices{$ca}{Index} ][ $choices{$cb}{Index} ]; + return scalar @$v; +} + +sub weaker ($$) { + # A.6(7)(1) + my ($def1,$def2) = @_; + my ($ca,$cx) = @$def1; + my ($cb,$cy) = @$def1; + return 1 if chvab($ca, $cx) < chvab($cb, $cy); + return 1 if chvab($ca, $cx) == chvab($cb, $cy) + && chvab($cx, $ca) > chvab($cy, $cb); + return 0; +} -my $tdefeats = $defeats->transitive_closure(); +our $schwartz; -print "# schwartz set A.6(6)\n" or die $!; +for (;;) { + # loop from A6(5) -my $schwartz = $defeats->copy(); + print "defeats graph: $defeats\n"; -foreach my $ia (0..$#ch) { - foreach my $ib (0..$#ch) { - next if $tdefeats->has_edge($ia,$b); - next if !$tdefeats->has_edge($b,$ia); - print "not in Schwartz set: $choices[$ia] because $choices[$ib]\n" - or die $!; - $schwartz->delete_vertex($ia); - last; + print "\nTransitive closure A.6(5)\n"; + + my $tdefeats = $defeats->transitive_closure(); + + print "closure graph: $tdefeats\n"; + + print "\nSchwartz set A.6(6)\n"; + + $schwartz = $defeats->copy(); + + foreach my $ia (chremain()) { + foreach my $ib (chremain()) { + next if $tdefeats->has_edge($choices[$ia],$choices[$ib]); + next if !$tdefeats->has_edge($choices[$ib],$choices[$ia]); + print "not in Schwartz set: $choices[$ia] because $choices[$ib]\n"; + $schwartz->delete_vertex($choices[$ia]); + last; + } } -} -print "# dropping weakest defeats A.6(7)\n" or die $!; + print "\nDropping weakest defeats A.6(7)\n"; -my @weakest = (); + our @weakest = (); -foreach my $edge (@{ $schwartz->edges() }) { - if (!@weakest) { - # no weakest edges yet - } elsif (weaker($edge, $weakest[0])) { - # this edge is weaker than previous weakest, start new set - @weakest = (); - } elsif (weaker($weakest[0], $edge)) { - # weakest edge is weaker than this one, ignore this one - next; - } else { - # weakest edge is exactly as weak as this one, add this one + foreach my $edge ($schwartz->edges()) { +# print " considering @$edge\n"; + if (!@weakest) { + # no weakest edges yet + } elsif (weaker($edge, $weakest[0])) { + # this edge is weaker than previous weakest, start new set + @weakest = (); + } elsif (weaker($weakest[0], $edge)) { + # weakest edge is weaker than this one, ignore this one + next; + } else { + # weakest edge is exactly as weak as this one, add this one + } + push @weakest, $edge; + } + + last unless @weakest; + + my $w = $weakest[0]; + printf "weakest defeats %d > %d\n", + chvab($w->[0], $w->[1]), + chvab($w->[1], $w->[0]); + foreach my $weakest (@weakest) { + my ($ca,$cb) = @$weakest; + print "weakest defeat $ca > $cb\n"; + $defeats->delete_edge($ca,$cb); } - push @weakest, $edge; + + print "defeats within the Schwartz set, round again\n"; +} + +print "no defeats within the Schwartz set\n"; +print "final schwartz set:\n\n"; + +if ($schwartz->vertices() == 1) { + print "WINNER IS:\n"; +} else { + print "WINNER IS ONE OF (CASTING VOTE DECIDES):\n"; } +printf " %-5s %s\n", $_, $choices{$_}{Desc} + foreach ($schwartz->vertices()); + +print ".\n"; + #p %choices; #p @vab;