Skip to content

Commit 22e0357

Browse files
authored
Merge pull request #820 from Axelrod-Python/testing
Rework basic tests and update a number of explicit tests
2 parents 5bf6f10 + a6b0087 commit 22e0357

File tree

104 files changed

+1710
-2334
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+1710
-2334
lines changed

axelrod/actions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
Action = NewType('Action', str)
44

5+
56
class Actions(object):
67
C = 'C'
78
D = 'D'

axelrod/deterministic_cache.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
class DeterministicCache(UserDict):
8-
"""A class to cache the results of deterministic matches
8+
"""A class to cache the results of deterministic matches.
99
1010
For fixed length matches with no noise between pairs of deterministic
1111
players, the results will always be the same. We can hold those results
@@ -41,7 +41,8 @@ def __init__(self, file_name=None):
4141
if file_name is not None:
4242
self.load(file_name)
4343

44-
def _key_transform(self, key):
44+
@staticmethod
45+
def _key_transform(key):
4546
"""
4647
Parameters
4748
----------
@@ -67,16 +68,18 @@ def __setitem__(self, key, value):
6768

6869
if not self._is_valid_key(key):
6970
raise ValueError(
70-
'Key must be a tuple of 2 deterministic axelrod Player classes and an integer')
71+
"Key must be a tuple of 2 deterministic axelrod Player classes "
72+
"and an integer")
7173

7274
if not self._is_valid_value(value):
7375
raise ValueError(
7476
'Value must be a list with length equal to turns attribute')
7577

7678
super().__setitem__(self._key_transform(key), value)
7779

78-
def _is_valid_key(self, key):
79-
"""Validate a proposed dictionary key
80+
@staticmethod
81+
def _is_valid_key(key):
82+
"""Validate a proposed dictionary key.
8083
8184
Parameters
8285
----------
@@ -112,8 +115,9 @@ def _is_valid_key(self, key):
112115

113116
return True
114117

115-
def _is_valid_value(self, value):
116-
"""Validate a proposed dictionary value
118+
@staticmethod
119+
def _is_valid_value(value):
120+
"""Validate a proposed dictionary value.
117121
118122
Parameters
119123
----------
@@ -130,7 +134,7 @@ def _is_valid_value(self, value):
130134
return True
131135

132136
def save(self, file_name):
133-
"""Serialise the cache dictionary to a file
137+
"""Serialise the cache dictionary to a file.
134138
135139
Parameters
136140
----------
@@ -142,7 +146,7 @@ def save(self, file_name):
142146
return True
143147

144148
def load(self, file_name):
145-
"""Load a previously saved cache into the dictionary
149+
"""Load a previously saved cache into the dictionary.
146150
147151
Parameters
148152
----------
@@ -156,5 +160,6 @@ def load(self, file_name):
156160
self.data = data
157161
else:
158162
raise ValueError(
159-
'Cache file exists but is not the correct format. Try deleting and re-building the cache file.')
163+
"Cache file exists but is not the correct format. "
164+
"Try deleting and re-building the cache file.")
160165
return True

axelrod/ecosystem.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33

44
class Ecosystem(object):
5-
"""Create an ecosystem based on the payoff matrix from an Axelrod tournament."""
5+
"""Create an ecosystem based on the payoff matrix from an Axelrod
6+
tournament."""
67

78
def __init__(self, results, fitness=None, population=None):
89

axelrod/eigen.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ def power_iteration(mat: numpy.matrix, initial: numpy.ndarray) -> numpy.ndarray:
4545
yield vec
4646

4747

48-
def principal_eigenvector(mat: numpy.matrix, maximum_iterations=1000, max_error=1e-3) -> Tuple[numpy.ndarray, float]:
48+
def principal_eigenvector(mat: numpy.matrix, maximum_iterations=1000,
49+
max_error=1e-3) -> Tuple[numpy.ndarray, float]:
4950
"""
5051
Computes the (normalised) principal eigenvector of the given matrix.
5152

axelrod/fingerprint.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
import axelrod as axl
2-
import numpy as np
1+
from collections import namedtuple
2+
from tempfile import NamedTemporaryFile
33
import matplotlib.pyplot as plt
4+
import numpy as np
45
import tqdm
5-
from axelrod.strategy_transformers import JossAnnTransformer, DualTransformer
6-
from axelrod.interaction_utils import compute_final_score_per_turn, read_interactions_from_file
6+
import axelrod as axl
7+
78
from axelrod import on_windows
8-
from collections import namedtuple
9-
from tempfile import NamedTemporaryFile
9+
from axelrod.strategy_transformers import JossAnnTransformer, DualTransformer
10+
from axelrod.interaction_utils import (
11+
compute_final_score_per_turn, read_interactions_from_file)
1012

1113

1214
Point = namedtuple('Point', 'x y')
@@ -95,7 +97,8 @@ def create_jossann(point, probe):
9597
init_args = ()
9698

9799
if x + y >= 1:
98-
joss_ann = DualTransformer()(JossAnnTransformer((1 - x, 1 - y))(probe))(*init_args)
100+
joss_ann = DualTransformer()(
101+
JossAnnTransformer((1 - x, 1 - y))(probe))(*init_args)
99102
else:
100103
joss_ann = JossAnnTransformer((x, y))(probe)(*init_args)
101104
return joss_ann
@@ -308,7 +311,8 @@ def reshape_data(data, points, size):
308311
plotting_data = np.flipud(shaped_data)
309312
return plotting_data
310313

