Skip to content

Note

Click here to download the full example code

Prisoner's dilemma tournament

Agents play six-round prisoner's dilemmas against each other with strategies coded as genomes that answer the opponent's last two moves. The fittest reproduce with rare mutations, and the population never settles: cooperative eras, when reciprocating strategies dominate, alternate with eras of exploitation and mutual defection.

One hundred agents start from random genomes and evolve for 3000 steps. The default blueprint shows the mean score per round, which wanders between about 1.4, close to mutual defection at 1, and 2.7, close to mutual cooperation at 3.

import matplotlib.pyplot as plt
import numpy as np

from skcomplex.engine.runtime import Simulation
from skcomplex.engine.viz import RerunObserver
from skcomplex.models import create

MODEL = 'prisoners_dilemma_tournament'

system = create(MODEL, random_state=0)
observer = RerunObserver(MODEL, save_path=f'{MODEL}.rrd', blueprint='default', interval=12)
simulation = Simulation(system, observers=[observer], random_state=0).check().prepare().run(until=3000)

plot prisoners dilemma tournament

Open the recording in the Rerun viewer

Eras of strategies

Each gene answers one history of the opponent's last moves. The share of agents that cooperate on each history should switch between eras in step with the mean score: the score is high when the answer to the opponent's cooperation (genes C and CC) is cooperation, and falls when exploiters that defect after C spread.

trajectory = simulation.trajectory_
frames = range(0, len(trajectory.times), 10)
genes = np.array([np.asarray(trajectory.agents('agents', frame).values['genome']).mean(axis=0) for frame in frames])
scores = [np.mean(trajectory.agents('agents', frame).values['fitness']) for frame in frames]
times = np.asarray(trajectory.times)[list(frames)]
fig, (strategy, score) = plt.subplots(2, 1, figsize=(9, 5.5), sharex=True, height_ratios=[2, 1])
strategy.imshow(genes.T, aspect='auto', cmap='viridis', extent=(times[0], times[-1], 6.5, -0.5), vmin=0, vmax=1)
strategy.set_yticks(range(7), ['start', 'C', 'D', 'CC', 'CD', 'DC', 'DD'])
strategy.set_ylabel("opponent's last moves")
strategy.set_title('Share of agents that cooperate after each history (yellow: all cooperate)')
score.plot(times, scores)
score.set_xlabel('step')
score.set_ylabel('mean score per round')
fig.tight_layout()
plt.show()

Share of agents that cooperate after each history (yellow: all cooperate)

About the model

The evolution of strategies of the iterated prisoner's dilemma from random genomes.

References

  • Axelrod 1984
  • Downey 2018

Total running time of the script: ( 0 minutes 7.577 seconds)

Download Python source code: plot_prisoners_dilemma_tournament.py

Download Jupyter notebook: plot_prisoners_dilemma_tournament.ipynb

Gallery generated by mkdocs-gallery