|
4 | 4 | import unittest
|
5 | 5 |
|
6 | 6 | import numpy as np
|
| 7 | +from hypothesis import given, settings |
| 8 | +from hypothesis.strategies import integers |
7 | 9 |
|
8 | 10 | import axelrod
|
9 | 11 | from axelrod import DefaultGame, Player
|
10 | 12 | from axelrod.player import get_state_distribution_from_history, update_history
|
| 13 | +from axelrod.tests.property import strategy_lists |
11 | 14 |
|
12 | 15 |
|
13 | 16 | C, D = axelrod.Action.C, axelrod.Action.D
|
14 | 17 |
|
| 18 | +short_run_time_short_mem = [s for s in axelrod.short_run_time_strategies |
| 19 | + if s().classifier["memory_depth"] <= 1] |
| 20 | + |
15 | 21 |
|
16 | 22 | # Generic strategy functions for testing
|
17 | 23 |
|
@@ -446,6 +452,27 @@ def test_clone(self):
|
446 | 452 | self.assertEqual(len(player1.history), turns)
|
447 | 453 | self.assertEqual(player1.history, player2.history)
|
448 | 454 |
|
| 455 | + @given(strategies=strategy_lists(max_size=5, |
| 456 | + strategies=short_run_time_short_mem), |
| 457 | + seed=integers(min_value=1, max_value=200), |
| 458 | + turns=integers(min_value=1, max_value=200)) |
| 459 | + @settings(max_examples=1, max_iterations=1) |
| 460 | + def test_memory_depth_upper_bound(self, strategies, seed, turns): |
| 461 | + """ |
| 462 | + Test that the memory depth is indeed an upper bound. |
| 463 | + """ |
| 464 | + player = self.player() |
| 465 | + memory = player.classifier["memory_depth"] |
| 466 | + if memory < float("inf"): |
| 467 | + for strategy in strategies: |
| 468 | + opponent = strategy() |
| 469 | + self.assertTrue(test_memory(player=player, |
| 470 | + opponent=opponent, |
| 471 | + seed=seed, |
| 472 | + turns=turns, |
| 473 | + memory_length=memory), |
| 474 | + msg="Failed for seed={} and opponent={}".format(seed, opponent)) |
| 475 | + |
449 | 476 | def versus_test(self, opponent, expected_actions,
|
450 | 477 | noise=None, seed=None, turns=10,
|
451 | 478 | match_attributes=None, attrs=None,
|
@@ -564,3 +591,50 @@ def test_four_vector(test_class, expected_dictionary):
|
564 | 591 | for key in sorted(expected_dictionary.keys(), key=str):
|
565 | 592 | test_class.assertAlmostEqual(
|
566 | 593 | player1._four_vector[key], expected_dictionary[key])
|
| 594 | + |
| 595 | + |
| 596 | +def test_memory(player, opponent, memory_length, seed=None, turns=10): |
| 597 | + """ |
| 598 | + Checks if a player reacts to the plays of an opponent in the same way if |
| 599 | + only the given amount of memory is used. |
| 600 | + """ |
| 601 | + if seed is not None: |
| 602 | + axelrod.seed(seed) |
| 603 | + |
| 604 | + match = axelrod.Match((player, opponent), turns=turns) |
| 605 | + expected_results = match.play() |
| 606 | + |
| 607 | + if seed is not None: |
| 608 | + axelrod.seed(seed) |
| 609 | + player.reset() |
| 610 | + opponent.reset() |
| 611 | + |
| 612 | + results = [] |
| 613 | + for _ in range(turns): |
| 614 | + player.history = player.history[-memory_length:] |
| 615 | + opponent.history = opponent.history[-memory_length:] |
| 616 | + player.play(opponent) |
| 617 | + results.append(player.history[-1]) |
| 618 | + return results == [interactions[0] for interactions in expected_results] |
| 619 | + |
| 620 | +class TestMemoryTest(unittest.TestCase): |
| 621 | + """ |
| 622 | + Test for the memory test function. |
| 623 | + """ |
| 624 | + def test_passes(self): |
| 625 | + """ |
| 626 | + The memory test function returns True in this case as the correct mem |
| 627 | + length is used |
| 628 | + """ |
| 629 | + player = axelrod.TitFor2Tats() |
| 630 | + opponent = axelrod.Defector() |
| 631 | + self.assertTrue(test_memory(player, opponent, memory_length=2)) |
| 632 | + |
| 633 | + def test_failures(self): |
| 634 | + """ |
| 635 | + The memory test function returns False in this case as the incorrect mem |
| 636 | + length is used |
| 637 | + """ |
| 638 | + player = axelrod.TitFor2Tats() |
| 639 | + opponent = axelrod.Defector() |
| 640 | + self.assertFalse(test_memory(player, opponent, memory_length=1)) |
0 commit comments