311-
def plot(self, col_map='seismic', interpolation='none', title=None, colorbar=True, labels=True):
314+
def plot(self, col_map='seismic', interpolation='none', title=None,
315+
colorbar=True, labels=True):
312316
"""Plot the results of the spatial tournament.
313317
314318
Parameters

axelrod/interaction_utils.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""
32
Functions to calculate results from interactions. Interactions are lists of the
43
form:
@@ -8,11 +7,11 @@
87
This is used by both the Match class and the ResultSet class which analyse
98
interactions.
109
"""
11-
import csv
1210
from collections import Counter
11+
import csv
1312

14-
from .game import Game
1513
from axelrod import Actions
14+
from .game import Game
1615

1716
import tqdm
1817

axelrod/load_data_.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def load_file(filename, directory):
1515
rows.append(s)
1616
return rows
1717

18+
1819
def load_weights(filename="ann_weights.csv", directory="data"):
1920
"""Load Neural Network Weights."""
2021
rows = load_file(filename, directory)
@@ -27,6 +28,7 @@ def load_weights(filename="ann_weights.csv", directory="data"):
2728
d[name] = (num_features, num_hidden, weights)
2829
return d
2930

31+
3032
def load_lookerup_tables(filename="lookup_tables.csv", directory="data"):
3133
"""Load lookup tables."""
3234
rows = load_file(filename, directory)
@@ -36,6 +38,7 @@ def load_lookerup_tables(filename="lookup_tables.csv", directory="data"):
3638
d[(name, int(a), int(b), int(c))] = (initial, pattern)
3739
return d
3840

41+
3942
def load_pso_tables(filename="pso_gambler.csv", directory="data"):
4043
"""Load lookup tables."""
4144
rows = load_file(filename, directory)

axelrod/match.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
# -*- coding: utf-8 -*-
21
from axelrod import Actions, Game
2+
import axelrod.interaction_utils as iu
33
from .deterministic_cache import DeterministicCache
44

5-
import axelrod.interaction_utils as iu
65

76
C, D = Actions.C, Actions.D
87

@@ -85,7 +84,7 @@ def _stochastic(self):
8584
@property
8685
def _cache_update_required(self):
8786
"""
88-
A boolean to show whether the deterministic cache should be updated
87+
A boolean to show whether the deterministic cache should be updated.
8988
"""
9089
return (
9190
not self.noise and
@@ -112,7 +111,7 @@ def play(self):
112111
113112
i.e. One entry per turn containing a pair of actions.
114113
"""
115-
if (self._stochastic or self._cache_key not in self._cache):
114+
if self._stochastic or (self._cache_key not in self._cache):
116115
turn = 0
117116
for p in self.players:
118117
p.reset()
@@ -135,15 +134,15 @@ def scores(self):
135134
return iu.compute_scores(self.result, self.game)
136135

137136
def final_score(self):
138-
"""Returns the final score for a Match"""
137+
"""Returns the final score for a Match."""
139138
return iu.compute_final_score(self.result, self.game)
140139

141140
def final_score_per_turn(self):
142-
"""Returns the mean score per round for a Match"""
141+
"""Returns the mean score per round for a Match."""
143142
return iu.compute_final_score_per_turn(self.result, self.game)
144143

145144
def winner(self):
146-
"""Returns the winner of the Match"""
145+
"""Returns the winner of the Match."""
147146
winner_index = iu.compute_winner_index(self.result, self.game)
148147
if winner_index is False: # No winner
149148
return False
@@ -152,11 +151,11 @@ def winner(self):
152151
return self.players[winner_index]
153152

154153
def cooperation(self):
155-
"""Returns the count of cooperations by each player"""
154+
"""Returns the count of cooperations by each player."""
156155
return iu.compute_cooperations(self.result)
157156

158157
def normalised_cooperation(self):
159-
"""Returns the count of cooperations by each player per turn"""
158+
"""Returns the count of cooperations by each player per turn."""
160159
return iu.compute_normalised_cooperation(self.result)
161160

162161
def state_distribution(self):

axelrod/match_generator.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,8 @@ def build_single_match_params(self):
7777

7878
def __len__(self):
7979
"""
80-
The size of the generator.
81-
This corresponds to the number of match chunks as it
82-
ignores repetitions.
80+
The size of the generator. This corresponds to the number of match
81+
chunks as it ignores repetitions.
8382
"""
8483
n = len(self.players)
8584
num_matches = int(n * (n - 1) // 2 + n)
@@ -170,9 +169,10 @@ def estimated_size(self):
170169

171170
def graph_is_connected(edges, players):
172171
"""
173-
Test if a set of edges defines a complete graph on a set of players.
174-
175-
This is used by the spatial tournaments.
172+
Test if the set of edges defines a graph in which each player is connected
173+
to at least one other player. This function does not test if the graph is
174+
fully connected in the sense that each node is reachable from every other
175+
node.
176176
177177
Parameters:
178178
-----------
@@ -181,7 +181,7 @@ def graph_is_connected(edges, players):
181181
182182
Returns:
183183
--------
184-
boolean : True if the graph is connected
184+
boolean : True if the graph is connected as specified above.
185185
"""
186186
# Check if all players are connected.
187187
player_indices = set(range(len(players)))
@@ -193,7 +193,6 @@ def graph_is_connected(edges, players):
193193
return player_indices == node_indices
194194

195195

196-
197196
class SpatialMatches(RoundRobinMatches):
198197
"""
199198
A class that generates spatially-structured matches.

0 commit comments

Comments
 (0)