From 621d175f175baf8f323d243edd71a1fcced0296d Mon Sep 17 00:00:00 2001 From: Vince Knight Date: Wed, 20 Apr 2016 17:10:57 +0100 Subject: [PATCH 1/2] Removing run_axelrod and factor/manager classes Closes 552 - Remove run_axelrod. - Removing manager, managerfactory and utils. - Removing corresponding tests. - Removing prebuilt cache argument from tournament. - Removing tutorial on command line. - Minor modifications to README.rst. --- README.rst | 7 +- axelrod/__init__.py | 4 - axelrod/tests/integration/test_tournament.py | 93 -------- axelrod/tests/unit/test_tournament.py | 45 ++-- axelrod/tests/unit/test_tournament_manager.py | 106 --------- .../unit/test_tournament_manager_factory.py | 192 ---------------- axelrod/tests/unit/test_utils.py | 58 ----- axelrod/tournament.py | 29 +-- axelrod/tournament_manager.py | 206 ------------------ axelrod/tournament_manager_factory.py | 113 ---------- axelrod/utils.py | 116 ---------- .../getting_started/command_line.rst | 38 ---- docs/tutorials/getting_started/index.rst | 1 - run_axelrod | 135 ------------ 14 files changed, 27 insertions(+), 1116 deletions(-) delete mode 100644 axelrod/tests/unit/test_tournament_manager.py delete mode 100644 axelrod/tests/unit/test_tournament_manager_factory.py delete mode 100644 axelrod/tests/unit/test_utils.py delete mode 100644 axelrod/tournament_manager.py delete mode 100644 axelrod/tournament_manager_factory.py delete mode 100644 axelrod/utils.py delete mode 100644 docs/tutorials/getting_started/command_line.rst delete mode 100755 run_axelrod diff --git a/README.rst b/README.rst index 56961bfa3..1e1fb2e0b 100644 --- a/README.rst +++ b/README.rst @@ -47,10 +47,6 @@ Otherwise:: $ cd Axelrod $ python setup.py install -You might need to install the libraries in `requirements.txt`:: - - pip install -r requirements.txt - Note that on Ubuntu `some users `_ have had problems installing matplotlib. This seems to help with that:: @@ -80,6 +76,9 @@ gives:: ['Meta Hunter', 'Inverse', 'Forgetful Fool Me Once', 'GTFT: 0.33', 'Champion', 'ZD-GTFT-2', 'Eatherley', 'Math Constant Hunter', 'Random Hunter', 'Soft Joss: 0.9', 'Meta Majority', 'Nice Average Copier', 'Feld', 'Meta Minority', 'Grofman', 'Stochastic WSLS', 'ZD-Extort-2', 'Tullock', 'Joss: 0.9', 'Arrogant QLearner', 'Average Copier', 'Cautious QLearner', 'Hesitant QLearner', 'Risky QLearner', 'Random: 0.5', 'Meta Winner'] +There is also a `notebooks repository +`_ which shows further +examples of using the library. Results ======= diff --git a/axelrod/__init__.py b/axelrod/__init__.py index db33e4c34..7cb2ebda6 100644 --- a/axelrod/__init__.py +++ b/axelrod/__init__.py @@ -13,9 +13,5 @@ from .deterministic_cache import DeterministicCache from .match_generator import * from .tournament import Tournament, ProbEndTournament -from .tournament_manager import TournamentManager, ProbEndTournamentManager -from .tournament_manager_factory import (TournamentManagerFactory, - ProbEndTournamentManagerFactory) from .result_set import ResultSet, ResultSetFromFile from .ecosystem import Ecosystem -from .utils import run_tournaments, run_prob_end_tournaments, setup_logging diff --git a/axelrod/tests/integration/test_tournament.py b/axelrod/tests/integration/test_tournament.py index fff48ed81..9116d6fc1 100644 --- a/axelrod/tests/integration/test_tournament.py +++ b/axelrod/tests/integration/test_tournament.py @@ -2,8 +2,6 @@ import os import axelrod -from axelrod.utils import setup_logging, run_tournaments, run_prob_end_tournaments - class TestTournament(unittest.TestCase): @@ -57,94 +55,3 @@ def test_parallel_play(self): scores = tournament.play().scores actual_outcome = sorted(zip(self.player_names, scores)) self.assertEqual(actual_outcome, self.expected_outcome) - - -class TestTournamentManager(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.game = axelrod.Game() - cls.players = [s() for s in axelrod.demo_strategies] - - def test_tournament_manager(self): - strategies = [s() for s in axelrod.demo_strategies] - tm = axelrod.TournamentManager( - "./", False, load_cache=False, save_cache=False) - tm.add_tournament("test", strategies, repetitions=2, turns=10, - noise=0.05) - tm.run_tournaments() - - strategies = [s() for s in axelrod.basic_strategies] - tm = axelrod.TournamentManager("./", False, load_cache=False, - save_cache=True) - tm.add_tournament("test", strategies, repetitions=2, turns=10, noise=0.) - tm.run_tournaments() - - tm = axelrod.TournamentManager("./", False, load_cache=True, - save_cache=True) - tm.add_tournament("test", strategies, repetitions=2, turns=10, noise=0.) - tm.run_tournaments() - - def test_utils(self): - setup_logging(logging_destination="none") - run_tournaments(cache_file='', - output_directory='./', - repetitions=2, - turns=10, - processes=None, - no_ecological=False, - rebuild_cache=False, - exclude_combined=True, - exclude_basic=False, - exclude_cheating=True, - exclude_ordinary=True, - noise=0) - - -class TestProbEndTournamentManager(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.game = axelrod.Game() - cls.players = [s() for s in axelrod.demo_strategies] - - @classmethod - def tearDownClass(cls): - os.remove('./basic_strategies_prob_end.csv') - os.remove('./test-prob-end.csv') - - def test_tournament_manager(self): - strategies = [s() for s in axelrod.demo_strategies] - tm = axelrod.ProbEndTournamentManager( - "./", False, load_cache=False, save_cache=False) - tm.add_tournament("test-prob-end", strategies, repetitions=2, prob_end=.5, - noise=0.05) - tm.run_tournaments() - - strategies = [s() for s in axelrod.basic_strategies] - tm = axelrod.ProbEndTournamentManager("./", False, load_cache=False, - save_cache=True) - tm.add_tournament("test-prob-end", strategies, repetitions=2, - prob_end=.5, noise=0.) - tm.run_tournaments() - - tm = axelrod.ProbEndTournamentManager("./", False, load_cache=True, - save_cache=True) - tm.add_tournament("test-prob-end", strategies, repetitions=2, - prob_end=.5, noise=0.) - tm.run_tournaments() - - def test_utils(self): - setup_logging(logging_destination="none") - run_prob_end_tournaments(cache_file='', - output_directory='./', - repetitions=2, - prob_end=.5, - processes=None, - no_ecological=False, - rebuild_cache=False, - exclude_combined=True, - exclude_basic=False, - exclude_cheating=True, - exclude_ordinary=True, - noise=0) diff --git a/axelrod/tests/unit/test_tournament.py b/axelrod/tests/unit/test_tournament.py index c97e25c08..b7acc9a48 100644 --- a/axelrod/tests/unit/test_tournament.py +++ b/axelrod/tests/unit/test_tournament.py @@ -71,7 +71,6 @@ def test_init(self): self.assertEqual(tournament.repetitions, 10) self.assertEqual(tournament.name, 'test') self.assertEqual(tournament._processes, 4) - self.assertFalse(tournament.prebuilt_cache) self.assertTrue(tournament._with_morality) self.assertIsInstance(tournament._logger, logging.Logger) self.assertEqual(tournament.deterministic_cache, {}) @@ -91,7 +90,6 @@ def test_init(self): noise=0.2, deterministic_cache=cache) self.assertEqual(tournament.deterministic_cache, cache) - self.assertTrue(tournament.prebuilt_cache) def test_serial_play(self): # Test that we get an instance of ResultSet @@ -180,61 +178,46 @@ def test_parallel_play(self): self.assertEqual(len(scores), len(players)) def test_build_cache_required(self): - # Noisy, no prebuilt cache, empty deterministic cache + # Noisy empty deterministic cache + cache = axelrod.DeterministicCache() tournament = axelrod.Tournament( name=self.test_name, players=self.players, game=self.game, processes=4, noise=0.2, - prebuilt_cache=False) + deterministic_cache=cache) self.assertFalse(tournament._build_cache_required()) - # Noisy, with prebuilt cache, empty deterministic cache + # Not noisy, deterministic cache has content + key = (axelrod.TitForTat, axelrod.Defector, 3) + cache[key] = [('C', 'D'), ('D', 'D'), ('D', 'D')] tournament = axelrod.Tournament( name=self.test_name, players=self.players, + game=self.game, processes=4, noise=0.2, - prebuilt_cache=True) + deterministic_cache=cache) self.assertFalse(tournament._build_cache_required()) - # Not noisy, with prebuilt cache, deterministic cache has content + # Not noisy, deterministic cache has content tournament = axelrod.Tournament( name=self.test_name, players=self.players, game=self.game, processes=4, - prebuilt_cache=True) - tournament.deterministic_cache = {'test': 100} + deterministic_cache=cache) self.assertFalse(tournament._build_cache_required()) - # Not noisy, no prebuilt cache, deterministic cache has content - tournament = axelrod.Tournament( - name=self.test_name, - players=self.players, - game=self.game, - processes=4, - prebuilt_cache=False) - tournament.deterministic_cache = {'test': 100} - self.assertTrue(tournament._build_cache_required()) - - # Not noisy, with prebuilt cache, empty deterministic cache - tournament = axelrod.Tournament( - name=self.test_name, - players=self.players, - game=self.game, - processes=4, - prebuilt_cache=True) - self.assertTrue(tournament._build_cache_required()) - - # Not noisy, no prebuilt cache, empty deterministic cache + # Not noisy, empty deterministic cache + cache = axelrod.DeterministicCache() tournament = axelrod.Tournament( name=self.test_name, players=self.players, game=self.game, processes=4, - prebuilt_cache=False) + deterministic_cache=cache) self.assertTrue(tournament._build_cache_required()) def test_build_cache(self): @@ -559,7 +542,6 @@ def test_init(self): self.assertEqual(tournament.repetitions, 10) self.assertEqual(tournament.name, 'test') self.assertEqual(tournament._processes, None) - self.assertFalse(tournament.prebuilt_cache) self.assertTrue(tournament._with_morality) self.assertIsInstance(tournament._logger, logging.Logger) self.assertEqual(tournament.deterministic_cache, {}) @@ -579,7 +561,6 @@ def test_init(self): noise=0.2, deterministic_cache=cache) self.assertEqual(tournament.deterministic_cache, cache) - self.assertTrue(tournament.prebuilt_cache) @given(s=lists(sampled_from(axelrod.strategies), min_size=2, # Errors are returned if less than 2 strategies diff --git a/axelrod/tests/unit/test_tournament_manager.py b/axelrod/tests/unit/test_tournament_manager.py deleted file mode 100644 index 81b266e6f..000000000 --- a/axelrod/tests/unit/test_tournament_manager.py +++ /dev/null @@ -1,106 +0,0 @@ -import unittest -import axelrod - - -class TestTournamentManager(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.test_output_directory = './assets/' - cls.test_with_ecological = True - cls.test_tournament_name = 'test_tournament' - cls.test_file_name = 'test_file_name' - cls.test_file_extenstion = 'png' - cls.test_strategies = [axelrod.Defector, axelrod.Cooperator] - cls.test_players = [axelrod.Defector(), axelrod.Cooperator()] - - cls.expected_output_file_path = './assets/test_file_name.png' - cls.mgr_class = axelrod.TournamentManager - - def test_init(self): - mgr = self.mgr_class( - self.test_output_directory, - self.test_with_ecological, - load_cache=False) - self.assertEqual(mgr._output_directory, self.test_output_directory) - self.assertEqual(mgr._tournaments, []) - self.assertEqual(mgr._with_ecological, self.test_with_ecological) - self.assertTrue(mgr._pass_cache) - - def test_one_player_per_strategy(self): - mgr = self.mgr_class( - self.test_output_directory, - self.test_with_ecological, - load_cache=False) - players = mgr.one_player_per_strategy(self.test_strategies) - self.assertIsInstance(players[0], axelrod.Defector) - self.assertIsInstance(players[1], axelrod.Cooperator) - - def test_output_file_path(self): - mgr = self.mgr_class( - self.test_output_directory, - self.test_with_ecological, - load_cache=False) - output_file_path = mgr._output_file_path( - self.test_file_name, self.test_file_extenstion) - self.assertEqual(output_file_path, self.expected_output_file_path) - - def test_add_tournament(self): - mgr = self.mgr_class( - self.test_output_directory, - self.test_with_ecological, - load_cache=False) - mgr.add_tournament( - players=self.test_players, name=self.test_tournament_name) - self.assertEqual(len(mgr._tournaments), 1) - self.assertIsInstance(mgr._tournaments[0], axelrod.Tournament) - self.assertEqual(mgr._tournaments[0].name, self.test_tournament_name) - - def test_tournament_label(self): - tournament = axelrod.Tournament(self.test_players, turns=20, - repetitions=2) - mgr = self.mgr_class( - output_directory=self.test_output_directory, - with_ecological=self.test_with_ecological, load_cache=False) - expected_label = "Turns: {}, Repetitions: {}, Strategies: {}.".format(tournament.turns, - tournament.repetitions, len(tournament.players)) - - self.assertEqual(mgr._tournament_label(tournament), expected_label) - - -class TestProbEndTournamentManager(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.test_output_directory = './assets/' - cls.test_with_ecological = True - cls.test_tournament_name = 'test_prob_tournament' - cls.test_file_name = 'test_prob_end_file_name' - cls.test_file_extenstion = 'png' - cls.test_strategies = [axelrod.Defector, axelrod.Cooperator] - cls.test_players = [axelrod.Defector(), axelrod.Cooperator()] - - cls.expected_output_file_path = './assets/test__prob_end_file_name.png' - cls.mgr_class = axelrod.ProbEndTournamentManager - - def test_add_tournament(self): - mgr = self.mgr_class( - self.test_output_directory, - self.test_with_ecological, - load_cache=False) - mgr.add_tournament( - players=self.test_players, name=self.test_tournament_name) - self.assertEqual(len(mgr._tournaments), 1) - self.assertIsInstance(mgr._tournaments[0], axelrod.ProbEndTournament) - self.assertEqual(mgr._tournaments[0].name, self.test_tournament_name) - - def test_tournament_label(self): - tournament = axelrod.ProbEndTournament(self.test_players, prob_end=.5, - repetitions=2) - mgr = self.mgr_class( - output_directory=self.test_output_directory, - with_ecological=self.test_with_ecological, load_cache=False) - expected_label = "Prob end: {}, Repetitions: {}, Strategies: {}.".format(tournament.prob_end, - tournament.repetitions, - len(tournament.players)) - self.assertEqual(mgr._tournament_label(tournament), expected_label) diff --git a/axelrod/tests/unit/test_tournament_manager_factory.py b/axelrod/tests/unit/test_tournament_manager_factory.py deleted file mode 100644 index 6d3993a80..000000000 --- a/axelrod/tests/unit/test_tournament_manager_factory.py +++ /dev/null @@ -1,192 +0,0 @@ -import unittest -import sys -import os -import axelrod - - -def test_pickle(): - if sys.version_info[0] == 2: - # Python 2.x - test_pickle = b'\x80\x02}q\x00caxelrod.strategies.titfortat\nTitForTat\nq\x01caxelrod.strategies.defector\nDefector\nq\x02\x86q\x03]q\x04(U\x01Cq\x05U\x01Dq\x06\x86q\x07h\x06h\x06\x86q\x08h\x06h\x06\x86q\tes.' - else: - # Python 3.x - test_pickle = b'\x80\x03}q\x00caxelrod.strategies.titfortat\nTitForTat\nq\x01caxelrod.strategies.defector\nDefector\nq\x02\x86q\x03]q\x04(X\x01\x00\x00\x00Cq\x05X\x01\x00\x00\x00Dq\x06\x86q\x07h\x06h\x06\x86q\x08h\x06h\x06\x86q\tes.' - return test_pickle - -class TestTournamentManagerFactory(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.tmf = axelrod.TournamentManagerFactory - - cls.test_output_directory = './assets/' - cls.test_with_ecological = True - cls.test_rebuild_cache = False - cls.test_cache_file = './test_cache.txt' - - with open(cls.test_cache_file, 'wb') as f: - f.write(test_pickle()) - - cls.test_exclusions = ['basic_strategies', 'cheating_strategies'] - cls.test_kwargs = { - 'processes': 2, - 'turns': 10, - 'repetitions': 200, - 'noise': 0 - } - - cls.expected_basic_strategies = axelrod.basic_strategies - cls.expected_ordinary_strategies = ( - axelrod.ordinary_strategies) - cls.expected_cheating_strategies = axelrod.cheating_strategies - cls.expected_strategies = ( - axelrod.ordinary_strategies + - axelrod.cheating_strategies) - - @classmethod - def tearDownClass(cls): - os.remove(cls.test_cache_file) - - def test_tournaments_dict(self): - - # Tests to ensure that the tournaments dictionary contains the correct - # keys and values - actual_basic_strategies = ( - self.tmf._tournaments_dict()['basic_strategies']) - actual_strategies = self.tmf._tournaments_dict()['strategies'] - actual_cheating_strategies = ( - self.tmf._tournaments_dict()['cheating_strategies']) - actual_all_strategies = self.tmf._tournaments_dict()['strategies'] - - self.assertEqual( - actual_basic_strategies, self.expected_basic_strategies) - self.assertEqual(actual_strategies, self.expected_strategies) - self.assertEqual( - actual_cheating_strategies, self.expected_cheating_strategies) - self.assertEqual(actual_all_strategies, self.expected_strategies) - - # Tests to ensure that the exclusions list works as intended - with_exclusions = self.tmf._tournaments_dict(self.test_exclusions) - self.assertFalse('basic_strategies' in with_exclusions) - self.assertFalse('cheating_strategies' in with_exclusions) - self.assertEqual( - with_exclusions['strategies'], self.expected_strategies) - - def test_add_tournaments(self): - mgr = axelrod.TournamentManager( - self.test_output_directory, - self.test_with_ecological, - cache_file=self.test_cache_file) - - self.tmf._add_tournaments(mgr, self.test_exclusions, self.test_kwargs) - self.assertEqual(len(mgr._tournaments), 2) - self.assertIsInstance(mgr._tournaments[0], axelrod.Tournament) - self.assertEqual(mgr._tournaments[0].name, 'ordinary_strategies') - - def test_create_tournament_manager(self): - mgr = self.tmf.create_tournament_manager( - output_directory=self.test_output_directory, - no_ecological=False, - rebuild_cache=self.test_rebuild_cache, - cache_file=self.test_cache_file, - exclusions=self.test_exclusions, - **self.test_kwargs) - - self.assertIsInstance(mgr, axelrod.TournamentManager) - self.assertEqual(mgr._output_directory, self.test_output_directory) - self.assertEqual(len(mgr._tournaments), 2) - self.assertTrue(mgr._with_ecological) - self.assertTrue(mgr._pass_cache) - - -class TestProbEndTournamentManagerFactory(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.tmf = axelrod.ProbEndTournamentManagerFactory - - cls.test_output_directory = './assets/' - cls.test_with_ecological = True - cls.test_rebuild_cache = False - cls.test_cache_file = './test_cache.txt' - - with open(cls.test_cache_file, 'wb') as f: - f.write(test_pickle()) - - cls.test_exclusions = ['basic_strategies', 'cheating_strategies'] - cls.test_kwargs = { - 'processes': 2, - 'turns': 10, - 'repetitions': 200, - 'noise': 0 - } - cls.test_exclusions = ['basic_strategies', 'cheating_strategies'] - cls.test_kwargs = { - 'processes': 2, - 'prob_end': .1, - 'repetitions': 200, - 'noise': 0 - } - - cls.expected_basic_strategies = axelrod.basic_strategies - cls.expected_ordinary_strategies = ( - axelrod.ordinary_strategies) - cls.expected_cheating_strategies = axelrod.cheating_strategies - cls.expected_strategies = ( - axelrod.ordinary_strategies + - axelrod.cheating_strategies) - - @classmethod - def tearDownClass(cls): - os.remove(cls.test_cache_file) - - def test_tournaments_dict(self): - - # Tests to ensure that the tournaments dictionary contains the correct - # keys and values - actual_basic_strategies = ( - self.tmf._tournaments_dict()['basic_strategies_prob_end']) - actual_ordinary_strategies = self.tmf._tournaments_dict()['ordinary_strategies_prob_end'] - actual_cheating_strategies = ( - self.tmf._tournaments_dict()['cheating_strategies_prob_end']) - actual_all_strategies = self.tmf._tournaments_dict()['strategies_prob_end'] - - self.assertEqual( - actual_basic_strategies, self.expected_basic_strategies) - self.assertEqual(actual_ordinary_strategies, self.expected_ordinary_strategies) - self.assertEqual( - actual_cheating_strategies, self.expected_cheating_strategies) - self.assertEqual(actual_all_strategies, self.expected_strategies) - - # Tests to ensure that the exclusions list works as intended - with_exclusions = self.tmf._tournaments_dict(self.test_exclusions) - self.assertFalse('basic_strategies' in with_exclusions) - self.assertFalse('cheating_strategies' in with_exclusions) - self.assertEqual( - with_exclusions['strategies_prob_end'], self.expected_strategies) - - def test_add_tournaments(self): - mgr = axelrod.ProbEndTournamentManager( - self.test_output_directory, - self.test_with_ecological, - cache_file=self.test_cache_file) - - self.tmf._add_tournaments(mgr, self.test_exclusions, self.test_kwargs) - self.assertEqual(len(mgr._tournaments), 2) - self.assertIsInstance(mgr._tournaments[0], axelrod.Tournament) - self.assertEqual(mgr._tournaments[0].name, 'ordinary_strategies_prob_end') - - def test_create_tournament_manager(self): - mgr = self.tmf.create_tournament_manager( - output_directory=self.test_output_directory, - no_ecological=False, - rebuild_cache=self.test_rebuild_cache, - cache_file=self.test_cache_file, - exclusions=self.test_exclusions, - **self.test_kwargs) - - self.assertIsInstance(mgr, axelrod.TournamentManager) - self.assertEqual(mgr._output_directory, self.test_output_directory) - self.assertEqual(len(mgr._tournaments), 2) - self.assertTrue(mgr._with_ecological) - self.assertTrue(mgr._pass_cache) diff --git a/axelrod/tests/unit/test_utils.py b/axelrod/tests/unit/test_utils.py deleted file mode 100644 index b1028013f..000000000 --- a/axelrod/tests/unit/test_utils.py +++ /dev/null @@ -1,58 +0,0 @@ -"""Tests for the utils functions and classes.""" - -import axelrod -import unittest -import itertools - -from hypothesis import given -from hypothesis.strategies import floats, text - -import logging -from testfixtures import compare - -class TestTimedMessage(unittest.TestCase): - - @given(start_time=floats(min_value=0, allow_nan=False, - allow_infinity=False), - message=text()) - def test_time_message(self, start_time, message): - timed_message = axelrod.utils.timed_message(message, start_time) - self.assertEqual(timed_message[:len(message)], message) - - def test_time_message_example(self): - message = "Full tournament" - start_time = 0 - timed_message = axelrod.utils.timed_message(message, start_time) - self.assertEqual(timed_message[:len(message)], message) - self.assertGreaterEqual(float(timed_message[len(message)+4:-1]), 0) - - -class TestSetupLogging(unittest.TestCase): - - def test_basic_configuration_console(self): - logger = logging.getLogger("axelrod") - levels = {"CRITICAL": 50, - "ERROR": 40, - "WARNING": 30, - "INFO": 20, - "DEBUG": 10, - "NOTSET": 0} - for level in levels: - axelrod.utils.setup_logging(logging_destination='console', - verbosity=level) - compare(logger.level, levels[level]) - - -class TestBuildExclusionsDict(unittest.TestCase): - def test_build_exclusions_dict(self): - """This is really a regression test to make sure the names of the - tournaments stay consistent""" - bools = [True, False] - for (eb, eo, ec, eco) in itertools.product(bools, repeat=4): - expected_dict = { - 'basic_strategies': eb, - 'ordinary_strategies': eo, - 'cheating_strategies': ec, - 'strategies': eco} - self.assertEqual(axelrod.utils.build_exclusions_dict(eb, eo, ec, eco), - expected_dict) diff --git a/axelrod/tournament.py b/axelrod/tournament.py index 0380ce6c0..5e8ac6d61 100644 --- a/axelrod/tournament.py +++ b/axelrod/tournament.py @@ -15,8 +15,8 @@ class Tournament(object): def __init__(self, players, match_generator=RoundRobinMatches, name='axelrod', game=None, turns=200, repetitions=10, - processes=None, deterministic_cache=None, prebuilt_cache=False, - noise=0, with_morality=True): + processes=None, deterministic_cache=None, noise=0, + with_morality=True): """ Parameters ---------- @@ -36,8 +36,6 @@ def __init__(self, players, match_generator=RoundRobinMatches, The number of processes to be used for parallel processing deterministic_cache : instance An instance of the axelrod.DeterministicCache class - prebuilt_cache : boolean - Whether a cache has been passed in from an external object noise : float The probability that a player's intended action should be flipped with_morality : boolean @@ -50,12 +48,10 @@ def __init__(self, players, match_generator=RoundRobinMatches, self.game = game self.players = players self.repetitions = repetitions - if deterministic_cache is not None: - self.prebuilt_cache = True - self.deterministic_cache = deterministic_cache - else: - self.prebuilt_cache = prebuilt_cache + if deterministic_cache is None: self.deterministic_cache = DeterministicCache() + else: + self.deterministic_cache = deterministic_cache self.match_generator = match_generator( players, turns, self.game, self.deterministic_cache) self._with_morality = with_morality @@ -104,9 +100,7 @@ def _build_cache_required(self): deterministic cache. """ return ( - not self.noise and ( - len(self.deterministic_cache) == 0 or - not self.prebuilt_cache)) + not self.noise and len(self.deterministic_cache) == 0) def _build_cache(self, matches): """ @@ -310,8 +304,8 @@ class ProbEndTournament(Tournament): def __init__(self, players, match_generator=ProbEndRoundRobinMatches, name='axelrod', game=None, prob_end=.5, repetitions=10, - processes=None, deterministic_cache=None, prebuilt_cache=False, - noise=0, with_morality=True): + processes=None, deterministic_cache=None, noise=0, + with_morality=True): """ Parameters ---------- @@ -329,10 +323,10 @@ def __init__(self, players, match_generator=ProbEndRoundRobinMatches, The number of times the round robin should be repeated processes : integer The number of processes to be used for parallel processing - prebuilt_cache : boolean - Whether a cache has been passed in from an external object noise : float The probability that a player's intended action should be flipped + deterministic_cache : instance + An instance of the axelrod.DeterministicCache class with_morality : boolean Whether morality metrics should be calculated """ @@ -340,8 +334,7 @@ def __init__(self, players, match_generator=ProbEndRoundRobinMatches, players, name=name, game=game, turns=float("inf"), repetitions=repetitions, processes=processes, deterministic_cache=deterministic_cache, - prebuilt_cache=prebuilt_cache, noise=noise, - with_morality=with_morality) + noise=noise, with_morality=with_morality) self.prob_end = prob_end self.match_generator = ProbEndRoundRobinMatches( diff --git a/axelrod/tournament_manager.py b/axelrod/tournament_manager.py deleted file mode 100644 index f8adac577..000000000 --- a/axelrod/tournament_manager.py +++ /dev/null @@ -1,206 +0,0 @@ -from __future__ import absolute_import, unicode_literals, print_function - -import os - -from .tournament import * -from .deterministic_cache import DeterministicCache -from .plot import * -from .ecosystem import * -from .utils import * - - -class TournamentManager(object): - """A class to manage and create tournaments.""" - - plot_types = {'boxplot': "Payoffs. ", 'payoff': "Payoffs. ", - 'winplot': "Wins. ", 'sdvplot': "Std Payoffs. ", - 'pdplot': "Payoff differences. ", 'lengthplot': "Lengths. "} - - ecoturns = { - 'basic_strategies': 1000, - 'cheating_strategies': 10, - 'ordinary_strategies': 1000, - 'strategies': 10, - } - - def __init__(self, output_directory, with_ecological, - pass_cache=True, load_cache=True, save_cache=False, - cache_file='./cache.txt', image_format="svg"): - self._tournaments = [] - self._ecological_variants = [] - self._logger = logging.getLogger(__name__) - self._output_directory = output_directory - self._with_ecological = with_ecological - self._pass_cache = pass_cache - self._save_cache = save_cache - self._cache_file = cache_file - self._deterministic_cache = DeterministicCache() - self._load_cache = False - self._image_format = image_format - - if load_cache and not save_cache: - self.load_cache = self._load_cache_from_file(cache_file) - - @staticmethod - def one_player_per_strategy(strategies): - return [strategy() for strategy in strategies] - - def add_tournament(self, name, players, game=None, turns=200, - repetitions=10, processes=None, noise=0, - with_morality=True): - tournament = Tournament( - name=name, - players=players, - turns=turns, - repetitions=repetitions, - processes=processes, - noise=noise, - with_morality=with_morality) - self._tournaments.append(tournament) - - def run_tournaments(self): - t0 = time.time() - for tournament in self._tournaments: - self._run_single_tournament(tournament) - if self._save_cache and not tournament.noise: - self._save_cache_to_file(self._deterministic_cache, self._cache_file) - self._logger.info(timed_message('Finished all tournaments', t0)) - - def _run_single_tournament(self, tournament): - self._logger.info( - 'Starting {} tournament: '.format(tournament.name) + self._tournament_label(tournament) - ) - - t0 = time.time() - - if not tournament.noise and self._pass_cache: - self._logger.debug('Passing cache with %d entries to %s tournament' % - (len(self._deterministic_cache), tournament.name)) - tournament.deterministic_cache = self._deterministic_cache - if self._load_cache: - tournament.prebuilt_cache = True - else: - self._logger.debug('Cache is not valid for %s tournament' % - tournament.name) - tournament.play() - - self._logger.debug(timed_message('Finished %s tournament' % tournament.name, t0)) - - if self._with_ecological: - ecosystem = Ecosystem(tournament.result_set) - self.run_ecological_variant(tournament, ecosystem) - else: - ecosystem = None - - self._generate_output_files(tournament, ecosystem) - self._cache_valid_for_turns = tournament.turns - - self._logger.debug('Cache now has %d entries' % - len(self._deterministic_cache)) - - self._logger.info( - timed_message('Finished all %s tasks' % tournament.name, t0)) - - def run_ecological_variant(self, tournament, ecosystem): - self._logger.debug( - 'Starting ecological variant of %s' % tournament.name) - t0 = time.time() - ecosystem.reproduce(self.ecoturns.get(tournament.name)) - self._logger.debug( - timed_message('Finished ecological variant of %s' % tournament.name, t0)) - - def _generate_output_files(self, tournament, ecosystem=None): - self._save_csv(tournament) - self._save_plots(tournament, ecosystem, - image_format=self._image_format) - - def _save_csv(self, tournament): - csv = tournament.result_set.csv() - file_name = self._output_file_path( - tournament.name, 'csv') - with open(file_name, 'w') as f: - f.write(csv) - - def _save_plots(self, tournament, ecosystem=None, image_format="svg"): - results = tournament.result_set - plot = Plot(results) - if not plot.matplotlib_installed: - self._logger.error('The matplotlib library is not installed. ' - 'No plots will be produced') - return - label = self._tournament_label(tournament) - for plot_type, name in self.plot_types.items(): - title = name + label - figure = getattr(plot, plot_type)(title=title) - file_name = self._output_file_path( - tournament.name + '_' + plot_type, image_format) - self._save_plot(figure, file_name) - if ecosystem is not None: - title = "Eco. " + label - figure = plot.stackplot(ecosystem, title=title) - file_name = self._output_file_path( - tournament.name + '_reproduce', image_format) - self._save_plot(figure, file_name) - - def _tournament_label(self, tournament): - """A label for the tournament for the corresponding title plots""" - return "Turns: {}, Repetitions: {}, Strategies: {}.".format(tournament.turns, - tournament.repetitions, - len(tournament.players)) - - def _output_file_path(self, file_name, file_extension): - return os.path.join( - self._output_directory, - file_name + '.' + file_extension) - - @staticmethod - def _save_plot(figure, file_name, dpi=400): - figure.savefig(file_name, bbox_inches='tight', dpi=dpi) - figure.clf() - plt.close(figure) - - def _save_cache_to_file(self, cache, file_name): - self._logger.debug( - 'Saving cache with %d entries to %s' % (len(cache), file_name)) - cache.save(file_name) - return True - - def _load_cache_from_file(self, file_name): - try: - self._deterministic_cache.load(file_name) - self._logger.debug( - 'Loaded cache with %d entries' % len(self._deterministic_cache)) - return True - except IOError: - self._logger.debug('Cache file not found. Starting with empty cache') - return False - - -class ProbEndTournamentManager(TournamentManager): - """A class to manage and create probabilistic ending tournaments.""" - - ecoturns = { - 'basic_strategies_prob_end': 1000, - 'cheating_strategies_prob_end': 10, - 'ordinary_strategies_prob_end': 1000, - 'strategies_prob_end': 10, - } - - def add_tournament(self, name, players, game=None, prob_end=.01, - repetitions=10, processes=None, noise=0, - with_morality=True): - tournament = ProbEndTournament( - name=name, - players=players, - prob_end=prob_end, - repetitions=repetitions, - processes=processes, - noise=noise, - with_morality=with_morality) - self._tournaments.append(tournament) - - def _tournament_label(self, tournament): - """A label for the tournament for the corresponding title plots""" - return "Prob end: {}, Repetitions: {}, Strategies: {}.".format(tournament.prob_end, - tournament.repetitions, - len(tournament.players)) diff --git a/axelrod/tournament_manager_factory.py b/axelrod/tournament_manager_factory.py deleted file mode 100644 index 13fc686c2..000000000 --- a/axelrod/tournament_manager_factory.py +++ /dev/null @@ -1,113 +0,0 @@ -from __future__ import absolute_import -from collections import OrderedDict - -import axelrod.strategies - -from .tournament_manager import * - - -class TournamentManagerFactory(object): - - tournaments = OrderedDict([ - ('basic_strategies', axelrod.basic_strategies), - ('ordinary_strategies', - axelrod.ordinary_strategies), - ('cheating_strategies', axelrod.cheating_strategies), - ('strategies', - axelrod.ordinary_strategies + - axelrod.cheating_strategies) - ]) - - @classmethod - def create_tournament_manager( - cls, - output_directory, - no_ecological, - rebuild_cache, - cache_file, - exclusions, - processes, - turns, - repetitions, - noise, - image_format="svg"): - - kwargs = { - 'processes': processes, - 'turns': turns, - 'repetitions': repetitions, - 'noise': noise, - } - - manager = axelrod.TournamentManager( - output_directory=output_directory, - with_ecological=not no_ecological, - save_cache=rebuild_cache, - cache_file=cache_file, - image_format=image_format) - - cls._add_tournaments(manager, exclusions, kwargs) - - return manager - - @classmethod - def _add_tournaments(cls, manager, exclusions, kwargs): - for name, strategies in cls._tournaments_dict(exclusions).items(): - players = manager.one_player_per_strategy(strategies) - manager.add_tournament( - name=name, players=players, **kwargs) - - @classmethod - def _tournaments_dict(cls, exclusions=None): - if exclusions is None: - exclusions = [] - - return OrderedDict([ - (key, value) for - key, value in cls.tournaments.items() if key not in exclusions - ]) - - -class ProbEndTournamentManagerFactory(TournamentManagerFactory): - - @classmethod - def create_tournament_manager( - cls, - output_directory, - no_ecological, - rebuild_cache, - cache_file, - exclusions, - processes, - prob_end, - repetitions, - noise, - image_format="svg"): - - kwargs = { - 'processes': processes, - 'prob_end': prob_end, - 'repetitions': repetitions, - 'noise': noise, - } - - manager = axelrod.ProbEndTournamentManager( - output_directory=output_directory, - with_ecological=not no_ecological, - save_cache=rebuild_cache, - cache_file=cache_file, - image_format=image_format) - - cls._add_tournaments(manager, exclusions, kwargs) - - return manager - - @classmethod - def _tournaments_dict(cls, exclusions=None): - if exclusions is None: - exclusions = [] - - return OrderedDict([ - (key+'_prob_end', value) for - key, value in cls.tournaments.items() if key not in exclusions - ]) diff --git a/axelrod/utils.py b/axelrod/utils.py deleted file mode 100644 index 2e8129149..000000000 --- a/axelrod/utils.py +++ /dev/null @@ -1,116 +0,0 @@ -from __future__ import absolute_import - -import time -import logging - -from .tournament_manager_factory import (TournamentManagerFactory, - ProbEndTournamentManagerFactory) - - -def timed_message(message, start_time): - elapsed_time = time.time() - start_time - return message + " in %.1fs" % elapsed_time - - -def setup_logging(logging_destination='console', verbosity='INFO'): - """Sets up logging. Call this outside of run_tournaments to avoid - accumulating logging handlers.""" - logHandlers = { - 'console': logging.StreamHandler, - 'none': logging.NullHandler, - } - if logging_destination == 'file': - logHandler = logging.FileHandler('./axelrod.log') - else: - logHandler = logHandlers[logging_destination]() - - logFormatters = { - 'console': '%(message)s', - 'none': '', - 'file': '%(asctime)s - %(name)s - %(levelname)s - %(message)s' - } - logFormatter = logging.Formatter(logFormatters[logging_destination]) - - logHandler.setFormatter(logFormatter) - logger = logging.getLogger('axelrod') - logger.setLevel(verbosity.upper()) - logger.addHandler(logHandler) - - -def build_exclusions_dict(exclude_basic, exclude_ordinary, - exclude_cheating, exclude_combined): - """A utility function to return a dictionary mapping tournament string names - to booleans.""" - return { - 'basic_strategies': exclude_basic, - 'ordinary_strategies': exclude_ordinary, - 'cheating_strategies': exclude_cheating, - 'strategies': exclude_combined} - - -def run_tournaments(cache_file='./cache.txt', - output_directory='./', - repetitions=10, - turns=200, - processes=None, - no_ecological=False, - rebuild_cache=False, - exclude_combined=False, - exclude_basic=False, - exclude_cheating=False, - exclude_ordinary=False, - noise=0, - image_format="svg"): - - exclusions_dict = build_exclusions_dict(exclude_basic, exclude_ordinary, - exclude_cheating, exclude_combined) - - exclusions = [key for key, value in exclusions_dict.items() if value] - - manager = TournamentManagerFactory.create_tournament_manager( - output_directory=output_directory, - no_ecological=no_ecological, - rebuild_cache=rebuild_cache, - cache_file=cache_file, - exclusions=exclusions, - processes=processes, - turns=turns, - repetitions=repetitions, - noise=noise, - image_format=image_format) - - manager.run_tournaments() - - -def run_prob_end_tournaments(cache_file='./cache.txt', - output_directory='./', - repetitions=10, - prob_end=.01, # By default have mean of 100 rounds - processes=None, - no_ecological=False, - rebuild_cache=False, - exclude_combined=False, - exclude_basic=False, - exclude_cheating=False, - exclude_ordinary=False, - noise=0, - image_format="svg"): - - exclusions_dict = build_exclusions_dict(exclude_basic, exclude_ordinary, - exclude_cheating, exclude_combined) - - exclusions = [key for key, value in exclusions_dict.items() if value] - - manager = ProbEndTournamentManagerFactory.create_tournament_manager( - output_directory=output_directory, - no_ecological=no_ecological, - rebuild_cache=rebuild_cache, - cache_file=cache_file, - exclusions=exclusions, - processes=processes, - prob_end=prob_end, - repetitions=repetitions, - noise=noise, - image_format=image_format) - - manager.run_tournaments() diff --git a/docs/tutorials/getting_started/command_line.rst b/docs/tutorials/getting_started/command_line.rst deleted file mode 100644 index d8be12227..000000000 --- a/docs/tutorials/getting_started/command_line.rst +++ /dev/null @@ -1,38 +0,0 @@ -Using the command line tool -=========================== - -Once :code:`axelrod` is installed you have access to a `run_axelrod` script that -can help run some of the tournaments, including the tournament that involves all -of the strategies from the library. You can view them at `Axelrod-Python/tournament on GitHub `_ - -To view the help for the :code:`run_axelrod` file run:: - - $ run_axelrod -h - -Note that if you have not installed the package you can still use this script -directly from the repository:: - - $ run_axelrod -h - -There is a variety of options that include: - -- Excluding certain strategy sets. -- Not running the ecological variant. -- Running the rounds of the tournament in parallel. -- Include background noise. -- Running probabilistic ending tournament. - -Particular parameters can also be changed: - -- The output directory for the plot and csv files. -- The number of turns and repetitions for the tournament. -- The format of created images - -Here is a command that will run the whole tournament, excluding the strategies -that do not obey Axelrod's original rules and using all available CPUS (this can -take quite a while!):: - - $ run_axelrod --xc -p 0 - -You can see results from various tournaments here: -http://axelrod-tournament.readthedocs.org/en/latest/ diff --git a/docs/tutorials/getting_started/index.rst b/docs/tutorials/getting_started/index.rst index e6866d5a8..252746de4 100644 --- a/docs/tutorials/getting_started/index.rst +++ b/docs/tutorials/getting_started/index.rst @@ -16,4 +16,3 @@ Contents: interactions.rst visualising_results.rst moran.rst - command_line.rst diff --git a/run_axelrod b/run_axelrod deleted file mode 100755 index 72a9d6034..000000000 --- a/run_axelrod +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python - -"""A script to run the Axelrod tournament. - -The code for strategies is present in `axelrod/strategies`. -""" - -from __future__ import division -import argparse -from axelrod import run_tournaments, run_prob_end_tournaments, setup_logging - -if __name__ == "__main__": - - parser = argparse.ArgumentParser( - description="Run a recreation of Axelrod's tournament") - - parser.add_argument( - '-l', '--logging', - type=str, - default='console', - dest="logging_destination", - help='logging (none, console or file)') - - parser.add_argument( - '-v', '--verbosity', - type=str, - default='INFO', - help='Logging level. DEBUG, INFO, ERROR or CRITICAL') - - parser.add_argument( - '-t', - '--turns', - type=int, - default=200, - help='turns per pair') - - parser.add_argument( - '-pe', - '--prob_end', - type=float, - default=None, - help='probability of a match ending (if provided overrides turns)') - - parser.add_argument( - '-r', '--repetitions', - type=int, - default=10, - help='round-robin repetitions') - - parser.add_argument( - '-o', '--output_directory', - default='./', - help='output directory') - - parser.add_argument( - '--xb', - "--exclude-basic", - action='store_true', - dest="exclude_basic", - help='exclude basic strategies plot') - - parser.add_argument( - '--xs', "--exclude-ordinary", - action='store_true', - dest="exclude_ordinary", - help='exclude ordinary strategies plot') - - parser.add_argument( - '--xc', "--exclude-cheating", - action='store_true', - dest="exclude_cheating", - help='exclude cheating strategies plot') - - parser.add_argument( - '--xa', "--exclude-combined", - action='store_true', - dest="exclude_combined", - help='exclude combined strategies plot') - - parser.add_argument( - '--ne', "--no-ecological", - action='store_true', - dest="no_ecological", - help='no ecological variant') - - parser.add_argument( - '-p', '--processes', - type=int, - default=None, - help='Number of parallel processes to spawn. 0 uses cpu count.') - - parser.add_argument( - '--rc', "--rebuild-cache", - action='store_true', - dest="rebuild_cache", - help='rebuild cache and save to file') - - parser.add_argument( - '-c', '--cache_file', - type=str, - default='./cache.txt', - help='Path to cache file') - - parser.add_argument( - '-n', '--noise', - type=float, - default=0, - help='Noise level') - - parser.add_argument( - '-i', '--image_format', - type=str, - default="svg", - help='Image format for matplotlib, e.g. svg, jpeg, png') - - args = parser.parse_args() - - if all([args.exclude_basic, - args.exclude_ordinary, - args.exclude_cheating, - args.exclude_combined]): - print("You've excluded everything - nothing for me to do") - else: - setup_logging(args.logging_destination, args.verbosity) - # Unravel argparse Namespace object to python keyword arguments. - kwargs = vars(args) - del kwargs["logging_destination"] - del kwargs["verbosity"] - - if kwargs['prob_end'] is None: - del kwargs["prob_end"] - run_tournaments(**kwargs) - else: - del kwargs["turns"] - run_prob_end_tournaments(**kwargs) From 053a6ea7cf936fa279b468525176d0ad25140514 Mon Sep 17 00:00:00 2001 From: Vince Knight Date: Thu, 21 Apr 2016 18:37:55 +0100 Subject: [PATCH 2/2] Adding some missing tests for plots. --- axelrod/tests/unit/test_plot.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/axelrod/tests/unit/test_plot.py b/axelrod/tests/unit/test_plot.py index 7d8703a4b..14b59be1b 100644 --- a/axelrod/tests/unit/test_plot.py +++ b/axelrod/tests/unit/test_plot.py @@ -119,6 +119,13 @@ def test_winplot(self): else: self.skipTest('matplotlib not installed') + def test_sdvplot(self): + if matplotlib_installed: + plot = axelrod.Plot(self.test_result_set) + self.assertIsInstance(plot.sdvplot(), matplotlib.pyplot.Figure) + else: + self.skipTest('matplotlib not installed') + def test_lengthplot_dataset(self): plot = axelrod.Plot(self.test_result_set) self.assertSequenceEqual( @@ -132,6 +139,13 @@ def test_lengthplot(self): else: self.skipTest('matplotlib not installed') + def test_pdplot(self): + if matplotlib_installed: + plot = axelrod.Plot(self.test_result_set) + self.assertIsInstance(plot.pdplot(), matplotlib.pyplot.Figure) + else: + self.skipTest('matplotlib not installed') + def test_payoff_dataset(self): plot = axelrod.Plot(self.test_result_set) self.assertSequenceEqual(