Skip to content

Commit 1d34818

Browse files
Merge pull request #1036 from Axelrod-Python/tfx
Add strategies TF1, TF2, and TF3
2 parents 97f78e3 + 997f246 commit 1d34818

File tree

4 files changed

+213
-73
lines changed

4 files changed

+213
-73
lines changed

axelrod/strategies/_strategies.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from .finite_state_machines import (
2323
Fortress3, Fortress4, Predator, Pun1, Raider, Ripoff, SolutionB1,
2424
SolutionB5, Thumper, FSMPlayer, EvolvedFSM4, EvolvedFSM16,
25-
EvolvedFSM16Noise05)
25+
EvolvedFSM16Noise05, TF1, TF2, TF3)
2626
from .forgiver import Forgiver, ForgivingTitForTat
2727
from .geller import Geller, GellerCooperator, GellerDefector
2828
from .gambler import (
@@ -238,6 +238,9 @@
238238
StochasticWSLS,
239239
SuspiciousTitForTat,
240240
Tester,
241+
TF1,
242+
TF2,
243+
TF3,
241244
ThueMorse,
242245
ThueMorseInverse,
243246
Thumper,

axelrod/strategies/finite_state_machines.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,3 +571,128 @@ def __init__(self) -> None:
571571
)
572572

573573
super().__init__(transitions=transitions, initial_state=0, initial_action=C)
574+
575+
576+
## Strategies trained with Moran process objectives
577+
578+
579+
class TF1(FSMPlayer):
580+
"""
581+
A FSM player trained to maximize Moran fixation probabilities.
582+
583+
Names:
584+
585+
- TF1: Original name by Marc Harper
586+
"""
587+
588+
name = "TF1"
589+
classifier = {
590+
'memory_depth': float('inf'),
591+
'stochastic': False,
592+
'makes_use_of': set(),
593+
'long_run_time': False,
594+
'inspects_source': False,
595+
'manipulates_source': False,
596+
'manipulates_state': False
597+
}
598+
599+
def __init__(self) -> None:
600+
transitions = (
601+
(0, C, 7, C), (0, D, 1, C),
602+
(1, C, 11, D), (1, D, 11, D),
603+
(2, C, 8, D), (2, D, 8, C),
604+
(3, C, 3, C), (3, D, 12, D),
605+
(4, C, 6, C), (4, D, 3, C),
606+
(5, C, 11, C), (5, D, 8, D),
607+
(6, C, 13, D), (6, D, 14, C),
608+
(7, C, 4, D), (7, D, 2, D),
609+
(8, C, 14, D), (8, D, 8, D),
610+
(9, C, 0, C), (9, D, 10, D),
611+
(10, C, 8, C), (10, D, 15, C),
612+
(11, C, 6, D), (11, D, 5, D),
613+
(12, C, 6, D), (12, D, 9, D),
614+
(13, C, 9, D), (13, D, 8, D),
615+
(14, C, 8, D), (14, D, 13, D),
616+
(15, C, 4, C), (15, D, 5, C)
617+
)
618+
619+
super().__init__(transitions=transitions, initial_state=0,
620+
initial_action=C)
621+
622+
623+
class TF2(FSMPlayer):
624+
"""
625+
A FSM player trained to maximize Moran fixation probabilities.
626+
627+
Names:
628+
629+
- TF2: Original name by Marc Harper
630+
"""
631+
632+
name = "TF2"
633+
classifier = {
634+
'memory_depth': float('inf'),
635+
'stochastic': False,
636+
'makes_use_of': set(),
637+
'long_run_time': False,
638+
'inspects_source': False,
639+
'manipulates_source': False,
640+
'manipulates_state': False
641+
}
642+
643+
def __init__(self) -> None:
644+
transitions = (
645+
(0, C, 13, D), (0, D, 12, D),
646+
(1, C, 3, D), (1, D, 4, D),
647+
(2, C, 14, D), (2, D, 9, D),
648+
(3, C, 0, C), (3, D, 1, D),
649+
(4, C, 1, D), (4, D, 2, D),
650+
(7, C, 12, D), (7, D, 2, D),
651+
(8, C, 7, D), (8, D, 9, D),
652+
(9, C, 8, D), (9, D, 0, D),
653+
(10, C, 2, C), (10, D, 15, C),
654+
(11, C, 7, D), (11, D, 13, D),
655+
(12, C, 3, C), (12, D, 8, D),
656+
(13, C, 7, C), (13, D, 10, D),
657+
(14, C, 10, D), (14, D, 7, D),
658+
(15, C, 15, C), (15, D, 11, D)
659+
)
660+
661+
super().__init__(transitions=transitions, initial_state=0,
662+
initial_action=C)
663+
664+
665+
class TF3(FSMPlayer):
666+
"""
667+
A FSM player trained to maximize Moran fixation probabilities.
668+
669+
Names:
670+
671+
- TF3: Original name by Marc Harper
672+
"""
673+
674+
name = "TF3"
675+
classifier = {
676+
'memory_depth': float('inf'),
677+
'stochastic': False,
678+
'makes_use_of': set(),
679+
'long_run_time': False,
680+
'inspects_source': False,
681+
'manipulates_source': False,
682+
'manipulates_state': False
683+
}
684+
685+
def __init__(self) -> None:
686+
transitions = (
687+
(0, C, 0, C), (0, D, 3, C),
688+
(1, C, 5, D), (1, D, 0, C),
689+
(2, C, 3, C), (2, D, 2, D),
690+
(3, C, 4, D), (3, D, 6, D),
691+
(4, C, 3, C), (4, D, 1, D),
692+
(5, C, 6, C), (5, D, 3, D),
693+
(6, C, 6, D), (6, D, 6, D),
694+
(7, C, 7, D), (7, D, 5, C)
695+
)
696+
697+
super().__init__(transitions=transitions, initial_state=0,
698+
initial_action=C)

