Exemple #1
0
    def test_parallel_play(self):
        # Test that we get an instance of ResultSet
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        results = tournament.play(processes=2, progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(tournament.num_interactions, 75)

        # The following relates to #516
        players = [
            axelrod.Cooperator(),
            axelrod.Defector(),
            axelrod.BackStabber(),
            axelrod.PSOGambler2_2_2(),
            axelrod.ThueMorse(),
            axelrod.DoubleCrosser(),
        ]
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=players,
            game=self.game,
            turns=20,
            repetitions=self.test_repetitions,
        )
        scores = tournament.play(processes=2, progress_bar=False).scores
        self.assertEqual(len(scores), len(players))
Exemple #2
0
    def test_score_with_particular_players(self):
        """
        These are players that are known to be difficult to pickle
        """
        name = "score"
        turns = 10
        noise = 0
        repetitions = 5
        num_states = 2
        opponents = [axl.ThueMorse(),
                     axl.MetaHunter(),
                     axl.BackStabber(),
                     axl.Alexei()]
        size = 10

        objective = dojo.prepare_objective(name=name,
                                           turns=turns,
                                           noise=noise,
                                           repetitions=repetitions)

        population = dojo.Population(player_class=player_class,
                                     params_kwargs={"num_states": num_states},
                                     size=size,
                                     objective=objective,
                                     output_filename=self.temporary_file.name,
                                     opponents=opponents,
                                     bottleneck=2,
                                     mutation_probability = .01,
                                     processes=0)

        generations = 4
        axl.seed(0)
        population.run(generations, print_output=False)
        self.assertEqual(population.generation, 4)
Exemple #3
0
    def test_parallel_play(self):
        # Test that we get an instance of ResultSet
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=200,
            repetitions=self.test_repetitions,
            processes=2)
        results = tournament.play()
        self.assertIsInstance(results, axelrod.ResultSet)

        # The following relates to #516
        players = [axelrod.Cooperator(), axelrod.Defector(),
                   axelrod.BackStabber(), axelrod.PSOGambler(),
                   axelrod.ThueMorse(), axelrod.DoubleCrosser()]
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=players,
            game=self.game,
            turns=20,
            repetitions=self.test_repetitions,
            processes=2)
        scores = tournament.play().scores
        self.assertEqual(len(scores), len(players))
