Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
1 change: 1 addition & 0 deletions axelrod/strategies/_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@
ZDGen2,
ZDMischief,
ZDSet2,
AdaptiveZeroDet,
)

# Note: Meta* strategies are handled in .__init__.py
Expand Down
79 changes: 79 additions & 0 deletions axelrod/strategies/zero_determinant.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import random
from axelrod.action import Action
from axelrod.player import Player

from .memoryone import MemoryOnePlayer

Expand Down Expand Up @@ -225,3 +227,80 @@ class ZDSet2(LRPlayer):

def __init__(self, phi: float = 1 / 4, s: float = 0.0, l: float = 2) -> None:
super().__init__(phi, s, l)


class AdaptiveZeroDet(LRPlayer):
name = 'AdaptiveZeroDet'
classifier = {
'memory_depth': float('inf'), # Long memory
'stochastic': True,
'makes_use_of': set(["game"]),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def __init__(self, phi: float = 0.125, s: float = 0.5, l: float = 3,
initial: Action = C) -> None:
# This Keeps track of the parameter values (phi,s,l) as well as the
# four vector which makes final decisions.
super().__init__(phi=phi, s=s, l=l)
self._scores = {C: 0, D: 0}
self._initial = initial

def score_last_round(self, opponent: Player):
"""This gives the strategy the game attributes and allows the strategy
to score itself properly."""
game = self.match_attributes["game"]
if len(self.history):
last_round = (self.history[-1], opponent.history[-1])
scores = game.score(last_round)
self._scores[last_round[0]] += scores[0]

def _adjust_parameters(self):
d = random.randint(0, 9) / 1000 # Selects random value to adjust s and l

if self._scores[C] > self._scores[D]:
# This checks scores to determine how to adjust s and l either
# up or down by d
self.l = self.l + d
self.s = self.s - d
R, P, S, T = self.match_attributes["game"].RPST()
l = self.l
s = self.s
s_min = - min((T - l) / (l - S), (l - S) / (T - l)) # Sets minimum for s
if (l > R) or (s < s_min):
# This checks that neither s nor l is leaving its range
# If l would leave its range instead its distance from its max is halved
if l > R:
l = l - d
self.l = (l + R) / 2
# If s would leave its range instead its distance from its min is halved
if s < s_min:
s = s + d
self.s = (s + s_min) / 2
else:
# This adjusts s and l in the opposite direction
self.l = self.l - d
self.s = self.s + d
R, P, S, T = self.match_attributes["game"].RPST()
l = self.l
s = self.s
if (l < P) or (s > 1):
# This checks that neither s nor l is leaving its range
if l < P:
l = l + d
self.l = (l + P) / 2
# If l would leave its range instead its distance from its min is halved
if s > 1:
s = s - d
self.s = (s + 1) / 2
# Update the four vector for the new l and s values
self.receive_match_attributes()

def strategy(self, opponent: Player) -> Action:
if len(self.history) > 0:
self.score_last_round(opponent)
self._adjust_parameters()
return super().strategy(opponent)
24 changes: 24 additions & 0 deletions axelrod/tests/strategies/test_zero_determinant.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,27 @@ def test_strategy(self):

actions = [(C, D), (D, C), (D, D), (D, C), (D, D), (D, C)]
self.versus_test(opponent=axelrod.CyclerDC(), expected_actions=actions, seed=5)


class TestAdaptiveZeroDet(TestPlayer):
"""
Tests for the N Tit(s) For M Tat(s) strategy
"""

name = "AdaptiveZeroDet: 0.125, 0.5, 3, C"
player = axelrod.AdaptiveZeroDet
expected_classifier = {
"memory_depth": float('inf'),
"stochastic": True,
"makes_use_of": set(['game']),
"long_run_time": False,
"inspects_source": False,
"manipulates_source": False,
"manipulates_state": False,
}

Copy link
Member

Choose a reason for hiding this comment

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

Could we add few tests for the two specific methods: _adjust_parameters and score_last_round (just running the methods and checking that the attributes have changed accordingly?

def test_strategy(self):
actions = [(C, C), (C, D), (C, C), (C, D), (C, C)]
self.versus_test(
axelrod.Alternator(), expected_actions=actions
)
2 changes: 2 additions & 0 deletions docs/reference/all_strategies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Here are the docstrings of all the strategies in the library.

.. automodule:: axelrod.strategies.adaptive
:members:
.. automodule:: axelrod.strategies.adaptivezerodet
:members:
.. automodule:: axelrod.strategies.adaptor
:members:
.. automodule:: axelrod.strategies.alternator
Expand Down