Exemple #1
0
class TestStrategyList(unittest.TestCase):
    def test_call(self):
        strategies = strategy_lists().example()
        self.assertIsInstance(strategies, list)
        for p in strategies:
            self.assertIsInstance(p(), axelrod.Player)

    @given(strategies=strategy_lists(min_size=1, max_size=50))
    @settings(max_examples=5, max_iterations=20)
    def test_decorator(self, strategies):
        self.assertIsInstance(strategies, list)
        self.assertGreaterEqual(len(strategies), 1)
        self.assertLessEqual(len(strategies), 50)
        for strategy in strategies:
            self.assertIsInstance(strategy(), axelrod.Player)

    @given(strategies=strategy_lists(strategies=axelrod.basic_strategies))
    @settings(max_examples=5, max_iterations=20)
    def test_decorator_with_given_strategies(self, strategies):
        self.assertIsInstance(strategies, list)
        basic_player_names = [str(s()) for s in axelrod.basic_strategies]
        for strategy in strategies:
            player = strategy()
            self.assertIsInstance(player, axelrod.Player)
            self.assertIn(str(player), basic_player_names)
Exemple #2
0
class TestMatchOutcomes(unittest.TestCase):
    @given(
        strategies=strategy_lists(strategies=deterministic_strategies,
                                  min_size=2,
                                  max_size=2),
        turns=integers(min_value=1, max_value=20),
    )
    @settings(max_examples=5)
    def test_outcome_repeats(self, strategies, turns):
        """A test that if we repeat 3 matches with deterministic and well
        behaved strategies then we get the same result"""
        players = [s() for s in strategies]
        matches = [axl.Match(players, turns) for _ in range(3)]
        self.assertEqual(matches[0].play(), matches[1].play())
        self.assertEqual(matches[1].play(), matches[2].play())

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

        self.assertEqual(results[0], results[1])
        self.assertEqual(results[1], results[2])

    def test_matches_with_det_player_for_stochastic_classes(self):
        """A test based on a bug found in the cache.

        See: https://github.com/Axelrod-Python/Axelrod/issues/779"""
        p1 = axl.MemoryOnePlayer(four_vector=(0, 0, 0, 0))
        p2 = axl.MemoryOnePlayer(four_vector=(1, 0, 1, 0))
        p3 = axl.MemoryOnePlayer(four_vector=(1, 1, 1, 0))

        m = axl.Match((p1, p2), turns=3)
        self.assertEqual(m.play(), [(C, C), (D, C), (D, D)])

        m = axl.Match((p2, p3), turns=3)
        self.assertEqual(m.play(), [(C, C), (C, C), (C, C)])

        m = axl.Match((p1, p3), turns=3)
        self.assertEqual(m.play(), [(C, C), (D, C), (D, C)])
Exemple #3
0
    def test_init(self):
        tournament = axelrod.SpatialTournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=self.test_turns,
            edges=self.test_edges,
            noise=0.2)
        self.assertEqual(tournament.match_generator.edges, tournament.edges)
        self.assertEqual(len(tournament.players), len(test_strategies))
        self.assertEqual(tournament.game.score(('C', 'C')), (3, 3))
        self.assertEqual(tournament.turns, 100)
        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(strategies=strategy_lists(strategies=deterministic_strategies,
                                         min_size=2, max_size=2),
               turns=integers(min_value=1, max_value=20))

        def test_complete_tournament(self, strategies, turns):
            """
            A test to check that a spatial tournament on the complete multigraph
            gives the same results as the round robin.
            """

            players = [s() for s in strategies]
            # edges
            edges=[]
            for i in range(0, len(players)) :
                for j in range(i, len(players)) :
                    edges.append((i, j))
            # create a round robin tournament
            tournament = axelrod.Tournament(players, turns=turns)
            results = tournament.play()
            # create a complete spatial tournament
            spatial_tournament = axelrod.SpatialTournament(players, turns=turns,
                                                           edges=edges)
            spatial_results =  spatial_tournament.play()
            self.assertEqual(results.ranked_names, spatial_results.ranked_names)
            self.assertEqual(results.nplayers, spatial_results.nplayers)
            self.assertEqual(results.nrepetitions, spatial_results.nrepetitions)
            self.assertEqual(results.payoff_diffs_means, spatial_results.payoff_diffs_means)
            self.assertEqual(results.payoff_matrix, spatial_results.payoff_matrix)
            self.assertEqual(results.payoff_stddevs, spatial_results.payoff_stddevs)
            self.assertEqual(results.payoffs, spatial_results.payoffs)
            self.assertEqual(results.cooperating_rating, spatial_results.cooperating_rating)
            self.assertEqual(results.cooperation, spatial_results.cooperation)
            self.assertEqual(results.normalised_cooperation, spatial_results.normalised_cooperation)
            self.assertEqual(results.normalised_scores, spatial_results.normalised_scores)
            self.assertEqual(results.good_partner_matrix, spatial_results.good_partner_matrix)
            self.assertEqual(results.good_partner_rating, spatial_results.good_partner_rating)
Exemple #4
0
class TestFingerprint(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.strategy = axl.WinStayLoseShift
        cls.probe = axl.TitForTat
        cls.expected_points = [(0.0, 0.0), (0.0, 0.5), (0.0, 1.0), (0.5, 0.0),
                               (0.5, 0.5), (0.5, 1.0), (1.0, 0.0), (1.0, 0.5),
                               (1.0, 1.0)]
        cls.expected_edges = [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6),
                              (0, 7), (0, 8), (0, 9)]

    def test_create_points(self):
        test_points = create_points(0.5, progress_bar=False)
        self.assertEqual(test_points, self.expected_points)

    def test_create_jossann(self):
        # x + y < 1
        ja = create_jossann((.5, .4), self.probe)
        self.assertEqual(str(ja), "Joss-Ann Tit For Tat: (0.5, 0.4)")

        # x + y = 1
        ja = create_jossann((.4, .6), self.probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Tit For Tat: (0.6, 0.4)")

        # x + y > 1
        ja = create_jossann((.5, .6), self.probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Tit For Tat: (0.5, 0.4)")

    def test_create_jossann_parametrised_player(self):
        probe = axl.Random(p=0.1)

        # x + y < 1
        ja = create_jossann((.5, .4), probe)
        self.assertEqual(str(ja), "Joss-Ann Random: 0.1: (0.5, 0.4)")

        # x + y = 1
        ja = create_jossann((.4, .6), probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Random: 0.1: (0.6, 0.4)")

        # x + y > 1
        ja = create_jossann((.5, .6), probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Random: 0.1: (0.5, 0.4)")

    def test_create_probes(self):
        probes = create_probes(self.probe,
                               self.expected_points,
                               progress_bar=False)
        self.assertEqual(len(probes), 9)

    def test_create_edges(self):
        edges = create_edges(self.expected_points, progress_bar=False)
        self.assertEqual(edges, self.expected_edges)

    def test_generate_data(self):
        interactions = {
            (0, 1): [[(C, C)], [(C, C)]],
            (0, 2): [[(C, C), (C, C)], [(C, D)]],
            (0, 3): [[(C, C), (D, C)]],
            (0, 4): [[(C, C), (D, C)], [(D, D)]],
            (0, 5): [[(C, D), (D, C)]],
            (0, 6): [[(C, D), (C, D)]],
            (0, 7): [[(C, D), (D, D)]],
            (0, 8): [[(D, D), (D, D)]],
            (0, 9): [[(D, C), (D, C)]],
        }

        expected = {
            Point(0.0, 0.0): 3.0,
            Point(0.0, 0.5): 1.5,
            Point(0.0, 1.0): 4.0,
            Point(0.5, 0.0): 2.5,
            Point(0.5, 0.5): 2.5,
            Point(0.5, 1.0): 0.0,
            Point(1.0, 0.0): 0.5,
            Point(1.0, 0.5): 1.0,
            Point(1.0, 1.0): 5.0,
        }
        data = generate_data(interactions, self.expected_points,
                             self.expected_edges)
        self.assertEqual(data, expected)

    def test_reshape_data(self):
        test_points = [
            Point(x=0.0, y=0.0),
            Point(x=0.0, y=0.5),
            Point(x=0.0, y=1.0),
            Point(x=0.5, y=0.0),
            Point(x=0.5, y=0.5),
            Point(x=0.5, y=1.0),
            Point(x=1.0, y=0.0),
            Point(x=1.0, y=0.5),
            Point(x=1.0, y=1.0)
        ]
        test_data = {
            Point(x=0.0, y=0.0): 5,
            Point(x=0.0, y=0.5): 9,
            Point(x=0.0, y=1.0): 3,
            Point(x=0.5, y=0.0): 8,
            Point(x=0.5, y=0.5): 2,
            Point(x=0.5, y=1.0): 4,
            Point(x=1.0, y=0.0): 2,
            Point(x=1.0, y=0.5): 1,
            Point(x=1.0, y=1.0): 9
        }
        test_shaped_data = [[3, 4, 9], [9, 2, 1], [5, 8, 2]]
        plotting_data = reshape_data(test_data, test_points, 3)
        for i in range(len(plotting_data)):
            self.assertEqual(list(plotting_data[i]), test_shaped_data[i])

    def test_default_init(self):
        fingerprint = AshlockFingerprint(self.strategy)
        self.assertEqual(fingerprint.strategy, self.strategy)
        self.assertEqual(fingerprint.probe, self.probe)

    def test_init(self):
        fingerprint = AshlockFingerprint(self.strategy, self.probe)
        self.assertEqual(fingerprint.strategy, self.strategy)
        self.assertEqual(fingerprint.probe, self.probe)

    def test_init_with_instance(self):
        player = self.strategy()
        fingerprint = AshlockFingerprint(player)
        self.assertEqual(fingerprint.strategy, player)
        self.assertEqual(fingerprint.probe, self.probe)

        probe_player = self.probe()
        fingerprint = AshlockFingerprint(self.strategy, probe_player)
        self.assertEqual(fingerprint.strategy, self.strategy)
        self.assertEqual(fingerprint.probe, probe_player)

        fingerprint = AshlockFingerprint(player, probe_player)
        self.assertEqual(fingerprint.strategy, player)
        self.assertEqual(fingerprint.probe, probe_player)

    def test_construct_tournament_elemets(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        edges, tournament_players = af.construct_tournament_elements(
            0.5, progress_bar=False)
        self.assertEqual(edges, self.expected_edges)
        self.assertEqual(len(tournament_players), 10)
        self.assertEqual(tournament_players[0].__class__, af.strategy)

    def test_progress_bar_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        data = af.fingerprint(turns=10,
                              repetitions=2,
                              step=0.5,
                              progress_bar=True)
        self.assertEqual(sorted(data.keys()), self.expected_points)

    def test_fingerprint_with_filename(self):
        filename = "test_outputs/test_fingerprint.csv"
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=1,
                       repetitions=1,
                       step=0.5,
                       progress_bar=False,
                       filename=filename)
        with open(filename, 'r') as out:
            data = out.read()
            self.assertEqual(len(data.split("\n")), 10)

    def test_in_memory_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=10,
                       repetitions=2,
                       step=0.5,
                       progress_bar=False,
                       in_memory=True)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(af.data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(af.spatial_tournament.interactions_dict,
                         af.interactions)
        self.assertEqual(edge_keys, self.expected_edges)
        self.assertEqual(coord_keys, self.expected_points)

    def test_serial_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        data = af.fingerprint(turns=10,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(edge_keys, self.expected_edges)
        self.assertEqual(coord_keys, self.expected_points)

    @unittest.skipIf(axl.on_windows,
                     "Parallel processing not supported on Windows")
    def test_parallel_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=10,
                       repetitions=2,
                       step=0.5,
                       processes=2,
                       progress_bar=False)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(af.data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(edge_keys, self.expected_edges)
        self.assertEqual(coord_keys, self.expected_points)

    def test_plot(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=10, repetitions=2, step=0.25, progress_bar=False)
        p = af.plot()
        self.assertIsInstance(p, matplotlib.pyplot.Figure)
        q = af.plot(col_map='jet')
        self.assertIsInstance(q, matplotlib.pyplot.Figure)
        r = af.plot(interpolation='bicubic')
        self.assertIsInstance(r, matplotlib.pyplot.Figure)
        t = af.plot(title='Title')
        self.assertIsInstance(t, matplotlib.pyplot.Figure)
        u = af.plot(colorbar=False)
        self.assertIsInstance(u, matplotlib.pyplot.Figure)
        v = af.plot(labels=False)
        self.assertIsInstance(v, matplotlib.pyplot.Figure)

    def test_wsls_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process
        test_data = {
            Point(x=0.25, y=1.0): 0.84,
            Point(x=0.25, y=0.5): 1.85,
            Point(x=0.75, y=0.5): 3.01,
            Point(x=0.25, y=0.25): 2.23,
            Point(x=0.0, y=0.75): 1.08,
            Point(x=0.75, y=1.0): 1.14,
            Point(x=0.5, y=0.25): 2.66,
            Point(x=0.0, y=0.0): 3.0,
            Point(x=0.75, y=0.25): 3.12,
            Point(x=1.0, y=0.75): 3.57,
            Point(x=1.0, y=0.5): 3.94,
            Point(x=1.0, y=0.0): 3.0,
            Point(x=1.0, y=0.25): 4.78,
            Point(x=0.0, y=1.0): 0.5,
            Point(x=0.5, y=0.0): 3.0,
            Point(x=0.25, y=0.0): 3.0,
            Point(x=0.0, y=0.25): 1.71,
            Point(x=0.0, y=0.5): 1.44,
            Point(x=0.5, y=0.75): 1.62,
            Point(x=0.5, y=0.5): 2.77,
            Point(x=0.75, y=0.75): 2.27,
            Point(x=0.5, y=1.0): 1.02,
            Point(x=0.75, y=0.0): 3.0,
            Point(x=0.25, y=0.75): 1.27,
            Point(x=1.0, y=1.0): 1.3
        }

        af = axl.AshlockFingerprint(self.strategy, self.probe)
        data = af.fingerprint(turns=50,
                              repetitions=2,
                              step=0.25,
                              progress_bar=False)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key], places=2)

    def test_tft_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process
        test_data = {
            Point(x=0.25, y=1.0): 1.63,
            Point(x=0.25, y=0.5): 1.92,
            Point(x=0.75, y=0.5): 2.33,
            Point(x=0.25, y=0.25): 2.31,
            Point(x=0.0, y=0.75): 1.05,
            Point(x=0.75, y=1.0): 2.07,
            Point(x=0.5, y=0.25): 2.6,
            Point(x=0.0, y=0.0): 3.0,
            Point(x=0.75, y=0.25): 2.76,
            Point(x=1.0, y=0.75): 2.38,
            Point(x=1.0, y=0.5): 2.58,
            Point(x=1.0, y=0.0): 3.0,
            Point(x=1.0, y=0.25): 2.72,
            Point(x=0.0, y=1.0): 0.98,
            Point(x=0.5, y=0.0): 3.0,
            Point(x=0.25, y=0.0): 3.0,
            Point(x=0.0, y=0.25): 1.82,
            Point(x=0.0, y=0.5): 1.13,
            Point(x=0.5, y=0.75): 1.93,
            Point(x=0.5, y=0.5): 2.46,
            Point(x=0.75, y=0.75): 2.3,
            Point(x=0.5, y=1.0): 1.91,
            Point(x=0.75, y=0.0): 3.0,
            Point(x=0.25, y=0.75): 1.62,
            Point(x=1.0, y=1.0): 2.18
        }

        af = axl.AshlockFingerprint(axl.TitForTat, self.probe)
        data = af.fingerprint(turns=50,
                              repetitions=2,
                              step=0.25,
                              progress_bar=False)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key], places=2)

    def test_majority_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process
        test_data = {
            Point(x=0.25, y=1.0): 2.179,
            Point(x=0.25, y=0.5): 1.9,
            Point(x=0.75, y=0.5): 1.81,
            Point(x=0.25, y=0.25): 2.31,
            Point(x=0.0, y=0.75): 1.03,
            Point(x=0.75, y=1.0): 2.58,
            Point(x=0.5, y=0.25): 2.34,
            Point(x=0.0, y=0.0): 3.0,
            Point(x=0.75, y=0.25): 2.4,
            Point(x=1.0, y=0.75): 2.0,
            Point(x=1.0, y=0.5): 1.74,
            Point(x=1.0, y=0.0): 3.0,
            Point(x=1.0, y=0.25): 2.219,
            Point(x=0.0, y=1.0): 0.98,
            Point(x=0.5, y=0.0): 3.0,
            Point(x=0.25, y=0.0): 3.0,
            Point(x=0.0, y=0.25): 1.94,
            Point(x=0.0, y=0.5): 1.13,
            Point(x=0.5, y=0.75): 2.6,
            Point(x=0.5, y=0.5): 1.89,
            Point(x=0.75, y=0.75): 2.13,
            Point(x=0.5, y=1.0): 2.7,
            Point(x=0.75, y=0.0): 3.0,
            Point(x=0.25, y=0.75): 1.859,
            Point(x=1.0, y=1.0): 2.26
        }

        af = axl.AshlockFingerprint(axl.GoByMajority, self.probe)
        data = af.fingerprint(turns=50,
                              repetitions=2,
                              step=0.25,
                              progress_bar=False)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key], places=2)

    @given(strategy_pair=strategy_lists(min_size=2, max_size=2))
    def test_pair_fingerprints(self, strategy_pair):
        """
        A test to check that we can fingerprint
        with any two given strategies or instances
        """
        strategy, probe = strategy_pair
        af = AshlockFingerprint(strategy, probe)
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy(), probe)
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy, probe())
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy(), probe())
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)
Exemple #5
0
class TestContriteTitForTat(TestPlayer):
    name = "Contrite Tit For Tat"
    player = axl.ContriteTitForTat
    expected_classifier = {
        "memory_depth": 3,
        "stochastic": False,
        "makes_use_of": set(),
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }

    deterministic_strategies = [
        s for s in axl.strategies if not axl.Classifiers["stochastic"](s())
    ]

    def test_init(self):
        ctft = self.player()
        self.assertFalse(ctft.contrite, False)
        self.assertEqual(ctft._recorded_history, [])

    @given(
        strategies=strategy_lists(strategies=deterministic_strategies, max_size=1),
        turns=integers(min_value=1, max_value=20),
    )
    def test_is_tit_for_tat_with_no_noise(self, strategies, turns):
        tft = axl.TitForTat()
        ctft = self.player()
        opponent = strategies[0]()
        m1 = axl.Match((tft, opponent), turns)
        m2 = axl.Match((ctft, opponent), turns)
        self.assertEqual(m1.play(), m2.play())

    def test_strategy_with_noise(self):
        ctft = self.player()
        opponent = axl.Defector()
        self.assertEqual(ctft.strategy(opponent), C)
        self.assertEqual(ctft._recorded_history, [C])
        ctft.reset()  # Clear the recorded history
        self.assertEqual(ctft._recorded_history, [])

        random.seed(0)
        ctft.play(opponent, noise=0.9)
        self.assertEqual(ctft.history, [D])
        self.assertEqual(ctft._recorded_history, [C])
        self.assertEqual(opponent.history, [C])

        # After noise: is contrite
        ctft.play(opponent)
        self.assertEqual(ctft.history, [D, C])
        self.assertEqual(ctft._recorded_history, [C, C])
        self.assertEqual(opponent.history, [C, D])
        self.assertTrue(ctft.contrite)

        # Cooperates and no longer contrite
        ctft.play(opponent)
        self.assertEqual(ctft.history, [D, C, C])
        self.assertEqual(ctft._recorded_history, [C, C, C])
        self.assertEqual(opponent.history, [C, D, D])
        self.assertFalse(ctft.contrite)

        # Goes back to playing tft
        ctft.play(opponent)
        self.assertEqual(ctft.history, [D, C, C, D])
        self.assertEqual(ctft._recorded_history, [C, C, C, D])
        self.assertEqual(opponent.history, [C, D, D, D])
        self.assertFalse(ctft.contrite)
Exemple #6
0
class TestContriteTitForTat(TestPlayer):

    name = "Contrite Tit For Tat"
    player = axelrod.ContriteTitForTat
    expected_classifier = {
        'memory_depth': 3,
        'stochastic': False,
        'makes_use_of': set(),
        'inspects_source': False,
        'manipulates_source': False,
        'manipulates_state': False
    }

    deterministic_strategies = [s for s in axelrod.strategies
                                if not s().classifier['stochastic']]

    @given(strategies=strategy_lists(strategies=deterministic_strategies,
                                     max_size=1),
           turns=integers(min_value=1, max_value=20))
    def test_is_tit_for_tat_with_no_noise(self, strategies, turns):
        tft = axelrod.TitForTat()
        ctft = self.player()
        opponent = strategies[0]()
        m1 = axelrod.Match((tft, opponent), turns)
        m2 = axelrod.Match((ctft, opponent), turns)
        self.assertEqual(m1.play(), m2.play())

    def test_strategy_with_noise(self):
        ctft = self.player()
        opponent = axelrod.Defector()
        self.assertEqual(ctft.strategy(opponent), C)
        self.assertEqual(ctft._recorded_history, [C])
        ctft.reset()  # Clear the recorded history
        self.assertEqual(ctft._recorded_history, [])

        random.seed(0)
        ctft.play(opponent, noise=.9)
        self.assertEqual(ctft.history, [D])
        self.assertEqual(ctft._recorded_history, [C])
        self.assertEqual(opponent.history, [C])

        # After noise: is contrite
        ctft.play(opponent)
        self.assertEqual(ctft.history, [D, C])
        self.assertEqual(ctft._recorded_history, [C, C])
        self.assertEqual(opponent.history, [C, D])
        self.assertTrue(ctft.contrite)

        # Cooperates and no longer contrite
        ctft.play(opponent)
        self.assertEqual(ctft.history, [D, C, C])
        self.assertEqual(ctft._recorded_history, [C, C, C])
        self.assertEqual(opponent.history, [C, D, D])
        self.assertFalse(ctft.contrite)

        # Goes back to playing tft
        ctft.play(opponent)
        self.assertEqual(ctft.history, [D, C, C, D])
        self.assertEqual(ctft._recorded_history, [C, C, C, D])
        self.assertEqual(opponent.history, [C, D, D, D])
        self.assertFalse(ctft.contrite)

    def test_reset_cleans_all(self):
        p = self.player()
        p.contrite = True
        p.reset()
        self.assertFalse(p.contrite)
Exemple #7
0
class TestFiltersAgainstComprehensions(unittest.TestCase):
    """
    Test that the results of filtering strategies via a filterset dict
    match the results from using a list comprehension.
    """

    def setUp(self) -> None:
        # Ignore warnings about classifiers running on instances
        warnings.simplefilter("ignore", category=UserWarning)

    def tearDown(self) -> None:
        warnings.simplefilter("default", category=UserWarning)

    @settings(deadline=None)
    @given(strategies=strategy_lists(min_size=20, max_size=20))
    @example(strategies=[axl.DBS, axl.Cooperator])
    def test_boolean_filtering(self, strategies):

        classifiers = [
            "stochastic",
            "long_run_time",
            "manipulates_state",
            "manipulates_source",
            "inspects_source",
        ]

        for classifier in classifiers:
            comprehension = set(filter(axl.Classifiers[classifier], strategies))
            filterset = {classifier: True}
        filtered = set(axl.filtered_strategies(filterset, strategies=strategies))
        self.assertEqual(comprehension, filtered)

    @given(
        min_memory_depth=integers(min_value=1, max_value=10),
        max_memory_depth=integers(min_value=1, max_value=10),
        memory_depth=integers(min_value=1, max_value=10),
        strategies=strategy_lists(min_size=20, max_size=20),
    )
    @example(
        min_memory_depth=float("inf"),
        max_memory_depth=float("inf"),
        memory_depth=float("inf"),
        strategies=axl.short_run_time_strategies,
    )
    @settings(max_examples=5, deadline=None)
    def test_memory_depth_filtering(
        self, min_memory_depth, max_memory_depth, memory_depth, strategies
    ):

        min_comprehension = set(
            [
                s
                for s in strategies
                if axl.Classifiers["memory_depth"](s) >= min_memory_depth
            ]
        )
        min_filterset = {"min_memory_depth": min_memory_depth}
        min_filtered = set(
            axl.filtered_strategies(min_filterset, strategies=strategies)
        )
        self.assertEqual(min_comprehension, min_filtered)

        max_comprehension = set(
            [
                s
                for s in strategies
                if axl.Classifiers["memory_depth"](s) <= max_memory_depth
            ]
        )
        max_filterset = {"max_memory_depth": max_memory_depth}
        max_filtered = set(
            axl.filtered_strategies(max_filterset, strategies=strategies)
        )
        self.assertEqual(max_comprehension, max_filtered)

        comprehension = set(
            [
                s
                for s in strategies
                if axl.Classifiers["memory_depth"](s) == memory_depth
            ]
        )
        filterset = {"memory_depth": memory_depth}
        filtered = set(axl.filtered_strategies(filterset, strategies=strategies))
        self.assertEqual(comprehension, filtered)

    @given(strategies=strategy_lists(min_size=20, max_size=20))
    @settings(max_examples=5, deadline=None)
    def test_makes_use_of_filtering(self, strategies):
        """
        Test equivalent filtering using two approaches.
        """
        classifiers = [["game"], ["length"], ["game", "length"]]

        for classifier in classifiers:
            comprehension = set(
                [
                    s
                    for s in strategies
                    if set(classifier).issubset(set(axl.Classifiers["makes_use_of"](s)))
                ]
            )

            filterset = {"makes_use_of": classifier}
            filtered = set(axl.filtered_strategies(filterset, strategies=strategies))

            self.assertEqual(
                comprehension, filtered, msg="classifier: {}".format(classifier)
            )
Exemple #8
0
class TestProbEndingSpatialTournament(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
        cls.test_edges = test_edges

    def test_init(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            prob_end=self.test_prob_end,
            edges=self.test_edges,
            noise=0.2,
        )
        self.assertEqual(tournament.match_generator.edges, tournament.edges)
        self.assertEqual(len(tournament.players), len(test_strategies))
        self.assertEqual(tournament.game.score((C, C)), (3, 3))
        self.assertIsNone(tournament.turns)
        self.assertEqual(tournament.repetitions, 10)
        self.assertEqual(tournament.name, "test")
        self.assertIsInstance(tournament._logger, logging.Logger)
        self.assertEqual(tournament.noise, 0.2)
        self.assertEqual(tournament.match_generator.noise, 0.2)
        self.assertEqual(tournament.prob_end, self.test_prob_end)

    @given(
        strategies=strategy_lists(strategies=deterministic_strategies,
                                  min_size=2,
                                  max_size=2),
        prob_end=floats(min_value=.1, max_value=.9),
        reps=integers(min_value=1, max_value=3),
        seed=integers(min_value=0, max_value=4294967295),
    )
    @settings(max_examples=5, max_iterations=20)
    def test_complete_tournament(self, strategies, prob_end, seed, reps):
        """
        A test to check that a spatial tournament on the complete graph
        gives the same results as the round robin.
        """
        players = [s() for s in strategies]

        # create a prob end round robin tournament
        tournament = axelrod.Tournament(players,
                                        prob_end=prob_end,
                                        repetitions=reps)
        axelrod.seed(seed)
        results = tournament.play(progress_bar=False)

        # create a complete spatial tournament
        # edges
        edges = [(i, j) for i in range(len(players))
                 for j in range(i, len(players))]

        spatial_tournament = axelrod.Tournament(players,
                                                prob_end=prob_end,
                                                repetitions=reps,
                                                edges=edges)
        axelrod.seed(seed)
        spatial_results = spatial_tournament.play(progress_bar=False)
        self.assertEqual(results.match_lengths, spatial_results.match_lengths)
        self.assertEqual(results.ranked_names, spatial_results.ranked_names)
        self.assertEqual(results.wins, spatial_results.wins)
        self.assertEqual(results.scores, spatial_results.scores)
        self.assertEqual(results.cooperation, spatial_results.cooperation)

    @given(
        tournament=spatial_tournaments(
            strategies=axelrod.basic_strategies,
            max_turns=1,
            max_noise=0,
            max_repetitions=3,
        ),
        seed=integers(min_value=0, max_value=4294967295),
    )
    @settings(max_examples=5, max_iterations=20)
    def test_one_turn_tournament(self, tournament, seed):
        """
        Tests that gives same result as the corresponding spatial round robin
        spatial tournament
        """
        prob_end_tour = axelrod.Tournament(
            tournament.players,
            prob_end=1,
            edges=tournament.edges,
            repetitions=tournament.repetitions,
        )
        axelrod.seed(seed)
        prob_end_results = prob_end_tour.play(progress_bar=False)
        axelrod.seed(seed)
        one_turn_results = tournament.play(progress_bar=False)
        self.assertEqual(prob_end_results.scores, one_turn_results.scores)
        self.assertEqual(prob_end_results.wins, one_turn_results.wins)
        self.assertEqual(prob_end_results.cooperation,
                         one_turn_results.cooperation)
Exemple #9
0
class TestMoranProcess(unittest.TestCase):
    def test_init(self):
        players = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess(players)
        self.assertEqual(mp.turns, axelrod.DEFAULT_TURNS)
        self.assertIsNone(mp.prob_end)
        self.assertIsNone(mp.game)
        self.assertEqual(mp.noise, 0)
        self.assertEqual(mp.initial_players, players)
        self.assertEqual(mp.players, list(players))
        self.assertEqual(mp.populations, [Counter({"Cooperator": 1, "Defector": 1})])
        self.assertIsNone(mp.winning_strategy_name)
        self.assertEqual(mp.mutation_rate, 0)
        self.assertEqual(mp.mode, "bd")
        self.assertEqual(mp.deterministic_cache, axelrod.DeterministicCache())
        self.assertEqual(
            mp.mutation_targets, {"Cooperator": [players[1]], "Defector": [players[0]]}
        )
        self.assertEqual(mp.interaction_graph._edges, [(0, 1), (1, 0)])
        self.assertEqual(mp.reproduction_graph._edges, [(0, 1), (1, 0), (0, 0), (1, 1)])
        self.assertEqual(mp.fitness_transformation, None)
        self.assertEqual(mp.locations, [0, 1])
        self.assertEqual(mp.index, {0: 0, 1: 1})

        # Test non default graph cases
        players = axelrod.Cooperator(), axelrod.Defector(), axelrod.TitForTat()
        edges = [(0, 1), (2, 0), (1, 2)]
        graph = axelrod.graph.Graph(edges, directed=True)
        mp = MoranProcess(players, interaction_graph=graph)
        self.assertEqual(mp.interaction_graph._edges, [(0, 1), (2, 0), (1, 2)])
        self.assertEqual(
            sorted(mp.reproduction_graph._edges),
            sorted([(0, 1), (2, 0), (1, 2), (0, 0), (1, 1), (2, 2)]),
        )

        mp = MoranProcess(players, interaction_graph=graph, reproduction_graph=graph)
        self.assertEqual(mp.interaction_graph._edges, [(0, 1), (2, 0), (1, 2)])
        self.assertEqual(mp.reproduction_graph._edges, [(0, 1), (2, 0), (1, 2)])

    def test_set_players(self):
        """Test that set players resets all players"""
        players = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess(players)
        players[0].cooperations += 1
        mp.set_players()
        self.assertEqual(players[0].cooperations, 0)

    def test_mutate(self):
        """Test that a mutated player is returned"""
        players = axelrod.Cooperator(), axelrod.Defector(), axelrod.TitForTat()
        mp = MoranProcess(players, mutation_rate=0.5)
        axelrod.seed(0)
        self.assertEqual(mp.mutate(0), players[0])
        axelrod.seed(1)
        self.assertEqual(mp.mutate(0), players[2])
        axelrod.seed(4)
        self.assertEqual(mp.mutate(0), players[1])

    def test_death_in_db(self):
        players = axelrod.Cooperator(), axelrod.Defector(), axelrod.TitForTat()
        mp = MoranProcess(players, mutation_rate=0.5, mode="db")
        axelrod.seed(1)
        self.assertEqual(mp.death(), 0)
        self.assertEqual(mp.dead, 0)
        axelrod.seed(5)
        self.assertEqual(mp.death(), 1)
        self.assertEqual(mp.dead, 1)
        axelrod.seed(2)
        self.assertEqual(mp.death(), 2)
        self.assertEqual(mp.dead, 2)

    def test_death_in_bd(self):
        players = axelrod.Cooperator(), axelrod.Defector(), axelrod.TitForTat()
        edges = [(0, 1), (2, 0), (1, 2)]
        graph = axelrod.graph.Graph(edges, directed=True)
        mp = MoranProcess(players, mode="bd", interaction_graph=graph)
        axelrod.seed(1)
        self.assertEqual(mp.death(0), 0)
        axelrod.seed(5)
        self.assertEqual(mp.death(0), 1)
        axelrod.seed(2)
        self.assertEqual(mp.death(0), 0)

    def test_birth_in_db(self):
        players = axelrod.Cooperator(), axelrod.Defector(), axelrod.TitForTat()
        mp = MoranProcess(players, mode="db")
        axelrod.seed(1)
        self.assertEqual(mp.death(), 0)
        self.assertEqual(mp.birth(0), 2)

    def test_birth_in_bd(self):
        players = axelrod.Cooperator(), axelrod.Defector(), axelrod.TitForTat()
        mp = MoranProcess(players, mode="bd")
        axelrod.seed(1)
        self.assertEqual(mp.birth(), 0)

    def test_fixation_check(self):
        players = axelrod.Cooperator(), axelrod.Cooperator()
        mp = MoranProcess(players)
        self.assertTrue(mp.fixation_check())
        players = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess(players)
        self.assertFalse(mp.fixation_check())

    def test_next(self):
        players = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess(players)
        self.assertIsInstance(next(mp), MoranProcess)

    def test_matchup_indices(self):
        players = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess(players)
        self.assertEqual(mp._matchup_indices(), {(0, 1)})

        players = axelrod.Cooperator(), axelrod.Defector(), axelrod.TitForTat()
        edges = [(0, 1), (2, 0), (1, 2)]
        graph = axelrod.graph.Graph(edges, directed=True)
        mp = MoranProcess(players, mode="bd", interaction_graph=graph)
        self.assertEqual(mp._matchup_indices(), {(0, 1), (1, 2), (2, 0)})

    def test_fps(self):
        self.assertEqual(fitness_proportionate_selection([0, 0, 1]), 2)
        axelrod.seed(1)
        self.assertEqual(fitness_proportionate_selection([1, 1, 1]), 0)
        self.assertEqual(fitness_proportionate_selection([1, 1, 1]), 2)

    def test_exit_condition(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp), 1)

    def test_two_players(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        axelrod.seed(17)
        mp = MoranProcess((p1, p2))
        populations = mp.play()
        self.assertEqual(len(mp), 5)
        self.assertEqual(len(populations), 5)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p2))

    def test_two_prob_end(self):
        p1, p2 = axelrod.Random(), axelrod.TitForTat()
        axelrod.seed(0)
        mp = MoranProcess((p1, p2), prob_end=.5)
        populations = mp.play()
        self.assertEqual(len(mp), 4)
        self.assertEqual(len(populations), 4)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p1))

    def test_different_game(self):
        # Possible for Cooperator to become fixed when using a different game
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        axelrod.seed(0)
        game = axelrod.Game(r=4, p=2, s=1, t=6)
        mp = MoranProcess((p1, p2), turns=5, game=game)
        populations = mp.play()
        self.assertEqual(mp.winning_strategy_name, str(p1))

    def test_death_birth(self):
        """Two player death-birth should fixate after one round."""
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        seeds = range(0, 20)
        for seed in seeds:
            axelrod.seed(seed)
            mp = MoranProcess((p1, p2), mode="db")
            next(mp)
            self.assertIsNotNone(mp.winning_strategy_name)

    def test_death_birth_outcomes(self):
        """Show that birth-death and death-birth can produce different
        outcomes."""
        seeds = [(1, True), (23, False)]
        players = []
        N = 6
        for _ in range(N // 2):
            players.append(axelrod.Cooperator())
            players.append(axelrod.Defector())
        for seed, outcome in seeds:
            axelrod.seed(seed)
            mp = MoranProcess(players, mode="bd")
            mp.play()
            winner = mp.winning_strategy_name
            axelrod.seed(seed)
            mp = MoranProcess(players, mode="db")
            mp.play()
            winner2 = mp.winning_strategy_name
            self.assertEqual((winner == winner2), outcome)

    def test_two_random_players(self):
        p1, p2 = axelrod.Random(p=0.5), axelrod.Random(p=0.25)
        axelrod.seed(0)
        mp = MoranProcess((p1, p2))
        populations = mp.play()
        self.assertEqual(len(mp), 2)
        self.assertEqual(len(populations), 2)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p2))

    def test_two_players_with_mutation(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        axelrod.seed(5)
        mp = MoranProcess((p1, p2), mutation_rate=0.2)
        self.assertDictEqual(mp.mutation_targets, {str(p1): [p2], str(p2): [p1]})
        # Test that mutation causes the population to alternate between
        # fixations
        counters = [
            Counter({"Cooperator": 2}),
            Counter({"Defector": 2}),
            Counter({"Cooperator": 2}),
            Counter({"Defector": 2}),
        ]
        for counter in counters:
            for _ in itertools.takewhile(
                lambda x: x.population_distribution() != counter, mp
            ):
                pass
            self.assertEqual(mp.population_distribution(), counter)

    def test_play_exception(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2), mutation_rate=0.2)
        with self.assertRaises(ValueError):
            mp.play()

    def test_three_players(self):
        players = [axelrod.Cooperator(), axelrod.Cooperator(), axelrod.Defector()]
        axelrod.seed(11)
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(len(mp), 7)
        self.assertEqual(len(populations), 7)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axelrod.Defector()))

    def test_three_players_with_mutation(self):
        p1 = axelrod.Cooperator()
        p2 = axelrod.Random()
        p3 = axelrod.Defector()
        players = [p1, p2, p3]
        mp = MoranProcess(players, mutation_rate=0.2)
        self.assertDictEqual(
            mp.mutation_targets,
            {str(p1): [p3, p2], str(p2): [p1, p3], str(p3): [p1, p2]},
        )
        # Test that mutation causes the population to alternate between
        # fixations
        counters = [Counter({"Cooperator": 3}), Counter({"Defector": 3})]
        for counter in counters:
            for _ in itertools.takewhile(
                lambda x: x.population_distribution() != counter, mp
            ):
                pass
            self.assertEqual(mp.population_distribution(), counter)

    def test_four_players(self):
        players = [axelrod.Cooperator() for _ in range(3)]
        players.append(axelrod.Defector())
        axelrod.seed(29)
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(len(mp), 9)
        self.assertEqual(len(populations), 9)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axelrod.Defector()))

    @given(strategies=strategy_lists(min_size=2, max_size=4))
    @settings(max_examples=5, max_iterations=20)

    # Two specific examples relating to cloning of strategies
    @example(strategies=[axelrod.BackStabber, axelrod.MindReader])
    @example(strategies=[axelrod.ThueMorse, axelrod.MindReader])
    def test_property_players(self, strategies):
        """Hypothesis test that randomly checks players"""
        players = [s() for s in strategies]
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(populations, mp.populations)
        self.assertIn(mp.winning_strategy_name, [str(p) for p in players])

    def test_reset(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        axelrod.seed(45)
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp), 4)
        self.assertEqual(len(mp.score_history), 3)
        mp.reset()
        self.assertEqual(len(mp), 1)
        self.assertEqual(mp.winning_strategy_name, None)
        self.assertEqual(mp.score_history, [])
        # Check that players reset
        for player, initial_player in zip(mp.players, mp.initial_players):
            self.assertEqual(str(player), str(initial_player))

    def test_constant_fitness_case(self):
        # Scores between an Alternator and Defector will be: (1,  6)
        axelrod.seed(0)
        players = (
            axelrod.Alternator(),
            axelrod.Alternator(),
            axelrod.Defector(),
            axelrod.Defector(),
        )
        mp = MoranProcess(players, turns=2)
        winners = []
        for _ in range(100):
            mp.play()
            winners.append(mp.winning_strategy_name)
            mp.reset()
        winners = Counter(winners)
        self.assertEqual(winners["Defector"], 88)

    def test_cache(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp.deterministic_cache), 1)

        # Check that can pass a pre built cache
        cache = axelrod.DeterministicCache()
        mp = MoranProcess((p1, p2), deterministic_cache=cache)
        self.assertEqual(cache, mp.deterministic_cache)

    def test_iter(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2))
        self.assertEqual(mp.__iter__(), mp)

    def test_population_plot(self):
        # Test that can plot on a given matplotlib axes
        axelrod.seed(15)
        players = [random.choice(axelrod.demo_strategies)() for _ in range(5)]
        mp = axelrod.MoranProcess(players=players, turns=30)
        mp.play()
        fig, axarr = plt.subplots(2, 2)
        ax = axarr[1, 0]
        mp.populations_plot(ax=ax)
        self.assertEqual(ax.get_xlim(), (-0.8, 16.8))
        self.assertEqual(ax.get_ylim(), (0, 5.25))
        # Run without a given axis
        ax = mp.populations_plot()
        self.assertEqual(ax.get_xlim(), (-0.8, 16.8))
        self.assertEqual(ax.get_ylim(), (0, 5.25))

    def test_cooperator_can_win_with_fitness_transformation(self):
        axelrod.seed(689)
        players = (
            axelrod.Cooperator(),
            axelrod.Defector(),
            axelrod.Defector(),
            axelrod.Defector(),
        )
        w = 0.95
        fitness_transformation = lambda score: 1 - w + w * score
        mp = MoranProcess(
            players, turns=10, fitness_transformation=fitness_transformation
        )
        populations = mp.play()
        self.assertEqual(mp.winning_strategy_name, "Cooperator")
Exemple #10
0
class TestFingerprint(unittest.TestCase):

    points_when_using_half_step = [
        (0.0, 0.0),
        (0.0, 0.5),
        (0.0, 1.0),
        (0.5, 0.0),
        (0.5, 0.5),
        (0.5, 1.0),
        (1.0, 0.0),
        (1.0, 0.5),
        (1.0, 1.0),
    ]
    edges_when_using_half_step = [
        (0, 1),
        (0, 2),
        (0, 3),
        (0, 4),
        (0, 5),
        (0, 6),
        (0, 7),
        (0, 8),
        (0, 9),
    ]

    def test_default_init(self):
        fingerprint = AshlockFingerprint(axl.WinStayLoseShift)
        self.assertEqual(fingerprint.strategy, axl.WinStayLoseShift)
        self.assertEqual(fingerprint.probe, axl.TitForTat)

    def test_init_with_explicit_probe(self):
        fingerprint = AshlockFingerprint(axl.WinStayLoseShift, axl.Random)
        self.assertEqual(fingerprint.strategy, axl.WinStayLoseShift)
        self.assertEqual(fingerprint.probe, axl.Random)

    def test_init_with_instances(self):
        player = axl.WinStayLoseShift()
        fingerprint = AshlockFingerprint(player)
        self.assertEqual(fingerprint.strategy, player)
        self.assertEqual(fingerprint.probe, axl.TitForTat)

        probe = axl.Random()
        fingerprint = AshlockFingerprint(axl.WinStayLoseShift, probe)
        self.assertEqual(fingerprint.strategy, axl.WinStayLoseShift)
        self.assertEqual(fingerprint.probe, probe)

        fingerprint = AshlockFingerprint(player, probe)
        self.assertEqual(fingerprint.strategy, player)
        self.assertEqual(fingerprint.probe, probe)

    def test_fingerprint_player(self):
        af = AshlockFingerprint(axl.Cooperator())
        af.fingerprint(turns=5, repetitions=3, step=0.5, progress_bar=False)

        self.assertEqual(af.step, 0.5)
        self.assertEqual(af.points, self.points_when_using_half_step)
        self.assertEqual(af.spatial_tournament.turns, 5)
        self.assertEqual(af.spatial_tournament.repetitions, 3)
        self.assertEqual(af.spatial_tournament.edges,
                         self.edges_when_using_half_step)

        # The first player is the fingerprinted one, the rest are probes.
        self.assertIsInstance(af.spatial_tournament.players[0], axl.Cooperator)
        self.assertEqual(len(af.spatial_tournament.players), 10)
        probes = af.spatial_tournament.players[1:]
        self.assertEqual(len(probes), len(af.points))
        self.assertEqual(str(probes[0]),
                         "Joss-Ann Tit For Tat: (0.0, 0.0)")  # x + y < 1
        self.assertEqual(str(probes[2]),
                         "Dual Joss-Ann Tit For Tat: (1.0, 0.0)")  # x + y = 1
        self.assertEqual(str(probes[8]),
                         "Dual Joss-Ann Tit For Tat: (0.0, 0.0)")  # x + y > 1

    def test_fingeprint_explicit_probe(self):
        af = AshlockFingerprint(axl.TitForTat(), probe=axl.Random(p=0.1))
        af.fingerprint(turns=10, repetitions=2, step=0.5, progress_bar=False)

        probes = af.spatial_tournament.players[1:]
        self.assertEqual(str(probes[0]),
                         "Joss-Ann Random: 0.1: (0.0, 0.0)")  # x + y < 1
        self.assertEqual(str(probes[2]),
                         "Dual Joss-Ann Random: 0.1: (1.0, 0.0)")  # x + y = 1
        self.assertEqual(str(probes[8]),
                         "Dual Joss-Ann Random: 0.1: (0.0, 0.0)")  # x + y > 1

    def test_fingerprint_interactions_cooperator(self):
        af = AshlockFingerprint(axl.Cooperator())
        af.fingerprint(turns=5, repetitions=3, step=0.5, progress_bar=False)

        # The keys are edges between players, values are repetitions.
        self.assertCountEqual(
            af.interactions.keys(),
            [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8),
             (0, 9)],
        )
        self.assertEqual(len(af.interactions.values()), 9)

        # Each edge has 3 repetitions with 5 turns each.
        repetitions = af.interactions.values()
        self.assertTrue(all(len(rep) == 3 for rep in repetitions))
        for iturn in range(3):
            self.assertTrue(all(len(rep[iturn]) == 5 for rep in repetitions))

        # Interactions are invariant for any points where y is zero, and
        # the score should be maximum possible.
        # Player 1 is Point(0.0, 0.0).
        # Player 4 is Point(0.5, 0.0).
        # Player 7 is Point(1.0, 0.0).
        for iplayer in (1, 4, 7):
            for turns in af.interactions[(0, iplayer)]:
                self.assertEqual(len(turns), 5)
                self.assertTrue(all(t == (C, C) for t in turns))
        self.assertEqual(af.data[Point(0.0, 0.0)], 3.0)
        self.assertEqual(af.data[Point(0.5, 0.0)], 3.0)
        self.assertEqual(af.data[Point(1.0, 0.0)], 3.0)

        # Player 3 is Point(0.0, 1.0), which means constant defection
        # from the probe. But the Cooperator doesn't change and score is zero.
        for turns in af.interactions[(0, 3)]:
            self.assertEqual(len(turns), 5)
            self.assertTrue(all(t == (C, D) for t in turns))
        self.assertEqual(af.data[Point(0.0, 1.0)], 0.0)

    def test_fingerprint_interactions_titfortat(self):
        af = AshlockFingerprint(axl.TitForTat())
        af.fingerprint(turns=5, repetitions=3, step=0.5, progress_bar=False)

        # Tit-for-Tats will always cooperate if left to their own devices,
        # so interactions are invariant for any points where y is zero,
        # and the score should be maximum possible.
        # Player 1 is Point(0.0, 0.0).
        # Player 4 is Point(0.5, 0.0).
        # Player 7 is Point(1.0, 0.0).
        for iplayer in (1, 4, 7):
            for turns in af.interactions[(0, iplayer)]:
                self.assertEqual(len(turns), 5)
                self.assertTrue(all(t == (C, C) for t in turns))
        self.assertEqual(af.data[Point(0.0, 0.0)], 3.0)
        self.assertEqual(af.data[Point(0.5, 0.0)], 3.0)
        self.assertEqual(af.data[Point(1.0, 0.0)], 3.0)

        # Player 3 is Point(0.0, 1.0) which implies defection after the
        # first turn since Tit-for-Tat is playing, and a score of 0.8
        # since we get zero on first turn and one point per turn later.
        for turns in af.interactions[(0, 3)]:
            self.assertEqual(len(turns), 5)
            self.assertTrue(all(t == (D, D) for t in turns[1:]))
        self.assertAlmostEqual(af.data[Point(0.0, 1.0)], 0.8)

    def test_progress_bar_fingerprint(self):
        af = AshlockFingerprint(axl.TitForTat)
        data = af.fingerprint(turns=10,
                              repetitions=2,
                              step=0.5,
                              progress_bar=True)
        self.assertEqual(sorted(data.keys()), self.points_when_using_half_step)

    @patch("axelrod.fingerprint.mkstemp", RecordedMksTemp.mkstemp)
    def test_temp_file_creation(self):

        RecordedMksTemp.reset_record()
        af = AshlockFingerprint(axl.TitForTat)
        path = pathlib.Path("test_outputs/test_fingerprint.csv")
        filename = axl_filename(path)

        self.assertEqual(RecordedMksTemp.record, [])

        # Temp file is created and destroyed.
        af.fingerprint(turns=1,
                       repetitions=1,
                       step=0.5,
                       progress_bar=False,
                       filename=None)

        self.assertEqual(len(RecordedMksTemp.record), 1)
        filename = RecordedMksTemp.record[0][1]
        self.assertIsInstance(filename, str)
        self.assertNotEqual(filename, "")
        self.assertFalse(os.path.isfile(filename))

    def test_fingerprint_with_filename(self):
        path = pathlib.Path("test_outputs/test_fingerprint.csv")
        filename = axl_filename(path)
        af = AshlockFingerprint(axl.TitForTat)
        af.fingerprint(turns=1,
                       repetitions=1,
                       step=0.5,
                       progress_bar=False,
                       filename=filename)
        with open(filename, "r") as out:
            data = out.read()
            self.assertEqual(len(data.split("\n")), 20)

    def test_serial_fingerprint(self):
        af = AshlockFingerprint(axl.TitForTat)
        data = af.fingerprint(turns=10,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(edge_keys, self.edges_when_using_half_step)
        self.assertEqual(coord_keys, self.points_when_using_half_step)

    def test_parallel_fingerprint(self):
        af = AshlockFingerprint(axl.TitForTat)
        af.fingerprint(turns=10,
                       repetitions=2,
                       step=0.5,
                       processes=2,
                       progress_bar=False)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(af.data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(edge_keys, self.edges_when_using_half_step)
        self.assertEqual(coord_keys, self.points_when_using_half_step)

    def test_plot_data(self):
        axl.seed(0)  # Fingerprinting is a random process.
        af = AshlockFingerprint(axl.Cooperator())
        af.fingerprint(turns=5, repetitions=3, step=0.5, progress_bar=False)

        reshaped_data = np.array([[0.0, 0.0, 0.0], [2.0, 1.0, 2.0],
                                  [3.0, 3.0, 3.0]])
        plotted_data = af.plot().gca().images[0].get_array()
        np.testing.assert_allclose(plotted_data, reshaped_data)

    def test_plot_figure(self):
        af = AshlockFingerprint(axl.WinStayLoseShift, axl.TitForTat)
        af.fingerprint(turns=10, repetitions=2, step=0.25, progress_bar=False)
        p = af.plot()
        self.assertIsInstance(p, matplotlib.pyplot.Figure)
        q = af.plot(cmap="jet")
        self.assertIsInstance(q, matplotlib.pyplot.Figure)
        r = af.plot(interpolation="bicubic")
        self.assertIsInstance(r, matplotlib.pyplot.Figure)
        t = af.plot(title="Title")
        self.assertIsInstance(t, matplotlib.pyplot.Figure)
        u = af.plot(colorbar=False)
        self.assertIsInstance(u, matplotlib.pyplot.Figure)
        v = af.plot(labels=False)
        self.assertIsInstance(v, matplotlib.pyplot.Figure)

    def test_wsls_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process.
        test_data = {
            Point(x=0.0, y=0.0): 3.000,
            Point(x=0.0, y=0.25): 1.710,
            Point(x=0.0, y=0.5): 1.440,
            Point(x=0.0, y=0.75): 1.080,
            Point(x=0.0, y=1.0): 0.500,
            Point(x=0.25, y=0.0): 3.000,
            Point(x=0.25, y=0.25): 2.280,
            Point(x=0.25, y=0.5): 1.670,
            Point(x=0.25, y=0.75): 1.490,
            Point(x=0.25, y=1.0): 0.770,
            Point(x=0.5, y=0.0): 3.000,
            Point(x=0.5, y=0.25): 2.740,
            Point(x=0.5, y=0.5): 2.240,
            Point(x=0.5, y=0.75): 1.730,
            Point(x=0.5, y=1.0): 1.000,
            Point(x=0.75, y=0.0): 3.000,
            Point(x=0.75, y=0.25): 3.520,
            Point(x=0.75, y=0.5): 2.830,
            Point(x=0.75, y=0.75): 1.750,
            Point(x=0.75, y=1.0): 1.250,
            Point(x=1.0, y=0.0): 3.000,
            Point(x=1.0, y=0.25): 4.440,
            Point(x=1.0, y=0.5): 4.410,
            Point(x=1.0, y=0.75): 4.440,
            Point(x=1.0, y=1.0): 1.300,
        }
        af = axl.AshlockFingerprint(axl.WinStayLoseShift(), axl.TitForTat)
        data = af.fingerprint(turns=50,
                              repetitions=2,
                              step=0.25,
                              progress_bar=False)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key], places=2)

    def test_tft_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process.
        test_data = {
            Point(x=0.0, y=0.0): 3.000,
            Point(x=0.0, y=0.25): 1.820,
            Point(x=0.0, y=0.5): 1.130,
            Point(x=0.0, y=0.75): 1.050,
            Point(x=0.0, y=1.0): 0.980,
            Point(x=0.25, y=0.0): 3.000,
            Point(x=0.25, y=0.25): 2.440,
            Point(x=0.25, y=0.5): 1.770,
            Point(x=0.25, y=0.75): 1.700,
            Point(x=0.25, y=1.0): 1.490,
            Point(x=0.5, y=0.0): 3.000,
            Point(x=0.5, y=0.25): 2.580,
            Point(x=0.5, y=0.5): 2.220,
            Point(x=0.5, y=0.75): 2.000,
            Point(x=0.5, y=1.0): 1.940,
            Point(x=0.75, y=0.0): 3.000,
            Point(x=0.75, y=0.25): 2.730,
            Point(x=0.75, y=0.5): 2.290,
            Point(x=0.75, y=0.75): 2.310,
            Point(x=0.75, y=1.0): 2.130,
            Point(x=1.0, y=0.0): 3.000,
            Point(x=1.0, y=0.25): 2.790,
            Point(x=1.0, y=0.5): 2.480,
            Point(x=1.0, y=0.75): 2.310,
            Point(x=1.0, y=1.0): 2.180,
        }

        af = axl.AshlockFingerprint(axl.TitForTat(), axl.TitForTat)
        data = af.fingerprint(turns=50,
                              repetitions=2,
                              step=0.25,
                              progress_bar=False)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key], places=2)

    def test_majority_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process.
        test_data = {
            Point(x=0.0, y=0.0): 3.000,
            Point(x=0.0, y=0.25): 1.940,
            Point(x=0.0, y=0.5): 1.130,
            Point(x=0.0, y=0.75): 1.030,
            Point(x=0.0, y=1.0): 0.980,
            Point(x=0.25, y=0.0): 3.000,
            Point(x=0.25, y=0.25): 2.130,
            Point(x=0.25, y=0.5): 1.940,
            Point(x=0.25, y=0.75): 2.060,
            Point(x=0.25, y=1.0): 1.940,
            Point(x=0.5, y=0.0): 3.000,
            Point(x=0.5, y=0.25): 2.300,
            Point(x=0.5, y=0.5): 2.250,
            Point(x=0.5, y=0.75): 2.420,
            Point(x=0.5, y=1.0): 2.690,
            Point(x=0.75, y=0.0): 3.000,
            Point(x=0.75, y=0.25): 2.400,
            Point(x=0.75, y=0.5): 2.010,
            Point(x=0.75, y=0.75): 2.390,
            Point(x=0.75, y=1.0): 2.520,
            Point(x=1.0, y=0.0): 3.000,
            Point(x=1.0, y=0.25): 2.360,
            Point(x=1.0, y=0.5): 1.740,
            Point(x=1.0, y=0.75): 2.260,
            Point(x=1.0, y=1.0): 2.260,
        }

        af = axl.AshlockFingerprint(axl.GoByMajority, axl.TitForTat)
        data = af.fingerprint(turns=50,
                              repetitions=2,
                              step=0.25,
                              progress_bar=False)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key], places=2)

    @given(strategy_pair=strategy_lists(min_size=2, max_size=2))
    @settings(max_examples=5)
    def test_pair_fingerprints(self, strategy_pair):
        """
        A test to check that we can fingerprint
        with any two given strategies or instances
        """
        strategy, probe = strategy_pair
        af = AshlockFingerprint(strategy, probe)
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy(), probe)
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy, probe())
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy(), probe())
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)
Exemple #11
0
class TestPlayer(unittest.TestCase):
    """A Test class from which other player test classes are inherited."""

    player = TestOpponent
    expected_class_classifier = None

    def test_initialisation(self):
        """Test that the player initiates correctly."""
        if self.__class__ != TestPlayer:
            player = self.player()
            self.assertEqual(len(player.history), 0)
            self.assertEqual(player.match_attributes, {
                "length": -1,
                "game": DefaultGame,
                "noise": 0
            })
            self.assertEqual(player.cooperations, 0)
            self.assertEqual(player.defections, 0)
            self.classifier_test(self.expected_class_classifier)

    def test_repr(self):
        """Test that the representation is correct."""
        if self.__class__ != TestPlayer:
            self.assertEqual(str(self.player()), self.name)

    def test_match_attributes(self):
        player = self.player()
        # Default
        player.set_match_attributes()
        t_attrs = player.match_attributes
        self.assertEqual(t_attrs["length"], -1)
        self.assertEqual(t_attrs["noise"], 0)
        self.assertEqual(t_attrs["game"].RPST(), (3, 1, 0, 5))

        # Common
        player.set_match_attributes(length=200)
        t_attrs = player.match_attributes
        self.assertEqual(t_attrs["length"], 200)
        self.assertEqual(t_attrs["noise"], 0)
        self.assertEqual(t_attrs["game"].RPST(), (3, 1, 0, 5))

        # Noisy
        player.set_match_attributes(length=200, noise=.5)
        t_attrs = player.match_attributes
        self.assertEqual(t_attrs["noise"], .5)

    def test_reset_history_and_attributes(self):
        """Make sure resetting works correctly."""
        for opponent in [
                axelrod.Defector(),
                axelrod.Random(),
                axelrod.Alternator(),
                axelrod.Cooperator(),
        ]:

            player = self.player()
            clone = player.clone()
            for seed in range(10):
                axelrod.seed(seed)
                player.play(opponent)

            player.reset()
            self.assertEqual(player, clone)

    def test_reset_clone(self):
        """Make sure history resetting with cloning works correctly, regardless
        if self.test_reset() is overwritten."""
        player = self.player()
        clone = player.clone()
        self.assertEqual(player, clone)

    def test_clone(self):
        # Test that the cloned player produces identical play
        player1 = self.player()
        if player1.name in ["Darwin", "Human"]:
            # Known exceptions
            return
        player2 = player1.clone()
        self.assertEqual(len(player2.history), 0)
        self.assertEqual(player2.cooperations, 0)
        self.assertEqual(player2.defections, 0)
        self.assertEqual(player2.state_distribution, {})
        self.assertEqual(player2.classifier, player1.classifier)
        self.assertEqual(player2.match_attributes, player1.match_attributes)

        turns = 50
        r = random.random()
        for op in [
                axelrod.Cooperator(),
                axelrod.Defector(),
                axelrod.TitForTat(),
                axelrod.Random(p=r),
        ]:
            player1.reset()
            player2.reset()
            seed = random.randint(0, 10**6)
            for p in [player1, player2]:
                axelrod.seed(seed)
                m = axelrod.Match((p, op), turns=turns)
                m.play()
            self.assertEqual(len(player1.history), turns)
            self.assertEqual(player1.history, player2.history)

    @given(
        strategies=strategy_lists(max_size=5,
                                  strategies=short_run_time_short_mem),
        seed=integers(min_value=1, max_value=200),
        turns=integers(min_value=1, max_value=200),
    )
    @settings(max_examples=1, max_iterations=1)
    def test_memory_depth_upper_bound(self, strategies, seed, turns):
        """
        Test that the memory depth is indeed an upper bound.
        """
        player = self.player()
        memory = player.classifier["memory_depth"]
        if memory < float("inf"):
            for strategy in strategies:
                opponent = strategy()
                self.assertTrue(
                    test_memory(
                        player=player,
                        opponent=opponent,
                        seed=seed,
                        turns=turns,
                        memory_length=memory,
                    ),
                    msg="Failed for seed={} and opponent={}".format(
                        seed, opponent),
                )

    def versus_test(
        self,
        opponent,
        expected_actions,
        noise=None,
        seed=None,
        turns=10,
        match_attributes=None,
        attrs=None,
        init_kwargs=None,
    ):
        """
        Tests a sequence of outcomes for two given players.

        Parameters:
        -----------

        opponent: Player or list
            An instance of a player OR a sequence of actions. If a sequence of
            actions is passed, a Mock Player is created that cycles over that
            sequence.
        expected_actions: List
            The expected outcomes of the match (list of tuples of actions).
        noise: float
            Any noise to be passed to a match
        seed: int
            The random seed to be used
        length: int
            The length of the game. If `opponent` is a sequence of actions then
            the length is taken to be the length of the sequence.
        match_attributes: dict
            The match attributes to be passed to the players.  For example,
            `{length:-1}` implies that the players do not know the length of the
            match.
        attrs: dict
            Dictionary of internal attributes to check at the end of all plays
            in player
        init_kwargs: dict
            A dictionary of keyword arguments to instantiate player with
        """

        turns = len(expected_actions)
        if init_kwargs is None:
            init_kwargs = dict()

        if seed is not None:
            axelrod.seed(seed)

        player = self.player(**init_kwargs)

        match = axelrod.Match(
            (player, opponent),
            turns=turns,
            noise=noise,
            match_attributes=match_attributes,
        )
        self.assertEqual(match.play(), expected_actions)

        if attrs:
            player = match.players[0]
            for attr, value in attrs.items():
                self.assertEqual(getattr(player, attr), value)

    def classifier_test(self, expected_class_classifier=None):
        """Test that the keys in the expected_classifier dictionary give the
        expected values in the player classifier dictionary. Also checks that
        two particular keys (memory_depth and stochastic) are in the
        dictionary."""
        player = self.player()

        # Test that player has same classifier as it's class unless otherwise
        # specified
        if expected_class_classifier is None:
            expected_class_classifier = player.classifier
        self.assertEqual(expected_class_classifier, self.player.classifier)

        self.assertTrue("memory_depth" in player.classifier,
                        msg="memory_depth not in classifier")
        self.assertTrue("stochastic" in player.classifier,
                        msg="stochastic not in classifier")
        for key in TestOpponent.classifier:
            self.assertEqual(
                player.classifier[key],
                self.expected_classifier[key],
                msg="%s - Behaviour: %s != Expected Behaviour: %s" %
                (key, player.classifier[key], self.expected_classifier[key]),
            )
