commit f9e133434276c04fd31b62584b998efe834e9871
parent 1f3f2c12c54ed515f3e6c3423d183dec02bd0259
Author: Ryan Wolf <rwolf@borderstylo.com>
Date: Wed, 3 Mar 2010 02:15:23 -0800
rewrite. simpler math, more comments, just as fast
Diffstat:
| M | resera.pl | | | 166 | +++++++++++++++++++++++++++++++++++-------------------------------------------- |
1 file changed, 73 insertions(+), 93 deletions(-)
diff --git a/resera.pl b/resera.pl
@@ -7,109 +7,89 @@
use strict;
use warnings;
+my $iterations = 100000;
+
+my $frequencies = [
+ [0, 0],
+ [0, 0]
+];
+
# default taken from http://en.wikipedia.org/wiki/Prisoner%27s_dilemma
-my $grid = [
- [[3, 3], [0, 5]],
- [[5, 0], [1, 1]]
+my $payoff_matrices = [
+ [
+ [3, 0],
+ [5, 1]
+ ],
+ [
+ [3, 0],
+ [5, 1]
+ ]
];
+
+# also takes command line arguments
if (scalar @ARGV == 8) {
- $grid = [
- [[$ARGV[0], $ARGV[1]], [$ARGV[2], $ARGV[3]]],
- [[$ARGV[4], $ARGV[5]], [$ARGV[6], $ARGV[7]]]
+ $payoff_matrices->[0] = [
+ [$ARGV[0], $ARGV[2]],
+ [$ARGV[4], $ARGV[6]]
];
-}
-
-my $pm = " Choice 1 | Choice 2\n" .
- " --------------------\n" .
- "Choice 1 | %3d, %3d | %3d, %3d\n" .
- "Choice 2 | %3d, %3d | %3d, %3d\n\n";
-printf(
- $pm,
- $grid->[0][0][0],
- $grid->[0][0][1],
- $grid->[0][1][0],
- $grid->[0][1][1],
- $grid->[1][0][0],
- $grid->[1][0][1],
- $grid->[1][1][0],
- $grid->[1][1][1]
-);
-
-
-my $choices = [[0,0], [0,0]];
-
-my $iterations = 10000;
-
-for (my $n = 0; $n < $iterations; $n++) {
- my $this_choice = choice($choices,$grid);
- $choices->[0][$this_choice->[0]]++;
- $choices->[1][$this_choice->[1]]++;
-}
-
-printf("Player Column:\t(%.0f%%, %.0f%%)\n",
- ($choices->[0][0] / $iterations) * 100,
- ($choices->[0][1] / $iterations) * 100);
-printf("Player Row:\t(%.0f%%, %.0f%%)\n",
- ($choices->[1][0] / $iterations) * 100,
- ($choices->[1][1] / $iterations) * 100);
-
-sub player_outcome {
- my ($player,$row,$col,$grid) = @_;
- return $grid->[$row][$col][$player];
-}
-
-sub player_slope {
- my ($player,$other_p,$grid) = @_;
- my $a = player_outcome($player,0,0,$grid);
- my $b = player_outcome($player,0,1,$grid);
- my $c = player_outcome($player,1,0,$grid);
- my $d = player_outcome($player,1,1,$grid);
- if ($player == 0) {
- return ($a-$b-$c+$d)*$other_p + ($b-$d);
- }
- return ($a-$b-$c+$d)*$other_p + ($c-$d);
-}
-
-sub distributions {
- my $choices = shift;
- # if no one has picked anything, guess
- if ($choices->[0][0] + $choices->[0][1] == 0 ||
- $choices->[1][0] + $choices->[1][1] == 0) {
- return [.5,.5];
- }
- return [
- $choices->[0][0] /
- ($choices->[0][0] + $choices->[0][1]),
- $choices->[1][0] /
- ($choices->[1][0] + $choices->[1][1])
+ $payoff_matrices->[1] = [
+ [$ARGV[1], $ARGV[5]],
+ [$ARGV[3], $ARGV[7]]
];
}
-sub choice {
- my ($choices, $grid) = @_;
- my $dist = distributions($choices);
- my $this_choice = [undef,undef];
- foreach my $player (0,1) {
- my $other = ($player==0) ? 1 : 0;
- my $slope = player_slope(
- $player,
- $dist->[$other],
- $grid
- );
- if ($slope > 0) {
- $this_choice->[$player] = 0;
+for (my $i = 0; $i < $iterations; $i++) {
+ # players must choose simultaneously--don't update the frequencies in loop
+ my $choices = [undef, undef];
+ foreach my $player (0, 1) {
+ # find the probability the other player will choose the first option
+ my $other_player = ($player + 1) % 2;
+ my $frequency = $frequencies->[$other_player];
+ my $chose_first = $frequency->[0];
+ my $total_choices = $chose_first + $frequency->[1];
+ my $p = .5;
+ unless ($total_choices == 0) {
+ $p = $chose_first / $total_choices;
}
- elsif ($slope < 0) {
- $this_choice->[$player] = 1;
+ # find the expected value of each option
+ # we'll skip the /2, since we're comparing them
+ my $pm = $payoff_matrices->[$player];
+ my $first_choice_ev = $p * $pm->[0][0] + (1 - $p) * $pm->[0][1];
+ my $second_choice_ev = $p * $pm->[1][0] + (1 - $p) * $pm->[1][1];
+ # pick the choice with the highest ev, or choose at random if they tie
+ if ($first_choice_ev != $second_choice_ev) {
+ $choices->[$player] = ($first_choice_ev > $second_choice_ev) ? 0 : 1;
}
else {
- if (rand() < .5) {
- $this_choice->[$player] = 0;
- }
- else {
- $this_choice->[$player] = 1;
- }
+ $choices->[$player] = int(rand() + .5);
}
}
- return $this_choice;
+ # update frequencies to reflect this round
+ foreach my $player (0, 1) {
+ $frequencies->[$player][$choices->[$player]]++;
+ }
+}
+
+my $pm = " Column 1 | Column 2\n" .
+ " ---------------------\n" .
+ "Row 1 | %3d, %3d | %3d, %3d\n" .
+ "Row 2 | %3d, %3d | %3d, %3d\n\n";
+printf(
+ $pm,
+ $payoff_matrices->[0][0][0],
+ $payoff_matrices->[1][0][0],
+ $payoff_matrices->[0][0][1],
+ $payoff_matrices->[1][1][0],
+ $payoff_matrices->[0][1][0],
+ $payoff_matrices->[1][0][1],
+ $payoff_matrices->[0][1][1],
+ $payoff_matrices->[1][1][1],
+);
+foreach my $player (0, 1) {
+ printf(
+ "Player %d: (%.3f%%, %.3f%%)\n",
+ $player,
+ ($frequencies->[$player][0] / $iterations) * 100,
+ ($frequencies->[$player][1] / $iterations) * 100
+ );
}