Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework basic tests and update a number of explicit tests #820

Merged
merged 11 commits into from
Jan 18, 2017
1 change: 1 addition & 0 deletions axelrod/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

Action = NewType('Action', str)


class Actions(object):
C = 'C'
D = 'D'
Expand Down
25 changes: 15 additions & 10 deletions axelrod/deterministic_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class DeterministicCache(UserDict):
"""A class to cache the results of deterministic matches
"""A class to cache the results of deterministic matches.

For fixed length matches with no noise between pairs of deterministic
players, the results will always be the same. We can hold those results
Expand Down Expand Up @@ -41,7 +41,8 @@ def __init__(self, file_name=None):
if file_name is not None:
self.load(file_name)

def _key_transform(self, key):
@staticmethod
def _key_transform(key):
"""
Parameters
----------
Expand All @@ -67,16 +68,18 @@ def __setitem__(self, key, value):

if not self._is_valid_key(key):
raise ValueError(
'Key must be a tuple of 2 deterministic axelrod Player classes and an integer')
"Key must be a tuple of 2 deterministic axelrod Player classes "
"and an integer")

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

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

def _is_valid_key(self, key):
"""Validate a proposed dictionary key
@staticmethod
def _is_valid_key(key):
"""Validate a proposed dictionary key.

Parameters
----------
Expand Down Expand Up @@ -112,8 +115,9 @@ def _is_valid_key(self, key):

return True

def _is_valid_value(self, value):
"""Validate a proposed dictionary value
@staticmethod
def _is_valid_value(value):
"""Validate a proposed dictionary value.

Parameters
----------
Expand All @@ -130,7 +134,7 @@ def _is_valid_value(self, value):
return True

def save(self, file_name):
"""Serialise the cache dictionary to a file
"""Serialise the cache dictionary to a file.

Parameters
----------
Expand All @@ -142,7 +146,7 @@ def save(self, file_name):
return True

def load(self, file_name):
"""Load a previously saved cache into the dictionary
"""Load a previously saved cache into the dictionary.

Parameters
----------
Expand All @@ -156,5 +160,6 @@ def load(self, file_name):
self.data = data
else:
raise ValueError(
'Cache file exists but is not the correct format. Try deleting and re-building the cache file.')
"Cache file exists but is not the correct format. "
"Try deleting and re-building the cache file.")
return True
3 changes: 2 additions & 1 deletion axelrod/ecosystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@


class Ecosystem(object):
"""Create an ecosystem based on the payoff matrix from an Axelrod tournament."""
"""Create an ecosystem based on the payoff matrix from an Axelrod
tournament."""

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

Expand Down
3 changes: 2 additions & 1 deletion axelrod/eigen.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def power_iteration(mat: numpy.matrix, initial: numpy.ndarray) -> numpy.ndarray:
yield vec


def principal_eigenvector(mat: numpy.matrix, maximum_iterations=1000, max_error=1e-3) -> Tuple[numpy.ndarray, float]:
def principal_eigenvector(mat: numpy.matrix, maximum_iterations=1000,
max_error=1e-3) -> Tuple[numpy.ndarray, float]:
"""
Computes the (normalised) principal eigenvector of the given matrix.
Expand Down
20 changes: 12 additions & 8 deletions axelrod/fingerprint.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import axelrod as axl
import numpy as np
from collections import namedtuple
from tempfile import NamedTemporaryFile
import matplotlib.pyplot as plt
import numpy as np
import tqdm
from axelrod.strategy_transformers import JossAnnTransformer, DualTransformer
from axelrod.interaction_utils import compute_final_score_per_turn, read_interactions_from_file
import axelrod as axl

from axelrod import on_windows
from collections import namedtuple
from tempfile import NamedTemporaryFile
from axelrod.strategy_transformers import JossAnnTransformer, DualTransformer
from axelrod.interaction_utils import (
compute_final_score_per_turn, read_interactions_from_file)


Point = namedtuple('Point', 'x y')
Expand Down Expand Up @@ -95,7 +97,8 @@ def create_jossann(point, probe):
init_args = ()

if x + y >= 1:
joss_ann = DualTransformer()(JossAnnTransformer((1 - x, 1 - y))(probe))(*init_args)
joss_ann = DualTransformer()(
JossAnnTransformer((1 - x, 1 - y))(probe))(*init_args)
else:
joss_ann = JossAnnTransformer((x, y))(probe)(*init_args)
return joss_ann
Expand Down Expand Up @@ -308,7 +311,8 @@ def reshape_data(data, points, size):
plotting_data = np.flipud(shaped_data)
return plotting_data

