Accessing tournament results

This tutorial will show you how to access the various results of a tournament:

  • Wins: the number of matches won by each player
  • Match lengths: the number of turns of each match played by each player (relevant for tournaments with probabilistic ending).
  • Scores: the total scores of each player.
  • Normalised scores: the scores normalised by matches played and turns.
  • Ranking: ranking of players based on median score.
  • Ranked names: names of players in ranked order.
  • Payoffs: average payoff per turn of each player.
  • Payoff matrix: the payoff matrix showing the payoffs of each row player against each column player.
  • Payoff standard deviation: the standard deviation of the payoffs matrix.
  • Score differences: the score difference between each player.
  • Payoff difference means: the mean score differences.
  • Cooperation counts: the number of times each player cooperated.
  • Normalised cooperation: cooperation count per turn.
  • Normalised cooperation: cooperation count per turn.
  • State distribution: the count of each type of state of a match
  • Normalised state distribution: the normalised count of each type of state of a match
  • State to action distribution: the count of each type of state to action pair of a match
  • Normalised state distribution: the normalised count of each type of state to action pair of a match
  • Initial cooperation count: the count of initial cooperation by each player.
  • Initial cooperation rate: the rate of initial cooperation by each player.
  • Cooperation rating: cooperation rating of each player
  • Vengeful cooperation: a morality metric from the literature (see Morality Metrics).
  • Good partner matrix: a morality metric from [Singer-Clark2014].
  • Good partner rating: a morality metric from [Singer-Clark2014].
  • Eigenmoses rating: a morality metric from [Singer-Clark2014].
  • Eigenjesus rating: a morality metric from [Singer-Clark2014].

As shown in Creating and running a simple tournament let us create a tournament:

>>> import axelrod as axl
>>> players = [axl.Cooperator(), axl.Defector(),
...            axl.TitForTat(), axl.Grudger()]
>>> tournament = axl.Tournament(players, turns=10, repetitions=3)
>>> results = tournament.play()

Wins

This gives the number of wins obtained by each player:

>>> results.wins
[[0, 0, 0], [3, 3, 3], [0, 0, 0], [0, 0, 0]]

The Defector is the only player to win any matches (all other matches are ties).

Match lengths

This gives the length of the matches played by each player:

>>> import pprint  # Nicer formatting of output
>>> pprint.pprint(results.match_lengths)
[[[10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10]],
 [[10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10]],
 [[10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10], [10, 10, 10, 10]]]

Every player plays 10 turns against every other player (including themselves) for every repetition of the tournament.

Scores

This gives all the total tournament scores (per player and per repetition):

>>> results.scores
[[60, 60, 60], [78, 78, 78], [69, 69, 69], [69, 69, 69]]

Normalised scores

This gives the scores, averaged per opponent and turns:

>>> results.normalised_scores  
[[2.0, 2.0, 2.0], [2.6, 2.6, 2.6], [2.3, 2.3, 2.3], [2.3, 2.3, 2.3]]

We see that Cooperator got on average a score of 2 per turn per opponent:

>>> results.normalised_scores[0]
[2.0, 2.0, 2.0]

Ranking

This gives the ranked index of each player:

>>> results.ranking
[1, 2, 3, 0]

The first player has index 1 (Defector) and the last has index 0 (Cooperator).

Ranked names

This gives the player names in ranked order:

>>> results.ranked_names
['Defector', 'Tit For Tat', 'Grudger', 'Cooperator']

Payoffs

This gives for each player, against each opponent every payoff received for each repetition:

>>> pprint.pprint(results.payoffs)
[[[3.0, 3.0, 3.0], [0.0, 0.0, 0.0], [3.0, 3.0, 3.0], [3.0, 3.0, 3.0]],
 [[5.0, 5.0, 5.0], [1.0, 1.0, 1.0], [1.4, 1.4, 1.4], [1.4, 1.4, 1.4]],
 [[3.0, 3.0, 3.0], [0.9, 0.9, 0.9], [3.0, 3.0, 3.0], [3.0, 3.0, 3.0]],
 [[3.0, 3.0, 3.0], [0.9, 0.9, 0.9], [3.0, 3.0, 3.0], [3.0, 3.0, 3.0]]]

Payoff matrix

This gives the mean payoff of each player against every opponent:

>>> pprint.pprint(results.payoff_matrix)  
[[3.0, 0.0, 3.0, 3.0],
 [5.0, 1.0, 1.4, 1.4],
 [3.0, 0.9, 3.0, 3.0],
 [3.0, 0.9, 3.0, 3.0]]

