Skip to content

Commit

Permalink
Merge pull request #582 from Axelrod-Python/580
Browse files Browse the repository at this point in the history
Move processes argument from Tournament.__init__ to tournament.play
  • Loading branch information
meatballs committed May 12, 2016
2 parents 03dd1a9 + 150fb67 commit 1501f19
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 77 deletions.
5 changes: 2 additions & 3 deletions axelrod/tests/integration/test_tournament.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ def test_parallel_play(self):
players=self.players,
game=self.game,
turns=20,
repetitions=self.test_repetitions,
processes=2)
scores = tournament.play(progress_bar=False).scores
repetitions=self.test_repetitions)
scores = tournament.play(processes=2, progress_bar=False).scores
actual_outcome = sorted(zip(self.player_names, scores))
self.assertEqual(actual_outcome, self.expected_outcome)
26 changes: 4 additions & 22 deletions axelrod/tests/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ def tournaments(draw, strategies=axelrod.strategies,
min_size=1, max_size=10,
min_turns=1, max_turns=200,
min_noise=0, max_noise=1,
min_repetitions=1, max_repetitions=20,
max_processes=None):
min_repetitions=1, max_repetitions=20):
"""
A hypothesis decorator to return a tournament and a random seed (to ensure
reproducibility for strategies that make use of the random module when
Expand All @@ -85,8 +84,6 @@ def tournaments(draw, strategies=axelrod.strategies,
The minimum number of repetitions
max_repetitions : integer
The maximum number of repetitions
max_processes : bool
Maximum number of processes to use
"""
seed = draw(random_module())
strategies = draw(strategy_lists(strategies=strategies,
Expand All @@ -98,14 +95,8 @@ def tournaments(draw, strategies=axelrod.strategies,
max_value=max_repetitions))
noise = draw(floats(min_value=min_noise, max_value=max_noise))

if max_processes is not None:
processes = draw(integers(min_value=1, max_value=max_processes))
else:
processes = None

tournament = axelrod.Tournament(players, turns=turns,
repetitions=repetitions, noise=noise,
processes=processes)
repetitions=repetitions, noise=noise)
return tournament, seed


Expand All @@ -114,8 +105,7 @@ def prob_end_tournaments(draw, strategies=axelrod.strategies,
min_size=1, max_size=10,
min_prob_end=0, max_prob_end=1,
min_noise=0, max_noise=1,
min_repetitions=1, max_repetitions=20,
max_processes=None):
min_repetitions=1, max_repetitions=20):
"""
A hypothesis decorator to return a tournament and a random seed (to ensure
reproducibility for strategies that make use of the random module when
Expand All @@ -139,8 +129,6 @@ def prob_end_tournaments(draw, strategies=axelrod.strategies,
The minimum number of repetitions
max_repetitions : integer
The maximum number of repetitions
max_processes : bool
Maximum number of processes to use
"""
seed = draw(random_module())
strategies = draw(strategy_lists(strategies=strategies,
Expand All @@ -152,14 +140,8 @@ def prob_end_tournaments(draw, strategies=axelrod.strategies,
max_value=max_repetitions))
noise = draw(floats(min_value=min_noise, max_value=max_noise))

if max_processes is not None:
processes = draw(integers(min_value=1, max_value=max_processes))
else:
processes = None

tournament = axelrod.ProbEndTournament(players, prob_end=prob_end,
repetitions=repetitions, noise=noise,
processes=processes)
repetitions=repetitions, noise=noise)
return tournament, seed


Expand Down
14 changes: 0 additions & 14 deletions axelrod/tests/unit/test_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ def test_decorator(self, tournament_and_seed):
self.assertGreaterEqual(tournament.noise, 0)
self.assertLessEqual(tournament.repetitions, 50)
self.assertGreaterEqual(tournament.repetitions, 2)
self.assertIsNone(tournament._processes)

@given(tournament_and_seed=tournaments(strategies=axelrod.basic_strategies))
def test_decorator_with_given_strategies(self, tournament_and_seed):
Expand All @@ -127,12 +126,6 @@ def test_decorator_with_stochastic_strategies(self, tournament_and_seed):
for p in tournament.players:
self.assertIn(str(p), stochastic_player_names)

@given(tournament_and_seed=tournaments(max_processes=2))
def test_decorator_with_stochastic_strategies(self, tournament_and_seed):
tournament, seed = tournament_and_seed
self.assertGreaterEqual(tournament._processes, 1)
self.assertLessEqual(tournament._processes, 2)