axelrod/tests/strategies/test_finite_state_machines.py

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,18 @@ def test_bad_transitions_raise_error(self):
6666

6767
def test_bad_initial_state_raises_error(self):
6868
self.assertRaises(ValueError, SimpleFSM,
69-
transitions=self.two_state_transition, initial_state=5)
69+
transitions=self.two_state_transition,
70+
initial_state=5)
7071

7172
def test_state_setter_raises_error_for_bad_input(self):
7273
with self.assertRaises(ValueError) as cm:
7374
self.two_state.state = 5
7475
error_msg = cm.exception.args[0]
75-
self.assertEqual(error_msg, 'state: 5 does not have values for both C and D')
76+
self.assertEqual(error_msg,
77+
'state: 5 does not have values for both C and D')
7678

7779

78-
class TestFSMPlayer(TestPlayer):
80+
class TestSampleFSMPlayer(TestPlayer):
7981
"""Test a few sample tables to make sure that the finite state machines are
8082
working as intended."""
8183

@@ -98,7 +100,8 @@ def test_cooperator(self):
98100
cooperator_init_kwargs = {'transitions': ((1, C, 1, C), (1, D, 1, C)),
99101
'initial_state': 1,
100102
'initial_action': C}
101-
self.versus_test(axelrod.Alternator(), expected_actions=[(C, C), (C, D)] * 5,
103+
self.versus_test(axelrod.Alternator(),
104+
expected_actions=[(C, C), (C, D)] * 5,
102105
init_kwargs=cooperator_init_kwargs)
103106

104107
def test_defector(self):
@@ -107,7 +110,8 @@ def test_defector(self):
107110
defector_init_kwargs = {'transitions': ((1, C, 1, D), (1, D, 1, D)),
108111
'initial_state': 1,
109112
'initial_action': D}
110-
self.versus_test(axelrod.Alternator(), expected_actions=[(D, C), (D, D)] * 5,
113+
self.versus_test(axelrod.Alternator(),
114+
expected_actions=[(D, C), (D, D)] * 5,
111115
init_kwargs=defector_init_kwargs)
112116

113117
def test_tft(self):
@@ -132,7 +136,7 @@ def test_wsls(self):
132136
init_kwargs=wsls_init_kwargs)
133137

134138

135-
class TestFsmTransitions(TestPlayer):
139+
class TestFSMPlayer(TestPlayer):
136140
name = "FSM Player: ((1, 'C', 1, 'C'), (1, 'D', 1, 'D')), 1, C"
137141
player = axelrod.FSMPlayer
138142

@@ -169,10 +173,11 @@ def transitions_test(self, state_and_action):
169173
expected_actions.append((fsm_move, current_opponent_move))
170174
opponent_actions.append(current_opponent_move)
171175

172-
self.verify_against_finite_state_machine(current_state=current_state,
173-
expected_state=new_state,
174-
last_opponent_move=last_opponent_move,
175-
expected_move=fsm_move)
176+
self.verify_against_finite_state_machine(
177+
current_state=current_state,
178+
expected_state=new_state,
179+
last_opponent_move=last_opponent_move,
180+
expected_move=fsm_move)
176181

177182
self.versus_test(axelrod.MockPlayer(actions=opponent_actions),
178183
expected_actions=expected_actions)
@@ -219,7 +224,7 @@ def test_strategy(self):
219224
init_kwargs={"transitions": transitions})
220225

221226

222-
class TestFortress3(TestFsmTransitions):
227+
class TestFortress3(TestFSMPlayer):
223228

224229
name = "Fortress3"
225230
player = axelrod.Fortress3
@@ -259,7 +264,7 @@ def test_incorrect_transitions(self):
259264
self.transitions_test(state_and_actions)
260265

261266

262-
class TestFortress4(TestFsmTransitions):
267+
class TestFortress4(TestFSMPlayer):
263268

264269
name = "Fortress4"
265270
player = axelrod.Fortress4
@@ -299,7 +304,7 @@ def test_strategy(self):
299304
self.transitions_test(state_and_actions)
300305

301306

302-
class TestPredator(TestFsmTransitions):
307+
class TestPredator(TestFSMPlayer):
303308

304309
name = "Predator"
305310
player = axelrod.Predator
@@ -350,7 +355,7 @@ def test_strategy(self):
350355
self.transitions_test(state_and_actions)
351356

352357

353-
class TestPun1(TestFsmTransitions):
358+
class TestPun1(TestFSMPlayer):
354359

355360
name = "Pun1"
356361
player = axelrod.Pun1
@@ -380,7 +385,7 @@ def test_strategy(self):
380385
self.transitions_test(state_and_actions)
381386

382387

383-
class TestRaider(TestFsmTransitions):
388+
class TestRaider(TestFSMPlayer):
384389

385390
name = "Raider"
386391
player = axelrod.Raider
@@ -420,7 +425,7 @@ def test_strategy(self):
420425
self.transitions_test(state_and_actions)
421426

422427

423-
class TestRipoff(TestFsmTransitions):
428+
class TestRipoff(TestFSMPlayer):
424429

425430
name = "Ripoff"
426431
player = axelrod.Ripoff
@@ -455,7 +460,7 @@ def test_strategy(self):
455460
self.transitions_test(state_and_actions)
456461

457462

458-
class TestSolutionB1(TestFsmTransitions):
463+
class TestSolutionB1(TestFSMPlayer):
459464

460465
name = "SolutionB1"
461466
player = axelrod.SolutionB1
@@ -488,7 +493,7 @@ def test_strategy(self):
488493
self.transitions_test(state_and_actions)
489494

490495

491-
class TestSolutionB5(TestFsmTransitions):
496+
class TestSolutionB5(TestFSMPlayer):
492497

493498
name = "SolutionB5"
494499
player = axelrod.SolutionB5
@@ -533,7 +538,7 @@ def test_strategy(self):
533538
self.transitions_test(state_and_actions)
534539

535540

536-
class TestThumper(TestFsmTransitions):
541+
class TestThumper(TestFSMPlayer):
537542

538543
name = "Thumper"
539544
player = axelrod.Thumper
@@ -563,7 +568,7 @@ def test_strategy(self):
563568
self.transitions_test(state_and_actions)
564569

565570

566-
class TestEvolvedFSM4(TestFsmTransitions):
571+
class TestEvolvedFSM4(TestFSMPlayer):
567572

568573
name = "Evolved FSM 4"
569574
player = axelrod.EvolvedFSM4
@@ -601,7 +606,7 @@ def test_strategy(self):
601606
self.transitions_test(state_and_actions)
602607

603608

604-
class TestEvolvedFSM16(TestFsmTransitions):
609+
class TestEvolvedFSM16(TestFSMPlayer):
605610

606611
name = "Evolved FSM 16"
607612
player = axelrod.EvolvedFSM16
@@ -693,7 +698,7 @@ def test_strategy(self):
693698
self.transitions_test(state_and_actions)
694699

695700

696-
class TestEvolvedFSM16Noise05(TestFsmTransitions):
701+
class TestEvolvedFSM16Noise05(TestFSMPlayer):
697702

698703
name = "Evolved FSM 16 Noise 05"
699704
player = axelrod.EvolvedFSM16Noise05
@@ -780,3 +785,60 @@ def test_strategy(self):
780785
# finished 0, 1, 2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 15
781786
state_and_actions = to_state_eleven + [(11, C), (14, D)] + [(13, C)] * 3
782787
self.transitions_test(state_and_actions)
788+
789+
790+
class TestTF1(TestFSMPlayer):
791+
name = "TF1"
792+
player = axelrod.TF1
793+
expected_classifier = {
794+
'memory_depth': float('inf'),
795+
'stochastic': False,
796+
'makes_use_of': set(),
797+
'long_run_time': False,
798+
'inspects_source': False,
799+
'manipulates_source': False,
800+
'manipulates_state': False
801+
}
802+
803+
def test_strategy(self):
804+
self.first_play_test(C)
805+
actions = [(C, C), (C, D), (D, C), (D, D), (D, C)]
806+
self.versus_test(axelrod.Alternator(), expected_actions=actions)
807+
808+
809+
class TestTF2(TestFSMPlayer):
810+
name = "TF2"
811+
player = axelrod.TF2
812+
expected_classifier = {
813+
'memory_depth': float('inf'),
814+
'stochastic': False,
815+
'makes_use_of': set(),
816+
'long_run_time': False,
817+
'inspects_source': False,
818+
'manipulates_source': False,
819+
'manipulates_state': False
820+
}
821+
822+
def test_strategy(self):
823+
self.first_play_test(C)
824+
actions = [(C, C), (D, D), (D, C), (C, D), (D, C)]
825+
self.versus_test(axelrod.Alternator(), expected_actions=actions)
826+
827+
828+
class TestTF3(TestFSMPlayer):
829+
name = "TF3"
830+
player = axelrod.TF3
831+
expected_classifier = {
832+
'memory_depth': float('inf'),
833+
'stochastic': False,
834+
'makes_use_of': set(),
835+
'long_run_time': False,
836+
'inspects_source': False,
837+
'manipulates_source': False,
838+
'manipulates_state': False
839+
}
840+
841+
def test_strategy(self):
842+
self.first_play_test(C)
843+
actions = [(C, C), (C, D), (C, C), (D, D), (D, C)]
844+
self.versus_test(axelrod.Alternator(), expected_actions=actions)

0 commit comments

Comments
 (0)