We see that the Cooperator gets a mean score of 3 against all players except the Defector:

>>> results.payoff_matrix[0]
[3.0, 0.0, 3.0, 3.0]

Payoff standard deviation

This gives the standard deviation of the payoff of each player against every opponent:

>>> pprint.pprint(results.payoff_stddevs)  
[[0.0, 0.0, 0.0, 0.0],
 [0.0, 0.0, 2.2, 2.2],
 [0.0, 0.0, 0.0, 0.0],
 [0.0, 0.0, 0.0, 0.0]]

We see that there is no variation for the payoff for Cooperator:

>>> results.payoff_stddevs[0]
[0.0, 0.0, 0.0, 0.0]

Score differences

This gives the score difference for each player against each opponent for every repetition:

>>> pprint.pprint(results.score_diffs)  
[[[0.0, 0.0, 0.0], [-5.0, -5.0, -5.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
 [[5.0, 5.0, 5.0], [0.0, 0.0, 0.0], [0.5, 0.5, 0.5], [0.5, 0.5, 0.5]],
 [[0.0, 0.0, 0.0], [-0.5, -0.5, -0.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]],
 [[0.0, 0.0, 0.0], [-0.5, -0.5, -0.5], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]]

We see that Cooperator has no difference in score with all players except against the Defector:

>>> results.score_diffs[0][1]
[-5.0, -5.0, -5.0]

Payoff difference means

This gives the mean payoff differences over each repetition:

>>> pprint.pprint(results.payoff_diffs_means)  
[[0.0, -5.0, 0.0, 0.0],
 [5.0, 0.0, 0.49999999999999983, 0.49999999999999983],
 [0.0, -0.49999999999999983, 0.0, 0.0],
 [0.0, -0.49999999999999983, 0.0, 0.0]]

Here is the mean payoff difference for the Cooperator strategy, shows that it has no difference with all players except against the Defector:

>>> results.payoff_diffs_means[0]
[0.0, -5.0, 0.0, 0.0]

Cooperation counts

This gives a total count of cooperation for each player against each opponent:

>>> results.cooperation
[[0, 30, 30, 30], [0, 0, 0, 0], [30, 3, 0, 30], [30, 3, 30, 0]]

Normalised cooperation

This gives the average rate of cooperation against each opponent:

>>> pprint.pprint(results.normalised_cooperation)  
[[1.0, 1.0, 1.0, 1.0],
 [0.0, 0.0, 0.0, 0.0],
 [1.0, 0.1, 1.0, 1.0],
 [1.0, 0.1, 1.0, 1.0]]

We see that Cooperator for all the rounds (as expected):

>>> results.normalised_cooperation[0]
[1.0, 1.0, 1.0, 1.0]

State distribution counts

This gives a total state count against each opponent. A state corresponds to 1 turn of a match and can be one of ('C', 'C'), ('C', 'D'), ('D', 'C'), ('D', 'D') where the first element is the action of the player in question and the second the action of the opponent:

>>> pprint.pprint(results.state_distribution)
[[Counter(),
  Counter({('C', 'D'): 30}),
  Counter({('C', 'C'): 30}),
  Counter({('C', 'C'): 30})],
 [Counter({('D', 'C'): 30}),
  Counter(),
  Counter({('D', 'D'): 27, ('D', 'C'): 3}),
  Counter({('D', 'D'): 27, ('D', 'C'): 3})],
 [Counter({('C', 'C'): 30}),
  Counter({('D', 'D'): 27, ('C', 'D'): 3}),
  Counter(),
  Counter({('C', 'C'): 30})],
 [Counter({('C', 'C'): 30}),
  Counter({('D', 'D'): 27, ('C', 'D'): 3}),
  Counter({('C', 'C'): 30}),
  Counter()]]

Normalised state distribution

This gives the average rate state distribution against each opponent. A state corresponds to 1 turn of a match and can be one of ('C', 'C'), ('C', 'D'), ('D', 'C'), ('D', 'D') where the first element is the action of the player in question and the second the action of the opponent:

>>> pprint.pprint(results.normalised_state_distribution)
[[Counter(),
  Counter({('C', 'D'): 1.0}),
  Counter({('C', 'C'): 1.0}),
  Counter({('C', 'C'): 1.0})],
 [Counter({('D', 'C'): 1.0}),
  Counter(),
  Counter({('D', 'D'): 0.9, ('D', 'C'): 0.1}),
  Counter({('D', 'D'): 0.9, ('D', 'C'): 0.1})],
 [Counter({('C', 'C'): 1.0}),
  Counter({('D', 'D'): 0.9, ('C', 'D'): 0.1}),
  Counter(),
  Counter({('C', 'C'): 1.0})],
 [Counter({('C', 'C'): 1.0}),
  Counter({('D', 'D'): 0.9, ('C', 'D'): 0.1}),
  Counter({('C', 'C'): 1.0}),
  Counter()]]

State to action distribution counts

This gives a total state action pair count against each opponent. A state corresponds to 1 turn of a match and can be one of ('C', 'C'), ('C', 'D'), ('D', 'C'), ('D', 'D') where the first element is the action of the player in question and the second the action of the opponent:

>>> pprint.pprint(results.state_to_action_distribution)  
[[Counter(),
  Counter({(('C', 'D'), 'C'): 27}),
  Counter({(('C', 'C'), 'C'): 27}),
  Counter({(('C', 'C'), 'C'): 27})],
 [Counter({(('D', 'C'), 'D'): 27}),
  Counter(),
  Counter({(('D', 'D'), 'D'): 24, (('D', 'C'), 'D'): 3}),
  Counter({(('D', 'D'), 'D'): 24, (('D', 'C'), 'D'): 3})],
 [Counter({(('C', 'C'), 'C'): 27}),
  Counter({(('D', 'D'), 'D'): 24, (('C', 'D'), 'D'): 3}),
  Counter(),
  Counter({(('C', 'C'), 'C'): 27})],
 [Counter({(('C', 'C'), 'C'): 27}),
  Counter({(('D', 'D'), 'D'): 24, (('C', 'D'), 'D'): 3}),
  Counter({(('C', 'C'), 'C'): 27}),
  Counter()]]

Normalised state to action distribution

This gives the average rate state to action pair distribution against each opponent. A state corresponds to 1 turn of a match and can be one of ('C', 'C'), ('C', 'D'), ('D', 'C'), ('D', 'D') where the first element is the action of the player in question and the second the action of the opponent:

>>> pprint.pprint(results.normalised_state_to_action_distribution) 
[[Counter(),
  Counter({(('C', 'D'), 'C'): 1.0}),
  Counter({(('C', 'C'), 'C'): 1.0}),
  Counter({(('C', 'C'), 'C'): 1.0})],
 [Counter({(('D', 'C'), 'D'): 1.0}),
  Counter(),
  Counter({(('D', 'C'), 'D'): 1.0, (('D', 'D'), 'D'): 1.0}),
  Counter({(('D', 'C'), 'D'): 1.0, (('D', 'D'), 'D'): 1.0})],
 [Counter({(('C', 'C'), 'C'): 1.0}),
  Counter({(('C', 'D'), 'D'): 1.0, (('D', 'D'), 'D'): 1.0}),
  Counter(),
  Counter({(('C', 'C'), 'C'): 1.0})],
 [Counter({(('C', 'C'), 'C'): 1.0}),
  Counter({(('C', 'D'), 'D'): 1.0, (('D', 'D'), 'D'): 1.0}),
  Counter({(('C', 'C'), 'C'): 1.0}),
  Counter()]]

Initial cooperation counts

This gives the count of cooperations made by each player during the first turn of every match:

>>> results.initial_cooperation_count
[9, 0, 9, 9]

Each player plays an opponent a total of 9 times (3 opponents and 3 repetitions). Apart from the Defector, they all cooperate on the first turn.

Initial cooperation rates

This gives the rate of which a strategy cooperates during the first turn:

>>> results.initial_cooperation_rate
[1.0, 0.0, 1.0, 1.0]

Morality Metrics

The following morality metrics are available, they are calculated as a function of the cooperation rating:

>>> results.cooperating_rating
[1.0, 0.0, 0.7, 0.7]
>>> pprint.pprint(results.vengeful_cooperation)  
[[1.0, 1.0, 1.0, 1.0],
 [-1.0, -1.0, -1.0, -1.0],
 [1.0, -0.8, 1.0, 1.0],
 [1.0, -0.78 1.0, 1.0]]
>>> pprint.pprint(results.good_partner_matrix)
[[0, 3, 3, 3], [0, 0, 0, 0], [3, 3, 0, 3], [3, 3, 3, 0]]
>>> pprint.pprint(results.good_partner_rating)
[1.0, 0.0, 1.0, 1.0]
>>> results.eigenmoses_rating
[0.37..., -0.37..., 0.59..., 0.59...]
>>> results.eigenjesus_rating
[0.57..., 0.0, 0.57..., 0.57...]

For more information about these see Morality Metrics.