def plot(self, col_map='seismic', interpolation='none', title=None, colorbar=True, labels=True):
def plot(self, col_map='seismic', interpolation='none', title=None,
colorbar=True, labels=True):
"""Plot the results of the spatial tournament.

Parameters
Expand Down
5 changes: 2 additions & 3 deletions axelrod/interaction_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
Functions to calculate results from interactions. Interactions are lists of the
form:
Expand All @@ -8,11 +7,11 @@
This is used by both the Match class and the ResultSet class which analyse
interactions.
"""
import csv
from collections import Counter
import csv

from .game import Game
from axelrod import Actions
from .game import Game

import tqdm

Expand Down
3 changes: 3 additions & 0 deletions axelrod/load_data_.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def load_file(filename, directory):
rows.append(s)
return rows


def load_weights(filename="ann_weights.csv", directory="data"):
"""Load Neural Network Weights."""
rows = load_file(filename, directory)
Expand All @@ -27,6 +28,7 @@ def load_weights(filename="ann_weights.csv", directory="data"):
d[name] = (num_features, num_hidden, weights)
return d


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


def load_pso_tables(filename="pso_gambler.csv", directory="data"):
"""Load lookup tables."""
rows = load_file(filename, directory)
Expand Down
17 changes: 8 additions & 9 deletions axelrod/match.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
from axelrod import Actions, Game
import axelrod.interaction_utils as iu
from .deterministic_cache import DeterministicCache

import axelrod.interaction_utils as iu

C, D = Actions.C, Actions.D

Expand Down Expand Up @@ -85,7 +84,7 @@ def _stochastic(self):
@property
def _cache_update_required(self):
"""
A boolean to show whether the deterministic cache should be updated
A boolean to show whether the deterministic cache should be updated.
"""
return (
not self.noise and
Expand All @@ -112,7 +111,7 @@ def play(self):

i.e. One entry per turn containing a pair of actions.
"""
if (self._stochastic or self._cache_key not in self._cache):
if self._stochastic or (self._cache_key not in self._cache):
turn = 0
for p in self.players:
p.reset()
Expand All @@ -135,15 +134,15 @@ def scores(self):
return iu.compute_scores(self.result, self.game)

def final_score(self):
"""Returns the final score for a Match"""
"""Returns the final score for a Match."""
return iu.compute_final_score(self.result, self.game)

def final_score_per_turn(self):
"""Returns the mean score per round for a Match"""
"""Returns the mean score per round for a Match."""
return iu.compute_final_score_per_turn(self.result, self.game)

def winner(self):
"""Returns the winner of the Match"""
"""Returns the winner of the Match."""
winner_index = iu.compute_winner_index(self.result, self.game)
if winner_index is False: # No winner
return False
Expand All @@ -152,11 +151,11 @@ def winner(self):
return self.players[winner_index]

def cooperation(self):
"""Returns the count of cooperations by each player"""
"""Returns the count of cooperations by each player."""
return iu.compute_cooperations(self.result)

def normalised_cooperation(self):
"""Returns the count of cooperations by each player per turn"""
"""Returns the count of cooperations by each player per turn."""
return iu.compute_normalised_cooperation(self.result)

def state_distribution(self):
Expand Down
15 changes: 7 additions & 8 deletions axelrod/match_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,8 @@ def build_single_match_params(self):

def __len__(self):
"""
The size of the generator.
This corresponds to the number of match chunks as it
ignores repetitions.
The size of the generator. This corresponds to the number of match
chunks as it ignores repetitions.
"""
n = len(self.players)
num_matches = int(n * (n - 1) // 2 + n)
Expand Down Expand Up @@ -170,9 +169,10 @@ def estimated_size(self):

def graph_is_connected(edges, players):
"""
Test if a set of edges defines a complete graph on a set of players.

This is used by the spatial tournaments.
Test if the set of edges defines a graph in which each player is connected
to at least one other player. This function does not test if the graph is
fully connected in the sense that each node is reachable from every other
node.

Parameters:
-----------
Expand All @@ -181,7 +181,7 @@ def graph_is_connected(edges, players):

Returns:
--------
boolean : True if the graph is connected
boolean : True if the graph is connected as specified above.
"""
# Check if all players are connected.
player_indices = set(range(len(players)))
Expand All @@ -193,7 +193,6 @@ def graph_is_connected(edges, players):
return player_indices == node_indices



class SpatialMatches(RoundRobinMatches):
"""
A class that generates spatially-structured matches.
Expand Down
Loading