Skip to content

Commit

Permalink
Merge pull request #608 from Axelrod-Python/generator
Browse files Browse the repository at this point in the history
Refactors match_generator
  • Loading branch information
marcharper committed May 31, 2016
2 parents 106afff + 1027320 commit 227f399
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 37 deletions.
43 changes: 17 additions & 26 deletions axelrod/match_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

class MatchGenerator(object):

def __init__(self, players, turns, game, repetitions):
def __init__(self, players, turns, game, repetitions, noise=0):
"""
A class to generate matches. This is used by the Tournament class which
is in charge of playing the matches and collecting the results.
Expand All @@ -20,11 +20,14 @@ def __init__(self, players, turns, game, repetitions):
The game object used to score the match
repetitions : int
The number of repetitions of a given match
noise : float, 0
The probability that a player's intended action should be flipped
"""
self.players = players
self.turns = turns
self.game = game
self.repetitions = repetitions
self.noise = noise
self.opponents = players

@property
Expand All @@ -50,38 +53,28 @@ def build_single_match_params(self):

class RoundRobinMatches(MatchGenerator):

def build_match_chunks(self, noise=0):
def build_match_chunks(self):
"""
A generator that returns player index pairs and match parameters for a
round robin tournament.
parameters
----------
noise : float, 0
The probability that a player's intended action should be flipped
Yields
-------
tuples
((player1 index, player2 index), match object)
"""
for player1_index in range(len(self.players)):
for player2_index in range(player1_index, len(self.players)):
match_params = self.build_single_match_params(noise)
match_params = self.build_single_match_params()
index_pair = (player1_index, player2_index)
yield (index_pair, match_params, self.repetitions)

def build_single_match_params(self, noise=0):
def build_single_match_params(self):
"""
Creates a single set of match parameters.
parameters
----------
noise : float, 0
The probability that a player's intended action should be flipped
"""
cache = None
return (self.turns, self.game, cache, noise)
return (self.turns, self.game, cache, self.noise)

def __len__(self):
"""
Expand All @@ -101,7 +94,7 @@ def estimated_size(self):

class ProbEndRoundRobinMatches(RoundRobinMatches):

def __init__(self, players, prob_end, game, repetitions):
def __init__(self, players, prob_end, game, repetitions, noise=0):
"""
A class that generates matches for which the players do not
know the length of the Match (to their knowledge it is infinite) but
Expand All @@ -115,23 +108,21 @@ def __init__(self, players, prob_end, game, repetitions):
The probability that a turn of a Match is the last
game : axelrod.Game
The game object used to score the match
deterministic_cache : an instance of axelrod.DeterministicCache
A cache of resulting actions for deterministic matches
repetitions : int
The number of repetitions of a given match
noise : float, 0
The probability that a player's intended action should be flipped
"""
super(ProbEndRoundRobinMatches, self).__init__(
players, turns=float("inf"), game=game, repetitions=repetitions)
players, turns=float("inf"), game=game, repetitions=repetitions,
noise=noise)
self.prob_end = prob_end

def build_single_match_params(self, noise=0):
def build_single_match_params(self):
"""
Creates a single set of match parameters.
parameters
----------
noise : float, 0
The probability that a player's intended action should be flipped
"""
return (self.sample_length(self.prob_end), self.game, None, noise)
return (self.sample_length(self.prob_end), self.game, None, self.noise)

def sample_length(self, prob_end):
"""
Expand Down
8 changes: 6 additions & 2 deletions axelrod/tests/unit/test_match_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ def test_build_single_match_params(self):
self.assertEqual(len(match), test_turns)

# Testing with noise
match_params = rr.build_single_match_params(noise=.5)
rr = axelrod.RoundRobinMatches(
self.players, test_turns, test_game, test_repetitions, noise=0.5)
match_params = rr.build_single_match_params()
self.assertIsInstance(match_params, tuple)
self.assertEqual(match_params[0], rr.turns)
self.assertEqual(match_params[1], rr.game)
Expand Down Expand Up @@ -178,7 +180,9 @@ def test_build_single_match_params(self, prob_end, rm):
self.assertGreater(len(match), 0)

# Testing with noise
match_params = rr.build_single_match_params(noise=.5)
rr = axelrod.ProbEndRoundRobinMatches(
self.players, prob_end, test_game, test_repetitions, noise=0.5)
match_params = rr.build_single_match_params()
self.assertIsInstance(match_params, tuple)
self.assertLess(match_params[0], float('inf'))
self.assertGreater(match_params[0], 0)
Expand Down
2 changes: 1 addition & 1 deletion axelrod/tests/unit/test_tournament.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import warnings

from hypothesis import given, example, settings
from hypothesis.strategies import integers, lists, sampled_from, random_module, floats
from hypothesis.strategies import integers
from axelrod.tests.property import tournaments, prob_end_tournaments

import axelrod
Expand Down
8 changes: 4 additions & 4 deletions axelrod/tournament.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ def __init__(self, players, match_generator=RoundRobinMatches,
self.game = game
self.players = players
self.repetitions = repetitions
self.match_generator = match_generator(players, turns, self.game,
self.repetitions)
self.match_generator = match_generator(
players, turns, self.game, self.repetitions, self.noise)
self._with_morality = with_morality
self._logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -130,7 +130,7 @@ def _run_serial(self, progress_bar=False):
progress_bar : bool
Whether or not to update the tournament progress bar
"""
chunks = self.match_generator.build_match_chunks(noise=self.noise)
chunks = self.match_generator.build_match_chunks()

for chunk in chunks:
results = self._play_matches(chunk)
Expand Down Expand Up @@ -171,7 +171,7 @@ def _run_parallel(self, processes=2, progress_bar=False):
done_queue = Queue()
workers = self._n_workers(processes=processes)

chunks = self.match_generator.build_match_chunks(noise=self.noise)
chunks = self.match_generator.build_match_chunks()
for chunk in chunks:
work_queue.put(chunk)

Expand Down
8 changes: 4 additions & 4 deletions docs/tutorials/advanced/making_tournaments.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ To do this let us create a new class to generate matches::
>>> class StochasticMatchups(axl.RoundRobinMatches):
... """Inherit from the `axelrod.match_generator.RoundRobinMatches` class"""
...
... def build_match_chunks(self, noise=0):
... def build_match_chunks(self):
... """
... A generator that yields match parameters only with a given probability.
...
Expand All @@ -32,7 +32,7 @@ To do this let us create a new class to generate matches::
... for player1_index in range(len(self.players)):
... for player2_index in range(player1_index, len(self.players)):
... if random.random() < 0.5: # This is the modification
... match_params = self.build_single_match_params(noise)
... match_params = self.build_single_match_params()
... index_pair = (player1_index, player2_index)
... yield (index_pair, match_params, self.repetitions)

Expand Down Expand Up @@ -75,12 +75,12 @@ builds matches that were either 200 turns or single 1 shot games::
... """Inherit from the `axelrod.match_generator.RoundRobinMatches` class"""
...
...
... def build_single_match_params(self, noise=0):
... def build_single_match_params(self):
... """Create a single set of match parameters"""
... turns = 1
... if random.random() < 0.5:
... turns = 200
... return (turns, self.game, None, noise)
... return (turns, self.game, None, self.noise)

We can take a look at the match lengths when using this generator::

Expand Down

0 comments on commit 227f399

Please sign in to comment.