Exemple #12
0
class TestMoranProcess(unittest.TestCase):
    def test_fps(self):
        self.assertEqual(fitness_proportionate_selection([0, 0, 1]), 2)
        random.seed(1)
        self.assertEqual(fitness_proportionate_selection([1, 1, 1]), 0)
        self.assertEqual(fitness_proportionate_selection([1, 1, 1]), 2)

    def test_stochastic(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        mp = MoranProcess((p1, p2))
        self.assertFalse(mp._stochastic)
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        mp = MoranProcess((p1, p2), noise=0.05)
        self.assertTrue(mp._stochastic)
        p1, p2 = axelrod.Cooperator(), axelrod.Random()
        mp = MoranProcess((p1, p2))
        self.assertTrue(mp._stochastic)

    def test_exit_condition(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp), 1)

    def test_two_players(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        random.seed(5)
        mp = MoranProcess((p1, p2))
        populations = mp.play()
        self.assertEqual(len(mp), 5)
        self.assertEqual(len(populations), 5)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p2))

    def test_two_random_players(self):
        p1, p2 = axelrod.Random(0.5), axelrod.Random(0.25)
        random.seed(5)
        mp = MoranProcess((p1, p2))
        populations = mp.play()
        self.assertEqual(len(mp), 2)
        self.assertEqual(len(populations), 2)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p1))

    def test_two_players_with_mutation(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        random.seed(5)
        mp = MoranProcess((p1, p2), mutation_rate=0.2)
        self.assertEqual(mp._stochastic, True)
        self.assertDictEqual(mp.mutation_targets, {
            str(p1): [p2],
            str(p2): [p1]
        })
        # Test that mutation causes the population to alternate between fixations
        counters = [
            Counter({'Cooperator': 2}),
            Counter({'Defector': 2}),
            Counter({'Cooperator': 2}),
            Counter({'Defector': 2})
        ]
        for counter in counters:
            for _ in itertools.takewhile(
                    lambda x: x.population_distribution() != counter, mp):
                pass
            self.assertEqual(mp.population_distribution(), counter)

    def test_play_exception(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2), mutation_rate=0.2)
        with self.assertRaises(ValueError):
            mp.play()

    def test_three_players(self):
        players = [
            axelrod.Cooperator(),
            axelrod.Cooperator(),
            axelrod.Defector()
        ]
        random.seed(5)
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(len(mp), 7)
        self.assertEqual(len(populations), 7)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axelrod.Defector()))

    def test_three_players_with_mutation(self):
        p1 = axelrod.Cooperator()
        p2 = axelrod.Random()
        p3 = axelrod.Defector()
        players = [p1, p2, p3]
        mp = MoranProcess(players, mutation_rate=0.2)
        self.assertEqual(mp._stochastic, True)
        self.assertDictEqual(mp.mutation_targets, {
            str(p1): [p3, p2],
            str(p2): [p1, p3],
            str(p3): [p1, p2]
        })
        # Test that mutation causes the population to alternate between fixations
        counters = [
            Counter({'Cooperator': 3}),
            Counter({'Defector': 3}),
        ]
        for counter in counters:
            for _ in itertools.takewhile(
                    lambda x: x.population_distribution() != counter, mp):
                pass
            self.assertEqual(mp.population_distribution(), counter)

    def test_four_players(self):
        players = [axelrod.Cooperator() for _ in range(3)]
        players.append(axelrod.Defector())
        random.seed(10)
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(len(mp), 9)
        self.assertEqual(len(populations), 9)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axelrod.Defector()))

    @given(strategies=strategy_lists(min_size=2, max_size=5))
    @settings(max_examples=5, timeout=0)  # Very low number of examples
    # Two specific examples relating to cloning of strategies
    @example(strategies=[axelrod.BackStabber, axelrod.MindReader])
    @example(strategies=[axelrod.ThueMorse, axelrod.MindReader])
    def test_property_players(self, strategies):
        """Hypothesis test that randomly checks players"""
        players = [s() for s in strategies]
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(populations, mp.populations)
        self.assertIn(mp.winning_strategy_name, [str(p) for p in players])

    def test_reset(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        random.seed(8)
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp), 4)
        self.assertEqual(len(mp.score_history), 3)
        mp.reset()
        self.assertEqual(len(mp), 1)
        self.assertEqual(mp.winning_strategy_name, None)
        self.assertEqual(mp.score_history, [])
        # Check that players reset
        for player, intial_player in zip(mp.players, mp.initial_players):
            self.assertEqual(str(player), str(intial_player))

    def test_cache(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp.deterministic_cache), 1)

        # Check that can pass a pre built cache
        cache = axelrod.DeterministicCache()
        mp = MoranProcess((p1, p2), deterministic_cache=cache)
        self.assertEqual(cache, mp.deterministic_cache)

    def test_iter(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2))
        self.assertEqual(mp.__iter__(), mp)
