rockemsockemrationalagents

find nash equilibrium with fictitious play
git clone https://wehaveforgeathome.hates.computer/rockemsockemrationalagents.git
Log | Files | Refs | LICENSE

resera.pl (2379B)


      1 #!/usr/bin/perl
      2 
      3 use strict;
      4 use warnings;
      5 
      6 my $iterations = 100000;
      7 
      8 my $frequencies = [
      9   [0, 0],
     10   [0, 0]
     11 ];
     12 
     13 # default taken from http://en.wikipedia.org/wiki/Prisoner%27s_dilemma
     14 my $payoff_matrices = [
     15   [
     16     [3, 0],
     17     [5, 1]
     18   ],
     19   [
     20     [3, 0],
     21     [5, 1]
     22   ]
     23 ];
     24 
     25 # also takes command line arguments
     26 if (scalar @ARGV == 8) {
     27   $payoff_matrices->[0] = [
     28     [$ARGV[0], $ARGV[2]],
     29     [$ARGV[4], $ARGV[6]]
     30   ];
     31   $payoff_matrices->[1] = [
     32     [$ARGV[1], $ARGV[5]],
     33     [$ARGV[3], $ARGV[7]]
     34   ];
     35 }
     36 
     37 for (my $i = 0; $i < $iterations; $i++) {
     38   # players must choose simultaneously--don't update the frequencies in loop
     39   my $choices = [undef, undef];
     40   foreach my $player (0, 1) {
     41     # find the probability the other player will choose the first option
     42     my $other_player = ($player + 1) % 2;
     43     my $frequency = $frequencies->[$other_player];
     44     my $chose_first = $frequency->[0];
     45     my $total_choices = $chose_first + $frequency->[1];
     46     my $p = .5;
     47     unless ($total_choices == 0) {
     48       $p = $chose_first / $total_choices;
     49     }
     50     # find the expected value of each option
     51     # we'll skip the /2, since we're comparing them
     52     my $pm = $payoff_matrices->[$player];
     53     my $first_choice_ev = $p * $pm->[0][0] + (1 - $p) * $pm->[0][1];
     54     my $second_choice_ev = $p * $pm->[1][0] + (1 - $p) * $pm->[1][1];
     55     # pick the choice with the highest ev, or choose at random if they tie
     56     if ($first_choice_ev != $second_choice_ev) {
     57       $choices->[$player] = ($first_choice_ev > $second_choice_ev) ? 0 : 1;
     58     }
     59     else {
     60       $choices->[$player] = int(rand() + .5);
     61     }
     62   }
     63   # update frequencies to reflect this round
     64   foreach my $player (0, 1) {
     65     $frequencies->[$player][$choices->[$player]]++;
     66   }
     67 }
     68 
     69 my $pm =  "        Column 1 | Column 2\n" .
     70           "       ---------------------\n" .
     71           "Row 1 | %3d, %3d | %3d, %3d\n" .
     72           "Row 2 | %3d, %3d | %3d, %3d\n\n";
     73 printf(
     74   $pm,
     75   $payoff_matrices->[0][0][0],
     76   $payoff_matrices->[1][0][0],
     77   $payoff_matrices->[0][0][1],
     78   $payoff_matrices->[1][1][0],
     79   $payoff_matrices->[0][1][0],
     80   $payoff_matrices->[1][0][1],
     81   $payoff_matrices->[0][1][1],
     82   $payoff_matrices->[1][1][1],
     83 );
     84 foreach my $player (0, 1) {
     85   printf(
     86     "Player %d: (%.3f%%, %.3f%%)\n",
     87     $player,
     88     ($frequencies->[$player][0] / $iterations) * 100,
     89     ($frequencies->[$player][1] / $iterations) * 100
     90   );
     91 }