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 reticulate 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 players:

> 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 per turn:

> 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. In version 3.5.0:

> length(axl$strategies)

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()

The 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 footprints).

Thankfully the reticulate library has an iter_next function that speaks to these generators:

> 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)

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: github.com/rstudio/reticulate#overview

EDIT: Here is a Jupyter notebook with all the above code.