class TestProbEndTournament(unittest.TestCase):

Expand All @@ -157,7 +150,6 @@ def test_decorator(self, tournament_and_seed):
self.assertGreaterEqual(tournament.noise, 0)
self.assertLessEqual(tournament.repetitions, 50)
self.assertGreaterEqual(tournament.repetitions, 2)
self.assertIsNone(tournament._processes)

@given(tournament_and_seed=prob_end_tournaments(strategies=axelrod.basic_strategies))
def test_decorator_with_given_strategies(self, tournament_and_seed):
Expand All @@ -179,12 +171,6 @@ def test_decorator_with_stochastic_strategies(self, tournament_and_seed):
for p in tournament.players:
self.assertIn(str(p), stochastic_player_names)

@given(tournament_and_seed=prob_end_tournaments(max_processes=2))
def test_decorator_with_stochastic_strategies(self, tournament_and_seed):
tournament, seed = tournament_and_seed
self.assertGreaterEqual(tournament._processes, 1)
self.assertLessEqual(tournament._processes, 2)

class TestGame(unittest.TestCase):

def test_call(self):
Expand Down
40 changes: 15 additions & 25 deletions axelrod/tests/unit/test_tournament.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ def test_init(self):
players=self.players,
game=self.game,
turns=self.test_turns,
processes=4,
noise=0.2)
self.assertEqual(len(tournament.players), len(test_strategies))
self.assertIsInstance(
Expand All @@ -73,7 +72,6 @@ def test_init(self):
self.assertEqual(tournament.turns, self.test_turns)
self.assertEqual(tournament.repetitions, 10)
self.assertEqual(tournament.name, 'test')
self.assertEqual(tournament._processes, 4)
self.assertTrue(tournament._with_morality)
self.assertIsInstance(tournament._logger, logging.Logger)
self.assertEqual(tournament.noise, 0.2)
Expand Down Expand Up @@ -183,10 +181,9 @@ def test_progress_bar_play_parallel(self):
players=self.players,
game=self.game,
turns=200,
repetitions=self.test_repetitions,
processes=2)
repetitions=self.test_repetitions)

results = tournament.play()
results = tournament.play(processes=2)
self.assertIsInstance(results, axelrod.ResultSet)

results = tournament.play(progress_bar=True)
Expand Down Expand Up @@ -229,9 +226,8 @@ def test_parallel_play(self):
players=self.players,
game=self.game,
turns=200,
repetitions=self.test_repetitions,
processes=2)
results = tournament.play(progress_bar=False)
repetitions=self.test_repetitions)
results = tournament.play(processes=2, progress_bar=False)
self.assertIsInstance(results, axelrod.ResultSet)

# The following relates to #516
Expand All @@ -243,9 +239,8 @@ def test_parallel_play(self):
players=players,
game=self.game,
turns=20,
repetitions=self.test_repetitions,
processes=2)
scores = tournament.play(progress_bar=False).scores
repetitions=self.test_repetitions)
scores = tournament.play(processes=2, progress_bar=False).scores
self.assertEqual(len(scores), len(players))

def test_run_serial(self):
Expand All @@ -254,8 +249,7 @@ def test_run_serial(self):
players=self.players,
game=self.game,
turns=200,
repetitions=self.test_repetitions,
processes=2)
repetitions=self.test_repetitions)
tournament._write_interactions = MagicMock(
name='_write_interactions')
self.assertTrue(tournament._run_serial())
Expand All @@ -270,8 +264,7 @@ def test_run_parallel(self):
players=self.players,
game=self.game,
turns=200,
repetitions=self.test_repetitions,
processes=2)
repetitions=self.test_repetitions)
tournament._write_interactions = MagicMock(
name='_write_interactions')
self.assertTrue(tournament._run_parallel())
Expand All @@ -288,18 +281,17 @@ def test_n_workers(self):
players=self.players,
game=self.game,
turns=200,
repetitions=self.test_repetitions,
processes=1)
self.assertEqual(tournament._n_workers(), max_processes)
repetitions=self.test_repetitions)
self.assertEqual(tournament._n_workers(processes=1), max_processes)

tournament = axelrod.Tournament(
name=self.test_name,
players=self.players,
game=self.game,
turns=200,
repetitions=self.test_repetitions,
processes=max_processes + 2)
self.assertEqual(tournament._n_workers(), max_processes)
repetitions=self.test_repetitions)
self.assertEqual(tournament._n_workers(processes=max_processes+2),
max_processes)

@unittest.skipIf(
cpu_count() < 2,
Expand All @@ -313,9 +305,8 @@ def test_2_workers(self):
players=self.players,
game=self.game,
turns=200,
repetitions=self.test_repetitions,
processes=2)
self.assertEqual(tournament._n_workers(), 2)
repetitions=self.test_repetitions,)
self.assertEqual(tournament._n_workers(processes=2), 2)

def test_start_workers(self):
workers = 2
Expand Down Expand Up @@ -521,7 +512,6 @@ def test_init(self):
self.assertEqual(tournament.turns, float("inf"))
self.assertEqual(tournament.repetitions, 10)
self.assertEqual(tournament.name, 'test')
self.assertEqual(tournament._processes, None)
self.assertTrue(tournament._with_morality)
self.assertIsInstance(tournament._logger, logging.Logger)
self.assertEqual(tournament.noise, 0.2)
Expand Down
23 changes: 10 additions & 13 deletions axelrod/tournament.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Tournament(object):

def __init__(self, players, match_generator=RoundRobinMatches,
name='axelrod', game=None, turns=200, repetitions=10,
processes=None, noise=0, with_morality=True):
noise=0, with_morality=True):
"""
Parameters
----------
Expand Down Expand Up @@ -53,7 +53,6 @@ def __init__(self, players, match_generator=RoundRobinMatches,
self.match_generator = match_generator(players, turns, self.game,
self.repetitions)
self._with_morality = with_morality
self._processes = processes
self._logger = logging.getLogger(__name__)

def setup_output_file(self, filename=None):
Expand All @@ -68,7 +67,7 @@ def setup_output_file(self, filename=None):
# Save filename for loading ResultSet later
self.filename = filename

def play(self, build_results=True, filename=None, progress_bar=True):
def play(self, build_results=True, filename=None, processes=None, progress_bar=True):
"""
Plays the tournament and passes the results to the ResultSet class
Expand All @@ -92,10 +91,10 @@ def play(self, build_results=True, filename=None, progress_bar=True):
if not build_results and not filename:
warnings.warn("Tournament results will not be accessible since build_results=False and no filename was supplied.")

if self._processes is None:
if processes is None:
self._run_serial(progress_bar=progress_bar)
else:
self._run_parallel(progress_bar=progress_bar)
self._run_parallel(processes=processes, progress_bar=progress_bar)

# Make sure that python has finished writing to disk
self.outputfile.flush()
Expand Down Expand Up @@ -151,7 +150,7 @@ def _write_interactions(self, results):
row.append(history2)
self.writer.writerow(row)

def _run_parallel(self, progress_bar=False):
def _run_parallel(self, processes=2, progress_bar=False):
"""
Run all matches in parallel
Expand All @@ -166,7 +165,7 @@ def _run_parallel(self, progress_bar=False):
# target functions which can be pickled and instance methods cannot.
work_queue = Queue()
done_queue = Queue()
workers = self._n_workers()
workers = self._n_workers(processes=processes)

chunks = self.match_generator.build_match_chunks()
for chunk in chunks:
Expand All @@ -177,16 +176,16 @@ def _run_parallel(self, progress_bar=False):

return True

def _n_workers(self):
def _n_workers(self, processes=2):
"""
Determines the number of parallel processes to use.
Returns
-------
integer
"""
if (2 <= self._processes <= cpu_count()):
n_workers = self._processes
if (2 <= processes <= cpu_count()):
n_workers = processes
else:
n_workers = cpu_count()
return n_workers
Expand Down Expand Up @@ -297,7 +296,6 @@ class ProbEndTournament(Tournament):

def __init__(self, players, match_generator=ProbEndRoundRobinMatches,
name='axelrod', game=None, prob_end=.5, repetitions=10,
processes=None,
noise=0,
with_morality=True):
"""
Expand All @@ -324,8 +322,7 @@ def __init__(self, players, match_generator=ProbEndRoundRobinMatches,
"""
super(ProbEndTournament, self).__init__(
players, name=name, game=game, turns=float("inf"),
repetitions=repetitions, processes=processes,
noise=noise, with_morality=with_morality)
repetitions=repetitions, noise=noise, with_morality=with_morality)

self.prob_end = prob_end
self.match_generator = ProbEndRoundRobinMatches(
Expand Down

0 comments on commit 1501f19

Please sign in to comment.