Skip to content

Add test for memory depth #1157

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion axelrod/strategies/axelrod_first.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ class SteinAndRapoport(Player):

name = 'Stein and Rapoport'
classifier = {
'memory_depth': 15,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': {"length"},
'long_run_time': False,
Expand Down
6 changes: 3 additions & 3 deletions axelrod/strategies/geller.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Geller(Player):

name = 'Geller'
classifier = {
'memory_depth': -1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: This one I think we did because "it looks into the future" (not suggesting we change it back necessarily).

'memory_depth': float("inf"),
'stochastic': True,
'makes_use_of': set(),
'long_run_time': False,
Expand Down Expand Up @@ -74,7 +74,7 @@ class GellerCooperator(Geller):
"""
name = 'Geller Cooperator'
classifier = {
'memory_depth': -1,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand All @@ -101,7 +101,7 @@ class GellerDefector(Geller):
"""
name = 'Geller Defector'
classifier = {
'memory_depth': -1,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand Down
6 changes: 3 additions & 3 deletions axelrod/strategies/mindreader.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MindReader(Player):

name = 'Mind Reader'
classifier = {
'memory_depth': -10,
Copy link
Member

@marcharper marcharper Jan 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same. I think for these cheating strategies we don't care so much...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I thought it was probably due to the "looking in to the future" but taking the notion of infinity to mean "backwards and forwards" I think we're good :) (I agree that we don't care too much :)).

'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand Down Expand Up @@ -60,7 +60,7 @@ class ProtectedMindReader(MindReader):

name = 'Protected Mind Reader'
classifier = {
'memory_depth': -10,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand Down Expand Up @@ -90,7 +90,7 @@ class MirrorMindReader(ProtectedMindReader):
name = 'Mirror Mind Reader'

classifier = {
'memory_depth': -10,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand Down
11 changes: 8 additions & 3 deletions axelrod/strategies/titfortat.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class DynamicTwoTitsForTat(Player):

name = 'Dynamic Two Tits For Tat'
classifier = {
'memory_depth': 2, # Long memory, memory-2
'memory_depth': float("inf"),
'stochastic': True,
'makes_use_of': set(),
'long_run_time': False,
Expand All @@ -127,7 +127,7 @@ class DynamicTwoTitsForTat(Player):
def strategy(opponent):
# First move
if not opponent.history:
# Make sure we cooporate first turn
# Make sure we cooperate first turn
return C
if D in opponent.history[-2:]:
# Probability of cooperating regardless
Expand Down Expand Up @@ -826,6 +826,7 @@ def __init__(self, p: float=0.5) -> None:
"""
super().__init__()
self.p = p
self.act_random = False
if p in [0, 1]:
self.classifier['stochastic'] = False

Expand All @@ -834,6 +835,10 @@ def strategy(self, opponent: Player) -> Action:
"""This is the actual strategy"""
if not self.history:
return C
if len(opponent.history) % 2 == 0:

if self.act_random:
self.act_random = False
return random_choice(self.p)

self.act_random = True
return opponent.history[-1]
12 changes: 6 additions & 6 deletions axelrod/tests/strategies/test_axelrod_first.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ class TestSteinAndRapoport(TestPlayer):
name = "Stein and Rapoport: 0.05: (D, D)"
player = axelrod.SteinAndRapoport
expected_classifier = {
'memory_depth': 15,
'memory_depth': float("inf"),
'long_run_time': False,
'stochastic': False,
'makes_use_of': {'length'},
Expand Down Expand Up @@ -524,11 +524,11 @@ def test_strategy(self):
attrs={'fresh_start': False})

# check the fresh start condition: least 20 rounds since the last ‘fresh start’
opponent = axelrod.Cycler('CCCCD')
actions = [(C, C), (C, C), (C, C), (C, C), (C, D), (D, C), (C, C),
(C, C), (C, C), (C, D), (D, C), (D, C), (C, C), (C, C),
(C, D), (D, C), (D, C), (D, C), (C, C), (C, D), (D, C),
(D, C), (D, C), (C, C), (C, D), (D, C), (C, C), (C, C),
opponent = axelrod.Cycler('CCCCD')
actions = [(C, C), (C, C), (C, C), (C, C), (C, D), (D, C), (C, C),
(C, C), (C, C), (C, D), (D, C), (D, C), (C, C), (C, C),
(C, D), (D, C), (D, C), (D, C), (C, C), (C, D), (D, C),
(D, C), (D, C), (C, C), (C, D), (D, C), (C, C), (C, C),
(C, C), (C, D), (D, C), (D, C), (C, C), (C, C), (C, D)]
self.versus_test(opponent, expected_actions=actions,
match_attributes={'length': 35},
Expand Down
6 changes: 3 additions & 3 deletions axelrod/tests/strategies/test_geller.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class TestGeller(TestPlayer):
name = "Geller"
player = axelrod.Geller
expected_classifier = {
'memory_depth': -1,
'memory_depth': float("inf"),
'stochastic': True,
'makes_use_of': set(),
'long_run_time': False,
Expand Down Expand Up @@ -59,7 +59,7 @@ class TestGellerCooperator(TestGeller):
name = "Geller Cooperator"
player = axelrod.GellerCooperator
expected_classifier = {
'memory_depth': -1,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand All @@ -85,7 +85,7 @@ class TestGellerDefector(TestGeller):
name = "Geller Defector"
player = axelrod.GellerDefector
expected_classifier = {
'memory_depth': -1,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand Down
2 changes: 1 addition & 1 deletion axelrod/tests/strategies/test_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ class TestNMWELongMemory(TestMetaPlayer):
}

def test_strategy(self):
actions = [(C, C), (C, D), (D, C), (C, D), (D, C)]
actions = [(C, C), (C, D), (D, C), (D, D), (D, C)]
self.versus_test(opponent=axelrod.Alternator(),
expected_actions=actions)

Expand Down
6 changes: 3 additions & 3 deletions axelrod/tests/strategies/test_mindreader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class TestMindReader(TestPlayer):
name = "Mind Reader"
player = axelrod.MindReader
expected_classifier = {
'memory_depth': -10,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand Down Expand Up @@ -104,7 +104,7 @@ class TestProtectedMindReader(TestPlayer):
name = "Protected Mind Reader"
player = axelrod.ProtectedMindReader
expected_classifier = {
'memory_depth': -10,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand Down Expand Up @@ -148,7 +148,7 @@ class TestMirrorMindReader(TestPlayer):
name = 'Mirror Mind Reader'
player = axelrod.MirrorMindReader
expected_classifier = {
'memory_depth': -10,
'memory_depth': float("inf"),
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
Expand Down
71 changes: 71 additions & 0 deletions axelrod/tests/strategies/test_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@
import unittest

import numpy as np
from hypothesis import given, settings
from hypothesis.strategies import integers

import axelrod
from axelrod import DefaultGame, Player
from axelrod.player import get_state_distribution_from_history, update_history
from axelrod.tests.property import strategy_lists


C, D = axelrod.Action.C, axelrod.Action.D

short_run_time_short_mem = [s for s in axelrod.short_run_time_strategies
if s().classifier["memory_depth"] <= 1]


# Generic strategy functions for testing

Expand Down Expand Up @@ -446,6 +452,27 @@ def test_clone(self):
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,
Expand Down Expand Up @@ -564,3 +591,47 @@ def test_four_vector(test_class, expected_dictionary):
for key in sorted(expected_dictionary.keys(), key=str):
test_class.assertAlmostEqual(
player1._four_vector[key], expected_dictionary[key])


def test_memory(player, opponent, memory_length, seed=0, turns=10):
"""
Checks if a player reacts to the plays of an opponent in the same way if
only the given amount of memory is used.
"""
axelrod.seed(seed)
match = axelrod.Match((player, opponent), turns=turns)
expected_results = [turn[0] for turn in match.play()]

axelrod.seed(seed)
player.reset()
opponent.reset()

results = []
for _ in range(turns):
player.history = player.history[-memory_length:]
opponent.history = opponent.history[-memory_length:]
player.play(opponent)
results.append(player.history[-1])
return results == expected_results

class TestMemoryTest(unittest.TestCase):
"""
Test for the memory test function.
"""
def test_passes(self):
"""
The memory test function returns True in this case as the correct mem
length is used
"""
player = axelrod.TitFor2Tats()
opponent = axelrod.Defector()
self.assertTrue(test_memory(player, opponent, memory_length=2))

def test_failures(self):
"""
The memory test function returns False in this case as the incorrect mem
length is used
"""
player = axelrod.TitFor2Tats()
opponent = axelrod.Defector()
self.assertFalse(test_memory(player, opponent, memory_length=1))
2 changes: 1 addition & 1 deletion axelrod/tests/strategies/test_titfortat.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class TestDynamicTwoTitsForTat(TestPlayer):
name = 'Dynamic Two Tits For Tat'
player = axelrod.DynamicTwoTitsForTat
expected_classifier = {
'memory_depth': 2,
'memory_depth': float("inf"),
'stochastic': True,
'makes_use_of': set(),
'inspects_source': False,
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/advanced/classification_of_strategies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ range of memory_depth values, we can use the 'min_memory_depth' and
... }
>>> strategies = axl.filtered_strategies(filterset)
>>> len(strategies)
57
56

We can also identify strategies that make use of particular properties of the
tournament. For example, here is the number of strategies that make use of the
Expand Down