Exemple #13
0
class TestMoranProcess(unittest.TestCase):
    def test_fps(self):
        self.assertEqual(fitness_proportionate_selection([0, 0, 1]), 2)
        random.seed(1)
        self.assertEqual(fitness_proportionate_selection([1, 1, 1]), 0)
        self.assertEqual(fitness_proportionate_selection([1, 1, 1]), 2)

    def test_stochastic(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        mp = MoranProcess((p1, p2))
        self.assertFalse(mp._stochastic)
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        mp = MoranProcess((p1, p2), noise=0.05)
        self.assertTrue(mp._stochastic)
        p1, p2 = axelrod.Cooperator(), axelrod.Random()
        mp = MoranProcess((p1, p2))
        self.assertTrue(mp._stochastic)

    def test_exit_condition(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp), 1)

    def test_two_players(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        random.seed(5)
        mp = MoranProcess((p1, p2))
        populations = mp.play()
        self.assertEqual(len(mp), 5)
        self.assertEqual(len(populations), 5)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p2))

    def test_three_players(self):
        players = [
            axelrod.Cooperator(),
            axelrod.Cooperator(),
            axelrod.Defector()
        ]
        random.seed(5)
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(len(mp), 7)
        self.assertEqual(len(populations), 7)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axelrod.Defector()))

    def test_four_players(self):
        players = [axelrod.Cooperator() for _ in range(3)]
        players.append(axelrod.Defector())
        random.seed(10)
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(len(mp), 9)
        self.assertEqual(len(populations), 9)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axelrod.Defector()))

    @given(strategies=strategy_lists(min_size=2, max_size=5),
           rm=random_module())
    @settings(max_examples=5, timeout=0)  # Very low number of examples
    # Two specific examples relating to cloning of strategies
    @example(strategies=[axelrod.BackStabber, axelrod.MindReader],
             rm=random.seed(0))
    @example(strategies=[axelrod.ThueMorse, axelrod.MindReader],
             rm=random.seed(0))
    def test_property_players(self, strategies, rm):
        """Hypothesis test that randomly checks players"""
        players = [s() for s in strategies]
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(populations, mp.populations)
        self.assertIn(mp.winning_strategy_name, [str(p) for p in players])

    def test_reset(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        random.seed(8)
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp), 4)
        self.assertEqual(len(mp.score_history), 3)
        mp.reset()
        self.assertEqual(len(mp), 1)
        self.assertEqual(mp.winning_strategy_name, None)
        self.assertEqual(mp.score_history, [])
        # Check that players reset
        for player, intial_player in zip(mp.players, mp.initial_players):
            self.assertEqual(str(player), str(intial_player))

    def test_cache(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp.deterministic_cache), 1)

        # Check that can pass a pre built cache
        cache = axelrod.DeterministicCache()
        mp = MoranProcess((p1, p2), deterministic_cache=cache)
        self.assertEqual(cache, mp.deterministic_cache)

    def test_iter(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2))
        self.assertEqual(mp.__iter__(), mp)
Exemple #14
0
class TestMoranProcess(unittest.TestCase):
    def test_fps(self):
        self.assertEqual(fitness_proportionate_selection([0, 0, 1]), 2)
        random.seed(1)
        self.assertEqual(fitness_proportionate_selection([1, 1, 1]), 0)
        self.assertEqual(fitness_proportionate_selection([1, 1, 1]), 2)

    def test_exit_condition(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Cooperator()
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp), 1)

    def test_two_players(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        random.seed(5)
        mp = MoranProcess((p1, p2))
        populations = mp.play()
        self.assertEqual(len(mp), 5)
        self.assertEqual(len(populations), 5)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p2))

    def test_death_birth(self):
        """Two player death-birth should fixate after one round."""
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        seeds = range(0, 20)
        for seed in seeds:
            random.seed(seed)
            mp = MoranProcess((p1, p2), mode='db')
            next(mp)
            self.assertIsNotNone(mp.winning_strategy_name)

    def test_death_birth_outcomes(self):
        """Show that birth-death and death-birth can produce different
        outcomes."""
        seeds = [(1, True), (23, False)]
        players = []
        N = 6
        for _ in range(N // 2):
            players.append(axelrod.Cooperator())
            players.append(axelrod.Defector())
        for seed, outcome in seeds:
            axelrod.seed(seed)
            mp = MoranProcess(players, mode='bd')
            mp.play()
            winner = mp.winning_strategy_name
            axelrod.seed(seed)
            mp = MoranProcess(players, mode='db')
            mp.play()
            winner2 = mp.winning_strategy_name
            self.assertEqual((winner == winner2), outcome)

    def test_two_random_players(self):
        p1, p2 = axelrod.Random(0.5), axelrod.Random(0.25)
        random.seed(5)
        mp = MoranProcess((p1, p2))
        populations = mp.play()
        self.assertEqual(len(mp), 2)
        self.assertEqual(len(populations), 2)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p1))

    def test_two_players_with_mutation(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        random.seed(5)
        mp = MoranProcess((p1, p2), mutation_rate=0.2)
        self.assertDictEqual(mp.mutation_targets, {
            str(p1): [p2],
            str(p2): [p1]
        })
        # Test that mutation causes the population to alternate between
        # fixations
        counters = [
            Counter({'Cooperator': 2}),
            Counter({'Defector': 2}),
            Counter({'Cooperator': 2}),
            Counter({'Defector': 2})
        ]
        for counter in counters:
            for _ in itertools.takewhile(
                    lambda x: x.population_distribution() != counter, mp):
                pass
            self.assertEqual(mp.population_distribution(), counter)

    def test_play_exception(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2), mutation_rate=0.2)
        with self.assertRaises(ValueError):
            mp.play()

    def test_three_players(self):
        players = [
            axelrod.Cooperator(),
            axelrod.Cooperator(),
            axelrod.Defector()
        ]
        random.seed(5)
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(len(mp), 7)
        self.assertEqual(len(populations), 7)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axelrod.Defector()))

    def test_three_players_with_mutation(self):
        p1 = axelrod.Cooperator()
        p2 = axelrod.Random()
        p3 = axelrod.Defector()
        players = [p1, p2, p3]
        mp = MoranProcess(players, mutation_rate=0.2)
        self.assertDictEqual(mp.mutation_targets, {
            str(p1): [p3, p2],
            str(p2): [p1, p3],
            str(p3): [p1, p2]
        })
        # Test that mutation causes the population to alternate between
        # fixations
        counters = [
            Counter({'Cooperator': 3}),
            Counter({'Defector': 3}),
        ]
        for counter in counters:
            for _ in itertools.takewhile(
                    lambda x: x.population_distribution() != counter, mp):
                pass
            self.assertEqual(mp.population_distribution(), counter)

    def test_four_players(self):
        players = [axelrod.Cooperator() for _ in range(3)]
        players.append(axelrod.Defector())
        random.seed(10)
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(len(mp), 9)
        self.assertEqual(len(populations), 9)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axelrod.Defector()))

    def test_standard_fixation(self):
        """Test a traditional Moran process with a MockMatch."""
        axelrod.seed(0)
        players = (axelrod.Cooperator(), axelrod.Cooperator(),
                   axelrod.Defector(), axelrod.Defector())
        mp = MoranProcess(players, match_class=MockMatch)
        winners = []
        for i in range(100):
            mp.play()
            winner = mp.winning_strategy_name
            winners.append(winner)
            mp.reset()
        winners = Counter(winners)
        self.assertEqual(winners["Cooperator"], 82)

    @given(strategies=strategy_lists(min_size=2, max_size=5))
    @settings(max_examples=5, timeout=0)  # Very low number of examples
    # Two specific examples relating to cloning of strategies
    @example(strategies=[axelrod.BackStabber, axelrod.MindReader])
    @example(strategies=[axelrod.ThueMorse, axelrod.MindReader])
    def test_property_players(self, strategies):
        """Hypothesis test that randomly checks players"""
        players = [s() for s in strategies]
        mp = MoranProcess(players)
        populations = mp.play()
        self.assertEqual(populations, mp.populations)
        self.assertIn(mp.winning_strategy_name, [str(p) for p in players])

    def test_reset(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        random.seed(8)
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp), 4)
        self.assertEqual(len(mp.score_history), 3)
        mp.reset()
        self.assertEqual(len(mp), 1)
        self.assertEqual(mp.winning_strategy_name, None)
        self.assertEqual(mp.score_history, [])
        # Check that players reset
        for player, initial_player in zip(mp.players, mp.initial_players):
            self.assertEqual(str(player), str(initial_player))

    def test_cache(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp.deterministic_cache), 1)

        # Check that can pass a pre built cache
        cache = axelrod.DeterministicCache()
        mp = MoranProcess((p1, p2), deterministic_cache=cache)
        self.assertEqual(cache, mp.deterministic_cache)

    def test_iter(self):
        p1, p2 = axelrod.Cooperator(), axelrod.Defector()
        mp = MoranProcess((p1, p2))
        self.assertEqual(mp.__iter__(), mp)
Exemple #15
0
class TestFiltersAgainstComprehensions(unittest.TestCase):
    """
    Test that the results of filtering strategies via a filterset dict
    match the results from using a list comprehension.
    """
    @given(strategies=strategy_lists(min_size=20, max_size=20))
    def test_boolean_filtering(self, strategies):

        classifiers = [
            "stochastic",
            "long_run_time",
            "manipulates_state",
            "manipulates_source",
            "inspects_source",
        ]

        for classifier in classifiers:
            comprehension = set(
                [s for s in strategies if s.classifier[classifier]])
            filterset = {classifier: True}
        filtered = set(filtered_strategies(filterset, strategies=strategies))
        self.assertEqual(comprehension, filtered)

    @given(
        min_memory_depth=integers(min_value=1, max_value=10),
        max_memory_depth=integers(min_value=1, max_value=10),
        memory_depth=integers(min_value=1, max_value=10),
        strategies=strategy_lists(min_size=20, max_size=20),
    )
    @example(
        min_memory_depth=float("inf"),
        max_memory_depth=float("inf"),
        memory_depth=float("inf"),
        strategies=short_run_time_strategies,
    )
    @settings(max_examples=5)
    def test_memory_depth_filtering(self, min_memory_depth, max_memory_depth,
                                    memory_depth, strategies):

        min_comprehension = set([
            s for s in strategies
            if s().classifier["memory_depth"] >= min_memory_depth
        ])
        min_filterset = {"min_memory_depth": min_memory_depth}
        min_filtered = set(
            filtered_strategies(min_filterset, strategies=strategies))
        self.assertEqual(min_comprehension, min_filtered)

        max_comprehension = set([
            s for s in strategies
            if s().classifier["memory_depth"] <= max_memory_depth
        ])
        max_filterset = {"max_memory_depth": max_memory_depth}
        max_filtered = set(
            filtered_strategies(max_filterset, strategies=strategies))
        self.assertEqual(max_comprehension, max_filtered)

        comprehension = set([
            s for s in strategies
            if s().classifier["memory_depth"] == memory_depth
        ])
        filterset = {"memory_depth": memory_depth}
        filtered = set(filtered_strategies(filterset, strategies=strategies))
        self.assertEqual(comprehension, filtered)

    @given(
        seed_=integers(min_value=0, max_value=4294967295),
        strategies=strategy_lists(min_size=20, max_size=20),
    )
    @settings(max_examples=5)
    def test_makes_use_of_filtering(self, seed_, strategies):
        """
        Test equivalent filtering using two approaches.

        This needs to be seeded as some players classification is random.
        """
        classifiers = [["game"], ["length"], ["game", "length"]]

        for classifier in classifiers:
            seed(seed_)
            comprehension = set([
                s for s in strategies if set(classifier).issubset(
                    set(s().classifier["makes_use_of"]))
            ])

            seed(seed_)
            filterset = {"makes_use_of": classifier}
            filtered = set(
                filtered_strategies(filterset, strategies=strategies))

            self.assertEqual(comprehension,
                             filtered,
                             msg="classifier: {}".format(classifier))
Exemple #16
0
 def test_call(self):
     strategies = strategy_lists().example()
     self.assertIsInstance(strategies, list)
     for p in strategies:
         self.assertIsInstance(p(), axelrod.Player)
