Skip to content

651 - Tests for random seeding and a random seeding function #653

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

Merged
merged 6 commits into from
Jul 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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')]