Exemple #4
0
class TestProbEndTournament(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.game = axelrod.Game()
        cls.players = [s() for s in test_strategies]
        cls.test_name = 'test'
        cls.test_repetitions = test_repetitions
        cls.test_prob_end = test_prob_end

    def test_init(self):
        tournament = axelrod.ProbEndTournament(name=self.test_name,
                                               players=self.players,
                                               game=self.game,
                                               prob_end=self.test_prob_end,
                                               noise=0.2)
        self.assertEqual(tournament.match_generator.prob_end,
                         tournament.prob_end)
        self.assertEqual(len(tournament.players), len(test_strategies))
        self.assertEqual(tournament.game.score(('C', 'C')), (3, 3))
        self.assertEqual(tournament.turns, float("inf"))
        self.assertEqual(tournament.repetitions, 10)
        self.assertEqual(tournament.name, 'test')
        self.assertTrue(tournament._with_morality)
        self.assertIsInstance(tournament._logger, logging.Logger)
        self.assertEqual(tournament.noise, 0.2)
        anonymous_tournament = axelrod.Tournament(players=self.players)
        self.assertEqual(anonymous_tournament.name, 'axelrod')

    @given(tournament=prob_end_tournaments(min_size=2,
                                           max_size=5,
                                           min_prob_end=.1,
                                           max_prob_end=.9,
                                           min_repetitions=2,
                                           max_repetitions=4))
    @settings(max_examples=50, timeout=0)
    @example(tournament=axelrod.ProbEndTournament(
        players=[s() for s in test_strategies],
        prob_end=.2,
        repetitions=test_repetitions))
    # These two examples are to make sure #465 is fixed.
    # As explained there: https://github.com/Axelrod-Python/Axelrod/issues/465,
    # these two examples were identified by hypothesis.
    @example(tournament=axelrod.ProbEndTournament(
        players=[axelrod.BackStabber(),
                 axelrod.MindReader()],
        prob_end=.2,
        repetitions=1))
    @example(tournament=axelrod.ProbEndTournament(
        players=[axelrod.ThueMorse(),
                 axelrod.MindReader()],
        prob_end=.2,
        repetitions=1))
    def test_property_serial_play(self, tournament):
        """Test serial play using hypothesis"""
        # Test that we get an instance of ResultSet
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(results.nplayers, len(tournament.players))
        self.assertEqual(results.players, [str(p) for p in tournament.players])
 def test_sequence_player(self):
     inline_transformed_thue = axl.strategy_transformers.IdentityTransformer(
         name_prefix="Transformed")(axl.ThueMorse)()
     for player in [
             axl.ThueMorse(),
             axl.ThueMorseInverse(),
             MetaThue(),
             TransformedMetaThue(),
             inline_transformed_thue,
             TransformedThue(),
     ]:
         self.assert_equals_instance_from_pickling(player)
         opponents = (axl.Defector, axl.Cooperator, axl.Random,
                      axl.CyclerCCCDCD)
         for opponent_class in opponents:
             player.reset()
             opponent = opponent_class()
             match_1 = axl.Match((player, opponent), turns=20, seed=10)
             _ = match_1.play()
             self.assert_equals_instance_from_pickling(player)
Exemple #6
0
 def test_sequence_player(self):
     player = axl.ThueMorse()
     self.assert_orignal_equals_pickled(player)
Exemple #7
0
class TestTournament(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.game = axelrod.Game()
        cls.players = [s() for s in test_strategies]
        cls.test_name = "test"
        cls.test_repetitions = test_repetitions
        cls.test_turns = test_turns

        cls.expected_payoff = [
            [600, 600, 0, 600, 600],
            [600, 600, 199, 600, 600],
            [1000, 204, 200, 204, 204],
            [600, 600, 199, 600, 600],
            [600, 600, 199, 600, 600],
        ]

        cls.expected_cooperation = [
            [200, 200, 200, 200, 200],
            [200, 200, 1, 200, 200],
            [0, 0, 0, 0, 0],
            [200, 200, 1, 200, 200],
            [200, 200, 1, 200, 200],
        ]

        cls.filename = "test_outputs/test_tournament.csv"

    def setUp(self):
        self.test_tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=2,
            repetitions=1,
        )

    def test_init(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=self.test_turns,
            noise=0.2,
        )
        self.assertEqual(len(tournament.players), len(test_strategies))
        self.assertIsInstance(tournament.players[0].match_attributes["game"],
                              axelrod.Game)
        self.assertEqual(tournament.game.score((C, C)), (3, 3))
        self.assertEqual(tournament.turns, self.test_turns)
        self.assertEqual(tournament.repetitions, 10)
        self.assertEqual(tournament.name, "test")
        self.assertIsInstance(tournament._logger, logging.Logger)
        self.assertEqual(tournament.noise, 0.2)
        anonymous_tournament = axelrod.Tournament(players=self.players)
        self.assertEqual(anonymous_tournament.name, "axelrod")

    def test_init_with_match_attributes(self):
        tournament = axelrod.Tournament(
            players=self.players, match_attributes={"length": float("inf")})
        mg = tournament.match_generator
        match_params = mg.build_single_match_params()
        self.assertEqual(match_params["match_attributes"],
                         {"length": float("inf")})

    def test_warning(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=10,
            repetitions=1,
        )
        with warnings.catch_warnings(record=True) as w:
            # Check that a warning is raised if no results set is built and no
            # filename is given
            results = tournament.play(build_results=False, progress_bar=False)
            self.assertEqual(len(w), 1)

        with warnings.catch_warnings(record=True) as w:
            # Check that no warning is raised if no results set is built and a
            # is filename given

            tournament.play(build_results=False,
                            filename=self.filename,
                            progress_bar=False)
            self.assertEqual(len(w), 0)

    def test_setup_output_with_filename(self):

        self.test_tournament.setup_output(self.filename)

        self.assertEqual(self.test_tournament.filename, self.filename)
        self.assertIsNone(self.test_tournament._temp_file_descriptor)
        self.assertFalse(hasattr(self.test_tournament, "interactions_dict"))

    def test_setup_output_no_filename(self):
        self.test_tournament.setup_output()

        self.assertIsInstance(self.test_tournament.filename, str)
        self.assertIsInstance(self.test_tournament._temp_file_descriptor, int)
        self.assertFalse(hasattr(self.test_tournament, "interactions_dict"))

        os.close(self.test_tournament._temp_file_descriptor)
        os.remove(self.test_tournament.filename)

    def test_play_resets_num_interactions(self):
        self.assertEqual(self.test_tournament.num_interactions, 0)
        self.test_tournament.play(progress_bar=False)
        self.assertEqual(self.test_tournament.num_interactions, 15)

        self.test_tournament.play(progress_bar=False)
        self.assertEqual(self.test_tournament.num_interactions, 15)

    def test_play_changes_use_progress_bar(self):
        self.assertTrue(self.test_tournament.use_progress_bar)

        self.test_tournament.play(progress_bar=False)
        self.assertFalse(self.test_tournament.use_progress_bar)

        self.test_tournament.play(progress_bar=True)
        self.assertTrue(self.test_tournament.use_progress_bar)

    def test_play_changes_temp_file_descriptor(self):
        self.assertIsNone(self.test_tournament._temp_file_descriptor)

        # No file descriptor for a named file.
        self.test_tournament.play(filename=self.filename, progress_bar=False)
        self.assertIsNone(self.test_tournament._temp_file_descriptor)

        # Temp file creates file descriptor.
        self.test_tournament.play(filename=None, progress_bar=False)
        self.assertIsInstance(self.test_tournament._temp_file_descriptor, int)

    def test_play_tempfile_removed(self):
        self.test_tournament.play(filename=None, progress_bar=False)

        self.assertFalse(os.path.isfile(self.test_tournament.filename))

    def test_play_resets_filename_and_temp_file_descriptor_each_time(self):
        self.test_tournament.play(progress_bar=False)
        self.assertIsInstance(self.test_tournament._temp_file_descriptor, int)
        self.assertIsInstance(self.test_tournament.filename, str)
        old_filename = self.test_tournament.filename

        self.test_tournament.play(filename=self.filename, progress_bar=False)
        self.assertIsNone(self.test_tournament._temp_file_descriptor)
        self.assertEqual(self.test_tournament.filename, self.filename)
        self.assertNotEqual(old_filename, self.test_tournament.filename)

        self.test_tournament.play(progress_bar=False)
        self.assertIsInstance(self.test_tournament._temp_file_descriptor, int)
        self.assertIsInstance(self.test_tournament.filename, str)
        self.assertNotEqual(old_filename, self.test_tournament.filename)
        self.assertNotEqual(self.test_tournament.filename, self.filename)

    def test_get_file_objects_no_filename(self):
        file, writer = self.test_tournament._get_file_objects()
        self.assertIsNone(file)
        self.assertIsNone(writer)

    def test_get_file_object_with_filename(self):
        self.test_tournament.filename = self.filename
        file_object, writer = self.test_tournament._get_file_objects()
        self.assertIsInstance(file_object, io.TextIOWrapper)
        self.assertEqual(writer.__class__.__name__, "writer")
        file_object.close()

    def test_get_progress_bar(self):
        self.test_tournament.use_progress_bar = False
        pbar = self.test_tournament._get_progress_bar()
        self.assertIsNone(pbar)

        self.test_tournament.use_progress_bar = True
        pbar = self.test_tournament._get_progress_bar()
        self.assertIsInstance(pbar, tqdm)
        self.assertEqual(pbar.desc, "Playing matches")
        self.assertEqual(pbar.n, 0)
        self.assertEqual(pbar.total, self.test_tournament.match_generator.size)

        new_edges = [(0, 1), (1, 2), (2, 3), (3, 4)]
        new_tournament = axelrod.Tournament(players=self.players,
                                            edges=new_edges)
        new_tournament.use_progress_bar = True
        pbar = new_tournament._get_progress_bar()
        self.assertEqual(pbar.desc, "Playing matches")
        self.assertEqual(pbar.n, 0)
        self.assertEqual(pbar.total, len(new_edges))

    def test_serial_play(self):
        # Test that we get an instance of ResultSet
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)

        # Test that _run_serial_repetitions is called with empty matches list
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        results = tournament.play(progress_bar=False)
        self.assertEqual(tournament.num_interactions, 75)

    def test_serial_play_with_different_game(self):
        # Test that a non default game is passed to the result set
        game = axelrod.Game(p=-1, r=-1, s=-1, t=-1)
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=game,
                                        turns=1,
                                        repetitions=1)
        results = tournament.play(progress_bar=False)
        self.assertLessEqual(np.max(results.scores), 0)

    @patch("tqdm.tqdm", RecordedTQDM)
    def test_no_progress_bar_play(self):
        """Test that progress bar is not created for progress_bar=False"""
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )

        # Test with build results
        RecordedTQDM.reset_record()
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
        # Check that no progress bar was created.
        self.assertEqual(RecordedTQDM.record, [])

        # Test without build results
        RecordedTQDM.reset_record()
        results = tournament.play(progress_bar=False,
                                  build_results=False,
                                  filename=self.filename)
        self.assertIsNone(results)
        self.assertEqual(RecordedTQDM.record, [])

    def assert_play_pbar_correct_total_and_finished(self, pbar, total):
        self.assertEqual(pbar.desc, "Playing matches")
        self.assertEqual(pbar.total, total)
        self.assertEqual(pbar.n, total)
        self.assertTrue(pbar.disable, True)

    @patch("tqdm.tqdm", RecordedTQDM)
    def test_progress_bar_play(self):
        """Test that progress bar is created by default and with True argument"""
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )

        RecordedTQDM.reset_record()
        results = tournament.play()
        self.assertIsInstance(results, axelrod.ResultSet)
        # Check that progress bar was created, updated and closed.
        self.assertEqual(len(RecordedTQDM.record), 2)
        play_pbar = RecordedTQDM.record[0]
        self.assert_play_pbar_correct_total_and_finished(play_pbar, total=15)
        # Check all progress bars are closed.
        self.assertTrue(all(pbar.disable for pbar in RecordedTQDM.record))

        RecordedTQDM.reset_record()
        results = tournament.play(progress_bar=True)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(len(RecordedTQDM.record), 2)
        play_pbar = RecordedTQDM.record[0]
        self.assert_play_pbar_correct_total_and_finished(play_pbar, total=15)

        # Test without build results
        RecordedTQDM.reset_record()
        results = tournament.play(progress_bar=True,
                                  build_results=False,
                                  filename=self.filename)
        self.assertIsNone(results)
        self.assertEqual(len(RecordedTQDM.record), 1)
        play_pbar = RecordedTQDM.record[0]
        self.assert_play_pbar_correct_total_and_finished(play_pbar, total=15)

    @patch("tqdm.tqdm", RecordedTQDM)
    def test_progress_bar_play_parallel(self):
        """Test that tournament plays when asking for progress bar for parallel
        tournament and that progress bar is created."""
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )

        # progress_bar = False
        RecordedTQDM.reset_record()
        results = tournament.play(progress_bar=False, processes=2)
        self.assertEqual(RecordedTQDM.record, [])
        self.assertIsInstance(results, axelrod.ResultSet)

        # progress_bar = True
        RecordedTQDM.reset_record()
        results = tournament.play(progress_bar=True, processes=2)
        self.assertIsInstance(results, axelrod.ResultSet)

        self.assertEqual(len(RecordedTQDM.record), 2)
        play_pbar = RecordedTQDM.record[0]
        self.assert_play_pbar_correct_total_and_finished(play_pbar, total=15)

        # progress_bar is default
        RecordedTQDM.reset_record()
        results = tournament.play(processes=2)
        self.assertIsInstance(results, axelrod.ResultSet)

        self.assertEqual(len(RecordedTQDM.record), 2)
        play_pbar = RecordedTQDM.record[0]
        self.assert_play_pbar_correct_total_and_finished(play_pbar, total=15)

    @given(tournament=tournaments(
        min_size=2,
        max_size=5,
        min_turns=2,
        max_turns=5,
        min_repetitions=2,
        max_repetitions=4,
    ))
    @settings(max_examples=5, max_iterations=20)
    @example(tournament=axelrod.Tournament(
        players=[s() for s in test_strategies],
        turns=test_turns,
        repetitions=test_repetitions,
    ))
    # These two examples are to make sure #465 is fixed.
    # As explained there: https://github.com/Axelrod-Python/Axelrod/issues/465,
    # these two examples were identified by hypothesis.
    @example(tournament=axelrod.Tournament(
        players=[axelrod.BackStabber(),
                 axelrod.MindReader()],
        turns=2,
        repetitions=1,
    ))
    @example(tournament=axelrod.Tournament(
        players=[axelrod.BackStabber(),
                 axelrod.ThueMorse()],
        turns=2,
        repetitions=1))
    def test_property_serial_play(self, tournament):
        """Test serial play using hypothesis"""
        # Test that we get an instance of ResultSet
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(results.num_players, len(tournament.players))
        self.assertEqual(results.players, [str(p) for p in tournament.players])

    def test_parallel_play(self):
        # Test that we get an instance of ResultSet
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        results = tournament.play(processes=2, progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(tournament.num_interactions, 75)

        # The following relates to #516
        players = [
            axelrod.Cooperator(),
            axelrod.Defector(),
            axelrod.BackStabber(),
            axelrod.PSOGambler2_2_2(),
            axelrod.ThueMorse(),
            axelrod.DoubleCrosser(),
        ]
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=players,
            game=self.game,
            turns=20,
            repetitions=self.test_repetitions,
        )
        scores = tournament.play(processes=2, progress_bar=False).scores
        self.assertEqual(len(scores), len(players))

    def test_parallel_play_with_writing_to_file(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )

        results = tournament.play(processes=2,
                                  progress_bar=False,
                                  filename=self.filename)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(tournament.num_interactions, 75)

    def test_run_serial(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        tournament._write_interactions_to_file = MagicMock(
            name="_write_interactions_to_file")
        self.assertTrue(tournament._run_serial())

        # Get the calls made to write_interactions
        calls = tournament._write_interactions_to_file.call_args_list
        self.assertEqual(len(calls), 15)

    def test_run_parallel(self):
        class PickleableMock(MagicMock):
            def __reduce__(self):
                return MagicMock, ()

        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        tournament._write_interactions_to_file = PickleableMock(
            name="_write_interactions_to_file")

        # For test coverage purposes. This confirms PickleableMock can be
        # pickled exactly once. Windows multi-processing must pickle this Mock
        # exactly once during testing.
        pickled = pickle.loads(pickle.dumps(tournament))
        self.assertIsInstance(pickled._write_interactions_to_file, MagicMock)
        self.assertRaises(pickle.PicklingError, pickle.dumps, pickled)

        self.assertTrue(tournament._run_parallel())

        # Get the calls made to write_interactions
        calls = tournament._write_interactions_to_file.call_args_list
        self.assertEqual(len(calls), 15)

    def test_n_workers(self):
        max_processes = cpu_count()

        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            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=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        self.assertEqual(tournament._n_workers(processes=max_processes + 2),
                         max_processes)

    @unittest.skipIf(cpu_count() < 2,
                     "not supported on single processor machines")
    def test_2_workers(self):
        # This is a separate test with a skip condition because we
        # cannot guarantee that the tests will always run on a machine
        # with more than one processor
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        self.assertEqual(tournament._n_workers(processes=2), 2)

    def test_start_workers(self):
        workers = 2
        work_queue = Queue()
        done_queue = Queue()
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        chunks = tournament.match_generator.build_match_chunks()
        for chunk in chunks:
            work_queue.put(chunk)
        tournament._start_workers(workers, work_queue, done_queue)

        stops = 0
        while stops < workers:
            payoffs = done_queue.get()
            if payoffs == "STOP":
                stops += 1
        self.assertEqual(stops, workers)

    def test_worker(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )

        work_queue = Queue()
        chunks = tournament.match_generator.build_match_chunks()
        count = 0
        for chunk in chunks:
            work_queue.put(chunk)
            count += 1
        work_queue.put("STOP")

        done_queue = Queue()
        tournament._worker(work_queue, done_queue)
        for r in range(count):
            new_matches = done_queue.get()
            for index_pair, matches in new_matches.items():
                self.assertIsInstance(index_pair, tuple)
                self.assertEqual(len(matches), self.test_repetitions)
        queue_stop = done_queue.get()
        self.assertEqual(queue_stop, "STOP")

    def test_build_result_set(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)

    def test_no_build_result_set(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=axelrod.DEFAULT_TURNS,
            repetitions=self.test_repetitions,
        )

        tournament._calculate_results = MagicMock(name="_calculate_results")
        # Mocking this as it is called by play
        self.assertIsNone(
            tournament.play(filename=self.filename,
                            progress_bar=False,
                            build_results=False))

        # Get the calls made to write_interactions
        calls = tournament._calculate_results.call_args_list
        self.assertEqual(len(calls), 0)

    @given(turns=integers(min_value=1, max_value=200))
    @settings(max_examples=5, max_iterations=20)
    @example(turns=3)
    @example(turns=axelrod.DEFAULT_TURNS)
    def test_play_matches(self, turns):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            repetitions=self.test_repetitions,
        )

        def make_chunk_generator():
            for player1_index in range(len(self.players)):
                for player2_index in range(player1_index, len(self.players)):
                    index_pair = (player1_index, player2_index)
                    match_params = {"turns": turns, "game": self.game}
                    yield (index_pair, match_params, self.test_repetitions)

        chunk_generator = make_chunk_generator()
        interactions = {}
        for chunk in chunk_generator:
            result = tournament._play_matches(chunk)
            for index_pair, inters in result.items():
                try:
                    interactions[index_pair].append(inters)
                except KeyError:
                    interactions[index_pair] = [inters]

        self.assertEqual(len(interactions), 15)

        for index_pair, inter in interactions.items():
            self.assertEqual(len(index_pair), 2)
            for plays in inter:
                # Check that have the expected number of repetitions
                self.assertEqual(len(plays), self.test_repetitions)
                for repetition in plays:
                    actions, results = repetition
                    self.assertEqual(len(actions), turns)
                    self.assertEqual(len(results), 10)

        # Check that matches no longer exist
        self.assertEqual((len(list(chunk_generator))), 0)

    def test_match_cache_is_used(self):
        """
        Create two Random players that are classified as deterministic.
        As they are deterministic the cache will be used.
        """
        FakeRandom = axelrod.Random
        FakeRandom.classifier["stochastic"] = False
        p1 = FakeRandom()
        p2 = FakeRandom()
        tournament = axelrod.Tournament((p1, p2), turns=5, repetitions=2)
        results = tournament.play(progress_bar=False)
        for player_scores in results.scores:
            self.assertEqual(player_scores[0], player_scores[1])

    def test_write_interactions(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=2,
            repetitions=2,
        )
        tournament._write_interactions_to_file = MagicMock(
            name="_write_interactions_to_file")
        # Mocking this as it is called by play
        self.assertIsNone(
            tournament.play(filename=self.filename,
                            progress_bar=False,
                            build_results=False))

        # Get the calls made to write_interactions
        calls = tournament._write_interactions_to_file.call_args_list
        self.assertEqual(len(calls), 15)

    def test_write_to_csv_with_results(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=2,
            repetitions=2,
        )
        tournament.play(filename=self.filename, progress_bar=False)
        df = pd.read_csv(self.filename)
        expected_df = pd.read_csv("test_outputs/expected_test_tournament.csv")
        self.assertTrue(df.equals(expected_df))

    def test_write_to_csv_without_results(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=2,
            repetitions=2,
        )
        tournament.play(filename=self.filename,
                        progress_bar=False,
                        build_results=False)
        df = pd.read_csv(self.filename)
        expected_df = pd.read_csv(
            "test_outputs/expected_test_tournament_no_results.csv")
        self.assertTrue(df.equals(expected_df))
