Skip to content

Commit 3bae266

Browse files
committed
Initial implementatino of Adaptor
1 parent 8dba4c0 commit 3bae266

File tree

6 files changed

+171
-2
lines changed

6 files changed

+171
-2
lines changed

axelrod/game.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def RPST(self) -> Tuple[Score, Score, Score, Score]:
3838
P = self.scores[(D, D)][0]
3939
S = self.scores[(C, D)][0]
4040
T = self.scores[(D, C)][0]
41-
return (R, P, S, T)
41+
return R, P, S, T
4242

4343
def score(self, pair: Tuple[Action, Action]) -> Tuple[Score, Score]:
4444
"""Returns the appropriate score for a decision pair.

axelrod/strategies/_strategies.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .adaptive import Adaptive
2+
from .adaptor import AdaptorBrief, AdaptorLong
23
from .alternator import Alternator
34
from .ann import EvolvedANN, EvolvedANN5, EvolvedANNNoise05
45
from .apavlov import APavlov2006, APavlov2011
@@ -230,6 +231,8 @@
230231
all_strategies = [
231232
Adaptive,
232233
AdaptiveTitForTat,
234+
AdaptorBrief,
235+
AdaptorLong,
233236
Aggravater,
234237
Alexei,
235238
ALLCorALLD,

axelrod/strategies/adaptor.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
from typing import Dict, Tuple
2+
3+
from axelrod.action import Action
4+
from axelrod.player import Player
5+
from axelrod.random_ import random_choice
6+
7+
from numpy import heaviside
8+
9+
C, D = Action.C, Action.D
10+
11+
12+
class AbstractAdaptor(Player):
13+
"""
14+
An adaptive strategy that updates an internal state based on the last
15+
round of play. Using this state the player Cooperates with a probability
16+
derived from the state.
17+
18+
Names:
19+
20+
- Adaptor: [Hauert2002]_
21+
22+
"""
23+
24+
name = "AbstractAdaptor"
25+
classifier = {
26+
"memory_depth": float("inf"), # Long memory
27+
"stochastic": True,
28+
"makes_use_of": set(),
29+
"long_run_time": False,
30+
"inspects_source": False,
31+
"manipulates_source": False,
32+
"manipulates_state": False,
33+
}
34+
35+
def __init__(self, d: Dict[Tuple[Action], float], perr: float = 0.01) -> None:
36+
super().__init__()
37+
self.perr = perr
38+
if not d:
39+
d = {(C, C): 1., # R
40+
(C, D): 1., # S
41+
(D, C): 1., # T
42+
(D, D): 1. # P
43+
}
44+
self.d = d
45+
self.s = 0.
46+
47+
def strategy(self, opponent: Player) -> Action:
48+
if self.history:
49+
# Update internal state from the last play
50+
last_round = (self.history[-1], opponent.history[-1])
51+
self.s += d[last_round]
52+
53+
# Compute probability of Cooperation
54+
p = self.perr + (1.0 - 2 * self.perr) * (
55+
heaviside(self.s + 1, 1) - heaviside(self.s - 1, 1))
56+
# Draw action
57+
action = random_choice(p)
58+
return action
59+
60+
61+
class AdaptorBrief(Player):
62+
"""
63+
An Adaptor trained on short interactions.
64+
65+
Names:
66+
67+
- AdaptorBrief: [Hauert2002]_
68+
69+
"""
70+
71+
name = "AdaptorBrief"
72+
73+
def __init__(self) -> None:
74+
d = {(C, C): 0., # R
75+
(C, D): 1.001505, # S
76+
(D, C): 0.992107, # T
77+
(D, D): 0.638734 # P
78+
}
79+
super().__init__(d=d)
80+
81+
82+
class AdaptorLong(Player):
83+
"""
84+
An Adaptor trained on long interactions.
85+
86+
Names:
87+
88+
- AdaptorLong: [Hauert2002]_
89+
90+
"""
91+
92+
name = "AdaptorLong"
93+
94+
def __init__(self) -> None:
95+
d = {(C, C): 0., # R
96+
(C, D): 1.888159, # S
97+
(D, C): 1.858883, # T
98+
(D, D): 0.995703 # P
99+
}
100+
super().__init__(d=d)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""Tests for the adaptor"""
2+
3+
import unittest
4+
5+
import axelrod
6+
from axelrod import Game
7+
8+
from .test_player import TestPlayer, test_four_vector
9+
10+
C, D = axelrod.Action.C, axelrod.Action.D
11+
12+
13+
class TestAdaptorBrief(TestPlayer):
14+
15+
name = "AdaptorBrief"
16+
player = axelrod.AdaptorBrief
17+
expected_classifier = {
18+
"memory_depth": 1,
19+
"stochastic": True,
20+
"makes_use_of": set(),
21+
"inspects_source": False,
22+
"manipulates_source": False,
23+
"manipulates_state": False,
24+
}
25+
26+
def test_strategy(self):
27+
# No error.
28+
actions = [(C, C), (C, C), (C, C), (C, C)]
29+
self.versus_test(
30+
opponent=axelrod.AdaptorBrief(), expected_actions=actions, seed=0
31+
)
32+
33+
# Error corrected.
34+
actions = [(C, C), (D, C), (C, D), (C, C)]
35+
self.versus_test(
36+
opponent=axelrod.AdaptorBrief(), expected_actions=actions, seed=1
37+
)
38+
39+
40+
class TestAdaptorLong(TestPlayer):
41+
42+
name = "AdaptorLong"
43+
player = axelrod.AdaptorLong
44+
expected_classifier = {
45+
"memory_depth": 1,
46+
"stochastic": True,
47+
"makes_use_of": set(),
48+
"inspects_source": False,
49+
"manipulates_source": False,
50+
"manipulates_state": False,
51+
}
52+
53+
def test_strategy(self):
54+
# No error.
55+
actions = [(C, C), (C, C), (C, C), (C, C)]
56+
self.versus_test(
57+
opponent=axelrod.AdaptorLong(), expected_actions=actions, seed=0
58+
)
59+
60+
# Error corrected.
61+
actions = [(C, C), (D, C), (D, D), (D, D), (C, C)]
62+
self.versus_test(
63+
opponent=axelrod.AdaptorLong(), expected_actions=actions, seed=1
64+
)

