diff --git a/axelrod/result_set.py b/axelrod/result_set.py index bcb5f3de3..41ecade37 100644 --- a/axelrod/result_set.py +++ b/axelrod/result_set.py @@ -46,6 +46,7 @@ def __init__(self, players, turns, repetitions, outcome, self.ranking = None self.ranked_names = None self.payoff_matrix = None + self.wins = None self.cooperation = None self.normalised_cooperation = None self.vengeful_cooperation = None @@ -61,6 +62,7 @@ def __init__(self, players, turns, repetitions, outcome, self.ranked_names = self._ranked_names(self.ranking) self.payoff_matrix, self.payoff_stddevs = ( self._payoff_matrix(self.results['payoff'])) + self.wins = self._wins(self.results['payoff']) if 'cooperation' in self.results and with_morality: self.cooperation = self._cooperation(self.results['cooperation']) self.normalised_cooperation = ( @@ -250,6 +252,62 @@ def _payoff_matrix(self, payoff): stddevs[-1].append(dev) return averages, stddevs + def _wins(self, payoff): + """ + Args: + payoff (list): a matrix of the form: + + [ + [[a, j], [b, k], [c, l]], + [[d, m], [e, n], [f, o]], + [[g, p], [h, q], [i, r]], + ] + + i.e. one row per player, containing one element per opponent (in + order of player index) which lists payoffs for each repetition. + + Returns: + A wins matrix of the form: + + [ + [player1 wins in repetition1, player1 wins in repetition2], + [player2 wins in repetition1, player2 wins in repetition2], + [player3 wins in repetition1, player3 wins in repetition2], + ] + + i.e. one row per player which lists the total wins for that player + in each repetition. + """ + wins = [ + [0 for r in range(self.repetitions)] for p in range(self.nplayers)] + for player in range(self.nplayers): + for opponent in range(self.nplayers): + players = (player, opponent) + for repetition in range(self.repetitions): + payoffs = ( + payoff[player][opponent][repetition], + payoff[opponent][player][repetition]) + winner = self._winner(players, payoffs) + if winner is not None: + wins[winner][repetition] += 1 + return wins + + def _winner(self, players, payoffs): + """ + Args: + players (tuple): A tuple of player indexes + payoffs (tuple): A tuple of payoffs for the two players + Returns: + The index of the winning player or None if a draw + """ + if payoffs[0] == payoffs[1]: + return None + else: + winning_payoff = max(payoffs) + winning_payoff_index = payoffs.index(winning_payoff) + winner = players[winning_payoff_index] + return winner + def _cooperation(self, results): """ Args: diff --git a/axelrod/tests/unit/test_resultset.py b/axelrod/tests/unit/test_resultset.py index 41ec43d38..37923dfac 100644 --- a/axelrod/tests/unit/test_resultset.py +++ b/axelrod/tests/unit/test_resultset.py @@ -60,6 +60,7 @@ def setUpClass(cls): ] cls.expected_ranking = [0, 2, 1] cls.expected_ranked_names = ['Alternator', 'Random', 'TitForTat'] + cls.expected_wins = [[2, 0], [0, 0], [0, 2]] cls.expected_cooperation = [ [6, 6, 6], [6, 10, 6], @@ -154,6 +155,24 @@ def test_payoff_matrix(self): self.assertEqual(self.round_matrix( rs.payoff_stddevs, 2), self.expected_stddevs) + def test_wins(self): + rs = axelrod.ResultSet(self.players, 5, 2, self.test_outcome) + wins = rs.wins + self.assertEqual(wins, self.expected_wins) + + def test_winner(self): + rs = axelrod.ResultSet(self.players, 5, 2, self.test_outcome) + test_players = (8, 4) + test_payoffs = (34, 44) + winner = rs._winner(test_players, test_payoffs) + self.assertEqual(winner, 4) + test_payoffs = (54, 44) + winner = rs._winner(test_players, test_payoffs) + self.assertEqual(winner, 8) + test_payoffs = (34, 34) + winner = rs._winner(test_players, test_payoffs) + self.assertEqual(winner, None) + def test_cooperation(self): rs = axelrod.ResultSet(self.players, 5, 2, self.test_outcome) self.assertEqual( diff --git a/docs/usage.rst b/docs/usage.rst index 4dd5cdb37..b2628fa5d 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -257,7 +257,6 @@ this is shown here: :width: 50% :align: center - As an aside we can use this matrix with `gambit `_ or `sagemath `_ to compute the Nash equilibria for the corresponding normal form game. Here is how to do this in Sage:: # This is not part of the Axelrod module (run in Sage) @@ -284,6 +283,26 @@ Recall the ordering of the players:: Thus we see that there are multiple Nash equilibria for this game. Two pure equilibria that involve both players playing :code:`Defector` and both players playing :code:`TitForTat`. +The ResultSet object also includes the 'wins' attribute, which is derived from the payoff matrix and lists the number of wins for each player:: + + import axelrod + strategies = [s() for s in axelrod.demo_strategies] + tournament = axelrod.Tournament(strategies) + results = tournament.play() + results.wins + +The resulting wins matrix is:: + + [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [8, 8, 8, 8, 8, 8, 8, 8, 8, 8], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], + [4, 2, 2, 2, 4, 4, 4, 4, 4, 4] + ] + +which shows, for example, that Cooperator had 0 wins, Defector won 8 times in each repetition and Random won 4 times in the first repetition and twice in the second. + Noisy Tournaments ^^^^^^^^^^^^^^^^^