Skip to content

Commit b72e03c

Browse files
Merge pull request #1 from Axelrod-Python/MariosZoulias-SteinRap-vk
Correct strategy and add relevant tests.
2 parents dc0fb13 + 9c03615 commit b72e03c

File tree

5 files changed

+86
-43
lines changed

5 files changed

+86
-43
lines changed

appveyor.yml

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
environment:
22
matrix:
3-
- PYTHON: "C:\\Python35"
4-
- PYTHON: "C:\\Python36"
3+
- PYTHON_VERSION: "3.5"
4+
MINICONDA: "C:\\Miniconda35"
5+
- PYTHON_VERSION: "3.6"
6+
MINICONDA: "C:\\Miniconda36"
57
install:
6-
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
8+
- "set PATH=%MINICONDA%;%MINICONDA%\\Scripts;%PATH%"
9+
- "conda config --set always_yes yes --set changeps1 no"
10+
- "conda update -q conda"
11+
- "conda create -q -n test-environment python=%PYTHON_VERSION% scipy>=0.19.0 numpy>=1.9.2"
12+
- "activate test-environment"
13+
- "python -m pip install -r requirements.txt"
714
build: off
815
test_script:
9-
- "%PYTHON%\\python.exe -m unittest discover"
10-
- "%PYTHON%\\python.exe doctests.py"
11-
- "%PYTHON%\\python.exe setup.py install"
16+
- "python -m unittest discover"
17+
- "python doctests.py"
18+
- "python setup.py install"

axelrod/player.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ def clone(self):
241241
return new_player
242242

243243
def reset(self):
244-
"""Resets history.
244+
"""
245+
Resets history.
245246
When creating strategies that create new attributes then this method
246247
should be re-written (in the inherited class) and should not only reset
247248
history but also rest all other attributes.

axelrod/strategies/axelrod_first.py

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -494,22 +494,23 @@ def strategy(opponent: Player) -> Action:
494494
class SteinAndRapoport(Player):
495495
"""
496496
A player who plays according to statistic methods.
497-
Begins by playing C for the first four (4) rounds , then it plays
497+
Begins by playing C for the first four (4) rounds, then it plays
498498
tit for tat and at the last 2 round it Defects. Every 15 turns it
499-
run a chi-squared test to check whether the opponent behaves randomly
500-
or not . In case the opponent behaves randomly then Stein_and_Rapoport
501-
Defects untill the next 15 round (where we check again), otherwise he
499+
runs a chi-squared test to check whether the opponent behaves randomly
500+
or not. In case the opponent behaves randomly then Stein and Rapoport
501+
Defects until the next 15 round (where we check again), otherwise it
502502
still plays TitForTat.0
503503
504504
Names:
505+
505506
- SteinAndRapoport [Axelrod1980]_
506507
"""
507508

