I just got back from a great camping holiday and as usual have started my return
by working through email. One particular email has asked if it was possible to
use the Axelrod library through the statistical
programming language: R. I have here and there heard of a variety of libraries
that let you call R from Python and vice versa so I thought it was worth
experimenting and seeing exactly how to do this. This blog post will be a very
brief demo of using the R package:
reticulate to interface to the Python
library for studying the Iterated Prisoners Dilemma.
Installing R as an anaconda user
My main language of choice is Python. I use the Anaconda distribution which can also be used to install R. Here are the commands I ran to get R on my machine:
$ conda install r-essentials
That brings down R without about 80 packages but does not include
so I install that also:
$ conda install -c mro r-reticulate
I expect that if you are an R user your main question would be how to install
Python. I am not entirely sure how the
reticulate package interfaces to
Python but I would recommend installing Python via the
anaconda distribution and then installing the
Axelrod library using:
pip install axelrod (or even
conda install axelrod).
Calling the Axelrod library in R
> library(reticulate) # Loading the `reticulate` library > axl <- import("axelrod") # Importing axelrod as axl
Now we can use this
axl object. First let us create a match between two
> tft <- axl$TitForTat() > alt <- axl$Alternator() > match <- axl$Match(c(tft, alt))
Playing this match outputs all the interactions:
> interactions <- match$play()
Once played the
match has attributes that contain things like the final score
> match$final_score_per_turn() 1. 2.49 2. 2.515
We see that in this case
Alternator gets a better score than
Tit For Tat.
It is also possible to create tournaments with the Axelrod library:
> players <- c(axl$Cooperator(), axl$Defector(), axl$TitForTat(), axl$Grudger()) > tournament <- axl$Tournament(players) > results <- tournament$play() > results$ranked_names 'Defector' 'Tit For Tat' 'Grudger' 'Cooperator'
As detailed in the documentation for creating a basic tournament we see that Defector wins.
The Axelrod library has a large number of
capabilities (including population dynamics) but one of the main treasures it
contains is the number of documented and tested strategies that are available.
> length(axl$strategies) 202
If you’d like to read more about the Axelrod library take a look at the documentation axelrod.readthedocs.io.
Nash equilibria in R
Another game theoretic library is called Nashpy and it is used to find Nash equilibria of 2 player games. As it requires using multi dimensional arrays as input (the payoff matrices) I though it might be helpful to include a quick example.
Here’s the Nash equilibria of Rock Paper Scissors:
> nash <- import("nash") > A = matrix(c(0, -1, 1, 1, 0, -1, -1, 1, 0), nrow=3, ncol=3) > rps <- nash$Game(A) > eq <- rps$vertex_enumeration()
vertex_enumeration method return a Python iterator object that can then be
iterated through in a step wise manner to search the equilibria (generators are
a fantastic part of the Python library with huge implication on memory
reticulate library has an
iter_next function that speaks to
> iter_next(eq) 1. 0.333333333333333 0.333333333333333 0.333333333333333 2. 0.333333333333333 0.333333333333333 0.333333333333333
We see that the equilibria for Rock Paper Scissors is for both players to uniformly randomly pick from Rock, Paper or Scissors.
Note that if we call
iter_next again we retrieve nothing (the generator has
gone through all possible vertex pairs):
> iter_next(eq) NULL
If you’d like to read more about the Nashpy library take a look at the documentation (which includes mathematical background to the implemented algorithms): nashpy.readthedocs.io.
I’m really impressed with
reticulate as an interface to Python from R. The
README seems to have sufficient information to get started: