Skip to content

Commit 6568fc4

Browse files
committed
2 parents 25eb130 + 68601b5 commit 6568fc4

File tree

4 files changed

+56
-110
lines changed

4 files changed

+56
-110
lines changed

axelrod/result_set.py

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import csv
33
import itertools
44
from multiprocessing import cpu_count
5-
from typing import List
65
import warnings
76

87
import numpy as np
@@ -118,12 +117,9 @@ def _reshape_out(
118117
alternative=0,
119118
)
120119

121-
self.wins = self._reshape_two_dim_list(
122-
sum_per_player_repetition_df["Win"])
123-
self.scores = self._reshape_two_dim_list(
124-
sum_per_player_repetition_df["Score"])
125-
self.normalised_scores = self._reshape_two_dim_list(
126-
normalised_scores_series)
120+
self.wins = self._reshape_two_dim_list(sum_per_player_repetition_df["Win"])
121+
self.scores = self._reshape_two_dim_list(sum_per_player_repetition_df["Score"])
122+
self.normalised_scores = self._reshape_two_dim_list(normalised_scores_series)
127123

128124
self.cooperation = self._build_cooperation(
129125
sum_per_player_opponent_df["Cooperation count"]
@@ -170,8 +166,7 @@ def _reshape_out(
170166
self.ranked_names = self._build_ranked_names()
171167

172168
self.payoff_matrix = self._build_summary_matrix(self.payoffs)
173-
self.payoff_stddevs = self._build_summary_matrix(self.payoffs,
174-
func=np.std)
169+
self.payoff_stddevs = self._build_summary_matrix(self.payoffs, func=np.std)
175170

176171
self.payoff_diffs_means = self._build_payoff_diffs_means()
177172
self.cooperating_rating = self._build_cooperating_rating()
@@ -271,9 +266,7 @@ def _build_good_partner_matrix(self, good_partner_series):
271266
# interactions.
272267
row.append(0)
273268
else:
274-
row.append(
275-
good_partner_dict.get((player_index, opponent_index),
276-
0))
269+
row.append(good_partner_dict.get((player_index, opponent_index), 0))
277270
good_partner_matrix.append(row)
278271
return good_partner_matrix
279272

@@ -341,15 +334,13 @@ def _build_normalised_state_distribution(self):
341334
for counter in player:
342335
total = sum(counter.values())
343336
counters.append(
344-
Counter(
345-
{key: value / total for key, value in counter.items()})
337+
Counter({key: value / total for key, value in counter.items()})
346338
)
347339
normalised_state_distribution.append(counters)
348340
return normalised_state_distribution
349341

350342
@update_progress_bar
351-
def _build_state_to_action_distribution(self,
352-
state_to_action_distribution_series):
343+
def _build_state_to_action_distribution(self, state_to_action_distribution_series):
353344
state_to_action_key_map = {
354345
"CC to C count": ((C, C), C),
355346
"CC to D count": ((C, C), D),
@@ -405,8 +396,7 @@ def _build_normalised_state_to_action_distribution(self):
405396
return normalised_state_to_action_distribution
406397

407398
@update_progress_bar
408-
def _build_initial_cooperation_count(self,
409-
initial_cooperation_count_series):
399+
def _build_initial_cooperation_count(self, initial_cooperation_count_series):
410400
initial_cooperation_count_dict = initial_cooperation_count_series.to_dict()
411401
initial_cooperation_count = [
412402
initial_cooperation_count_dict.get(player_index, 0)
@@ -421,7 +411,7 @@ def _build_normalised_cooperation(self):
421411
normalised_cooperation = [
422412
list(np.nan_to_num(row))
423413
for row in np.array(self.cooperation)
424-
/ sum(map(np.array, self.match_lengths))
414+
/ sum(map(np.array, self.match_lengths))
425415
]
426416
return normalised_cooperation
427417

@@ -436,8 +426,7 @@ def _build_initial_cooperation_rate(self, interactions_series):
436426
with warnings.catch_warnings():
437427
warnings.simplefilter("ignore")
438428
initial_cooperation_rate = list(
439-
np.nan_to_num(np.array(
440-
self.initial_cooperation_count) / interactions_array)
429+
np.nan_to_num(np.array(self.initial_cooperation_count) / interactions_array)
441430
)
442431
return initial_cooperation_rate
443432

@@ -462,8 +451,7 @@ def _build_eigenmoses_rating(self):
462451
The eigenmoses rating as defined in:
463452
http://www.scottaaronson.com/morality.pdf
464453
"""
465-
eigenvector, eigenvalue = eigen.principal_eigenvector(
466-
self.vengeful_cooperation)
454+
eigenvector, eigenvalue = eigen.principal_eigenvector(self.vengeful_cooperation)
467455

468456
return eigenvector.tolist()
469457

@@ -587,8 +575,7 @@ def _build_tasks(self, df):
587575
]
588576
sum_per_player_opponent_task = df.groupby(groups)[columns].sum()
589577

590-
ignore_self_interactions_task = df["Player index"] != df[
591-
"Opponent index"]
578+
ignore_self_interactions_task = df["Player index"] != df["Opponent index"]
592579
adf = df[ignore_self_interactions_task]
593580

594581
groups = ["Player index", "Repetition"]
@@ -602,8 +589,7 @@ def _build_tasks(self, df):
602589
groups = ["Player index"]
603590
column = "Initial cooperation"
604591
initial_cooperation_count_task = adf.groupby(groups)[column].sum()
605-
interactions_count_task = adf.groupby("Player index")[
606-
"Player index"].count()
592+
interactions_count_task = adf.groupby("Player index")["Player index"].count()
607593

608594
return (
609595
mean_per_reps_player_opponent_task,
@@ -623,18 +609,6 @@ def __eq__(self, other):
623609
other : axelrod.ResultSet
624610
Another results set against which to check equality
625611
"""
626-
627-
def list_equal_with_nans(v1: List[float], v2: List[float]) -> bool:
628-
"""Matches lists, accounting for NaNs."""
629-
if len(v1) != len(v2):
630-
return False
631-
for i1, i2 in zip(v1, v2):
632-
if np.isnan(i1) and np.isnan(i2):
633-
continue
634-
if i1 != i2:
635-
return False
636-
return True
637-
638612
return all(
639613
[
640614
self.wins == other.wins,
@@ -654,10 +628,8 @@ def list_equal_with_nans(v1: List[float], v2: List[float]) -> bool:
654628
self.cooperating_rating == other.cooperating_rating,
655629
self.good_partner_matrix == other.good_partner_matrix,
656630
self.good_partner_rating == other.good_partner_rating,
657-
list_equal_with_nans(self.eigenmoses_rating,
658-
other.eigenmoses_rating),
659-
list_equal_with_nans(self.eigenjesus_rating,
660-
other.eigenjesus_rating),
631+
self.eigenmoses_rating == other.eigenmoses_rating,
632+
self.eigenjesus_rating == other.eigenjesus_rating,
661633
]
662634
)
663635

@@ -727,8 +699,7 @@ def summarise(self):
727699
rates = []
728700
for state in states:
729701
counts = [
730-
counter[(state, C)] for counter in player if
731-
counter[(state, C)] > 0
702+
counter[(state, C)] for counter in player if counter[(state, C)] > 0
732703
]
733704

734705
if len(counts) > 0:
@@ -751,8 +722,7 @@ def summarise(self):
751722

752723
summary_data = []
753724
for rank, i in enumerate(self.ranking):
754-
data = list(summary_measures[i]) + state_prob[i] + state_to_C_prob[
755-
i]
725+
data = list(summary_measures[i]) + state_prob[i] + state_to_C_prob[i]
756726
summary_data.append(self.player(rank, *data))
757727

758728
return summary_data

axelrod/strategies/zero_determinant.py

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,44 @@
66

77

88
class LRPlayer(MemoryOnePlayer):
9-
"""Abstraction for Linear Relation players. These players enforce a linear
10-
difference in stationary payoffs s * (S_xy - l) = S_yx - l, with 0 <= l <= R.
11-
The parameter `s` is called the slope and the parameter `l` the
12-
baseline payoff. For extortionate strategies, the extortion factor is the
13-
inverse of the slope.
14-
15-
This parameterization is Equation 14 in
16-
http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0077886.
17-
See Figure 2 of the article for a more in-depth explanation.
9+
"""
10+
Abstraction for Linear Relation players. These players enforce a linear
11+
difference in stationary payoffs :math:`s (S_{xy} - l) = S_{yx} - l.`
12+
13+
The parameter :math:`s` is called the slope and the parameter :math:`l` the
14+
baseline payoff. For extortionate strategies, the extortion factor
15+
:math:`\chi` is the inverse of the slope :math:`s`.
16+
17+
For the standard prisoner's dilemma where :math:`T > R > P > S` and
18+
:math:`R > (T + S) / 2 > P`, a pair :math:`(l, s)` is enforceable iff
19+
20+
.. math::
21+
:nowrap:
22+
23+
\\begin{eqnarray}
24+
&P &<= l <= R \\\\
25+
&s_{min} &= -\min\\left( \\frac{T - l}{l - S}, \\frac{l - S}{T - l}\\right) <= s <= 1
26+
\\end{eqnarray}
27+
28+
And also that there exists :math:`\\phi` such that
29+
30+
.. math::
31+
:nowrap:
32+
33+
\\begin{eqnarray}
34+
p_1 &= P(C|CC) &= 1 - \\phi (1 - s)(R - l) \\\\
35+
p_2 &= P(C|CD) &= 1 - \\phi (s(l - S) + (T - l)) \\\\
36+
p_3 &= P(C|DC) &= \\phi ((l - S) + s(T - l)) \\\\
37+
p_4 &= P(C|DD) &= \\phi (1 - s)(l - P)
38+
\\end{eqnarray}
39+
40+
41+
These conditions also force :math:`\\phi >= 0`. For a given pair :math:`(l, s)`
42+
there may be multiple such :math:`\\phi`.
43+
44+
This parameterization is Equation 14 in [Hilbe2013]_.
45+
See Figure 2 of the article for a more in-depth explanation. Other game
46+
parameters can alter the relations and bounds above.
1847
1948
Names:
2049

axelrod/tests/unit/test_eigen.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,6 @@ def test_identity_matrices(self):
1515
self.assertAlmostEqual(evalue, 1)
1616
assert_array_almost_equal(evector, _normalise(numpy.ones(size)))
1717

18-
def test_zero_matrix(self):
19-
mat = numpy.array([[0, 0], [0, 0]])
20-
evector, evalue = principal_eigenvector(mat)
21-
self.assertTrue(numpy.isnan(evalue))
22-
self.assertTrue(numpy.isnan(evector[0]))
23-
self.assertTrue(numpy.isnan(evector[1]))
24-
2518
def test_2x2_matrix(self):
2619
mat = numpy.array([[2, 1], [1, 2]])
2720
evector, evalue = principal_eigenvector(mat)

axelrod/tests/unit/test_resultset.py

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import pandas as pd
88
from axelrod.result_set import create_counter_dict
99
from axelrod.tests.property import prob_end_tournaments, tournaments
10-
from numpy import mean, nan, nanmedian, std
10+
from numpy import mean, nanmedian, std
1111

1212
from dask.dataframe.core import DataFrame
1313
from hypothesis import given, settings
@@ -190,52 +190,6 @@ def test_init(self):
190190
self.assertEqual(rs.players, self.players)
191191
self.assertEqual(rs.num_players, len(self.players))
192192

193-
def _clear_matrix(self, matrix):
194-
for i in range(len(matrix)):
195-
for j in range(len(matrix[i])):
196-
matrix[i][j] = 0
197-
198-
def test_ne_vectors(self):
199-
rs_1 = axelrod.ResultSet(
200-
self.filename,
201-
self.players,
202-
self.repetitions
203-
)
204-
205-
rs_2 = axelrod.ResultSet(
206-
self.filename,
207-
self.players,
208-
self.repetitions
209-
)
210-
211-
# A different vector
212-
rs_2.eigenmoses_rating = (-1, -1, -1)
213-
214-
self.assertNotEqual(rs_1, rs_2)
215-
216-
def test_nan_vectors(self):
217-
rs_1 = axelrod.ResultSet(
218-
self.filename,
219-
self.players,
220-
self.repetitions
221-
)
222-
# Force a broken eigenmoses, by replacing vengeful_cooperation with
223-
# zeroes.
224-
self._clear_matrix(rs_1.vengeful_cooperation)
225-
rs_1.eigenmoses_rating = rs_1._build_eigenmoses_rating()
226-
227-
rs_2 = axelrod.ResultSet(
228-
self.filename,
229-
self.players,
230-
self.repetitions
231-
)
232-
# Force a broken eigenmoses, by replacing vengeful_cooperation with
233-
# zeroes.
234-
self._clear_matrix(rs_2.vengeful_cooperation)
235-
rs_2.eigenmoses_rating = rs_2._build_eigenmoses_rating()
236-
237-
self.assertEqual(rs_1, rs_2)
238-
239193
def test_init_multiprocessing(self):
240194
rs = axelrod.ResultSet(
241195
self.filename,

0 commit comments

Comments
 (0)