Repository: Axelrod-Python/Axelrod

Issue:
Error in payoff_diffs_means?
I think there's a bug for self interactions for the payoff_diffs_means (this only affects stochastic strategies):

```
>>> import axelrod as axl
>>> from numpy import mean
>>> axl.seed(0)
>>> players = [s() for s in axl.demo_strategies]
>>> tournament = axl.Tournament(players, repetitions=2, turns=5)
>>> results = tournament.play()
>>> results.score_diffs
[[[0.0, 0.0],
  [-5.0, -5.0],
  [0.0, 0.0],
  [0.0, 0.0],
  [-3.0, -1.9999999999999998]],
 [[5.0, 5.0], [0.0, 0.0], [1.0, 1.0], [1.0, 1.0], [1.0, 1.0]],
 [[0.0, 0.0], [-1.0, -1.0], [0.0, 0.0], [0.0, 0.0], [0.0, -1.0]],
 [[0.0, 0.0], [-1.0, -1.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]],
 [[3.0, 1.9999999999999998], [-1.0, -1.0], [0.0, 1.0], [0.0, 0.0], [2.0, 0.0]]]
```

If you look at the last element we see that over the two repetitions, the Random strategy scored 2 and 0 against itself (both positive numbers).

```
>>> results.payoff_diffs_means
[[0.0, -5.0, 0.0, 0.0, -2.5],
 [5.0, 0.0, 1.0, 1.0, 1.0],
 [0.0, -1.0, 0.0, 0.0, -0.5],
 [0.0, -1.0, 0.0, 0.0, 0.0],
 [2.5, -1.0, 0.5, 0.0, -1.0]]
```

That last mean is `-1.0` which is just the opposite mean (this is due to how the self interactions are handled and the fact that `build_payoff_diffs_means` rebuilds the payoff diff means from the interactions. A more direct calculation gives:

```
>>> [[mean(diff) for diff in player] for player in results.score_diffs]
[[0.0, -5.0, 0.0, 0.0, -2.5],
 [5.0, 0.0, 1.0, 1.0, 1.0],
 [0.0, -1.0, 0.0, 0.0, -0.5],
 [0.0, -1.0, 0.0, 0.0, 0.0],
 [2.5, -1.0, 0.5, 0.0, 1.0]]
```

which is the expected result. Just about to push a PR fix that replaces `build_payoff_diffs_means` with this.

Discussion:

Patch:
diff --git a/axelrod/result_set.py b/axelrod/result_set.py
index 6ec59ae6..0a8b4fb2 100644
--- a/axelrod/result_set.py
+++ b/axelrod/result_set.py
@@ -464,28 +464,8 @@ class ResultSet(object):
             Where pij is the mean difference of the
             scores per turn between player i and j in repetition m.
         """
-        plist = list(range(self.nplayers))
-        payoff_diffs_means = [[0 for opponent in plist] for player in plist]
-
-        for player in plist:
-            for opponent in plist:
-                diffs = []
-                for index_pair, repetitions in self.interactions.items():
-                    if (player, opponent) == index_pair:
-                        for interaction in repetitions:
-                            scores = iu.compute_final_score_per_turn(interaction,
-                                                                     self.game)
-                            diffs.append(scores[0] - scores[1])
-                    elif (opponent, player) == index_pair:
-                        for interaction in repetitions:
-                            scores = iu.compute_final_score_per_turn(interaction,
-                                                                    self.game)
-                            diffs.append(scores[1] - scores[0])
-                if diffs:
-                    payoff_diffs_means[player][opponent] = mean(diffs)
-                else:
-                    payoff_diffs_means[player][opponent] = 0
-
+        payoff_diffs_means = [[mean(diff) for diff in player]
+                              for player in self.score_diffs]
         return payoff_diffs_means
 
     @update_progress_bar


Test patch:
diff --git a/axelrod/tests/unit/test_resultset.py b/axelrod/tests/unit/test_resultset.py
index 5a81687b..dccd3e8f 100644
--- a/axelrod/tests/unit/test_resultset.py
+++ b/axelrod/tests/unit/test_resultset.py
@@ -364,6 +364,14 @@ class TestResultSet(unittest.TestCase):
         for j, rate in enumerate(rs.eigenmoses_rating):
             self.assertAlmostEqual(rate, self.expected_eigenmoses_rating[j])
 
+    def test_self_interaction_for_random_strategies(self):
+        # Based on https://github.com/Axelrod-Python/Axelrod/issues/670
+        axelrod.seed(0)
+        players = [s() for s in axelrod.demo_strategies]
+        tournament = axelrod.Tournament(players, repetitions=2, turns=5)
+        results = tournament.play()
+        self.assertEqual(results.payoff_diffs_means[-1][-1], 1.0)
+
 
 class TestResultSetFromFile(unittest.TestCase):
     tmp_file = tempfile.NamedTemporaryFile(mode='w', delete=False)