Exemple #8
0
class TestTournament(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.game = axelrod.Game()
        cls.players = [s() for s in test_strategies]
        cls.test_name = 'test'
        cls.test_repetitions = test_repetitions
        cls.test_turns = test_turns

        cls.expected_payoff = [[600, 600, 0, 600, 600],
                               [600, 600, 199, 600, 600],
                               [1000, 204, 200, 204, 204],
                               [600, 600, 199, 600, 600],
                               [600, 600, 199, 600, 600]]

        cls.expected_cooperation = [[200, 200, 200, 200, 200],
                                    [200, 200, 1, 200, 200], [0, 0, 0, 0, 0],
                                    [200, 200, 1, 200, 200],
                                    [200, 200, 1, 200, 200]]

        cls.filename = "test_outputs/test_tournament.csv"

    def test_init(self):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=self.test_turns,
                                        noise=0.2)
        self.assertEqual(len(tournament.players), len(test_strategies))
        self.assertIsInstance(tournament.players[0].match_attributes['game'],
                              axelrod.Game)
        self.assertEqual(tournament.game.score(('C', 'C')), (3, 3))
        self.assertEqual(tournament.turns, self.test_turns)
        self.assertEqual(tournament.repetitions, 10)
        self.assertEqual(tournament.name, 'test')
        self.assertTrue(tournament._with_morality)
        self.assertIsInstance(tournament._logger, logging.Logger)
        self.assertEqual(tournament.noise, 0.2)
        anonymous_tournament = axelrod.Tournament(players=self.players)
        self.assertEqual(anonymous_tournament.name, 'axelrod')

    def test_warning(self):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=10,
                                        repetitions=1)
        with warnings.catch_warnings(record=True) as w:
            # Check that a warning is raised if no results set is built and no
            # filename is given
            results = tournament.play(build_results=False, progress_bar=False)
            self.assertEqual(len(w), 1)

        with warnings.catch_warnings(record=True) as w:
            # Check that no warning is raised if no results set is built and a
            # is filename given

            tournament.play(build_results=False,
                            filename=self.filename,
                            progress_bar=False)
            self.assertEqual(len(w), 0)

    def test_serial_play(self):
        # Test that we get an instance of ResultSet
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)

        # Test that _run_serial_repetitions is called with empty matches list
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)
        results = tournament.play(progress_bar=False)
        self.assertEqual(tournament.num_interactions, 75)

    def test_serial_play_with_different_game(self):
        # Test that a non default game is passed to the result set
        game = axelrod.Game(p=-1, r=-1, s=-1, t=-1)
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=game,
                                        turns=1,
                                        repetitions=1)
        results = tournament.play(progress_bar=False)
        self.assertEqual(results.game.RPST(), (-1, -1, -1, -1))

    def test_no_progress_bar_play(self):
        """Test that progress bar is not created for progress_bar=False"""
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)

        # Test with build results
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
        # Check that no progress bar was created
        call_progress_bar = lambda: tournament.progress_bar.total
        self.assertRaises(AttributeError, call_progress_bar)

        # Test without build results
        results = tournament.play(progress_bar=False,
                                  build_results=False,
                                  filename=self.filename)
        self.assertIsNone(results)
        results = axelrod.ResultSetFromFile(self.filename, progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertRaises(AttributeError, call_progress_bar)

    def test_progress_bar_play(self):
        """Test that progress bar is created by default and with True argument"""
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)

        results = tournament.play()
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(tournament.progress_bar.total, 15)
        self.assertEqual(tournament.progress_bar.total,
                         tournament.progress_bar.n)

        results = tournament.play(progress_bar=True)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(tournament.progress_bar.total, 15)
        self.assertEqual(tournament.progress_bar.total,
                         tournament.progress_bar.n)

        # Test without build results
        results = tournament.play(progress_bar=True,
                                  build_results=False,
                                  filename=self.filename)
        self.assertIsNone(results)
        results = axelrod.ResultSetFromFile(self.filename)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(tournament.progress_bar.total, 15)
        self.assertEqual(tournament.progress_bar.total,
                         tournament.progress_bar.n)

    @unittest.skipIf(axelrod.on_windows,
                     "Parallel processing not supported on Windows")
    def test_progress_bar_play_parallel(self):
        """Test that tournament plays when asking for progress bar for parallel
        tournament"""
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)

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

        results = tournament.play(progress_bar=True)
        self.assertIsInstance(results, axelrod.ResultSet)

    @given(tournament=tournaments(min_size=2,
                                  max_size=5,
                                  min_turns=2,
                                  max_turns=50,
                                  min_repetitions=2,
                                  max_repetitions=4))
    @settings(max_examples=50, timeout=0)
    @example(tournament=axelrod.Tournament(
        players=[s() for s in test_strategies],
        turns=test_turns,
        repetitions=test_repetitions))
    # These two examples are to make sure #465 is fixed.
    # As explained there: https://github.com/Axelrod-Python/Axelrod/issues/465,
    # these two examples were identified by hypothesis.
    @example(
        tournament=axelrod.Tournament(
            players=[axelrod.BackStabber(),
                     axelrod.MindReader()],
            turns=2,
            repetitions=1), )
    @example(
        tournament=axelrod.Tournament(
            players=[axelrod.BackStabber(),
                     axelrod.ThueMorse()],
            turns=2,
            repetitions=1), )
    def test_property_serial_play(self, tournament):
        """Test serial play using hypothesis"""
        # Test that we get an instance of ResultSet
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(results.nplayers, len(tournament.players))
        self.assertEqual(results.players, [str(p) for p in tournament.players])

    @unittest.skipIf(axelrod.on_windows,
                     "Parallel processing not supported on Windows")
    def test_parallel_play(self):
        # Test that we get an instance of ResultSet
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)
        results = tournament.play(processes=2, progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
        self.assertEqual(tournament.num_interactions, 75)

        # The following relates to #516
        players = [
            axelrod.Cooperator(),
            axelrod.Defector(),
            axelrod.BackStabber(),
            axelrod.PSOGambler2_2_2(),
            axelrod.ThueMorse(),
            axelrod.DoubleCrosser()
        ]
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=players,
                                        game=self.game,
                                        turns=20,
                                        repetitions=self.test_repetitions)
        scores = tournament.play(processes=2, progress_bar=False).scores
        self.assertEqual(len(scores), len(players))

    def test_run_serial(self):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)
        tournament._write_interactions = MagicMock(name='_write_interactions')
        self.assertTrue(tournament._run_serial())

        # Get the calls made to write_interactions
        calls = tournament._write_interactions.call_args_list
        self.assertEqual(len(calls), 15)

    @unittest.skipIf(axelrod.on_windows,
                     "Parallel processing not supported on Windows")
    def test_run_parallel(self):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)
        tournament._write_interactions = MagicMock(name='_write_interactions')
        self.assertTrue(tournament._run_parallel())

        # Get the calls made to write_interactions
        calls = tournament._write_interactions.call_args_list
        self.assertEqual(len(calls), 15)

    @unittest.skipIf(axelrod.on_windows,
                     "Parallel processing not supported on Windows")
    def test_n_workers(self):
        max_processes = cpu_count()

        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        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)
        self.assertEqual(tournament._n_workers(processes=max_processes + 2),
                         max_processes)

    @unittest.skipIf(axelrod.on_windows,
                     "Parallel processing not supported on Windows")
    @unittest.skipIf(cpu_count() < 2,
                     "not supported on single processor machines")
    def test_2_workers(self):
        # This is a separate test with a skip condition because we
        # cannot guarantee that the tests will always run on a machine
        # with more than one processor
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=200,
            repetitions=self.test_repetitions,
        )
        self.assertEqual(tournament._n_workers(processes=2), 2)

    @unittest.skipIf(axelrod.on_windows,
                     "Parallel processing not supported on Windows")
    def test_start_workers(self):
        workers = 2
        work_queue = Queue()
        done_queue = Queue()
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)
        chunks = tournament.match_generator.build_match_chunks()
        for chunk in chunks:
            work_queue.put(chunk)
        tournament._start_workers(workers, work_queue, done_queue)

        stops = 0
        while stops < workers:
            payoffs = done_queue.get()
            if payoffs == 'STOP':
                stops += 1
        self.assertEqual(stops, workers)

    @unittest.skipIf(axelrod.on_windows,
                     "Parallel processing not supported on Windows")
    def test_worker(self):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)

        work_queue = Queue()
        chunks = tournament.match_generator.build_match_chunks()
        count = 0
        for chunk in chunks:
            work_queue.put(chunk)
            count += 1
        work_queue.put('STOP')

        done_queue = Queue()
        tournament._worker(work_queue, done_queue)
        for r in range(count):
            new_matches = done_queue.get()
            for index_pair, matches in new_matches.items():
                self.assertIsInstance(index_pair, tuple)
                self.assertEqual(len(matches), self.test_repetitions)
        queue_stop = done_queue.get()
        self.assertEqual(queue_stop, 'STOP')

    def test_build_result_set(self):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)

        # Test in memory
        results = tournament.play(progress_bar=False, in_memory=True)
        self.assertIsInstance(results, axelrod.ResultSet)

    def test_no_build_result_set(self):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=200,
                                        repetitions=self.test_repetitions)

        results = tournament.play(build_results=False,
                                  filename=self.filename,
                                  progress_bar=False)
        self.assertIsNone(results)

        # Checking that results were written properly
        results = axelrod.ResultSetFromFile(self.filename, progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)

    @given(turns=integers(min_value=1, max_value=200))
    @example(turns=3)
    @example(turns=200)
    def test_play_matches(self, turns):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        repetitions=self.test_repetitions)

        def make_chunk_generator():
            for player1_index in range(len(self.players)):
                for player2_index in range(player1_index, len(self.players)):
                    index_pair = (player1_index, player2_index)
                    match_params = (turns, self.game, None, 0)
                    yield (index_pair, match_params, self.test_repetitions)

        chunk_generator = make_chunk_generator()
        interactions = {}
        for chunk in chunk_generator:
            result = tournament._play_matches(chunk)
            for index_pair, inters in result.items():
                try:
                    interactions[index_pair].append(inters)
                except KeyError:
                    interactions[index_pair] = [inters]

        self.assertEqual(len(interactions), 15)

        for index_pair, inter in interactions.items():
            self.assertEqual(len(index_pair), 2)
            for plays in inter:
                # Check that have the expected number of repetitions
                self.assertEqual(len(plays), self.test_repetitions)
                for repetition in plays:
                    # Check that have the correct length for each rep
                    self.assertEqual(len(repetition), turns)

        # Check that matches no longer exist
        self.assertEqual((len(list(chunk_generator))), 0)

    def test_write_interactions(self):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=2,
                                        repetitions=2)
        tournament._write_interactions = MagicMock(name='_write_interactions')
        tournament._build_result_set = MagicMock(
            name='_build_result_set')  # Mocking this as it is called by play
        self.assertTrue(
            tournament.play(filename=self.filename, progress_bar=False))
        tournament.outputfile.close(
        )  # This is normally closed by `build_result_set`

        # Get the calls made to write_interactions
        calls = tournament._write_interactions.call_args_list
        self.assertEqual(len(calls), 15)

        # Test when runnning in memory
        tournament._write_interactions = MagicMock(name='_write_interactions')
        self.assertTrue(
            tournament.play(filename=self.filename,
                            progress_bar=False,
                            in_memory=True))
        # Get the calls made to write_interactions
        calls = tournament._write_interactions.call_args_list
        self.assertEqual(len(calls), 15)

    def test_write_to_csv(self):
        tournament = axelrod.Tournament(name=self.test_name,
                                        players=self.players,
                                        game=self.game,
                                        turns=2,
                                        repetitions=2)
        tournament.play(filename=self.filename, progress_bar=False)
        with open(self.filename, 'r') as f:
            written_data = [[int(r[0]), int(r[1])] + r[2:]
                            for r in csv.reader(f)]
            expected_data = [
                [0, 1, 'Cooperator', 'Tit For Tat', 'CC', 'CC'],
                [0, 1, 'Cooperator', 'Tit For Tat', 'CC', 'CC'],
                [1, 2, 'Tit For Tat', 'Defector', 'CD', 'DD'],
                [1, 2, 'Tit For Tat', 'Defector', 'CD', 'DD'],
                [0, 0, 'Cooperator', 'Cooperator', 'CC', 'CC'],
                [0, 0, 'Cooperator', 'Cooperator', 'CC', 'CC'],
                [3, 3, 'Grudger', 'Grudger', 'CC', 'CC'],
                [3, 3, 'Grudger', 'Grudger', 'CC', 'CC'],
                [2, 2, 'Defector', 'Defector', 'DD', 'DD'],
                [2, 2, 'Defector', 'Defector', 'DD', 'DD'],
                [
                    4, 4, 'Soft Go By Majority', 'Soft Go By Majority', 'CC',
                    'CC'
                ],
                [
                    4, 4, 'Soft Go By Majority', 'Soft Go By Majority', 'CC',
                    'CC'
                ], [1, 4, 'Tit For Tat', 'Soft Go By Majority', 'CC', 'CC'],
                [1, 4, 'Tit For Tat', 'Soft Go By Majority', 'CC', 'CC'],
                [1, 1, 'Tit For Tat', 'Tit For Tat', 'CC', 'CC'],
                [1, 1, 'Tit For Tat', 'Tit For Tat', 'CC', 'CC'],
                [1, 3, 'Tit For Tat', 'Grudger', 'CC', 'CC'],
                [1, 3, 'Tit For Tat', 'Grudger', 'CC', 'CC'],
                [2, 3, 'Defector', 'Grudger', 'DD', 'CD'],
                [2, 3, 'Defector', 'Grudger', 'DD', 'CD'],
                [0, 4, 'Cooperator', 'Soft Go By Majority', 'CC', 'CC'],
                [0, 4, 'Cooperator', 'Soft Go By Majority', 'CC', 'CC'],
                [2, 4, 'Defector', 'Soft Go By Majority', 'DD', 'CD'],
                [2, 4, 'Defector', 'Soft Go By Majority', 'DD', 'CD'],
                [0, 3, 'Cooperator', 'Grudger', 'CC', 'CC'],
                [0, 3, 'Cooperator', 'Grudger', 'CC', 'CC'],
                [3, 4, 'Grudger', 'Soft Go By Majority', 'CC', 'CC'],
                [3, 4, 'Grudger', 'Soft Go By Majority', 'CC', 'CC'],
                [0, 2, 'Cooperator', 'Defector', 'CC', 'DD'],
                [0, 2, 'Cooperator', 'Defector', 'CC', 'DD']
            ]
            self.assertEqual(sorted(written_data), sorted(expected_data))