508509
name = 'Stein and Rapoport'
509510
classifier = {
510511
'memory_depth': 15,
511512
'stochastic': False,
512-
'makes_use_of': set(),
513+
'makes_use_of': {"length"},
513514
'long_run_time': False,
514515
'inspects_source': False,
515516
'manipulates_source': False,
@@ -526,34 +527,29 @@ def __init__(self, alpha: float=0.05) -> None:
526527
"""
527528
super().__init__()
528529
self.alpha = alpha
529-
if (self.alpha > 1) or (self.alpha < 0):
530-
self.alpha = 0.05
530+
self.opponent_is_random = None
531531

532-
def strategy(self , opponent: Player , chi_tests = [0]) -> Action:
532+
def strategy(self , opponent: Player) -> Action:
533533
round_number = len(self.history) + 1
534534

535535
# First 4 moves
536536
if round_number < 5:
537537
return C
538+
# For first 15 rounds tit for tat as we do not know opponents strategy
539+
elif round_number < 15:
540+
return opponent.history[-1]
538541

539-
# For first 15 rounds tit for tat as we dont know opponents strategy
540-
if round_number < 16:
541-
if opponent.history[-1] == 'D':
542-
return D
543-
else :
544-
return C
545-
546-
if len(self.history) % 15 == 0:
547-
if chisquare([opponent.cooperations, opponent.defections]).pvalue >= self.alpha:
548-
chi_tests.append(1)
549-
else:
550-
chi_tests.append(0)
542+
if round_number % 15 == 0:
543+
p_value = chisquare([opponent.cooperations,
544+
opponent.defections]).pvalue
545+
self.opponent_is_random = p_value >= self.alpha
551546

552-
if chi_tests[-1] == 1:
547+
if self.opponent_is_random:
553548
# Defect if opponent plays randomly
554549
return D
555-
else : # TitForTatat if opponent plays not randomly
556-
if opponent.history[-1] == 'D':
557-
return D
558-
else:
559-
return C
550+
else: # TitForTatat if opponent plays not randomly
551+
return opponent.history[-1]
552+
553+
def reset(self):
554+
super().reset()
555+
self.random_opponent = None

axelrod/tests/strategies/test_axelrod_first.py

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -391,37 +391,76 @@ def test_strategy(self):
391391

392392
class SteinAndRapoport(TestPlayer):
393393

394-
name = "SteinAndRapoport"
394+
name = "Stein and Rapoport: 0.05: ('D', 'D')"
395395
player = axelrod.SteinAndRapoport
396396
expected_classifier = {
397397
'memory_depth': 15,
398398
'long_run_time': False,
399399
'stochastic': False,
400-
'makes_use_of': set(),
400+
'makes_use_of': {'length'},
401401
'inspects_source': False,
402402
'manipulates_source': False,
403403
'manipulates_state': False
404404
}
405405

406+
def test_init(self):
407+
player = self.player()
408+
self.assertEqual(player.alpha, 0.05)
409+
self.assertIsNone(player.opponent_is_random)
410+
411+
player = self.player(alpha=.5)
412+
self.assertEqual(player.alpha, 0.5)
413+
self.assertIsNone(player.opponent_is_random)
414+
406415
def test_strategy(self):
407416
self.first_play_test(C)
408417

409418
# Our Player (SteinAndRapoport) vs Cooperator
410419
# After 15th round (pvalue < alpha) still plays titfortat
420+
# Note it always defects on the last two rounds
411421
opponent = axelrod.Cooperator()
412422
actions = [(C, C)] * 17 + [(D, C)] * 2
413-
self.versus_test(opponent, expected_actions=actions)
423+
self.versus_test(opponent, expected_actions=actions,
424+
attrs={"opponent_is_random": False})
425+
426+
actions = actions[:-2] + [(C, C)] * 2
427+
self.versus_test(opponent, expected_actions=actions[:-2],
428+
match_attributes={"length": -1},
429+
attrs={"opponent_is_random": False})
414430

415431
# Our Player (SteinAndRapoport) vs Defector
416432
# After 15th round (pvalue < alpha) still plays titfortat
417-
opponent = axelrod.Cooperator()
433+
opponent = axelrod.Defector()
418434
actions = [(C, D)] * 4 + [(D, D)] * 15
419-
self.versus_test(opponent, expected_actions=actions)
435+
self.versus_test(opponent, expected_actions=actions,
436+
attrs={"opponent_is_random": False})
420437

421438
# Our Player (SteinAndRapoport) vs Alternator
422439
# After 15th round (pvalue > alpha) starts defect
423440
opponent = axelrod.Alternator()
424-
actions = [(C, C), (C, D), (C, C), (C, D), (D, C), (C, D), (D, C),
425-
(C, D), (D, C), (C, D), (D, C), (C, D),(D, C), (C, D),
426-
(D, C), (D, D), (D, C), (D, D), (D, C)]
427-
self.versus_test(opponent, expected_actions=actions)
441+
actions = [(C, C), (C, D), (C, C), (C, D)]
442+
443+
# On 15th round carry out chisquare test
444+
actions += [(D, C), (C, D)] * 5 + [(D, C)]
445+
446+
# Defect throughout
447+
actions += [(D, D), (D, C), (D, D), (D, C)]
448+
449+
self.versus_test(opponent, expected_actions=actions,
450+
attrs={"opponent_is_random": True})
451+
452+
# The test is carried out again every 15 rounds.
453+
# If the strategy alternates for the first 12 rounds and then cooperates
454+
# it is no longer recognised as random
455+
opponent = axelrod.MockPlayer([C, D] * 6 + [C] * 50)
456+
457+
actions = [(C, C), (C, D), (C, C), (C, D)]
458+
# On 15th round carry out chisquare test
459+
actions += [(D, C), (C, D)] * 4 + [(D, C), (C, C), (D, C)]
460+
# Defect throughout and carry out chisquare test on round 30
461+
# Opponent is no longer recognised as random, revert to TfT
462+
actions += [(D, C)] * 14 + [(C, C)]
463+
self.versus_test(opponent, expected_actions=actions,
464+
match_attributes={"length": -1},
465+
attrs={"opponent_is_random": False})
466+

docs/tutorials/advanced/classification_of_strategies.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ length of each match of the tournament::
8080
... }
8181
>>> strategies = axl.filtered_strategies(filterset)
8282
>>> len(strategies)
83-
26
83+
27
8484

8585
Note that in the filterset dictionary, the value for the 'makes_use_of' key
8686
must be a list. Here is how we might identify the number of strategies that use

0 commit comments

Comments
 (0)