Skip to content

Commit 5f527fb

Browse files
authored
Merge pull request #1157 from Axelrod-Python/add-test-for-memory-depth
Add test for memory depth
2 parents aca6ffd + e0871b0 commit 5f527fb

File tree

11 files changed

+101
-25
lines changed

11 files changed

+101
-25
lines changed

axelrod/strategies/axelrod_first.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ class SteinAndRapoport(Player):
529529

530530
name = 'Stein and Rapoport'
531531
classifier = {
532-
'memory_depth': 15,
532+
'memory_depth': float("inf"),
533533
'stochastic': False,
534534
'makes_use_of': {"length"},
535535
'long_run_time': False,

axelrod/strategies/geller.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class Geller(Player):
4040

4141
name = 'Geller'
4242
classifier = {
43-
'memory_depth': -1,
43+
'memory_depth': float("inf"),
4444
'stochastic': True,
4545
'makes_use_of': set(),
4646
'long_run_time': False,
@@ -74,7 +74,7 @@ class GellerCooperator(Geller):
7474
"""
7575
name = 'Geller Cooperator'
7676
classifier = {
77-
'memory_depth': -1,
77+
'memory_depth': float("inf"),
7878
'stochastic': False,
7979
'makes_use_of': set(),
8080
'long_run_time': False,
@@ -101,7 +101,7 @@ class GellerDefector(Geller):
101101
"""
102102
name = 'Geller Defector'
103103
classifier = {
104-
'memory_depth': -1,
104+
'memory_depth': float("inf"),
105105
'stochastic': False,
106106
'makes_use_of': set(),
107107
'long_run_time': False,

axelrod/strategies/mindreader.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class MindReader(Player):
2222

2323
name = 'Mind Reader'
2424
classifier = {
25-
'memory_depth': -10,
25+
'memory_depth': float("inf"),
2626
'stochastic': False,
2727
'makes_use_of': set(),
2828
'long_run_time': False,
@@ -60,7 +60,7 @@ class ProtectedMindReader(MindReader):
6060

6161
name = 'Protected Mind Reader'
6262
classifier = {
63-
'memory_depth': -10,
63+
'memory_depth': float("inf"),
6464
'stochastic': False,
6565
'makes_use_of': set(),
6666
'long_run_time': False,
@@ -90,7 +90,7 @@ class MirrorMindReader(ProtectedMindReader):
9090
name = 'Mirror Mind Reader'
9191

9292
classifier = {
93-
'memory_depth': -10,
93+
'memory_depth': float("inf"),
9494
'stochastic': False,
9595
'makes_use_of': set(),
9696
'long_run_time': False,

axelrod/strategies/titfortat.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class DynamicTwoTitsForTat(Player):
114114

115115
name = 'Dynamic Two Tits For Tat'
116116
classifier = {
117-
'memory_depth': 2, # Long memory, memory-2
117+
'memory_depth': float("inf"),
118118
'stochastic': True,
119119
'makes_use_of': set(),
120120
'long_run_time': False,
@@ -127,7 +127,7 @@ class DynamicTwoTitsForTat(Player):
127127
def strategy(opponent):
128128
# First move
129129
if not opponent.history:
130-
# Make sure we cooporate first turn
130+
# Make sure we cooperate first turn
131131
return C
132132
if D in opponent.history[-2:]:
133133
# Probability of cooperating regardless
@@ -826,6 +826,7 @@ def __init__(self, p: float=0.5) -> None:
826826
"""
827827
super().__init__()
828828
self.p = p
829+
self.act_random = False
829830
if p in [0, 1]:
830831
self.classifier['stochastic'] = False
831832

@@ -834,6 +835,10 @@ def strategy(self, opponent: Player) -> Action:
834835
"""This is the actual strategy"""
835836
if not self.history:
836837
return C
837-
if len(opponent.history) % 2 == 0:
838+
839+
if self.act_random:
840+
self.act_random = False
838841
return random_choice(self.p)
842+
843+
self.act_random = True
839844
return opponent.history[-1]

axelrod/tests/strategies/test_axelrod_first.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ class TestSteinAndRapoport(TestPlayer):
370370
name = "Stein and Rapoport: 0.05: (D, D)"
371371
player = axelrod.SteinAndRapoport
372372
expected_classifier = {
373-
'memory_depth': 15,
373+
'memory_depth': float("inf"),
374374
'long_run_time': False,
375375
'stochastic': False,
376376
'makes_use_of': {'length'},
@@ -524,11 +524,11 @@ def test_strategy(self):
524524
attrs={'fresh_start': False})
525525

526526
# check the fresh start condition: least 20 rounds since the last ‘fresh start’
527-
opponent = axelrod.Cycler('CCCCD')
528-
actions = [(C, C), (C, C), (C, C), (C, C), (C, D), (D, C), (C, C),
529-
(C, C), (C, C), (C, D), (D, C), (D, C), (C, C), (C, C),
530-
(C, D), (D, C), (D, C), (D, C), (C, C), (C, D), (D, C),
531-
(D, C), (D, C), (C, C), (C, D), (D, C), (C, C), (C, C),
527+
opponent = axelrod.Cycler('CCCCD')
528+
actions = [(C, C), (C, C), (C, C), (C, C), (C, D), (D, C), (C, C),
529+
(C, C), (C, C), (C, D), (D, C), (D, C), (C, C), (C, C),
530+
(C, D), (D, C), (D, C), (D, C), (C, C), (C, D), (D, C),
531+
(D, C), (D, C), (C, C), (C, D), (D, C), (C, C), (C, C),
532532
(C, C), (C, D), (D, C), (D, C), (C, C), (C, C), (C, D)]
533533
self.versus_test(opponent, expected_actions=actions,
534534
match_attributes={'length': 35},

axelrod/tests/strategies/test_geller.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class TestGeller(TestPlayer):
1111
name = "Geller"
1212
player = axelrod.Geller
1313
expected_classifier = {
14-
'memory_depth': -1,
14+
'memory_depth': float("inf"),
1515
'stochastic': True,
1616
'makes_use_of': set(),
1717
'long_run_time': False,
@@ -59,7 +59,7 @@ class TestGellerCooperator(TestGeller):
5959
name = "Geller Cooperator"
6060
player = axelrod.GellerCooperator
6161
expected_classifier = {
62-
'memory_depth': -1,
62+
'memory_depth': float("inf"),
6363
'stochastic': False,
6464
'makes_use_of': set(),
6565
'long_run_time': False,
@@ -85,7 +85,7 @@ class TestGellerDefector(TestGeller):
8585
name = "Geller Defector"
8686
player = axelrod.GellerDefector
8787
expected_classifier = {
88-
'memory_depth': -1,
88+
'memory_depth': float("inf"),
8989
'stochastic': False,
9090
'makes_use_of': set(),
9191
'long_run_time': False,

axelrod/tests/strategies/test_meta.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ class TestNMWELongMemory(TestMetaPlayer):
563563
}
564564

565565
def test_strategy(self):
566-
actions = [(C, C), (C, D), (D, C), (C, D), (D, C)]
566+
actions = [(C, C), (C, D), (D, C), (D, D), (D, C)]
567567
self.versus_test(opponent=axelrod.Alternator(),
568568
expected_actions=actions)
569569

axelrod/tests/strategies/test_mindreader.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class TestMindReader(TestPlayer):
1313
name = "Mind Reader"
1414
player = axelrod.MindReader
1515
expected_classifier = {
16-
'memory_depth': -10,
16+
'memory_depth': float("inf"),
1717
'stochastic': False,
1818
'makes_use_of': set(),
1919
'long_run_time': False,
@@ -104,7 +104,7 @@ class TestProtectedMindReader(TestPlayer):
104104
name = "Protected Mind Reader"
105105
player = axelrod.ProtectedMindReader
106106
expected_classifier = {
107-
'memory_depth': -10,
107+
'memory_depth': float("inf"),
108108
'stochastic': False,
109109
'makes_use_of': set(),
110110
'long_run_time': False,
@@ -148,7 +148,7 @@ class TestMirrorMindReader(TestPlayer):
148148
name = 'Mirror Mind Reader'
149149
player = axelrod.MirrorMindReader
150150
expected_classifier = {
151-
'memory_depth': -10,
151+
'memory_depth': float("inf"),
152152
'stochastic': False,
153153
'makes_use_of': set(),
154154
'long_run_time': False,

axelrod/tests/strategies/test_player.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@
44
import unittest
55

66
import numpy as np
7+
from hypothesis import given, settings
8+
from hypothesis.strategies import integers
79

810
import axelrod
911
from axelrod import DefaultGame, Player
1012
from axelrod.player import get_state_distribution_from_history, update_history
13+
from axelrod.tests.property import strategy_lists
1114

1215

1316
C, D = axelrod.Action.C, axelrod.Action.D
1417

18+
short_run_time_short_mem = [s for s in axelrod.short_run_time_strategies
19+
if s().classifier["memory_depth"] <= 1]
20+
1521

1622
# Generic strategy functions for testing
1723

@@ -446,6 +452,27 @@ def test_clone(self):
446452
self.assertEqual(len(player1.history), turns)
447453
self.assertEqual(player1.history, player2.history)
448454

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+
449476
def versus_test(self, opponent, expected_actions,
450477
noise=None, seed=None, turns=10,
451478
match_attributes=None, attrs=None,
@@ -564,3 +591,47 @@ def test_four_vector(test_class, expected_dictionary):
564591
for key in sorted(expected_dictionary.keys(), key=str):
565592
test_class.assertAlmostEqual(
566593
player1._four_vector[key], expected_dictionary[key])
594+
595+
596+
def test_memory(player, opponent, memory_length, seed=0, 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+
axelrod.seed(seed)
602+
match = axelrod.Match((player, opponent), turns=turns)
603+
expected_results = [turn[0] for turn in match.play()]
604+
605+
axelrod.seed(seed)
606+
player.reset()
607+
opponent.reset()
608+
609+
results = []
610+
for _ in range(turns):
611+
player.history = player.history[-memory_length:]
612+
opponent.history = opponent.history[-memory_length:]
613+
player.play(opponent)
614+
results.append(player.history[-1])
615+
return results == expected_results
616+
617+
class TestMemoryTest(unittest.TestCase):
618+
"""
619+
Test for the memory test function.
620+
"""
621+
def test_passes(self):
622+
"""
623+
The memory test function returns True in this case as the correct mem
624+
length is used
625+
"""
626+
player = axelrod.TitFor2Tats()
627+
opponent = axelrod.Defector()
628+
self.assertTrue(test_memory(player, opponent, memory_length=2))
629+
630+
def test_failures(self):
631+
"""
632+
The memory test function returns False in this case as the incorrect mem
633+
length is used
634+
"""
635+
player = axelrod.TitFor2Tats()
636+
opponent = axelrod.Defector()
637+
self.assertFalse(test_memory(player, opponent, memory_length=1))

axelrod/tests/strategies/test_titfortat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class TestDynamicTwoTitsForTat(TestPlayer):
124124
name = 'Dynamic Two Tits For Tat'
125125
player = axelrod.DynamicTwoTitsForTat
126126
expected_classifier = {
127-
'memory_depth': 2,
127+
'memory_depth': float("inf"),
128128
'stochastic': True,
129129
'makes_use_of': set(),
130130
'inspects_source': False,

0 commit comments

Comments
 (0)