Exemple #17
0
class TestFingerprint(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.strategy = axl.WinStayLoseShift
        cls.probe = axl.TitForTat
        cls.expected_points = [(0.0, 0.0), (0.0, 0.5), (0.0, 1.0),
                               (0.5, 0.0), (0.5, 0.5), (0.5, 1.0),
                               (1.0, 0.0), (1.0, 0.5), (1.0, 1.0)]
        cls.expected_edges = [(0, 1), (0, 2), (0, 3),
                              (0, 4), (0, 5), (0, 6),
                              (0, 7), (0, 8), (0, 9)]

    def test_default_init(self):
        fingerprint = AshlockFingerprint(self.strategy)
        self.assertEqual(fingerprint.strategy, self.strategy)
        self.assertEqual(fingerprint.probe, self.probe)

    def test_init(self):
        fingerprint = AshlockFingerprint(self.strategy, self.probe)
        self.assertEqual(fingerprint.strategy, self.strategy)
        self.assertEqual(fingerprint.probe, self.probe)

    def test_init_with_instance(self):
        player = self.strategy()
        fingerprint = AshlockFingerprint(player)
        self.assertEqual(fingerprint.strategy, player)
        self.assertEqual(fingerprint.probe, self.probe)

        probe_player = self.probe()
        fingerprint = AshlockFingerprint(self.strategy, probe_player)
        self.assertEqual(fingerprint.strategy, self.strategy)
        self.assertEqual(fingerprint.probe, probe_player)

        fingerprint = AshlockFingerprint(player, probe_player)
        self.assertEqual(fingerprint.strategy, player)
        self.assertEqual(fingerprint.probe, probe_player)

    def test_create_jossann(self):
        fingerprint = AshlockFingerprint(self.strategy)

        # x + y < 1
        ja = fingerprint.create_jossann((.5, .4), self.probe)
        self.assertEqual(str(ja), "Joss-Ann Tit For Tat")

        # x + y = 1
        ja = fingerprint.create_jossann((.4, .6), self.probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Tit For Tat")

        # x + y > 1
        ja = fingerprint.create_jossann((.5, .6), self.probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Tit For Tat")

    def test_create_jossann_parametrised_player(self):
        fingerprint = AshlockFingerprint(self.strategy)

        probe = axl.Random(0.1)

        # x + y < 1
        ja = fingerprint.create_jossann((.5, .4), probe)
        self.assertEqual(str(ja), "Joss-Ann Random: 0.1")

        # x + y = 1
        ja = fingerprint.create_jossann((.4, .6), probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Random: 0.1")

        # x + y > 1
        ja = fingerprint.create_jossann((.5, .6), probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Random: 0.1")

    def test_create_points(self):
        test_points = create_points(0.5, progress_bar=False)
        self.assertEqual(test_points, self.expected_points)

    def test_create_probes(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        probes = af.create_probes(self.probe, self.expected_points,
                                  progress_bar=False)
        self.assertEqual(len(probes), 9)

    def test_create_edges(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        edges = af.create_edges(self.expected_points, progress_bar=False)
        self.assertEqual(edges, self.expected_edges)

    def test_construct_tournament_elemets(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        edges, tournament_players = af.construct_tournament_elements(0.5,
                                                            progress_bar=False)
        self.assertEqual(edges, self.expected_edges)
        self.assertEqual(len(tournament_players), 10)
        self.assertEqual(tournament_players[0].__class__, af.strategy)

    def test_progress_bar_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        data = af.fingerprint(turns=10, repetitions=2, step=0.5,
                              progress_bar=True)
        self.assertEqual(sorted(data.keys()), self.expected_points)

    def test_in_memory_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=10, repetitions=2, step=0.5, progress_bar=False,
                       in_memory=True)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(af.data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(af.spatial_tournament.interactions_dict,
                         af.interactions)
        self.assertEqual(edge_keys, self.expected_edges)
        self.assertEqual(coord_keys, self.expected_points)

    def test_serial_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        data = af.fingerprint(turns=10, repetitions=2, step=0.5, progress_bar=False)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(edge_keys, self.expected_edges)
        self.assertEqual(coord_keys, self.expected_points)

    @unittest.skipIf(axl.on_windows,
                     "Parallel processing not supported on Windows")
    def test_parallel_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=10, repetitions=2, step=0.5, processes=2,
                       progress_bar=False)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(af.data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(edge_keys, self.expected_edges)
        self.assertEqual(coord_keys, self.expected_points)

    def test_generate_data(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        edges, players = af.construct_tournament_elements(0.5)
        spatial_tournament = axl.SpatialTournament(players,
                                                   turns=10,
                                                   repetitions=2,
                                                   edges=edges)
        results = spatial_tournament.play(progress_bar=False,
                                          keep_interactions=True)
        data = af.generate_data(results.interactions, self.expected_points,
                                self.expected_edges)
        keys = sorted(list(data.keys()))
        values = [0 < score < 5 for score in data.values()]
        self.assertEqual(sorted(keys), self.expected_points)
        self.assertEqual(all(values), True)

    def test_reshape_data(self):
        test_points = [Point(x=0.0, y=0.0),
                       Point(x=0.0, y=0.5),
                       Point(x=0.0, y=1.0),
                       Point(x=0.5, y=0.0),
                       Point(x=0.5, y=0.5),
                       Point(x=0.5, y=1.0),
                       Point(x=1.0, y=0.0),
                       Point(x=1.0, y=0.5),
                       Point(x=1.0, y=1.0)]
        test_data = {Point(x=0.0, y=0.0): 5,
                     Point(x=0.0, y=0.5): 9,
                     Point(x=0.0, y=1.0): 3,
                     Point(x=0.5, y=0.0): 8,
                     Point(x=0.5, y=0.5): 2,
                     Point(x=0.5, y=1.0): 4,
                     Point(x=1.0, y=0.0): 2,
                     Point(x=1.0, y=0.5): 1,
                     Point(x=1.0, y=1.0): 9}
        test_shaped_data = [[3, 4, 9],
                            [9, 2, 1],
                            [5, 8, 2]]
        af = AshlockFingerprint(self.strategy, self.probe)
        plotting_data = af.reshape_data(test_data, test_points, 3)
        for i in range(len(plotting_data)):
            self.assertEqual(list(plotting_data[i]), test_shaped_data[i])

    def test_plot(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=10, repetitions=2, step=0.25, progress_bar=False)
        p = af.plot()
        self.assertIsInstance(p, matplotlib.pyplot.Figure)
        q = af.plot(col_map='jet')
        self.assertIsInstance(q, matplotlib.pyplot.Figure)
        r = af.plot(interpolation='bicubic')
        self.assertIsInstance(r, matplotlib.pyplot.Figure)
        t = af.plot(title='Title')
        self.assertIsInstance(t, matplotlib.pyplot.Figure)
        u = af.plot(colorbar=False)
        self.assertIsInstance(u, matplotlib.pyplot.Figure)
        v = af.plot(labels=False)
        self.assertIsInstance(v, matplotlib.pyplot.Figure)

    def test_wsls_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process
        test_data = {Point(x=0.0, y=0.0): 3.0,
                     Point(x=0.0, y=0.25): 1.46,
                     Point(x=0.0, y=0.5): 1.54,
                     Point(x=0.0, y=0.75): 1.12,
                     Point(x=0.0, y=1.0): 0.5,
                     Point(x=0.25, y=0.0): 3.0,
                     Point(x=0.25, y=0.25): 2.04,
                     Point(x=0.25, y=0.5): 2.0,
                     Point(x=0.25, y=0.75): 1.34,
                     Point(x=0.25, y=1.0): 0.9,
                     Point(x=0.5, y=0.0): 3.0,
                     Point(x=0.5, y=0.25): 3.0,
                     Point(x=0.5, y=0.5): 2.06,
                     Point(x=0.5, y=0.75): 1.36,
                     Point(x=0.5, y=1.0): 1.0,
                     Point(x=0.75, y=0.0): 3.0,
                     Point(x=0.75, y=0.25): 3.56,
                     Point(x=0.75, y=0.5): 2.06,
                     Point(x=0.75, y=0.75): 3.0,
                     Point(x=0.75, y=1.0): 1.04,
                     Point(x=1.0, y=0.0): 3.0,
                     Point(x=1.0, y=0.25): 4.86,
                     Point(x=1.0, y=0.5): 4.9,
                     Point(x=1.0, y=0.75): 4.9,
                     Point(x=1.0, y=1.0): 1.3}

        af = axl.AshlockFingerprint(self.strategy, self.probe)
        data = af.fingerprint(turns=50, repetitions=2, step=0.25)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key])

    def test_tft_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process
        test_data = {Point(x=0.0, y=0.0): 3.0,
                     Point(x=0.0, y=0.25): 1.1,
                     Point(x=0.0, y=0.5): 1.08,
                     Point(x=0.0, y=0.75): 1.04,
                     Point(x=0.0, y=1.0): 0.98,
                     Point(x=0.25, y=0.0): 3.0,
                     Point(x=0.25, y=0.25): 2.26,
                     Point(x=0.25, y=0.5): 2.1,
                     Point(x=0.25, y=0.75): 1.66,
                     Point(x=0.25, y=1.0): 1.64,
                     Point(x=0.5, y=0.0): 3.0,
                     Point(x=0.5, y=0.25): 2.5,
                     Point(x=0.5, y=0.5): 2.12,
                     Point(x=0.5, y=0.75): 1.86,
                     Point(x=0.5, y=1.0): 1.88,
                     Point(x=0.75, y=0.0): 3.0,
                     Point(x=0.75, y=0.25): 2.84,
                     Point(x=0.75, y=0.5): 2.36,
                     Point(x=0.75, y=0.75): 2.28,
                     Point(x=0.75, y=1.0): 1.98,
                     Point(x=1.0, y=0.0): 3.0,
                     Point(x=1.0, y=0.25): 2.78,
                     Point(x=1.0, y=0.5): 2.56,
                     Point(x=1.0, y=0.75): 2.44,
                     Point(x=1.0, y=1.0): 2.18}
        af = axl.AshlockFingerprint(axl.TitForTat, self.probe)
        data = af.fingerprint(turns=50, repetitions=2, step=0.25)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key])

    def test_majority_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process
        test_data = {Point(x=0.0, y=0.0): 3.0,
                     Point(x=0.0, y=0.25): 1.18,
                     Point(x=0.0, y=0.5): 1.98,
                     Point(x=0.0, y=0.75): 1.04,
                     Point(x=0.0, y=1.0): 0.98,
                     Point(x=0.25, y=0.0): 3.0,
                     Point(x=0.25, y=0.25): 2.16,
                     Point(x=0.25, y=0.5): 1.74,
                     Point(x=0.25, y=0.75): 1.96,
                     Point(x=0.25, y=1.0): 2.24,
                     Point(x=0.5, y=0.0): 3.0,
                     Point(x=0.5, y=0.25): 2.46,
                     Point(x=0.5, y=0.5): 2.44,
                     Point(x=0.5, y=0.75): 2.24,
                     Point(x=0.5, y=1.0): 2.74,
                     Point(x=0.75, y=0.0): 3.0,
                     Point(x=0.75, y=0.25): 2.52,
                     Point(x=0.75, y=0.5): 2.16,
                     Point(x=0.75, y=0.75): 2.1,
                     Point(x=0.75, y=1.0): 2.44,
                     Point(x=1.0, y=0.0): 3.0,
                     Point(x=1.0, y=0.25): 2.22,
                     Point(x=1.0, y=0.5): 1.64,
                     Point(x=1.0, y=0.75): 2.08,
                     Point(x=1.0, y=1.0): 2.26}
        af = axl.AshlockFingerprint(axl.GoByMajority, self.probe)
        data = af.fingerprint(turns=50, repetitions=2, step=0.25)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key])

    @given(strategy_pair=strategy_lists(min_size=2, max_size=2))
    def test_pair_fingerprints(self, strategy_pair):
        """
        A test to check that we can fingerprint
        with any two given strategies or instances
        """
        strategy, probe = strategy_pair
        af = AshlockFingerprint(strategy, probe)
        data = af.fingerprint(turns=2, repetitions=2, step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy(), probe)
        data = af.fingerprint(turns=2, repetitions=2, step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy, probe())
        data = af.fingerprint(turns=2, repetitions=2, step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy(), probe())
        data = af.fingerprint(turns=2, repetitions=2, step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)
class TestContriteTitForTat(TestPlayer):
    name = "Contrite Tit For Tat"
    player = axl.ContriteTitForTat
    expected_classifier = {
        "memory_depth": 3,
        "stochastic": False,
        "makes_use_of": set(),
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }

    deterministic_strategies = [
        s for s in axl.strategies if not axl.Classifiers["stochastic"](s())
    ]

    def test_init(self):
        player = self.player()
        self.assertFalse(player.contrite, False)
        self.assertEqual(player._recorded_history, [])

    @given(strategies=strategy_lists(strategies=deterministic_strategies,
                                     max_size=1),
           turns=integers(min_value=1, max_value=20))
    @settings(deadline=None)
    def test_is_tit_for_tat_with_no_noise(self, strategies, turns):
        tft = axl.TitForTat()
        player = self.player()
        opponent = strategies[0]()
        m1 = axl.Match((tft, opponent), turns)
        m2 = axl.Match((player, opponent), turns)
        self.assertEqual(m1.play(), m2.play())

    def test_strategy_with_noise1(self):
        self.versus_test(axl.Defector(), [(C, D)],
                         turns=1,
                         seed=9,
                         attrs={"_recorded_history": [C]})

    def test_strategy_with_noise2(self):
        self.versus_test(axl.Defector(), [(D, C)],
                         turns=1,
                         noise=0.5,
                         seed=11,
                         attrs={"_recorded_history": [C]})

    def test_strategy_with_noise3(self):
        # After noise: is contrite
        actions = list(zip([D, C], [C, D]))
        self.versus_test(axl.Defector(),
                         actions,
                         turns=2,
                         noise=0.5,
                         seed=49,
                         attrs={
                             "_recorded_history": [C, C],
                             "contrite": True
                         })

    def test_strategy_with_noise4(self):
        # Cooperates and no longer contrite
        actions = list(zip([D, C, C], [C, D, D]))
        self.versus_test(axl.Defector(),
                         actions,
                         turns=3,
                         noise=0.5,
                         seed=49,
                         attrs={
                             "_recorded_history": [C, C, C],
                             "contrite": False
                         })

    def test_strategy_with_noise5(self):
        # Defects and no longer contrite
        actions = list(zip([D, C, C, D], [C, D, D, D]))
        self.versus_test(axl.Defector(),
                         actions,
                         turns=4,
                         noise=0.5,
                         seed=158,
                         attrs={
                             "_recorded_history": [C, C, C, D],
                             "contrite": False
                         })
Exemple #19
0
 def test_call(self):
     strategies = strategy_lists().example()
     self.assertIsInstance(strategies, list)
     for p in strategies:
         self.assertIsInstance(p(), axelrod.Player)
Exemple #20
0
class TestSpatialTournament(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.test_edges = test_edges

    def test_init(self):
        tournament = axelrod.Tournament(
            name=self.test_name,
            players=self.players,
            game=self.game,
            turns=self.test_turns,
            edges=self.test_edges,
            noise=0.2,
        )
        self.assertEqual(tournament.match_generator.edges, tournament.edges)
        self.assertEqual(len(tournament.players), len(test_strategies))
        self.assertEqual(tournament.game.score((C, C)), (3, 3))
        self.assertEqual(tournament.turns, 100)
        self.assertEqual(tournament.repetitions, 10)
        self.assertEqual(tournament.name, "test")
        self.assertIsInstance(tournament._logger, logging.Logger)
        self.assertEqual(tournament.noise, 0.2)
        self.assertEqual(tournament.match_generator.noise, 0.2)
        anonymous_tournament = axelrod.Tournament(players=self.players)
        self.assertEqual(anonymous_tournament.name, "axelrod")

    @given(
        strategies=strategy_lists(strategies=deterministic_strategies,
                                  min_size=2,
                                  max_size=2),
        turns=integers(min_value=1, max_value=20),
        repetitions=integers(min_value=1, max_value=5),
        noise=floats(min_value=0, max_value=1),
        seed=integers(min_value=0, max_value=4294967295),
    )
    @settings(max_examples=5, max_iterations=20)
    def test_complete_tournament(self, strategies, turns, repetitions, noise,
                                 seed):
        """
        A test to check that a spatial tournament on the complete multigraph
        gives the same results as the round robin.
        """

        players = [s() for s in strategies]
        # edges
        edges = []
        for i in range(0, len(players)):
            for j in range(i, len(players)):
                edges.append((i, j))

        # create a round robin tournament
        tournament = axelrod.Tournament(players,
                                        repetitions=repetitions,
                                        turns=turns,
                                        noise=noise)
        # create a complete spatial tournament
        spatial_tournament = axelrod.Tournament(players,
                                                repetitions=repetitions,
                                                turns=turns,
                                                noise=noise,
                                                edges=edges)

        axelrod.seed(seed)
        results = tournament.play(progress_bar=False)
        axelrod.seed(seed)
        spatial_results = spatial_tournament.play(progress_bar=False)

        self.assertEqual(results.ranked_names, spatial_results.ranked_names)
        self.assertEqual(results.num_players, spatial_results.num_players)
        self.assertEqual(results.repetitions, spatial_results.repetitions)
        self.assertEqual(results.payoff_diffs_means,
                         spatial_results.payoff_diffs_means)
        self.assertEqual(results.payoff_matrix, spatial_results.payoff_matrix)
        self.assertEqual(results.payoff_stddevs,
                         spatial_results.payoff_stddevs)
        self.assertEqual(results.payoffs, spatial_results.payoffs)
        self.assertEqual(results.cooperating_rating,
                         spatial_results.cooperating_rating)
        self.assertEqual(results.cooperation, spatial_results.cooperation)
        self.assertEqual(results.normalised_cooperation,
                         spatial_results.normalised_cooperation)
        self.assertEqual(results.normalised_scores,
                         spatial_results.normalised_scores)
        self.assertEqual(results.good_partner_matrix,
                         spatial_results.good_partner_matrix)
        self.assertEqual(results.good_partner_rating,
                         spatial_results.good_partner_rating)

    def test_particular_tournament(self):
        """A test for a tournament that has caused failures during some bug
        fixing"""
        players = [
            axelrod.Cooperator(),
            axelrod.Defector(),
            axelrod.TitForTat(),
            axelrod.Grudger(),
        ]
        edges = [(0, 2), (0, 3), (1, 2), (1, 3)]
        tournament = axelrod.Tournament(players, edges=edges)
        results = tournament.play(progress_bar=False)
        expected_ranked_names = [
            "Cooperator", "Tit For Tat", "Grudger", "Defector"
        ]
        self.assertEqual(results.ranked_names, expected_ranked_names)

        # Check that this tournament runs with noise
        tournament = axelrod.Tournament(players, edges=edges, noise=.5)
        results = tournament.play(progress_bar=False)
        self.assertIsInstance(results, axelrod.ResultSet)
Exemple #21
0
class TestFingerprint(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.strategy = axl.WinStayLoseShift
        cls.probe = axl.TitForTat
        cls.expected_points = [(0.0, 0.0), (0.0, 0.5), (0.0, 1.0), (0.5, 0.0),
                               (0.5, 0.5), (0.5, 1.0), (1.0, 0.0), (1.0, 0.5),
                               (1.0, 1.0)]
        cls.expected_edges = [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6),
                              (0, 7), (0, 8), (0, 9)]

    def test_create_points(self):
        test_points = create_points(0.5, progress_bar=False)
        self.assertEqual(test_points, self.expected_points)

    def test_create_jossann(self):
        # x + y < 1
        ja = create_jossann((.5, .4), self.probe)
        self.assertEqual(str(ja), "Joss-Ann Tit For Tat: (0.5, 0.4)")

        # x + y = 1
        ja = create_jossann((.4, .6), self.probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Tit For Tat: (0.6, 0.4)")

        # x + y > 1
        ja = create_jossann((.5, .6), self.probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Tit For Tat: (0.5, 0.4)")

    def test_create_jossann_parametrised_player(self):
        probe = axl.Random(p=0.1)

        # x + y < 1
        ja = create_jossann((.5, .4), probe)
        self.assertEqual(str(ja), "Joss-Ann Random: 0.1: (0.5, 0.4)")

        # x + y = 1
        ja = create_jossann((.4, .6), probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Random: 0.1: (0.6, 0.4)")

        # x + y > 1
        ja = create_jossann((.5, .6), probe)
        self.assertEqual(str(ja), "Dual Joss-Ann Random: 0.1: (0.5, 0.4)")

    def test_create_probes(self):
        probes = create_probes(self.probe,
                               self.expected_points,
                               progress_bar=False)
        self.assertEqual(len(probes), 9)

    def test_create_edges(self):
        edges = create_edges(self.expected_points, progress_bar=False)
        self.assertEqual(edges, self.expected_edges)

    def test_generate_data(self):
        interactions = {
            (0, 1): [[(C, C)], [(C, C)]],
            (0, 2): [[(C, C), (C, C)], [(C, D)]],
            (0, 3): [[(C, C), (D, C)]],
            (0, 4): [[(C, C), (D, C)], [(D, D)]],
            (0, 5): [[(C, D), (D, C)]],
            (0, 6): [[(C, D), (C, D)]],
            (0, 7): [[(C, D), (D, D)]],
            (0, 8): [[(D, D), (D, D)]],
            (0, 9): [[(D, C), (D, C)]],
        }

        expected = {
            Point(0.0, 0.0): 3.0,
            Point(0.0, 0.5): 1.5,
            Point(0.0, 1.0): 4.0,
            Point(0.5, 0.0): 2.5,
            Point(0.5, 0.5): 2.5,
            Point(0.5, 1.0): 0.0,
            Point(1.0, 0.0): 0.5,
            Point(1.0, 0.5): 1.0,
            Point(1.0, 1.0): 5.0,
        }
        data = generate_data(interactions, self.expected_points,
                             self.expected_edges)
        self.assertEqual(data, expected)

    def test_reshape_data(self):
        test_points = [
            Point(x=0.0, y=0.0),
            Point(x=0.0, y=0.5),
            Point(x=0.0, y=1.0),
            Point(x=0.5, y=0.0),
            Point(x=0.5, y=0.5),
            Point(x=0.5, y=1.0),
            Point(x=1.0, y=0.0),
            Point(x=1.0, y=0.5),
            Point(x=1.0, y=1.0)
        ]
        test_data = {
            Point(x=0.0, y=0.0): 5,
            Point(x=0.0, y=0.5): 9,
            Point(x=0.0, y=1.0): 3,
            Point(x=0.5, y=0.0): 8,
            Point(x=0.5, y=0.5): 2,
            Point(x=0.5, y=1.0): 4,
            Point(x=1.0, y=0.0): 2,
            Point(x=1.0, y=0.5): 1,
            Point(x=1.0, y=1.0): 9
        }
        test_shaped_data = [[3, 4, 9], [9, 2, 1], [5, 8, 2]]
        plotting_data = reshape_data(test_data, test_points, 3)
        for i in range(len(plotting_data)):
            self.assertEqual(list(plotting_data[i]), test_shaped_data[i])

    def test_default_init(self):
        fingerprint = AshlockFingerprint(self.strategy)
        self.assertEqual(fingerprint.strategy, self.strategy)
        self.assertEqual(fingerprint.probe, self.probe)

    def test_init(self):
        fingerprint = AshlockFingerprint(self.strategy, self.probe)
        self.assertEqual(fingerprint.strategy, self.strategy)
        self.assertEqual(fingerprint.probe, self.probe)

    def test_init_with_instance(self):
        player = self.strategy()
        fingerprint = AshlockFingerprint(player)
        self.assertEqual(fingerprint.strategy, player)
        self.assertEqual(fingerprint.probe, self.probe)

        probe_player = self.probe()
        fingerprint = AshlockFingerprint(self.strategy, probe_player)
        self.assertEqual(fingerprint.strategy, self.strategy)
        self.assertEqual(fingerprint.probe, probe_player)

        fingerprint = AshlockFingerprint(player, probe_player)
        self.assertEqual(fingerprint.strategy, player)
        self.assertEqual(fingerprint.probe, probe_player)

    def test_construct_tournament_elemets(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        edges, tournament_players = af.construct_tournament_elements(
            0.5, progress_bar=False)
        self.assertEqual(edges, self.expected_edges)
        self.assertEqual(len(tournament_players), 10)
        self.assertEqual(tournament_players[0].__class__, af.strategy)

    def test_progress_bar_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        data = af.fingerprint(turns=10,
                              repetitions=2,
                              step=0.5,
                              progress_bar=True)
        self.assertEqual(sorted(data.keys()), self.expected_points)

    @patch('axelrod.fingerprint.mkstemp', RecordedMksTemp.mkstemp)
    def test_temp_file_creation(self):

        RecordedMksTemp.reset_record()
        af = AshlockFingerprint(self.strategy, self.probe)
        filename = "test_outputs/test_fingerprint.csv"

        self.assertEqual(RecordedMksTemp.record, [])

        # Temp file is created and destroyed.
        af.fingerprint(turns=1,
                       repetitions=1,
                       step=0.5,
                       progress_bar=False,
                       filename=None)

        self.assertEqual(len(RecordedMksTemp.record), 1)
        filename = RecordedMksTemp.record[0][1]
        self.assertIsInstance(filename, str)
        self.assertNotEqual(filename, '')
        self.assertFalse(os.path.isfile(filename))

    def test_fingerprint_with_filename(self):
        filename = "test_outputs/test_fingerprint.csv"
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=1,
                       repetitions=1,
                       step=0.5,
                       progress_bar=False,
                       filename=filename)
        with open(filename, 'r') as out:
            data = out.read()
            self.assertEqual(len(data.split("\n")), 20)

    def test_serial_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        data = af.fingerprint(turns=10,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(edge_keys, self.expected_edges)
        self.assertEqual(coord_keys, self.expected_points)

    def test_parallel_fingerprint(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=10,
                       repetitions=2,
                       step=0.5,
                       processes=2,
                       progress_bar=False)
        edge_keys = sorted(list(af.interactions.keys()))
        coord_keys = sorted(list(af.data.keys()))
        self.assertEqual(af.step, 0.5)
        self.assertEqual(edge_keys, self.expected_edges)
        self.assertEqual(coord_keys, self.expected_points)

    def test_plot(self):
        af = AshlockFingerprint(self.strategy, self.probe)
        af.fingerprint(turns=10, repetitions=2, step=0.25, progress_bar=False)
        p = af.plot()
        self.assertIsInstance(p, matplotlib.pyplot.Figure)
        q = af.plot(cmap='jet')
        self.assertIsInstance(q, matplotlib.pyplot.Figure)
        r = af.plot(interpolation='bicubic')
        self.assertIsInstance(r, matplotlib.pyplot.Figure)
        t = af.plot(title='Title')
        self.assertIsInstance(t, matplotlib.pyplot.Figure)
        u = af.plot(colorbar=False)
        self.assertIsInstance(u, matplotlib.pyplot.Figure)
        v = af.plot(labels=False)
        self.assertIsInstance(v, matplotlib.pyplot.Figure)

    def test_wsls_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process
        test_data = {
            Point(x=0.0, y=0.0): 3.000,
            Point(x=0.0, y=0.25): 1.710,
            Point(x=0.0, y=0.5): 1.440,
            Point(x=0.0, y=0.75): 1.080,
            Point(x=0.0, y=1.0): 0.500,
            Point(x=0.25, y=0.0): 3.000,
            Point(x=0.25, y=0.25): 2.280,
            Point(x=0.25, y=0.5): 1.670,
            Point(x=0.25, y=0.75): 1.490,
            Point(x=0.25, y=1.0): 0.770,
            Point(x=0.5, y=0.0): 3.000,
            Point(x=0.5, y=0.25): 2.740,
            Point(x=0.5, y=0.5): 2.240,
            Point(x=0.5, y=0.75): 1.730,
            Point(x=0.5, y=1.0): 1.000,
            Point(x=0.75, y=0.0): 3.000,
            Point(x=0.75, y=0.25): 3.520,
            Point(x=0.75, y=0.5): 2.830,
            Point(x=0.75, y=0.75): 1.750,
            Point(x=0.75, y=1.0): 1.250,
            Point(x=1.0, y=0.0): 3.000,
            Point(x=1.0, y=0.25): 4.440,
            Point(x=1.0, y=0.5): 4.410,
            Point(x=1.0, y=0.75): 4.440,
            Point(x=1.0, y=1.0): 1.300
        }
        af = axl.AshlockFingerprint(self.strategy, self.probe)
        data = af.fingerprint(turns=50,
                              repetitions=2,
                              step=0.25,
                              progress_bar=False)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key], places=2)

    def test_tft_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process
        test_data = {
            Point(x=0.0, y=0.0): 3.000,
            Point(x=0.0, y=0.25): 1.820,
            Point(x=0.0, y=0.5): 1.130,
            Point(x=0.0, y=0.75): 1.050,
            Point(x=0.0, y=1.0): 0.980,
            Point(x=0.25, y=0.0): 3.000,
            Point(x=0.25, y=0.25): 2.440,
            Point(x=0.25, y=0.5): 1.770,
            Point(x=0.25, y=0.75): 1.700,
            Point(x=0.25, y=1.0): 1.490,
            Point(x=0.5, y=0.0): 3.000,
            Point(x=0.5, y=0.25): 2.580,
            Point(x=0.5, y=0.5): 2.220,
            Point(x=0.5, y=0.75): 2.000,
            Point(x=0.5, y=1.0): 1.940,
            Point(x=0.75, y=0.0): 3.000,
            Point(x=0.75, y=0.25): 2.730,
            Point(x=0.75, y=0.5): 2.290,
            Point(x=0.75, y=0.75): 2.310,
            Point(x=0.75, y=1.0): 2.130,
            Point(x=1.0, y=0.0): 3.000,
            Point(x=1.0, y=0.25): 2.790,
            Point(x=1.0, y=0.5): 2.480,
            Point(x=1.0, y=0.75): 2.310,
            Point(x=1.0, y=1.0): 2.180
        }

        af = axl.AshlockFingerprint(axl.TitForTat, self.probe)
        data = af.fingerprint(turns=50,
                              repetitions=2,
                              step=0.25,
                              progress_bar=False)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key], places=2)

    def test_majority_fingerprint(self):
        axl.seed(0)  # Fingerprinting is a random process
        test_data = {
            Point(x=0.0, y=0.0): 3.000,
            Point(x=0.0, y=0.25): 1.940,
            Point(x=0.0, y=0.5): 1.130,
            Point(x=0.0, y=0.75): 1.030,
            Point(x=0.0, y=1.0): 0.980,
            Point(x=0.25, y=0.0): 3.000,
            Point(x=0.25, y=0.25): 2.130,
            Point(x=0.25, y=0.5): 1.940,
            Point(x=0.25, y=0.75): 2.060,
            Point(x=0.25, y=1.0): 1.940,
            Point(x=0.5, y=0.0): 3.000,
            Point(x=0.5, y=0.25): 2.300,
            Point(x=0.5, y=0.5): 2.250,
            Point(x=0.5, y=0.75): 2.420,
            Point(x=0.5, y=1.0): 2.690,
            Point(x=0.75, y=0.0): 3.000,
            Point(x=0.75, y=0.25): 2.400,
            Point(x=0.75, y=0.5): 2.010,
            Point(x=0.75, y=0.75): 2.390,
            Point(x=0.75, y=1.0): 2.520,
            Point(x=1.0, y=0.0): 3.000,
            Point(x=1.0, y=0.25): 2.360,
            Point(x=1.0, y=0.5): 1.740,
            Point(x=1.0, y=0.75): 2.260,
            Point(x=1.0, y=1.0): 2.260
        }

        af = axl.AshlockFingerprint(axl.GoByMajority, self.probe)
        data = af.fingerprint(turns=50,
                              repetitions=2,
                              step=0.25,
                              progress_bar=False)

        for key, value in data.items():
            self.assertAlmostEqual(value, test_data[key], places=2)

    @given(strategy_pair=strategy_lists(min_size=2, max_size=2))
    @settings(max_examples=5, max_iterations=20)
    def test_pair_fingerprints(self, strategy_pair):
        """
        A test to check that we can fingerprint
        with any two given strategies or instances
        """
        strategy, probe = strategy_pair
        af = AshlockFingerprint(strategy, probe)
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy(), probe)
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy, probe())
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)

        af = AshlockFingerprint(strategy(), probe())
        data = af.fingerprint(turns=2,
                              repetitions=2,
                              step=0.5,
                              progress_bar=False)
        self.assertIsInstance(data, dict)
Exemple #22
0
class TestPlayer(unittest.TestCase):
    """A Test class from which other player test classes are inherited."""

    player = TestOpponent
    expected_class_classifier = None

    def test_initialisation(self):
        """Test that the player initiates correctly."""
        if self.__class__ != TestPlayer:
            player = self.player()
            self.assertEqual(len(player.history), 0)
            self.assertEqual(
                player.match_attributes,
                {
                    "length": -1,
                    "game": axl.DefaultGame,
                    "noise": 0
                },
            )
            self.assertEqual(player.cooperations, 0)
            self.assertEqual(player.defections, 0)
            self.classifier_test(self.expected_class_classifier)

    def test_repr(self):
        """Test that the representation is correct."""
        if self.__class__ != TestPlayer:
            self.assertEqual(str(self.player()), self.name)

    def test_match_attributes(self):
        player = self.player()
        # Default
        player.set_match_attributes()
        t_attrs = player.match_attributes
        self.assertEqual(t_attrs["length"], -1)
        self.assertEqual(t_attrs["noise"], 0)
        self.assertEqual(t_attrs["game"].RPST(), (3, 1, 0, 5))

        # Common
        player.set_match_attributes(length=200)
        t_attrs = player.match_attributes
        self.assertEqual(t_attrs["length"], 200)
        self.assertEqual(t_attrs["noise"], 0)
        self.assertEqual(t_attrs["game"].RPST(), (3, 1, 0, 5))

        # Noisy
        player.set_match_attributes(length=200, noise=0.5)
        t_attrs = player.match_attributes
        self.assertEqual(t_attrs["noise"], 0.5)

    def equality_of_players_test(self, p1, p2, seed, opponent):
        a1 = opponent()
        a2 = opponent()
        self.assertEqual(p1, p2)
        for player, op in [(p1, a1), (p2, a2)]:
            m = axl.Match(players=(player, op), turns=10, seed=seed)
            m.play()
        self.assertEqual(p1, p2)
        p1 = pickle.loads(pickle.dumps(p1))
        p2 = pickle.loads(pickle.dumps(p2))
        self.assertEqual(p1, p2)

    @given(
        opponent=sampled_from(short_run_time_short_mem),
        seed=integers(min_value=1, max_value=200),
    )
    @settings(max_examples=1, deadline=None)
    def test_equality_of_clone(self, seed, opponent):
        p1 = self.player()
        p2 = p1.clone()
        self.equality_of_players_test(p1, p2, seed, opponent)

    @given(
        opponent=sampled_from(axl.short_run_time_strategies),
        seed=integers(min_value=1, max_value=200),
    )
    @settings(max_examples=1, deadline=None)
    def test_equality_of_pickle_clone(self, seed, opponent):
        p1 = self.player()
        p2 = pickle.loads(pickle.dumps(p1))
        self.equality_of_players_test(p1, p2, seed, opponent)

    def test_reset_history_and_attributes(self):
        """Make sure resetting works correctly."""
        for opponent in [
                axl.Defector(),
                axl.Random(),
                axl.Alternator(),
                axl.Cooperator(),
        ]:
            player = self.player()
            clone = player.clone()
            match = axl.Match((player, opponent), turns=10, seed=111)
            match.play()
            player.reset()
            self.assertEqual(player, clone)

    def test_reset_clone(self):
        """Make sure history resetting with cloning works correctly, regardless
        if self.test_reset() is overwritten."""
        player = self.player()
        clone = player.clone()
        self.assertEqual(player, clone)

    @given(seed=integers(min_value=1, max_value=20000000),
           turns=integers(min_value=5, max_value=10),
           noise=integers(min_value=0, max_value=10))
    @settings(max_examples=1, deadline=None)
    def test_clone_reproducible_play(self, seed, turns, noise):
        # Test that the cloned player produces identical play
        player = self.player()
        if player.name in [
                "Darwin", "Human", "Mind Bender", "Mind Controller",
                "Mind Warper"
        ]:
            # Known exceptions
            return

        for op in [
                axl.Cooperator(),
                axl.Defector(),
                axl.TitForTat(),
                axl.Random(p=0.5),
        ]:
            player = self.player()
            player_clone = player.clone()
            op = op.clone()
            op_clone = op.clone()
            m1 = axl.Match((player, op),
                           turns=turns,
                           seed=seed,
                           noise=noise / 100.)
            m2 = axl.Match((player_clone, op_clone),
                           turns=turns,
                           seed=seed,
                           noise=noise / 100.)
            m1.play()
            m2.play()
            self.assertEqual(m1.result, m2.result)
            self.assertEqual(player, player_clone)
            self.assertEqual(op, op_clone)

    @given(
        strategies=strategy_lists(max_size=5,
                                  strategies=short_run_time_short_mem),
        seed=integers(min_value=1, max_value=200),
        turns=integers(min_value=1, max_value=200),
    )
    @settings(max_examples=1, deadline=None)
    def test_memory_depth_upper_bound(self, strategies, seed, turns):
        """
        Test that the memory depth is indeed an upper bound.
        """
        def get_memory_depth_or_zero(player):
            # Some of the test strategies have no entry in the classifiers
            # table, so there isn't logic to load default value of zero.
            memory = axl.Classifiers["memory_depth"](player)
            return memory if memory else 0

        player = self.player()
        memory = get_memory_depth_or_zero(player)
        if memory < float("inf"):
            for strategy in strategies:
                player.reset()
                opponent = strategy()
                max_memory = max(memory, get_memory_depth_or_zero(opponent))
                self.assertTrue(
                    test_memory(
                        player=player,
                        opponent=opponent,
                        seed=seed,
                        turns=turns,
                        memory_length=max_memory,
                    ),
                    msg="{} failed for seed={} and opponent={}".format(
                        player.name, seed, opponent),
                )

    def versus_test(
        self,
        opponent,
        expected_actions,
        turns=None,
        noise=None,
        seed=None,
        match_attributes=None,
        attrs=None,
        init_kwargs=None,
    ):
        """
        Tests a sequence of outcomes for two given players.
        Parameters:
        -----------
        opponent: Player or list
            An instance of a player OR a sequence of actions. If a sequence of
            actions is passed, a Mock Player is created that cycles over that
            sequence.
        expected_actions: List
            The expected outcomes of the match (list of tuples of actions).
        noise: float
            Any noise to be passed to a match
        seed: int
            The random seed to be used
        match_attributes: dict
            The match attributes to be passed to the players.  For example,
            `{length:-1}` implies that the players do not know the length of the
            match.
        attrs: dict
            Dictionary of internal attributes to check at the end of all plays
            in player
        init_kwargs: dict
            A dictionary of keyword arguments to instantiate player with
        """

        if init_kwargs is None:
            init_kwargs = dict()

        player = self.player(**init_kwargs)

        test_match = TestMatch()
        test_match.versus_test(player,
                               opponent, [x for (x, y) in expected_actions],
                               [y for (x, y) in expected_actions],
                               turns=turns,
                               noise=noise,
                               seed=seed,
                               attrs=attrs,
                               match_attributes=match_attributes)

    def classifier_test(self, expected_class_classifier=None):
        """Test that the keys in the expected_classifier dictionary give the
        expected values in the player classifier dictionary. Also checks that
        two particular keys (memory_depth and stochastic) are in the
        dictionary."""
        player = self.player()

        # Test that player has same classifier as its class unless otherwise
        # specified
        if expected_class_classifier is None:
            expected_class_classifier = player.classifier
        actual_class_classifier = {
            c: axl.Classifiers[c](player)
            for c in expected_class_classifier.keys()
        }
        self.assertEqual(expected_class_classifier, actual_class_classifier)

        self.assertTrue(
            "memory_depth" in player.classifier,
            msg="memory_depth not in classifier",
        )
        self.assertTrue(
            "stochastic" in player.classifier,
            msg="stochastic not in classifier",
        )
        for key in TestOpponent.classifier:
            self.assertEqual(
                axl.Classifiers[key](player),
                self.expected_classifier[key],
                msg="%s - Behaviour: %s != Expected Behaviour: %s" % (
                    key,
                    axl.Classifiers[key](player),
                    self.expected_classifier[key],
                ),
            )
Exemple #23
0
class TestMoranProcess(unittest.TestCase):
    def test_init(self):
        players = axl.Cooperator(), axl.Defector()
        mp = axl.MoranProcess(players)
        self.assertEqual(mp.turns, axl.DEFAULT_TURNS)
        self.assertIsNone(mp.prob_end)
        self.assertIsNone(mp.game)
        self.assertEqual(mp.noise, 0)
        self.assertEqual(mp.initial_players, players)
        self.assertEqual(mp.players, list(players))
        self.assertEqual(mp.populations,
                         [Counter({
                             "Cooperator": 1,
                             "Defector": 1
                         })])
        self.assertIsNone(mp.winning_strategy_name)
        self.assertEqual(mp.mutation_rate, 0)
        self.assertEqual(mp.mode, "bd")
        self.assertEqual(mp.deterministic_cache, axl.DeterministicCache())
        self.assertEqual(mp.mutation_targets, {
            "Cooperator": [players[1]],
            "Defector": [players[0]]
        })
        self.assertEqual(mp.interaction_graph._edges, [(0, 1), (1, 0)])
        self.assertEqual(mp.reproduction_graph._edges, [(0, 1), (1, 0), (0, 0),
                                                        (1, 1)])
        self.assertEqual(mp.fitness_transformation, None)
        self.assertEqual(mp.locations, [0, 1])
        self.assertEqual(mp.index, {0: 0, 1: 1})

        # Test non default graph cases
        players = axl.Cooperator(), axl.Defector(), axl.TitForTat()
        edges = [(0, 1), (2, 0), (1, 2)]
        graph = axl.graph.Graph(edges, directed=True)
        mp = axl.MoranProcess(players, interaction_graph=graph)
        self.assertEqual(mp.interaction_graph._edges, [(0, 1), (2, 0), (1, 2)])
        self.assertEqual(
            sorted(mp.reproduction_graph._edges),
            sorted([(0, 1), (2, 0), (1, 2), (0, 0), (1, 1), (2, 2)]),
        )

        mp = axl.MoranProcess(players,
                              interaction_graph=graph,
                              reproduction_graph=graph)
        self.assertEqual(mp.interaction_graph._edges, [(0, 1), (2, 0), (1, 2)])
        self.assertEqual(mp.reproduction_graph._edges, [(0, 1), (2, 0),
                                                        (1, 2)])

    def test_set_players(self):
        """Test that set players resets all players"""
        players = axl.Cooperator(), axl.Defector()
        mp = axl.MoranProcess(players)
        players[0].history.append(C, D)
        mp.set_players()
        self.assertEqual(players[0].cooperations, 0)

    def test_mutate(self):
        """Test that a mutated player is returned"""
        players = axl.Cooperator(), axl.Defector(), axl.TitForTat()
        mp = MoranProcess(players, mutation_rate=0.5, seed=0)
        self.assertEqual(mp.mutate(0), players[0])
        mp = MoranProcess(players, mutation_rate=0.5, seed=2)
        self.assertEqual(mp.mutate(0), players[2])
        mp = MoranProcess(players, mutation_rate=0.5, seed=7)
        self.assertEqual(mp.mutate(0), players[1])

    def test_death_in_db(self):
        players = axl.Cooperator(), axl.Defector(), axl.TitForTat()
        mp = MoranProcess(players, mutation_rate=0.5, mode="db", seed=1)
        self.assertEqual(mp.death(), 2)
        self.assertEqual(mp.dead, 2)
        mp = MoranProcess(players, mutation_rate=0.5, mode="db", seed=2)
        self.assertEqual(mp.death(), 0)
        self.assertEqual(mp.dead, 0)
        mp = MoranProcess(players, mutation_rate=0.5, mode="db", seed=9)
        self.assertEqual(mp.death(), 1)
        self.assertEqual(mp.dead, 1)

    def test_death_in_bd(self):
        players = axl.Cooperator(), axl.Defector(), axl.TitForTat()
        edges = [(0, 1), (2, 0), (1, 2)]
        graph = axl.graph.Graph(edges, directed=True)
        mp = MoranProcess(players, mode="bd", interaction_graph=graph, seed=1)
        self.assertEqual(mp.death(0), 1)
        mp = MoranProcess(players, mode="bd", interaction_graph=graph, seed=2)
        self.assertEqual(mp.death(0), 1)
        mp = MoranProcess(players, mode="bd", interaction_graph=graph, seed=3)
        self.assertEqual(mp.death(0), 0)

    def test_birth_in_db(self):
        players = axl.Cooperator(), axl.Defector(), axl.TitForTat()
        mp = MoranProcess(players, mode="db", seed=1)
        self.assertEqual(mp.death(), 2)
        self.assertEqual(mp.birth(0), 2)

    def test_birth_in_bd(self):
        players = axl.Cooperator(), axl.Defector(), axl.TitForTat()
        mp = MoranProcess(players, mode="bd", seed=2)
        self.assertEqual(mp.birth(), 0)

    def test_fixation_check(self):
        players = axl.Cooperator(), axl.Cooperator()
        mp = axl.MoranProcess(players)
        self.assertTrue(mp.fixation_check())
        players = axl.Cooperator(), axl.Defector()
        mp = axl.MoranProcess(players)
        self.assertFalse(mp.fixation_check())

    def test_next(self):
        players = axl.Cooperator(), axl.Defector()
        mp = axl.MoranProcess(players)
        self.assertIsInstance(next(mp), axl.MoranProcess)

    def test_matchup_indices(self):
        players = axl.Cooperator(), axl.Defector()
        mp = axl.MoranProcess(players)
        self.assertEqual(mp._matchup_indices(), {(0, 1)})

        players = axl.Cooperator(), axl.Defector(), axl.TitForTat()
        edges = [(0, 1), (2, 0), (1, 2)]
        graph = axl.graph.Graph(edges, directed=True)
        mp = axl.MoranProcess(players, mode="bd", interaction_graph=graph)
        self.assertEqual(mp._matchup_indices(), {(0, 1), (1, 2), (2, 0)})

    def test_fps(self):
        players = axl.Cooperator(), axl.Defector()
        mp = MoranProcess(players, seed=1)
        self.assertEqual(mp.fitness_proportionate_selection([0, 0, 1]), 2)
        self.assertEqual(mp.fitness_proportionate_selection([1, 1, 1]), 2)
        self.assertEqual(mp.fitness_proportionate_selection([1, 1, 1]), 0)

    def test_exit_condition(self):
        p1, p2 = axl.Cooperator(), axl.Cooperator()
        mp = axl.MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp), 1)

    @given(seed=integers(min_value=1, max_value=4294967295))
    @settings(max_examples=5, deadline=None)
    def test_seeding_equality(self, seed):
        players = [axl.Random(x) for x in (0.2, 0.4, 0.6, 0.8)]
        mp1 = MoranProcess(players, seed=seed)
        mp1.play()
        mp2 = MoranProcess(players, seed=seed)
        mp2.play()
        self.assertEqual(mp1.populations, mp2.populations)

    def test_seeding_inequality(self):
        players = [axl.Random(x) for x in (0.2, 0.4, 0.6, 0.8)]
        mp1 = MoranProcess(players, seed=0)
        mp1.play()
        mp2 = MoranProcess(players, seed=1)
        mp2.play()
        self.assertNotEqual(mp1, mp2)

    def test_two_players(self):
        p1, p2 = axl.Cooperator(), axl.Defector()
        mp = MoranProcess((p1, p2), seed=99)
        populations = mp.play()
        self.assertEqual(len(mp), 2)
        self.assertEqual(len(populations), 2)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p2))

    def test_two_prob_end(self):
        p1, p2 = axl.Random(), axl.TitForTat()
        mp = MoranProcess((p1, p2), prob_end=0.5, seed=10)
        populations = mp.play()
        self.assertEqual(len(mp), 2)
        self.assertEqual(len(populations), 2)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p1))

    def test_different_game(self):
        # Possible for Cooperator to become fixed when using a different game
        p1, p2 = axl.Cooperator(), axl.Defector()
        game = axl.Game(r=4, p=2, s=1, t=6)
        mp = MoranProcess((p1, p2), turns=5, game=game, seed=88)
        populations = mp.play()
        self.assertEqual(mp.winning_strategy_name, str(p2))

    def test_death_birth(self):
        """Two player death-birth should fixate after one round."""
        p1, p2 = axl.Cooperator(), axl.Defector()
        seeds = range(0, 20)
        for seed in seeds:
            mp = MoranProcess((p1, p2), mode="db", seed=seed)
            mp.play()
        self.assertIsNotNone(mp.winning_strategy_name)
        # Number of populations is 2: the original and the one after the first round.
        self.assertEqual(len(mp.populations), 2)

    def test_death_birth_outcomes(self):
        """Show that birth-death and death-birth can produce different
        outcomes."""
        seeds = [(1, True), (23, False)]
        players = []
        N = 6
        for _ in range(N // 2):
            players.append(axl.Cooperator())
            players.append(axl.Defector())
        for seed, outcome in seeds:
            mp = MoranProcess(players, mode="bd", seed=seed)
            mp.play()
            winner = mp.winning_strategy_name
            mp = MoranProcess(players, mode="db", seed=seed)
            mp.play()
            winner2 = mp.winning_strategy_name
            self.assertEqual((winner == winner2), outcome)

    def test_two_random_players(self):
        p1, p2 = axl.Random(p=0.5), axl.Random(p=0.25)
        mp = MoranProcess((p1, p2), seed=66)
        populations = mp.play()
        self.assertEqual(len(mp), 2)
        self.assertEqual(len(populations), 2)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(p1))

    def test_two_players_with_mutation(self):
        p1, p2 = axl.Cooperator(), axl.Defector()
        mp = MoranProcess((p1, p2),
                          mutation_rate=0.2,
                          stop_on_fixation=False,
                          seed=5)
        self.assertDictEqual(mp.mutation_targets, {
            str(p1): [p2],
            str(p2): [p1]
        })
        # Test that mutation causes the population to alternate between
        # fixations
        counters = [
            Counter({"Cooperator": 2}),
            Counter({"Defector": 2}),
            Counter({"Cooperator": 2}),
            Counter({"Defector": 2}),
        ]
        for counter in counters:
            for _ in itertools.takewhile(
                    lambda x: x.population_distribution() != counter, mp):
                pass
            self.assertEqual(mp.population_distribution(), counter)

    def test_play_exception(self):
        p1, p2 = axl.Cooperator(), axl.Defector()
        mp = axl.MoranProcess((p1, p2), mutation_rate=0.2)
        with self.assertRaises(ValueError):
            mp.play()

    def test_three_players(self):
        players = [axl.Cooperator(), axl.Cooperator(), axl.Defector()]
        mp = MoranProcess(players, seed=11)
        populations = mp.play()
        self.assertEqual(len(mp), 7)
        self.assertEqual(len(populations), 7)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axl.Defector()))

    def test_three_players_with_mutation(self):
        p1 = axl.Cooperator()
        p2 = axl.Random()
        p3 = axl.Defector()
        players = [p1, p2, p3]
        mp = axl.MoranProcess(players,
                              mutation_rate=0.2,
                              stop_on_fixation=False)
        self.assertDictEqual(
            mp.mutation_targets,
            {
                str(p1): [p3, p2],
                str(p2): [p1, p3],
                str(p3): [p1, p2]
            },
        )
        # Test that mutation causes the population to alternate between
        # fixations
        counters = [Counter({"Cooperator": 3}), Counter({"Defector": 3})]
        for counter in counters:
            for _ in itertools.takewhile(
                    lambda x: x.population_distribution() != counter, mp):
                pass
            self.assertEqual(mp.population_distribution(), counter)

    def test_four_players(self):
        players = [axl.Cooperator() for _ in range(3)]
        players.append(axl.Defector())
        mp = MoranProcess(players, seed=29)
        populations = mp.play()
        self.assertEqual(len(mp), 8)
        self.assertEqual(len(populations), 8)
        self.assertEqual(populations, mp.populations)
        self.assertEqual(mp.winning_strategy_name, str(axl.Defector()))

    @given(strategies=strategy_lists(min_size=2, max_size=4))
    @settings(max_examples=5, deadline=None)
    # Two specific examples relating to cloning of strategies
    @example(strategies=[axl.BackStabber, axl.MindReader])
    @example(strategies=[axl.ThueMorse, axl.MindReader])
    def test_property_players(self, strategies):
        """Hypothesis test that randomly checks players"""
        players = [s() for s in strategies]
        mp = axl.MoranProcess(players)
        populations = mp.play()
        self.assertEqual(populations, mp.populations)
        self.assertIn(mp.winning_strategy_name, [str(p) for p in players])

    def test_reset(self):
        p1, p2 = axl.Cooperator(), axl.Defector()
        mp = MoranProcess((p1, p2), seed=45)
        mp.play()
        self.assertEqual(len(mp), 2)
        self.assertEqual(len(mp.score_history), 1)
        mp.reset()
        self.assertEqual(len(mp), 1)
        self.assertEqual(mp.winning_strategy_name, None)
        self.assertEqual(mp.score_history, [])
        # Check that players reset
        for player, initial_player in zip(mp.players, mp.initial_players):
            self.assertEqual(str(player), str(initial_player))

    def test_constant_fitness_case(self):
        # Scores between an Alternator and Defector will be: (1,  6)
        players = (
            axl.Alternator(),
            axl.Alternator(),
            axl.Defector(),
            axl.Defector(),
        )
        mp = MoranProcess(players, turns=2, seed=0)
        winners = []
        for _ in range(100):
            mp.play()
            winners.append(mp.winning_strategy_name)
            mp.reset()
        winners = Counter(winners)
        self.assertEqual(winners["Defector"], 86)

    def test_cache(self):
        p1, p2 = axl.Cooperator(), axl.Defector()
        mp = axl.MoranProcess((p1, p2))
        mp.play()
        self.assertEqual(len(mp.deterministic_cache), 1)

        # Check that can pass a pre-built cache
        cache = axl.DeterministicCache()
        mp = axl.MoranProcess((p1, p2), deterministic_cache=cache)
        self.assertEqual(cache, mp.deterministic_cache)

    def test_iter(self):
        p1, p2 = axl.Cooperator(), axl.Defector()
        mp = axl.MoranProcess((p1, p2))
        self.assertEqual(mp.__iter__(), mp)

    def test_population_plot(self):
        # Test that can plot on a given matplotlib axes
        rng = axl.RandomGenerator(seed=15)
        players = [rng.choice(axl.demo_strategies)() for _ in range(5)]
        mp = axl.MoranProcess(players=players, turns=30, seed=20)
        mp.play()
        fig, axarr = plt.subplots(2, 2)
        ax = axarr[1, 0]
        mp.populations_plot(ax=ax)
        self.assertEqual(ax.get_xlim(), (-0.7000000000000001, 14.7))
        self.assertEqual(ax.get_ylim(), (0, 5.25))
        # Run without a given axis
        ax = mp.populations_plot()
        self.assertEqual(ax.get_xlim(), (-0.7000000000000001, 14.7))
        self.assertEqual(ax.get_ylim(), (0, 5.25))

    def test_cooperator_can_win_with_fitness_transformation(self):
        players = (
            axl.Cooperator(),
            axl.Defector(),
            axl.Defector(),
            axl.Defector(),
        )
        w = 0.95
        fitness_transformation = lambda score: 1 - w + w * score
        mp = MoranProcess(players,
                          turns=10,
                          fitness_transformation=fitness_transformation,
                          seed=3419)
        populations = mp.play()
        self.assertEqual(mp.winning_strategy_name, "Cooperator")

    def test_atomic_mutation_fsm(self):
        players = [
            axl.EvolvableFSMPlayer(num_states=2,
                                   initial_state=1,
                                   initial_action=C,
                                   seed=4) for _ in range(5)
        ]
        mp = MoranProcess(players, turns=10, mutation_method="atomic", seed=12)
        rounds = 10
        for _ in range(rounds):
            next(mp)
        self.assertEqual(
            list(sorted(mp.populations[-1].items()))[0][0],
            'EvolvableFSMPlayer: ((0, C, 0, C), (0, D, 1, C), (1, C, 1, D), (1, D, 1, D)), 0, D, 2, 0.1, 2240802643'
        )
        self.assertEqual(len(mp.populations), 11)
        self.assertFalse(mp.fixated)

    def test_atomic_mutation_cycler(self):
        cycle_length = 5
        players = [
            axl.EvolvableCycler(cycle_length=cycle_length, seed=4)
            for _ in range(5)
        ]
        mp = MoranProcess(players, turns=10, mutation_method="atomic", seed=10)
        rounds = 10
        for _ in range(rounds):
            next(mp)
        self.assertEqual(
            list(mp.populations[-1].items())[0],
            ('EvolvableCycler: CCDDD, 5, 0.2, 1, 1164244177', 1))
        self.assertEqual(len(mp.populations), 11)
        self.assertFalse(mp.fixated)

    def test_mutation_method_exceptions(self):
        cycle_length = 5
        players = [
            axl.EvolvableCycler(cycle_length=cycle_length, seed=4)
            for _ in range(5)
        ]
        with self.assertRaises(ValueError):
            MoranProcess(players, turns=10, mutation_method="random", seed=10)

        players = [
            axl.Cycler(cycle="CD" * random.randint(2, 10)) for _ in range(10)
        ]
        mp = MoranProcess(players, turns=10, mutation_method="atomic", seed=53)
        with self.assertRaises(TypeError):
            for _ in range(10):
                next(mp)