axelrod/tests/strategies/test_memoryone.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ class TestWinShiftLoseStayTestPlayer(TestPlayer):
7171
def test_strategy(self):
7272
# Check that switches if does not get best payoff.
7373
actions = [(D, C), (C, D), (C, C), (D, D), (D, C)]
74-
self.versus_test(opponent=axelrod.Alternator(), expected_actions=actions)
74+
self.versus_test(opponent=axelrod.Alternator(),
75+
expected_actions=actions)
7576

7677

7778
class TestGTFT(TestPlayer):

docs/reference/bibliography.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ documentation.
2727
.. [Berg2015] Berg, P. Van Den, & Weissing, F. J. (2015). The importance of mechanisms for the evolution of cooperation. Proceedings of the Royal Society B-Biological Sciences, 282.
2828
.. [Eckhart2015] Eckhart Arnold (2016) CoopSim v0.9.9 beta 6. https://github.com/jecki/CoopSim/
2929
.. [Frean1994] Frean, Marcus R. "The Prisoner's Dilemma without Synchrony." Proceedings: Biological Sciences, vol. 257, no. 1348, 1994, pp. 75–79. www.jstor.org/stable/50253.
30+
.. [Hauert2002] Hauert, Christoph, and Olaf Stenull. "Simple adaptive strategy wins the prisoner's dilemma." Journal of Theoretical Biology 218.3 (2002): 261-272.
3031
.. [Hilbe2013] Hilbe, C., Nowak, M.A. and Traulsen, A. (2013). Adaptive dynamics of extortion and compliance, PLoS ONE, 8(11), p. e77886. doi: 10.1371/journal.pone.0077886.
3132
.. [Hilbe2017] Hilbe, C., Martinez-Vaquero, L. A., Chatterjee K., Nowak M. A. (2017). Memory-n strategies of direct reciprocity, Proceedings of the National Academy of Sciences May 2017, 114 (18) 4715-4720; doi: 10.1073/pnas.1621239114.
3233
.. [Kuhn2017] Kuhn, Steven, "Prisoner's Dilemma", The Stanford Encyclopedia of Philosophy (Spring 2017 Edition), Edward N. Zalta (ed.), https://plato.stanford.edu/archives/spr2017/entries/prisoner-dilemma/

0 commit comments

Comments
 (0)