Skip to content

Commit

Permalink
Merge pull request #653 from Axelrod-Python/651
Browse files Browse the repository at this point in the history
651 - Tests for random seeding and a random seeding function
  • Loading branch information
meatballs authored Jul 18, 2016
2 parents ed8798a + f90da26 commit aa06f8b
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 2 deletions.
2 changes: 1 addition & 1 deletion axelrod/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# The order of imports matters!
from .actions import Actions, flip_action
from .random_ import random_choice
from .random_ import random_choice, seed
from .plot import Plot
from .game import DefaultGame, Game
from .player import init_args, is_basic, obey_axelrod, update_history, Player
Expand Down
7 changes: 7 additions & 0 deletions axelrod/random_.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import random
import numpy
from axelrod import Actions


Expand All @@ -21,3 +22,9 @@ def randrange(a, b):
c = b - a
r = c * random.random()
return a + int(r)


def seed(seed):
"""Sets a seed"""
random.seed(seed)
numpy.random.seed(seed)
20 changes: 20 additions & 0 deletions axelrod/tests/integration/test_matches.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
deterministic_strategies = [s for s in axelrod.ordinary_strategies
if not s().classifier['stochastic']] # Well behaved strategies

stochastic_strategies = [s for s in axelrod.ordinary_strategies
if s().classifier['stochastic']]


class TestMatchOutcomes(unittest.TestCase):

@given(strategies=strategy_lists(strategies=deterministic_strategies,
Expand All @@ -23,3 +27,19 @@ def test_outcome_repeats(self, strategies, turns):
matches = [axelrod.Match(players, turns) for _ in range(3)]
self.assertEqual(matches[0].play(), matches[1].play())
self.assertEqual(matches[1].play(), matches[2].play())

@given(strategies=strategy_lists(strategies=stochastic_strategies,
min_size=2, max_size=2),
turns=integers(min_value=1, max_value=20),
seed=integers(min_value=0, max_value=4294967295))
def test_outcome_repeats_stochastic(self, strategies, turns, seed):
"""a test to check that if a seed is set stochastic strategies give the
same result"""
results = []
for _ in range(3):
axelrod.seed(seed)
players = [s() for s in strategies]
results.append(axelrod.Match(players, turns).play())

self.assertEqual(results[0], results[1])
self.assertEqual(results[1], results[2])
34 changes: 34 additions & 0 deletions axelrod/tests/integration/test_tournament.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import unittest
import axelrod
import tempfile
import filecmp

from axelrod.strategy_transformers import FinalTransformer

Expand Down Expand Up @@ -60,6 +61,39 @@ def test_parallel_play(self):
actual_outcome = sorted(zip(self.player_names, scores))
self.assertEqual(actual_outcome, self.expected_outcome)

def test_repeat_tournament_deterministic(self):
"""A test to check that tournament gives same results."""
deterministic_players = [s() for s in axelrod.ordinary_strategies
if not s().classifier['stochastic']]
files = []
for _ in range(2):
tournament = axelrod.Tournament(name='test',
players=deterministic_players,
game=self.game, turns=2,
repetitions=2)
files.append(tempfile.NamedTemporaryFile())
tournament.play(progress_bar=False, filename=files[-1].name,
build_results=False)
self.assertTrue(filecmp.cmp(files[0].name, files[1].name))

def test_repeat_tournament_stochastic(self):
"""
A test to check that tournament gives same results when setting seed.
"""
files = []
for _ in range(2):
axelrod.seed(0)
stochastic_players = [s() for s in axelrod.ordinary_strategies
if s().classifier['stochastic']]
tournament = axelrod.Tournament(name='test',
players=stochastic_players,
game=self.game, turns=2,
repetitions=2)
files.append(tempfile.NamedTemporaryFile())
tournament.play(progress_bar=False, filename=files[-1].name,
build_results=False)
self.assertTrue(filecmp.cmp(files[0].name, files[1].name))


class TestNoisyTournament(unittest.TestCase):
def test_noisy_tournament(self):
Expand Down
17 changes: 16 additions & 1 deletion axelrod/tests/unit/test_random_.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""Test for the random strategy."""

import numpy
import random
import unittest

from axelrod import random_choice, Actions
from axelrod import random_choice, seed, Actions

C, D = Actions.C, Actions.D

Expand All @@ -16,3 +17,17 @@ def test_return_values(self):
self.assertEqual(random_choice(), C)
random.seed(2)
self.assertEqual(random_choice(), D)

def test_set_seed(self):
"""Test that numpy and stdlib random seed is set by axelrod seed"""

numpy_random_numbers = []
stdlib_random_numbers = []
for _ in range(2):
seed(0)
numpy_random_numbers.append(numpy.random.random())
stdlib_random_numbers.append(random.random())

self.assertEqual(numpy_random_numbers[0], numpy_random_numbers[1])
self.assertEqual(stdlib_random_numbers[0], stdlib_random_numbers[1])

1 change: 1 addition & 0 deletions docs/tutorials/advanced/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ Contents:
making_tournaments.rst
reading_and_writing_interactions.rst
using_the_cache.rst
setting_a_seed.rst
35 changes: 35 additions & 0 deletions docs/tutorials/advanced/setting_a_seed.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.. _setting_a_seed:

Setting a random seed
=====================

The library has a variety of strategies whose behaviour is stochastic. To ensure
reproducible results a random seed should be set. As both Numpy and the standard
library are used for random number generation, both seeds need to be
set. To do this we can use the `seed` function::

>>> import axelrod as axl
>>> players = (axl.Random(), axl.MetaMixer()) # Two stochastic strategies
>>> axl.seed(0)
>>> axl.Match(players, turns=3).play()
[('D', 'C'), ('D', 'D'), ('C', 'D')]

We obtain the same results is it is played with the same seed::

>>> axl.seed(0)
>>> axl.Match(players, turns=3).play()
[('D', 'C'), ('D', 'D'), ('C', 'D')]

Note that this is equivalent to::

>>> import numpy
>>> import random
>>> players = (axl.Random(), axl.MetaMixer())
>>> random.seed(0)
>>> numpy.random.seed(0)
>>> axl.Match(players, turns=3).play()
[('D', 'C'), ('D', 'D'), ('C', 'D')]
>>> numpy.random.seed(0)
>>> random.seed(0)
>>> axl.Match(players, turns=3).play()
[('D', 'C'), ('D', 'D'), ('C', 'D')]

0 comments on commit aa06f8b

Please sign in to comment.