From 0c1a2c922bfe9359ea18958b336a155e39e5598f Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Fri, 18 Aug 2017 12:12:03 +0100 Subject: [PATCH 01/28] tranquiliser test --- axelrod/strategies/tranquiliserstrategy.py | 122 +++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 axelrod/strategies/tranquiliserstrategy.py diff --git a/axelrod/strategies/tranquiliserstrategy.py b/axelrod/strategies/tranquiliserstrategy.py new file mode 100644 index 000000000..b9f382725 --- /dev/null +++ b/axelrod/strategies/tranquiliserstrategy.py @@ -0,0 +1,122 @@ +import axelrod as axl +import numpy +from axelrod.action import Action +from axelrod.player import Player +from axelrod.interaction_utils import compute_final_score +import random + +C, D = Action.C, Action.D + +dict = {C: 0, D: 1} + + +class Tranquilizer(Player): + ''' + A player that uses two ratios (which are dependent on the number of cooperations + defections of player and the opponent) to decide the next move to play. + The player can be present in three states(denoted FD): 0, 1 or 2 each causing a different outcome + dependent on the value of FD. Value of FD is dependent on the aforementioned ratios. + ''' + + name = 'Tranquilizer' + classifier = { + 'memory_depth': float('inf'), + 'stochastic': True, + 'long_run_time': False, + 'inspects_source': False, + 'manipulates_state': False + } + + # Initialised atributes + def __init__(self): + self.FD = 0 + self.consecutiveDefections = 0 + self.ratioFD1 = 5 + self.ratioFD2 = 0 + self.ratioFD1_count = 0 + self.ratioFD2_count = 0 + self.score = None + self.P = 10 + self.current_score = 0 + + def update_stateFD(self, + opponent): # Calculates the ratioFD values and P values, as well as sets the states of FD at the start of each turn + + self.current_score = compute_final_score(zip(self.history, opponent.history)) + + if self.FD == 2: + self.FD = 0 + self.ratioFD2 = ((self.ratioFD2 * self.ratioFD2_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ + self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratioFD2_count + 1) + self.ratioFD2_count += 1 + elif self.FD == 1: + self.FD = 2 + self.ratioFD1 = ((self.ratioFD1 * self.ratioFD1_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ + self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratioFD1_count + 1) + self.ratioFD1_count += 1 + else: + if (self.current_score[0] / (len(self.history)) + 1) >= 2.25: + self.P = .95 - ((self.ratioFD1) + (self.ratioFD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - ( + dict[opponent.history[-1]] / 4) + self.score = "good" + elif (self.current_score[0] / (len(self.history)) + 1) >= 1.75: + self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutiveDefections * .25) + ( + self.current_score[ + 0] - + self.current_score[ + 1]) / 100 + ( + 4 / (len(self.history) + 1)) + self.score = "average" + + def strategy(self, opponent: Player) -> Action: + + randomValue = random.random() # Random float between 0 and 1 to decide whether the player should defect or not + + current_score = compute_final_score(zip(self.history, opponent.history)) # Calculates current score + + print(self.FD, self.P) + + if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquiliser cooperates + return C + else: # If round number != 0, exectue the stateFD(self, opponent) function + Tranquilizer.update_stateFD(self, opponent) + if opponent.history[-1] == D: # Calculates number of consecutive defections + self.consecutive_defections += 1 + else: + self.consecutive_defections = 0 + + if self.FD != 0: # If FD != 0, then return value dependant on number of consecutive defections + if self.consecutive_defections == 0: + return C + else: + return D + elif (self.current_score[0] / (len(self.history)) + 1) < 1.75: # If score is too low, copy opponent + return opponent.history[-1] # "If you can't beat them join'em" + else: + if (randomValue < self.P): # Comapares randomValue to that of the calculated variable 'P' + if self.consecutiveDefections == 0: # Decides what to return (based on previous move), give randomValue < 'P' + return C + else: + return self.history[-1] + else: + if self.score == "good": # If score is above 2.25 && randomValue > P, set FD = 1, and defect + self.FD = 1 + else: # If score is greater than 1.75, but lower than 2.25 while randomValue > P, defect + pass + return D + + def reset(self): # Reset attributes ready for next game + super().reset() + self.FD = 0 + self.consecutiveDefections = 0 + self.ratioFD1 = 5 + self.ratioFD2 = 0 + self.ratioFD1_count = 0 + self.ratioFD2_count = 0 + self.P = 10 + self.current_score = 0 + + +match = axl.Match((Tranquilizer(), axl.DefectorHunter()), turns=1000) +match.play() +print(match.cooperation()) From 94556fe717e5d0e4c915f88e319579cb6fb536a0 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Fri, 18 Aug 2017 12:29:10 +0100 Subject: [PATCH 02/28] Tranquiliser Stratey + Test --- axelrod/strategies/tranquiliser.py | 122 ++++++++++++++++++ axelrod/tests/strategies/test_tranquiliser.py | 62 +++++++++ 2 files changed, 184 insertions(+) create mode 100644 axelrod/strategies/tranquiliser.py create mode 100644 axelrod/tests/strategies/test_tranquiliser.py diff --git a/axelrod/strategies/tranquiliser.py b/axelrod/strategies/tranquiliser.py new file mode 100644 index 000000000..0a2bc0bc1 --- /dev/null +++ b/axelrod/strategies/tranquiliser.py @@ -0,0 +1,122 @@ +import axelrod as axl +import numpy +from axelrod.action import Action +from axelrod.player import Player +from axelrod.interaction_utils import compute_final_score +import random + +C, D = Action.C, Action.D + +dict = {C: 0, D: 1} + + +class Tranquilizer(Player): + ''' +A player that uses two ratios (which are dependent on the number of cooperations +defections of player and the opponent) to decide the next move to play. +The player can be present in three states(denoted FD): 0, 1 or 2 each causing a different outcome +dependent on the value of FD. Value of FD is dependent on the aforementioned ratios. +''' + + name = 'Tranquilizer' + classifier = { + 'memory_depth': float('inf'), + 'stochastic': True, + 'long_run_time': False, + 'inspects_source': False, + 'manipulates_state': False + } + + # Initialised atributes + def __init__(self): + self.FD = 0 + self.consecutiveDefections = 0 + self.ratioFD1 = 5 + self.ratioFD2 = 0 + self.ratioFD1_count = 0 + self.ratioFD2_count = 0 + self.score = None + self.P = int + self.current_score = 0 + + def update_stateFD(self, + opponent): # Calculates the ratioFD values and P values, as well as sets the states of FD at the start of each turn + + self.current_score = compute_final_score(zip(self.history, opponent.history)) + + if self.FD == 2: + self.FD = 0 + self.ratioFD2 = ((self.ratioFD2 * self.ratioFD2_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ + self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratioFD2_count + 1) + self.ratioFD2_count += 1 + elif self.FD == 1: + self.FD = 2 + self.ratioFD1 = ((self.ratioFD1 * self.ratioFD1_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ + self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratioFD1_count + 1) + self.ratioFD1_count += 1 + else: + if (self.current_score[0] / (len(self.history)) + 1) >= 2.25: + self.P = .95 - ((self.ratioFD1) + (self.ratioFD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - ( + dict[opponent.history[-1]] / 4) + self.score = "good" + elif (self.current_score[0] / (len(self.history)) + 1) >= 1.75: + self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutiveDefections * .25) + ( + self.current_score[ + 0] - + self.current_score[ + 1]) / 100 + ( + 4 / (len(self.history) + 1)) + self.score = "average" + + def strategy(self, opponent: Player) -> Action: + + randomValue = random.random() # Random float between 0 and 1 to decide whether the player should defect or not + + current_score = compute_final_score(zip(self.history, opponent.history)) # Calculates current score + + print(self.FD, self.P) + + if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquiliser cooperates + return C + else: # If round number != 0, exectue the stateFD(self, opponent) function + Tranquilizer.update_stateFD(self, opponent) + if opponent.history[-1] == D: # Calculates number of consecutive defections + self.consecutive_defections += 1 + else: + self.consecutive_defections = 0 + + if self.FD != 0: # If FD != 0, then return value dependant on number of consecutive defections + if self.consecutive_defections == 0: + return C + else: + return D + elif (self.current_score[0] / (len(self.history)) + 1) < 1.75: # If score is too low, copy opponent + return opponent.history[-1] # "If you can't beat them join'em" + else: + if (randomValue < self.P): # Comapares randomValue to that of the calculated variable 'P' + if self.consecutiveDefections == 0: # Decides what to return (based on previous move), give randomValue < 'P' + return C + else: + return self.history[-1] + else: + if self.score == "good": # If score is above 2.25 && randomValue > P, set FD = 1, and defect + self.FD = 1 + else: # If score is greater than 1.75, but lower than 2.25 while randomValue > P, defect + pass + return D + + def reset(self): # Reset attributes ready for next game + super().reset() + self.FD = 0 + self.consecutiveDefections = 0 + self.ratioFD1 = 5 + self.ratioFD2 = 0 + self.ratioFD1_count = 0 + self.ratioFD2_count = 0 + self.P = int + self.current_score = 0 + + +match = axl.Match((Tranquilizer(), axl.DefectorHunter()), turns=1000) +match.play() +print(match.cooperation()) \ No newline at end of file diff --git a/axelrod/tests/strategies/test_tranquiliser.py b/axelrod/tests/strategies/test_tranquiliser.py new file mode 100644 index 000000000..a04338799 --- /dev/null +++ b/axelrod/tests/strategies/test_tranquiliser.py @@ -0,0 +1,62 @@ +import axelrod +from Axelrod.axelrod.tests.strategies.test_player import TestPlayer +import unittest + +C, D = axelrod.Action.C, axelrod.Action.D + + +class TestTitForTat(TestPlayer): + """ + Note that this test is referred to in the documentation as an example on + writing tests. If you modify the tests here please also modify the + documentation. + """ + + name = "Tit For Tat" + player = axelrod.TitForTat + expected_classifier = { + 'memory_depth': 1, + 'stochastic': False, + 'makes_use_of': set(), + 'inspects_source': False, + 'manipulates_source': False, + 'manipulates_state': False + } + + def test_strategy(self): + self.first_play_test(C) + self.second_play_test(rCC=C, rCD=D, rDC=C, rDD=D) + + # Play against opponents + actions = [(C, C), (C, D), (D, C), (C, D)] + self.versus_test(axelrod.Alternator(), expected_actions=actions) + + actions = [(C, C), (C, C), (C, C), (C, C)] + self.versus_test(axelrod.Cooperator(), expected_actions=actions) + + actions = [(C, D), (D, D), (D, D), (D, D)] + self.versus_test(axelrod.Defector(), expected_actions=actions) + + # This behaviour is independent of knowledge of the Match length + actions = [(C, C), (C, D), (D, C), (C, D)] + self.versus_test(axelrod.Alternator(), expected_actions=actions, + match_attributes={"length": -1}) + + # We can also test against random strategies + actions = [(C, D), (D, D), (D, C), (C, C)] + self.versus_test(axelrod.Random(), expected_actions=actions, + seed=0) + + actions = [(C, C), (C, D), (D, D), (D, C)] + self.versus_test(axelrod.Random(), expected_actions=actions, + seed=1) + + # If you would like to test against a sequence of moves you should use + # a MockPlayer + opponent = axelrod.MockPlayer(actions=[C, D]) + actions = [(C, C), (C, D), (D, C), (C, D)] + self.versus_test(opponent, expected_actions=actions) + + opponent = axelrod.MockPlayer(actions=[C, C, D, D, C, D]) + actions = [(C, C), (C, C), (C, D), (D, D), (D, C), (C, D)] + self.versus_test(opponent, expected_actions=actions) From a2d9828d7fddde73320ec8231e0425c6439299f7 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Fri, 18 Aug 2017 13:31:00 +0100 Subject: [PATCH 03/28] Make tests run. We added tranquiliser to the import so that it is known to the Axelrod library. --- axelrod/strategies/_strategies.py | 2 + axelrod/strategies/tranquiliser.py | 24 ++-- axelrod/strategies/tranquiliserstrategy.py | 122 ------------------ axelrod/tests/strategies/test_tranquiliser.py | 56 ++------ 4 files changed, 22 insertions(+), 182 deletions(-) delete mode 100644 axelrod/strategies/tranquiliserstrategy.py diff --git a/axelrod/strategies/_strategies.py b/axelrod/strategies/_strategies.py index 471c7a227..8d0df2ec0 100644 --- a/axelrod/strategies/_strategies.py +++ b/axelrod/strategies/_strategies.py @@ -77,6 +77,7 @@ SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats, OmegaTFT, Gradual, ContriteTitForTat, AdaptiveTitForTat, SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier, DynamicTwoTitsForTat, NTitsForMTats, Michaelos) +from .tranquiliser import Tranquiliser from .verybad import VeryBad from .worse_and_worse import (WorseAndWorse, KnowledgeableWorseAndWorse, WorseAndWorse2, WorseAndWorse3) @@ -253,6 +254,7 @@ TidemanAndChieruzzi, TitForTat, TitFor2Tats, + Tranquiliser, TrickyCooperator, TrickyDefector, Tullock, diff --git a/axelrod/strategies/tranquiliser.py b/axelrod/strategies/tranquiliser.py index 0a2bc0bc1..81cec0e9a 100644 --- a/axelrod/strategies/tranquiliser.py +++ b/axelrod/strategies/tranquiliser.py @@ -10,7 +10,7 @@ dict = {C: 0, D: 1} -class Tranquilizer(Player): +class Tranquiliser(Player): ''' A player that uses two ratios (which are dependent on the number of cooperations defections of player and the opponent) to decide the next move to play. @@ -18,25 +18,28 @@ class Tranquilizer(Player): dependent on the value of FD. Value of FD is dependent on the aforementioned ratios. ''' - name = 'Tranquilizer' + name = 'Tranquiliser' classifier = { 'memory_depth': float('inf'), 'stochastic': True, + 'makes_use_of': {"game"}, 'long_run_time': False, 'inspects_source': False, + 'manipulates_source': False, 'manipulates_state': False } # Initialised atributes def __init__(self): + super().__init__() self.FD = 0 - self.consecutiveDefections = 0 + self.consecutive_defections = 0 self.ratioFD1 = 5 self.ratioFD2 = 0 self.ratioFD1_count = 0 self.ratioFD2_count = 0 self.score = None - self.P = int + self.P = 1 self.current_score = 0 def update_stateFD(self, @@ -60,7 +63,7 @@ def update_stateFD(self, dict[opponent.history[-1]] / 4) self.score = "good" elif (self.current_score[0] / (len(self.history)) + 1) >= 1.75: - self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutiveDefections * .25) + ( + self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutive_defections * .25) + ( self.current_score[ 0] - self.current_score[ @@ -79,7 +82,7 @@ def strategy(self, opponent: Player) -> Action: if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquiliser cooperates return C else: # If round number != 0, exectue the stateFD(self, opponent) function - Tranquilizer.update_stateFD(self, opponent) + Tranquiliser.update_stateFD(self, opponent) if opponent.history[-1] == D: # Calculates number of consecutive defections self.consecutive_defections += 1 else: @@ -94,7 +97,7 @@ def strategy(self, opponent: Player) -> Action: return opponent.history[-1] # "If you can't beat them join'em" else: if (randomValue < self.P): # Comapares randomValue to that of the calculated variable 'P' - if self.consecutiveDefections == 0: # Decides what to return (based on previous move), give randomValue < 'P' + if self.consecutive_defections == 0: # Decides what to return (based on previous move), give randomValue < 'P' return C else: return self.history[-1] @@ -108,15 +111,12 @@ def strategy(self, opponent: Player) -> Action: def reset(self): # Reset attributes ready for next game super().reset() self.FD = 0 - self.consecutiveDefections = 0 + self.consecutive_defections = 0 self.ratioFD1 = 5 self.ratioFD2 = 0 self.ratioFD1_count = 0 self.ratioFD2_count = 0 - self.P = int + self.P = 1 self.current_score = 0 -match = axl.Match((Tranquilizer(), axl.DefectorHunter()), turns=1000) -match.play() -print(match.cooperation()) \ No newline at end of file diff --git a/axelrod/strategies/tranquiliserstrategy.py b/axelrod/strategies/tranquiliserstrategy.py deleted file mode 100644 index b9f382725..000000000 --- a/axelrod/strategies/tranquiliserstrategy.py +++ /dev/null @@ -1,122 +0,0 @@ -import axelrod as axl -import numpy -from axelrod.action import Action -from axelrod.player import Player -from axelrod.interaction_utils import compute_final_score -import random - -C, D = Action.C, Action.D - -dict = {C: 0, D: 1} - - -class Tranquilizer(Player): - ''' - A player that uses two ratios (which are dependent on the number of cooperations - defections of player and the opponent) to decide the next move to play. - The player can be present in three states(denoted FD): 0, 1 or 2 each causing a different outcome - dependent on the value of FD. Value of FD is dependent on the aforementioned ratios. - ''' - - name = 'Tranquilizer' - classifier = { - 'memory_depth': float('inf'), - 'stochastic': True, - 'long_run_time': False, - 'inspects_source': False, - 'manipulates_state': False - } - - # Initialised atributes - def __init__(self): - self.FD = 0 - self.consecutiveDefections = 0 - self.ratioFD1 = 5 - self.ratioFD2 = 0 - self.ratioFD1_count = 0 - self.ratioFD2_count = 0 - self.score = None - self.P = 10 - self.current_score = 0 - - def update_stateFD(self, - opponent): # Calculates the ratioFD values and P values, as well as sets the states of FD at the start of each turn - - self.current_score = compute_final_score(zip(self.history, opponent.history)) - - if self.FD == 2: - self.FD = 0 - self.ratioFD2 = ((self.ratioFD2 * self.ratioFD2_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ - self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratioFD2_count + 1) - self.ratioFD2_count += 1 - elif self.FD == 1: - self.FD = 2 - self.ratioFD1 = ((self.ratioFD1 * self.ratioFD1_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ - self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratioFD1_count + 1) - self.ratioFD1_count += 1 - else: - if (self.current_score[0] / (len(self.history)) + 1) >= 2.25: - self.P = .95 - ((self.ratioFD1) + (self.ratioFD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - ( - dict[opponent.history[-1]] / 4) - self.score = "good" - elif (self.current_score[0] / (len(self.history)) + 1) >= 1.75: - self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutiveDefections * .25) + ( - self.current_score[ - 0] - - self.current_score[ - 1]) / 100 + ( - 4 / (len(self.history) + 1)) - self.score = "average" - - def strategy(self, opponent: Player) -> Action: - - randomValue = random.random() # Random float between 0 and 1 to decide whether the player should defect or not - - current_score = compute_final_score(zip(self.history, opponent.history)) # Calculates current score - - print(self.FD, self.P) - - if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquiliser cooperates - return C - else: # If round number != 0, exectue the stateFD(self, opponent) function - Tranquilizer.update_stateFD(self, opponent) - if opponent.history[-1] == D: # Calculates number of consecutive defections - self.consecutive_defections += 1 - else: - self.consecutive_defections = 0 - - if self.FD != 0: # If FD != 0, then return value dependant on number of consecutive defections - if self.consecutive_defections == 0: - return C - else: - return D - elif (self.current_score[0] / (len(self.history)) + 1) < 1.75: # If score is too low, copy opponent - return opponent.history[-1] # "If you can't beat them join'em" - else: - if (randomValue < self.P): # Comapares randomValue to that of the calculated variable 'P' - if self.consecutiveDefections == 0: # Decides what to return (based on previous move), give randomValue < 'P' - return C - else: - return self.history[-1] - else: - if self.score == "good": # If score is above 2.25 && randomValue > P, set FD = 1, and defect - self.FD = 1 - else: # If score is greater than 1.75, but lower than 2.25 while randomValue > P, defect - pass - return D - - def reset(self): # Reset attributes ready for next game - super().reset() - self.FD = 0 - self.consecutiveDefections = 0 - self.ratioFD1 = 5 - self.ratioFD2 = 0 - self.ratioFD1_count = 0 - self.ratioFD2_count = 0 - self.P = 10 - self.current_score = 0 - - -match = axl.Match((Tranquilizer(), axl.DefectorHunter()), turns=1000) -match.play() -print(match.cooperation()) diff --git a/axelrod/tests/strategies/test_tranquiliser.py b/axelrod/tests/strategies/test_tranquiliser.py index a04338799..39f8cda6c 100644 --- a/axelrod/tests/strategies/test_tranquiliser.py +++ b/axelrod/tests/strategies/test_tranquiliser.py @@ -1,62 +1,22 @@ import axelrod from Axelrod.axelrod.tests.strategies.test_player import TestPlayer -import unittest C, D = axelrod.Action.C, axelrod.Action.D -class TestTitForTat(TestPlayer): - """ - Note that this test is referred to in the documentation as an example on - writing tests. If you modify the tests here please also modify the - documentation. - """ +class TestTranquiliser(TestPlayer): - name = "Tit For Tat" - player = axelrod.TitForTat + name = "Tranquiliser" + player = axelrod.Tranquiliser expected_classifier = { - 'memory_depth': 1, - 'stochastic': False, - 'makes_use_of': set(), + 'memory_depth': float('inf'), + 'stochastic': True, + 'makes_use_of': set(["game"]), + 'long_run_time': False, 'inspects_source': False, 'manipulates_source': False, 'manipulates_state': False } def test_strategy(self): - self.first_play_test(C) - self.second_play_test(rCC=C, rCD=D, rDC=C, rDD=D) - - # Play against opponents - actions = [(C, C), (C, D), (D, C), (C, D)] - self.versus_test(axelrod.Alternator(), expected_actions=actions) - - actions = [(C, C), (C, C), (C, C), (C, C)] - self.versus_test(axelrod.Cooperator(), expected_actions=actions) - - actions = [(C, D), (D, D), (D, D), (D, D)] - self.versus_test(axelrod.Defector(), expected_actions=actions) - - # This behaviour is independent of knowledge of the Match length - actions = [(C, C), (C, D), (D, C), (C, D)] - self.versus_test(axelrod.Alternator(), expected_actions=actions, - match_attributes={"length": -1}) - - # We can also test against random strategies - actions = [(C, D), (D, D), (D, C), (C, C)] - self.versus_test(axelrod.Random(), expected_actions=actions, - seed=0) - - actions = [(C, C), (C, D), (D, D), (D, C)] - self.versus_test(axelrod.Random(), expected_actions=actions, - seed=1) - - # If you would like to test against a sequence of moves you should use - # a MockPlayer - opponent = axelrod.MockPlayer(actions=[C, D]) - actions = [(C, C), (C, D), (D, C), (C, D)] - self.versus_test(opponent, expected_actions=actions) - - opponent = axelrod.MockPlayer(actions=[C, C, D, D, C, D]) - actions = [(C, C), (C, C), (C, D), (D, D), (D, C), (C, D)] - self.versus_test(opponent, expected_actions=actions) + self.assertEqual(2 + 2, 4) From 6098804407c3b38b97e6d3d84727dd248db9ac38 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Sat, 19 Aug 2017 01:37:05 +0100 Subject: [PATCH 04/28] Add to axelrod second, fix test_tranquiliser. Add to axelrod second, fix test_tranquiliserii --- axelrod/strategies/axelrod_second.py | 2 +- axelrod/strategies/tranquiliser.py | 5 ++-- .../tests/strategies/test_axelrod_second.py | 29 +++++++++++++++++++ axelrod/tests/strategies/test_tranquiliser.py | 21 ++++++++++++-- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 31a00da2c..06b7218a8 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -198,4 +198,4 @@ def strategy(self, opponent: Player) -> Action: return C else: # Play TFT - return opponent.history[-1] + return opponent.history[-1] \ No newline at end of file diff --git a/axelrod/strategies/tranquiliser.py b/axelrod/strategies/tranquiliser.py index 81cec0e9a..3b408e7ad 100644 --- a/axelrod/strategies/tranquiliser.py +++ b/axelrod/strategies/tranquiliser.py @@ -39,7 +39,7 @@ def __init__(self): self.ratioFD1_count = 0 self.ratioFD2_count = 0 self.score = None - self.P = 1 + self.P = int self.current_score = 0 def update_stateFD(self, @@ -116,7 +116,8 @@ def reset(self): # Reset attributes ready for next game self.ratioFD2 = 0 self.ratioFD1_count = 0 self.ratioFD2_count = 0 - self.P = 1 + self.score = None + self.P = int self.current_score = 0 diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 3e065b1b9..1a92a22e0 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -158,3 +158,32 @@ def test_strategy(self): actions = [(D, C), (C, C), (C, D), (C, D), (D, D)] self.versus_test(opponent, expected_actions=actions, attrs={'patsy': False}) + +import axelrod +from Axelrod.axelrod.tests.strategies.test_player import TestPlayer +import unittest + +C, D = axelrod.Action.C, axelrod.Action.D + + +class TestTranquiliser(TestPlayer): + """ + Note that this test is referred to in the documentation as an example on + writing tests. If you modify the tests here please also modify the + documentation. + """ + + name = "Tit For Tat" + player = axelrod.Tranquiliser + expected_classifier = { + 'memory_depth': float('inf'), + 'stochastic': True, + 'makes_use_of': {"game"}, + 'long_run_time': False, + 'inspects_source': False, + 'manipulates_source': False, + 'manipulates_state': False + } + + def test_strategy(self): + self.assertEqual(player.ratioFD2, 0) diff --git a/axelrod/tests/strategies/test_tranquiliser.py b/axelrod/tests/strategies/test_tranquiliser.py index 39f8cda6c..16e70a320 100644 --- a/axelrod/tests/strategies/test_tranquiliser.py +++ b/axelrod/tests/strategies/test_tranquiliser.py @@ -1,22 +1,39 @@ import axelrod from Axelrod.axelrod.tests.strategies.test_player import TestPlayer +import unittest C, D = axelrod.Action.C, axelrod.Action.D class TestTranquiliser(TestPlayer): + """ + Note that this test is referred to in the documentation as an example on + writing tests. If you modify the tests here please also modify the + documentation. + """ name = "Tranquiliser" player = axelrod.Tranquiliser expected_classifier = { 'memory_depth': float('inf'), 'stochastic': True, - 'makes_use_of': set(["game"]), + 'makes_use_of': {"game"}, 'long_run_time': False, 'inspects_source': False, 'manipulates_source': False, 'manipulates_state': False } + + def test_strategy(self): - self.assertEqual(2 + 2, 4) + + player = axelrod.Tranquiliser() + + opponent = axelrod.Defector() + actions = [(C, D)] + [(D, D)] * 20 + self.versus_test(opponent = opponent, expected_actions=actions) + + opponent = axelrod.Cooperator() + actions = [(C, C)] * 5 + ([(C, C)]) * 20 + self.versus_test(opponent, expected_actions=actions) From 51354b4bc49bc263baf9998943363a1929f31709 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Mon, 21 Aug 2017 09:27:17 +0100 Subject: [PATCH 05/28] Initial draft of tests, still needs fixes Finsih --- axelrod/strategies/tranquiliser.py | 10 +-- axelrod/tests/strategies/test_tranquiliser.py | 90 ++++++++++++++++++- 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/axelrod/strategies/tranquiliser.py b/axelrod/strategies/tranquiliser.py index 3b408e7ad..0bad8b718 100644 --- a/axelrod/strategies/tranquiliser.py +++ b/axelrod/strategies/tranquiliser.py @@ -39,7 +39,7 @@ def __init__(self): self.ratioFD1_count = 0 self.ratioFD2_count = 0 self.score = None - self.P = int + self.P = 1.1 self.current_score = 0 def update_stateFD(self, @@ -58,11 +58,11 @@ def update_stateFD(self, self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratioFD1_count + 1) self.ratioFD1_count += 1 else: - if (self.current_score[0] / (len(self.history)) + 1) >= 2.25: + if (self.current_score[0] / (len(self.history))) >= 2.25: self.P = .95 - ((self.ratioFD1) + (self.ratioFD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - ( dict[opponent.history[-1]] / 4) self.score = "good" - elif (self.current_score[0] / (len(self.history)) + 1) >= 1.75: + elif (self.current_score[0] / (len(self.history))) >= 1.75: self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutive_defections * .25) + ( self.current_score[ 0] - @@ -93,7 +93,7 @@ def strategy(self, opponent: Player) -> Action: return C else: return D - elif (self.current_score[0] / (len(self.history)) + 1) < 1.75: # If score is too low, copy opponent + elif (self.current_score[0] / (len(self.history))) < 1.75: # If score is too low, copy opponent return opponent.history[-1] # "If you can't beat them join'em" else: if (randomValue < self.P): # Comapares randomValue to that of the calculated variable 'P' @@ -117,7 +117,7 @@ def reset(self): # Reset attributes ready for next game self.ratioFD1_count = 0 self.ratioFD2_count = 0 self.score = None - self.P = int + self.P = 1.1 self.current_score = 0 diff --git a/axelrod/tests/strategies/test_tranquiliser.py b/axelrod/tests/strategies/test_tranquiliser.py index 16e70a320..82a3d8f97 100644 --- a/axelrod/tests/strategies/test_tranquiliser.py +++ b/axelrod/tests/strategies/test_tranquiliser.py @@ -25,15 +25,97 @@ class TestTranquiliser(TestPlayer): } + # test for initalised variables - def test_strategy(self): + def test_init(self): + player = axelrod.Tranquiliser() + self.assertEqual(player.P, 1.1) + self.assertEqual(player.FD, 0) + self.assertEqual(player.consecutive_defections, 0) + self.assertEqual(player.ratioFD1, 5) + self.assertEqual(player.ratioFD2, 0) + self.assertEqual(player.ratioFD1_count, 0) + self.assertEqual(player.ratioFD2_count, 0) + self.assertEqual(player.score, None) + + + def test_score_response(self): + + player = axelrod.Tranquiliser() + opponent = axelrod.Defector() + actions = [(C, D)] + [(D, D)] * 20 + self.versus_test(opponent = opponent, expected_actions=actions) - opponent = axelrod.Cooperator() - actions = [(C, C)] * 5 + ([(C, C)]) * 20 - self.versus_test(opponent, expected_actions=actions) + opponent = axelrod.MockPlayer([C] * 2 + [D] * 3 + [C] + [D] + [D] + [D] + [C] ) + + # Score + + actions = [(C, C)] # N/A + + actions += [(C, C)] # 3 + + actions += [(C, D)] # 3 + + actions += [(C, D)] # 2 + + actions += [(D, D)] # 1.5 - Copied + + actions += [(D, C)] # 1.4 - Copied + + actions += [(C, D)] # 2 + + actions += [(D, D)] # 1.714 - Copied + + actions += [(D, D)] # 1.625 - Copied + + actions += [(D, C)] # 1.55 - Copied + + self.versus_test(opponent = opponent, expected_actions=actions) + + + # If score is between 1.75 and 2.25, probability of defection is always atleast than .25 + + actions = [(C, D)] + + actions += [(D, D)] * 7 + + actions += [(D, C)] + + actions += [(C, C)] * 4 + + actions += ([(C, D)]) # average_score_per_turn = 1.875, with probability of each action being .75 and .25 respectively + + self.versus_test(opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 5 + [D]), expected_actions = actions, seed = 1) + + # If score is greater than 2.25 either cooperate or defect, if turn number <= 4; cooperate. + + actions = [(C, C)] * 4 + + actions += [(C, C) or (C, D)] + + actions += ([(C, D) or (D, D)]) + + actions += ([(C, C) or (D, C)]) * 15 + + actions += ([(C, D) or (D, D)]) + + self.versus_test(opponent = axelrod.MockPlayer(actions = [C] * 5 + [D] + [C] * 15 + [D]), expected_actions = actions, seed = 1) + + def test_consecutive_defections(self): + + player = axelrod.Tranquiliser() + + actions = [(C, D)] + [(D, D)] * 19 + + opponent = axelrod.Defector() + + player.play(opponent) + + print(player.consecutive_defections) + \ No newline at end of file From 1db4603d8cddca1e0c25871ad13f834f61aa3f46 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Mon, 21 Aug 2017 09:38:19 +0100 Subject: [PATCH 06/28] Remove reset method. No longer needed after an upstream change. --- axelrod/strategies/tranquiliser.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/axelrod/strategies/tranquiliser.py b/axelrod/strategies/tranquiliser.py index 0bad8b718..9a79852d2 100644 --- a/axelrod/strategies/tranquiliser.py +++ b/axelrod/strategies/tranquiliser.py @@ -108,16 +108,3 @@ def strategy(self, opponent: Player) -> Action: pass return D - def reset(self): # Reset attributes ready for next game - super().reset() - self.FD = 0 - self.consecutive_defections = 0 - self.ratioFD1 = 5 - self.ratioFD2 = 0 - self.ratioFD1_count = 0 - self.ratioFD2_count = 0 - self.score = None - self.P = 1.1 - self.current_score = 0 - - From b5e8c9fd76433f8bd0886ad53f8437366f05f7e3 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Mon, 21 Aug 2017 12:59:08 +0100 Subject: [PATCH 07/28] Fixed seeds in test_tranquiliser program Need to add more tests --- axelrod/tests/strategies/test_tranquiliser.py | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/axelrod/tests/strategies/test_tranquiliser.py b/axelrod/tests/strategies/test_tranquiliser.py index 82a3d8f97..a60f0dfb1 100644 --- a/axelrod/tests/strategies/test_tranquiliser.py +++ b/axelrod/tests/strategies/test_tranquiliser.py @@ -81,31 +81,57 @@ def test_score_response(self): # If score is between 1.75 and 2.25, probability of defection is always atleast than .25 - actions = [(C, D)] - + actions = [(C, D)] + actions += [(D, D)] * 7 actions += [(D, C)] actions += [(C, C)] * 4 - actions += ([(C, D)]) # average_score_per_turn = 1.875, with probability of each action being .75 and .25 respectively + actions += ([(C, D)]) # average_score_per_turn = 1.875, with probability of each action being .75 and .25 respectively + + self.versus_test(opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 5 + [D]), expected_actions=actions, seed=1) + - self.versus_test(opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 5 + [D]), expected_actions = actions, seed = 1) + + actions = [(C, D)] + + actions += [(D, D)] * 7 + + actions += [(D, C)] + + actions += [(C, C)] * 3 + + actions += ([(D, D)]) # average_score_per_turn = 1.875, with probability of each action being .75 and .25 respectively + + self.versus_test(opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 4 + [D]), + expected_actions=actions, seed=10, attrs = {"P" : .891025641025641}) + + + # If score is greater than 2.25 either cooperate or defect, if turn number <= 4; cooperate. actions = [(C, C)] * 4 - actions += [(C, C) or (C, D)] + actions += [(C, C)] - actions += ([(C, D) or (D, D)]) - - actions += ([(C, C) or (D, C)]) * 15 + self.versus_test(opponent = axelrod.MockPlayer(actions = [C] * 5), expected_actions = actions, seed = 1) + + actions = [(C, C)] * 4 - actions += ([(C, D) or (D, D)]) + actions += [(C, C)] + + self.versus_test(opponent = axelrod.MockPlayer(actions = [C] * 5), expected_actions = actions, seed = 69) + + + + + + + - self.versus_test(opponent = axelrod.MockPlayer(actions = [C] * 5 + [D] + [C] * 15 + [D]), expected_actions = actions, seed = 1) def test_consecutive_defections(self): From 50d3d7d65f7f756e30016ee2c7f6f6d1a2f6525e Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Mon, 21 Aug 2017 13:04:26 +0100 Subject: [PATCH 08/28] Actually fixed now Add more tests --- axelrod/tests/strategies/test_tranquiliser.py | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/axelrod/tests/strategies/test_tranquiliser.py b/axelrod/tests/strategies/test_tranquiliser.py index a60f0dfb1..6bd1710aa 100644 --- a/axelrod/tests/strategies/test_tranquiliser.py +++ b/axelrod/tests/strategies/test_tranquiliser.py @@ -113,24 +113,17 @@ def test_score_response(self): # If score is greater than 2.25 either cooperate or defect, if turn number <= 4; cooperate. - actions = [(C, C)] * 4 + opponent = axelrod.MockPlayer(actions = [C] * 5) - actions += [(C, C)] + actions = [(C, C)] * 4 + [(C, C)] - self.versus_test(opponent = axelrod.MockPlayer(actions = [C] * 5), expected_actions = actions, seed = 1) - - actions = [(C, C)] * 4 - - actions += [(C, C)] - - self.versus_test(opponent = axelrod.MockPlayer(actions = [C] * 5), expected_actions = actions, seed = 69) - - - - + self.versus_test(opponent, expected_actions = actions, seed = 1) + opponent + actions = [(C, C)] * 4 + [(D, C)] + self.versus_test(opponent = axelrod.MockPlayer(actions = [C] * 5), expected_actions = actions, seed = 70) def test_consecutive_defections(self): @@ -139,9 +132,5 @@ def test_consecutive_defections(self): actions = [(C, D)] + [(D, D)] * 19 - opponent = axelrod.Defector() - - player.play(opponent) - print(player.consecutive_defections) \ No newline at end of file From 74103d18131871fb0e47af967aa3ea0d490a5ed4 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Mon, 21 Aug 2017 14:36:44 +0100 Subject: [PATCH 09/28] Added test for double defection, changed var names --- axelrod/strategies/tranquiliser.py | 22 +++--- axelrod/tests/strategies/test_tranquiliser.py | 75 +++++++++++-------- 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/axelrod/strategies/tranquiliser.py b/axelrod/strategies/tranquiliser.py index 9a79852d2..556f47b80 100644 --- a/axelrod/strategies/tranquiliser.py +++ b/axelrod/strategies/tranquiliser.py @@ -34,10 +34,10 @@ def __init__(self): super().__init__() self.FD = 0 self.consecutive_defections = 0 - self.ratioFD1 = 5 - self.ratioFD2 = 0 - self.ratioFD1_count = 0 - self.ratioFD2_count = 0 + self.ratio_FD1 = 5 + self.ratio_FD2 = 0 + self.ratio_FD1_count = 0 + self.ratio_FD2_count = 0 self.score = None self.P = 1.1 self.current_score = 0 @@ -49,17 +49,17 @@ def update_stateFD(self, if self.FD == 2: self.FD = 0 - self.ratioFD2 = ((self.ratioFD2 * self.ratioFD2_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ - self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratioFD2_count + 1) - self.ratioFD2_count += 1 + self.ratio_FD2 = ((self.ratio_FD2 * self.ratio_FD2_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ + self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratio_FD2_count + 1) + self.ratio_FD2_count += 1 elif self.FD == 1: self.FD = 2 - self.ratioFD1 = ((self.ratioFD1 * self.ratioFD1_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ - self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratioFD1_count + 1) - self.ratioFD1_count += 1 + self.ratio_FD1 = ((self.ratio_FD1 * self.ratio_FD1_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ + self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratio_FD1_count + 1) + self.ratio_FD1_count += 1 else: if (self.current_score[0] / (len(self.history))) >= 2.25: - self.P = .95 - ((self.ratioFD1) + (self.ratioFD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - ( + self.P = .95 - ((self.ratio_FD1) + (self.ratio_FD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - ( dict[opponent.history[-1]] / 4) self.score = "good" elif (self.current_score[0] / (len(self.history))) >= 1.75: diff --git a/axelrod/tests/strategies/test_tranquiliser.py b/axelrod/tests/strategies/test_tranquiliser.py index 6bd1710aa..797452250 100644 --- a/axelrod/tests/strategies/test_tranquiliser.py +++ b/axelrod/tests/strategies/test_tranquiliser.py @@ -54,7 +54,7 @@ def test_score_response(self): opponent = axelrod.MockPlayer([C] * 2 + [D] * 3 + [C] + [D] + [D] + [D] + [C] ) - # Score + # Current score per turn: actions = [(C, C)] # N/A @@ -64,52 +64,48 @@ def test_score_response(self): actions += [(C, D)] # 2 - actions += [(D, D)] # 1.5 - Copied + actions += [(D, D)] # 1.5 - Copied opponent's last move - actions += [(D, C)] # 1.4 - Copied + actions += [(D, C)] # 1.4 - Copied opponent's last move actions += [(C, D)] # 2 - actions += [(D, D)] # 1.714 - Copied + actions += [(D, D)] # 1.714 - Copied opponent's last move - actions += [(D, D)] # 1.625 - Copied + actions += [(D, D)] # 1.625 - Copied opponent's last move - actions += [(D, C)] # 1.55 - Copied + actions += [(D, C)] # 1.55 - Copied opponent's last move self.versus_test(opponent = opponent, expected_actions=actions) - - # If score is between 1.75 and 2.25, probability of defection is always atleast than .25 - actions = [(C, D)] - - actions += [(D, D)] * 7 + def score_between(self): - actions += [(D, C)] - - actions += [(C, C)] * 4 + # If score is between 1.75 and 2.25, may cooperate or defect - actions += ([(C, D)]) # average_score_per_turn = 1.875, with probability of each action being .75 and .25 respectively + opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 5 + [D]) - self.versus_test(opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 5 + [D]), expected_actions=actions, seed=1) + actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 4 + + # average_score_per_turn = 1.875 + + actions += ([(C, D)]) # <-- Random + self.versus_test(opponent, expected_actions=actions, seed=1) - - actions = [(C, D)] - - actions += [(D, D)] * 7 - - actions += [(D, C)] - - actions += [(C, C)] * 3 - - actions += ([(D, D)]) # average_score_per_turn = 1.875, with probability of each action being .75 and .25 respectively - self.versus_test(opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 4 + [D]), - expected_actions=actions, seed=10, attrs = {"P" : .891025641025641}) + opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 4 + [D]) + actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 + + # average_score_per_turn = 1.875 + + actions += [(D, D)] # <-- Random + + self.versus_test(opponent, expected_actions=actions, seed=10, attrs = {"P" : .891025641025641}) + def score_greater(self): # If score is greater than 2.25 either cooperate or defect, if turn number <= 4; cooperate. @@ -118,19 +114,34 @@ def test_score_response(self): actions = [(C, C)] * 4 + [(C, C)] self.versus_test(opponent, expected_actions = actions, seed = 1) + + - opponent + opponent = axelrod.MockPlayer(actions = [C] * 5) actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent = axelrod.MockPlayer(actions = [C] * 5), expected_actions = actions, seed = 70) + self.versus_test(opponent, expected_actions = actions, seed = 70) + def test_consecutive_defections(self): - player = axelrod.Tranquiliser() - + opponent = axelrod.Defector() + actions = [(C, D)] + [(D, D)] * 19 + self.versus_test(opponent, expected_actions=actions, attrs={"consecutive_defections" : 19}) # Check + + def test_never_defects_twice(self): + # Given score per turn is greater than 2.25, Tranquiliser will never defect twice in a row + + opponent = axelrod.MockPlayer(actions = [C] * 5) + + actions = [(C, C)] * 4 + [(D, C)] + + self.versus_test(opponent, expected_actions = actions, seed = 70, attrs={"FD" : 1}) + + \ No newline at end of file From 90bf0ea5999562cc8c88ecddd1f5adb0caf0be0b Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Wed, 23 Aug 2017 12:20:45 +0100 Subject: [PATCH 10/28] Modified tranquiliser tests and tranquiliser program (changed variable names), added to axelrod_second and test_axelrod_second and deleted standalone tranquiliser.py and test_tranquiliser.py files --- axelrod/strategies/_strategies.py | 3 +- axelrod/strategies/axelrod_second.py | 128 ++++++++++++++- axelrod/strategies/tranquiliser.py | 110 ------------- .../tests/strategies/test_axelrod_second.py | 108 +++++++++++-- axelrod/tests/strategies/test_tranquiliser.py | 147 ------------------ 5 files changed, 222 insertions(+), 274 deletions(-) delete mode 100644 axelrod/strategies/tranquiliser.py delete mode 100644 axelrod/tests/strategies/test_tranquiliser.py diff --git a/axelrod/strategies/_strategies.py b/axelrod/strategies/_strategies.py index 8d0df2ec0..2bf2a89ed 100644 --- a/axelrod/strategies/_strategies.py +++ b/axelrod/strategies/_strategies.py @@ -7,7 +7,7 @@ from .axelrod_first import ( Davis, RevisedDowning, Feld, Grofman, Nydegger, Joss, Shubik, Tullock, UnnamedStrategy, SteinAndRapoport, TidemanAndChieruzzi) -from .axelrod_second import Champion, Eatherley, Tester, Gladstein +from .axelrod_second import Champion, Eatherley, Tester, Gladstein, Tranquiliser from .backstabber import BackStabber, DoubleCrosser from .better_and_better import BetterAndBetter from .calculator import Calculator @@ -77,7 +77,6 @@ SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats, OmegaTFT, Gradual, ContriteTitForTat, AdaptiveTitForTat, SpitefulTitForTat, SlowTitForTwoTats2, Alexei, EugineNier, DynamicTwoTitsForTat, NTitsForMTats, Michaelos) -from .tranquiliser import Tranquiliser from .verybad import VeryBad from .worse_and_worse import (WorseAndWorse, KnowledgeableWorseAndWorse, WorseAndWorse2, WorseAndWorse3) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 06b7218a8..fb22afc1b 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -8,8 +8,13 @@ from axelrod.player import Player from axelrod.random_ import random_choice +from axelrod.interaction_utils import compute_final_score + + C, D = Action.C, Action.D +dict = {C: 0, D: 1} + class Champion(Player): """ @@ -198,4 +203,125 @@ def strategy(self, opponent: Player) -> Action: return C else: # Play TFT - return opponent.history[-1] \ No newline at end of file + return opponent.history[-1] + +dict = {C: 0, D: 1} + + +class Tranquiliser(Player): + + """ + Submitted to Axelrod's second tournament by Craig Feathers + + This strategy is based on the reverse engineering of the + Fortran strategy K67R from Axelrod's second tournament. + Reversed engineered by: Owen Campbell, Will Guo and Mansour Hakem + + + Description given in Axelrod's "More Effective Choice in the Prisoner's Dilemma" + paper: The rule normally cooperates but is ready to defect if the other player + defects too often. Thus the rule tends to cooperate for the first dozen + or two moves if the other player is cooperating, but then it throws in a + defection. If the other player continues to cooperate, then defections + become more frequent. But as long as Tranquiliser is maintaining an + average payoff of at least 2.25 points per move, it will never defect + twice in succession and it will not defect more than one-quarter of the time. + + + + + + + + + Tranquiliser came in 27th place in Axelrod's second torunament. + + Names: + + - Craig Feathers: [Axelrod1980]_ + - Tranquiliser: [Axelrod1980]_ + """ + + name = 'Tranquiliser' + classifier = { + 'memory_depth': float('inf'), + 'stochastic': True, + 'makes_use_of': {"game"}, + 'long_run_time': False, + 'inspects_source': False, + 'manipulates_source': False, + 'manipulates_state': False + } + + # Initialised atributes + def __init__(self): + super().__init__() + self.FD = 0 + self.consecutive_defections = 0 + self.ratio_FD1 = 5 + self.ratio_FD2 = 0 + self.ratio_FD1_count = 1 + self.ratio_FD2_count = 1 + self.score = None + self.P = 1.1 + self.current_score = 0 + self.dict = {C: 0, D: 1} + + + def update_stateFD(self, opponent): # Calculates the ratioFD values and P values, as well as sets the states of FD at the start of each turn + + self.current_score = compute_final_score(zip(self.history, opponent.history)) + + if self.FD == 2: + self.FD = 0 + self.ratio_FD2 = ((self.ratio_FD2 * self.ratio_FD2_count + 3 - 3 * self.dict[opponent.history[-1]]) + 2 * self.dict[ + self.history[-1]] - self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) / (self.ratio_FD2_count + 1) + self.ratio_FD2_count += 1 + elif self.FD == 1: + self.FD = 2 + self.ratio_FD1 = ((self.ratio_FD1 * self.ratio_FD1_count + 3 - 3 * self.dict[opponent.history[-1]]) + 2 * self.dict[self.history[-1]] - self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) / (self.ratio_FD1_count + 1) + self.ratio_FD1_count += 1 + else: + if (self.current_score[0] / (len(self.history))) >= 2.25: + self.P = .95 - ((self.ratio_FD1) + (self.ratio_FD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - (self.dict[opponent.history[-1]] / 4) + self.P = round(self.P, 4) + self.score = "good" + elif (self.current_score[0] / (len(self.history))) >= 1.75: + self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutive_defections * .25) + (self.current_score[0] - self.current_score[1]) / 100 + (4 / (len(self.history) + 1)) + self.P = round(self.P, 4) + self.score = "average" + + def strategy(self, opponent: Player) -> Action: + + randomValue = random.random() # Random float between 0 and 1 to decide whether the player should defect or not + + current_score = compute_final_score(zip(self.history, opponent.history)) # Calculates current score + + if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquiliser cooperates + return C + else: # If round number != 0, exectue the stateFD(self, opponent) function + Tranquiliser.update_stateFD(self, opponent) + if opponent.history[-1] == D: # Calculates number of consecutive defections + self.consecutive_defections += 1 + else: + self.consecutive_defections = 0 + + if self.FD != 0: # If FD != 0, then return value dependant on number of consecutive defections + if self.consecutive_defections == 0: + return C + else: + return D + elif (self.current_score[0] / (len(self.history))) < 1.75: # If score is too low, copy opponent + return opponent.history[-1] # "If you can't beat them join'em" + else: + if (randomValue < self.P): # Comapares randomValue to that of the calculated variable 'P' + if self.consecutive_defections == 0: # Decides what to return (based on previous move), give randomValue < 'P' + return C + else: + return self.history[-1] + else: + if self.score == "good": # If score is above 2.25 && randomValue > P, set FD = 1, and defect + self.FD = 1 + else: # If score is greater than 1.75, but lower than 2.25 while randomValue > P, defect + pass + return D \ No newline at end of file diff --git a/axelrod/strategies/tranquiliser.py b/axelrod/strategies/tranquiliser.py deleted file mode 100644 index 556f47b80..000000000 --- a/axelrod/strategies/tranquiliser.py +++ /dev/null @@ -1,110 +0,0 @@ -import axelrod as axl -import numpy -from axelrod.action import Action -from axelrod.player import Player -from axelrod.interaction_utils import compute_final_score -import random - -C, D = Action.C, Action.D - -dict = {C: 0, D: 1} - - -class Tranquiliser(Player): - ''' -A player that uses two ratios (which are dependent on the number of cooperations -defections of player and the opponent) to decide the next move to play. -The player can be present in three states(denoted FD): 0, 1 or 2 each causing a different outcome -dependent on the value of FD. Value of FD is dependent on the aforementioned ratios. -''' - - name = 'Tranquiliser' - classifier = { - 'memory_depth': float('inf'), - 'stochastic': True, - 'makes_use_of': {"game"}, - 'long_run_time': False, - 'inspects_source': False, - 'manipulates_source': False, - 'manipulates_state': False - } - - # Initialised atributes - def __init__(self): - super().__init__() - self.FD = 0 - self.consecutive_defections = 0 - self.ratio_FD1 = 5 - self.ratio_FD2 = 0 - self.ratio_FD1_count = 0 - self.ratio_FD2_count = 0 - self.score = None - self.P = 1.1 - self.current_score = 0 - - def update_stateFD(self, - opponent): # Calculates the ratioFD values and P values, as well as sets the states of FD at the start of each turn - - self.current_score = compute_final_score(zip(self.history, opponent.history)) - - if self.FD == 2: - self.FD = 0 - self.ratio_FD2 = ((self.ratio_FD2 * self.ratio_FD2_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ - self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratio_FD2_count + 1) - self.ratio_FD2_count += 1 - elif self.FD == 1: - self.FD = 2 - self.ratio_FD1 = ((self.ratio_FD1 * self.ratio_FD1_count + 3 - 3 * dict[opponent.history[-1]]) + 2 * dict[ - self.history[-1]] - dict[opponent.history[-1]] * dict[self.history[-1]]) / (self.ratio_FD1_count + 1) - self.ratio_FD1_count += 1 - else: - if (self.current_score[0] / (len(self.history))) >= 2.25: - self.P = .95 - ((self.ratio_FD1) + (self.ratio_FD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - ( - dict[opponent.history[-1]] / 4) - self.score = "good" - elif (self.current_score[0] / (len(self.history))) >= 1.75: - self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutive_defections * .25) + ( - self.current_score[ - 0] - - self.current_score[ - 1]) / 100 + ( - 4 / (len(self.history) + 1)) - self.score = "average" - - def strategy(self, opponent: Player) -> Action: - - randomValue = random.random() # Random float between 0 and 1 to decide whether the player should defect or not - - current_score = compute_final_score(zip(self.history, opponent.history)) # Calculates current score - - print(self.FD, self.P) - - if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquiliser cooperates - return C - else: # If round number != 0, exectue the stateFD(self, opponent) function - Tranquiliser.update_stateFD(self, opponent) - if opponent.history[-1] == D: # Calculates number of consecutive defections - self.consecutive_defections += 1 - else: - self.consecutive_defections = 0 - - if self.FD != 0: # If FD != 0, then return value dependant on number of consecutive defections - if self.consecutive_defections == 0: - return C - else: - return D - elif (self.current_score[0] / (len(self.history))) < 1.75: # If score is too low, copy opponent - return opponent.history[-1] # "If you can't beat them join'em" - else: - if (randomValue < self.P): # Comapares randomValue to that of the calculated variable 'P' - if self.consecutive_defections == 0: # Decides what to return (based on previous move), give randomValue < 'P' - return C - else: - return self.history[-1] - else: - if self.score == "good": # If score is above 2.25 && randomValue > P, set FD = 1, and defect - self.FD = 1 - else: # If score is greater than 1.75, but lower than 2.25 while randomValue > P, defect - pass - return D - diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 1a92a22e0..77433a0b5 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -5,6 +5,8 @@ import axelrod from .test_player import TestPlayer +from axelrod.interaction_utils import compute_final_score + C, D = axelrod.Action.C, axelrod.Action.D @@ -159,21 +161,10 @@ def test_strategy(self): self.versus_test(opponent, expected_actions=actions, attrs={'patsy': False}) -import axelrod -from Axelrod.axelrod.tests.strategies.test_player import TestPlayer -import unittest - -C, D = axelrod.Action.C, axelrod.Action.D - class TestTranquiliser(TestPlayer): - """ - Note that this test is referred to in the documentation as an example on - writing tests. If you modify the tests here please also modify the - documentation. - """ - name = "Tit For Tat" + name = "Tranquiliser" player = axelrod.Tranquiliser expected_classifier = { 'memory_depth': float('inf'), @@ -185,5 +176,94 @@ class TestTranquiliser(TestPlayer): 'manipulates_state': False } - def test_strategy(self): - self.assertEqual(player.ratioFD2, 0) + + # test for initalised variables + + def test_init(self): + + player = axelrod.Tranquiliser() + + self.assertEqual(player.P, 1.1) + self.assertEqual(player.FD, 0) + self.assertEqual(player.consecutive_defections, 0) + self.assertEqual(player.ratio_FD1, 5) + self.assertEqual(player.ratio_FD2, 0) + self.assertEqual(player.ratio_FD1_count, 1) + self.assertEqual(player.ratio_FD2_count, 1) + self.assertEqual(player.score, None) + self.current_score = 0 + + def test_score_bad(self): + + # Tests whether TitForTat is played given score is below 1.75 + + opponent = axelrod.Defector() + actions = [(C, D)] + [(D, D)] * 20 + self.versus_test(opponent, expected_actions=actions, attrs={"P":1.1, "FD":0, "consecutive_defections":20, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + + opponent = axelrod.MockPlayer([C] * 2 + [D] * 9 + [C] * 4 ) + actions = [(C, C)] + [(C, C)] + [(C, D)] * 2 + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 + self.versus_test(opponent = opponent, expected_actions=actions, attrs={"P":1.8667, "FD":0, "consecutive_defections":0, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + + # If score is between 1.75 and 2.25, may cooperate or defect + opponent = axelrod.MockPlayer(actions=[D] * 8 + [C] * 5 + [D]) + actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 4 + # average_score_per_turn = 1.875 + actions += ([(C, D)]) # <-- Random + self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"P": 0.9203, "FD":0, "consecutive_defections":0, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + + opponent = axelrod.MockPlayer(actions=[D] * 8 + [C] * 4 + [D]) + actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 + # average_score_per_turn = 1.875 + actions += [(D, D)] # <-- Random + self.versus_test(opponent, expected_actions=actions, seed=10, attrs={"P": 0.891, "FD":0, "consecutive_defections":0, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + + # If score is greater than 2.25 either cooperate or defect, if turn number <= 4; cooperate + + opponent = axelrod.MockPlayer(actions=[C] * 5) + actions = [(C, C)] * 4 + [(C, C)] + self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"P": 0.99, "FD":0, "consecutive_defections":0, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + + opponent = axelrod.MockPlayer(actions=[C] * 5) + actions = [(C, C)] * 4 + [(D, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":1, "consecutive_defections":0, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + + # Given score per turn is greater than 2.25, Tranquiliser will never defect twice in a row + + opponent = axelrod.MockPlayer(actions = [C] * 5) + actions = [(C, C)] * 4 + [(D, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":1, "consecutive_defections":0, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + # Tests defection probability if score == good + + opponent = axelrod.MockPlayer(actions=[C] * 5) + actions = [(C, C)] * 4 + [(D, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":1, "consecutive_defections":0, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + + # Ensures FD1 values are calculated + + opponent = axelrod.MockPlayer(actions=[C] * 6) + actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":2, "consecutive_defections":0, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":2, "ratio_FD2_count":1}) + + # Ensures FD2 values are calculated + + opponent = axelrod.MockPlayer(actions=[C] * 6) + actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] + [(C, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":0, "consecutive_defections":0, "ratio_FD1":5, + "ratio_FD2":1.5, "ratio_FD1_count":2, "ratio_FD2_count":2}) + + # Ensures scores are being counted + + opponent = axelrod.Defector() + actions = [(C, D)] + [(D, D)] * 19 + self.versus_test(opponent, expected_actions=actions, attrs={"P": 1.1, "FD":0, "consecutive_defections":19, "ratio_FD1":5, + "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) # Check \ No newline at end of file diff --git a/axelrod/tests/strategies/test_tranquiliser.py b/axelrod/tests/strategies/test_tranquiliser.py deleted file mode 100644 index 797452250..000000000 --- a/axelrod/tests/strategies/test_tranquiliser.py +++ /dev/null @@ -1,147 +0,0 @@ -import axelrod -from Axelrod.axelrod.tests.strategies.test_player import TestPlayer -import unittest - -C, D = axelrod.Action.C, axelrod.Action.D - - -class TestTranquiliser(TestPlayer): - """ - Note that this test is referred to in the documentation as an example on - writing tests. If you modify the tests here please also modify the - documentation. - """ - - name = "Tranquiliser" - player = axelrod.Tranquiliser - expected_classifier = { - 'memory_depth': float('inf'), - 'stochastic': True, - 'makes_use_of': {"game"}, - 'long_run_time': False, - 'inspects_source': False, - 'manipulates_source': False, - 'manipulates_state': False - } - - - # test for initalised variables - - def test_init(self): - - - player = axelrod.Tranquiliser() - - self.assertEqual(player.P, 1.1) - self.assertEqual(player.FD, 0) - self.assertEqual(player.consecutive_defections, 0) - self.assertEqual(player.ratioFD1, 5) - self.assertEqual(player.ratioFD2, 0) - self.assertEqual(player.ratioFD1_count, 0) - self.assertEqual(player.ratioFD2_count, 0) - self.assertEqual(player.score, None) - - - def test_score_response(self): - - player = axelrod.Tranquiliser() - - opponent = axelrod.Defector() - - actions = [(C, D)] + [(D, D)] * 20 - - self.versus_test(opponent = opponent, expected_actions=actions) - - opponent = axelrod.MockPlayer([C] * 2 + [D] * 3 + [C] + [D] + [D] + [D] + [C] ) - - # Current score per turn: - - actions = [(C, C)] # N/A - - actions += [(C, C)] # 3 - - actions += [(C, D)] # 3 - - actions += [(C, D)] # 2 - - actions += [(D, D)] # 1.5 - Copied opponent's last move - - actions += [(D, C)] # 1.4 - Copied opponent's last move - - actions += [(C, D)] # 2 - - actions += [(D, D)] # 1.714 - Copied opponent's last move - - actions += [(D, D)] # 1.625 - Copied opponent's last move - - actions += [(D, C)] # 1.55 - Copied opponent's last move - - self.versus_test(opponent = opponent, expected_actions=actions) - - - def score_between(self): - - # If score is between 1.75 and 2.25, may cooperate or defect - - opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 5 + [D]) - - actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 4 - - # average_score_per_turn = 1.875 - - actions += ([(C, D)]) # <-- Random - - self.versus_test(opponent, expected_actions=actions, seed=1) - - - - opponent = axelrod.MockPlayer(actions = [D] * 8 + [C] * 4 + [D]) - - actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 - - # average_score_per_turn = 1.875 - - actions += [(D, D)] # <-- Random - - self.versus_test(opponent, expected_actions=actions, seed=10, attrs = {"P" : .891025641025641}) - - def score_greater(self): - - # If score is greater than 2.25 either cooperate or defect, if turn number <= 4; cooperate. - - opponent = axelrod.MockPlayer(actions = [C] * 5) - - actions = [(C, C)] * 4 + [(C, C)] - - self.versus_test(opponent, expected_actions = actions, seed = 1) - - - - opponent = axelrod.MockPlayer(actions = [C] * 5) - - actions = [(C, C)] * 4 + [(D, C)] - - self.versus_test(opponent, expected_actions = actions, seed = 70) - - - - def test_consecutive_defections(self): - - opponent = axelrod.Defector() - - actions = [(C, D)] + [(D, D)] * 19 - - self.versus_test(opponent, expected_actions=actions, attrs={"consecutive_defections" : 19}) # Check - - def test_never_defects_twice(self): - # Given score per turn is greater than 2.25, Tranquiliser will never defect twice in a row - - opponent = axelrod.MockPlayer(actions = [C] * 5) - - actions = [(C, C)] * 4 + [(D, C)] - - self.versus_test(opponent, expected_actions = actions, seed = 70, attrs={"FD" : 1}) - - - - \ No newline at end of file From 6fb1c6fabf777595cbdd763677478e99519f00d7 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Wed, 23 Aug 2017 12:41:27 +0100 Subject: [PATCH 11/28] Removed unnecessary dict declarations Signed-off-by: Mansour Hakem --- axelrod/strategies/_strategies.py | 4 +- axelrod/strategies/axelrod_second.py | 70 ++++++++++++++----- .../tests/strategies/test_axelrod_second.py | 10 +-- 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/axelrod/strategies/_strategies.py b/axelrod/strategies/_strategies.py index 2bf2a89ed..b32399caf 100644 --- a/axelrod/strategies/_strategies.py +++ b/axelrod/strategies/_strategies.py @@ -7,7 +7,7 @@ from .axelrod_first import ( Davis, RevisedDowning, Feld, Grofman, Nydegger, Joss, Shubik, Tullock, UnnamedStrategy, SteinAndRapoport, TidemanAndChieruzzi) -from .axelrod_second import Champion, Eatherley, Tester, Gladstein, Tranquiliser +from .axelrod_second import Champion, Eatherley, Tester, Gladstein, Tranquilizer from .backstabber import BackStabber, DoubleCrosser from .better_and_better import BetterAndBetter from .calculator import Calculator @@ -253,7 +253,7 @@ TidemanAndChieruzzi, TitForTat, TitFor2Tats, - Tranquiliser, + Tranquilizer, TrickyCooperator, TrickyDefector, Tullock, diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index fb22afc1b..3a18cd0e0 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -13,8 +13,6 @@ C, D = Action.C, Action.D -dict = {C: 0, D: 1} - class Champion(Player): """ @@ -205,17 +203,14 @@ def strategy(self, opponent: Player) -> Action: # Play TFT return opponent.history[-1] -dict = {C: 0, D: 1} - - -class Tranquiliser(Player): +class Tranquilizer(Player): """ Submitted to Axelrod's second tournament by Craig Feathers This strategy is based on the reverse engineering of the Fortran strategy K67R from Axelrod's second tournament. - Reversed engineered by: Owen Campbell, Will Guo and Mansour Hakem + Reversed engineered by: Owen Campbell, Will Guo and Mansour Hakem. Description given in Axelrod's "More Effective Choice in the Prisoner's Dilemma" @@ -223,26 +218,62 @@ class Tranquiliser(Player): defects too often. Thus the rule tends to cooperate for the first dozen or two moves if the other player is cooperating, but then it throws in a defection. If the other player continues to cooperate, then defections - become more frequent. But as long as Tranquiliser is maintaining an + become more frequent. But as long as Tranquilizer is maintaining an average payoff of at least 2.25 points per move, it will never defect twice in succession and it will not defect more than one-quarter of the time. + Has a variable, 'FD' which can be 0, 1 or 2. It has an initial value of 0 + Has a variable 'S', which counts the consecutive number of times the opponent has played D (i.e. it is reset to 0 if the opponent plays C). It has an initial value of 0. + Has a variable, 'C', which counts the number of times the opponent Cooperates + Has a variable 'AK' which increases each time a move is played whilst in state FD = 1. It has an initial value of 1. + Has a variable 'NK' which increases each time a move is played whilst in state FD = 2. It has an initial value of 1. + Has a variable 'AD' with an initial value of 5 + Has a variable 'NO with an initial value of 0 + When FD = 0: + If the opponent's last move (JA) was Cooperate, increase the value of C by 1 + If Score (K) < 1.75 * Move Number (M), play opponent's last move + If (1.75 * M) <= K < (2.25 * M): + Calculate Probability P: + P = 0.25 + C/M - 0.25*S + (K - L)/100 + 4/M + Where L is the opponent's score so far + If Random (R) <= P: + Cooperate + Else: + Defect + If K >= (2.25 * M): + Calculate probability P: + P = 0.95 - (AD + NO - 5)/15 + 1/M**2 - J/4 + Where J is the opponent's last move + If Random (R) <= P: + Cooperate + Else: + Set FD = 1 + Defect + When FD = 1: + Set FD = 2 + Set the variable 'AD': + AD = ((AD * AK) + 3 - (3 * J) + (2 * JA) - (JA * J)) / (AK + 1) + Where JA is the strategy's last move and J is the opponent's last move (C = 0, D = 1) + Increase the value of AK by 1 + Cooperate + When FD = 2: + Set FD = 0 + Set the variable 'NO': + NO = ((NO * NK) + 3 - (3 * J) + (2 * JA) - (JA * J) / (NK + 1) + Where JA the strategy's last move and J is the opponent's last move (C = 0, D = 1) + Increase the value of NK by 1 + Cooperate - - - - - - Tranquiliser came in 27th place in Axelrod's second torunament. + Tranquilizer came in 27th place in Axelrod's second torunament. Names: - Craig Feathers: [Axelrod1980]_ - - Tranquiliser: [Axelrod1980]_ + - Tranquilizer: [Axelrod1980]_ """ - name = 'Tranquiliser' + name = 'Tranquilizer' classifier = { 'memory_depth': float('inf'), 'stochastic': True, @@ -297,10 +328,10 @@ def strategy(self, opponent: Player) -> Action: current_score = compute_final_score(zip(self.history, opponent.history)) # Calculates current score - if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquiliser cooperates + if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquilizer cooperates return C else: # If round number != 0, exectue the stateFD(self, opponent) function - Tranquiliser.update_stateFD(self, opponent) + Tranquilizer.update_stateFD(self, opponent) if opponent.history[-1] == D: # Calculates number of consecutive defections self.consecutive_defections += 1 else: @@ -324,4 +355,5 @@ def strategy(self, opponent: Player) -> Action: self.FD = 1 else: # If score is greater than 1.75, but lower than 2.25 while randomValue > P, defect pass - return D \ No newline at end of file + return D + \ No newline at end of file diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 77433a0b5..870d86560 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -162,10 +162,10 @@ def test_strategy(self): attrs={'patsy': False}) -class TestTranquiliser(TestPlayer): +class TestTranquilizer(TestPlayer): - name = "Tranquiliser" - player = axelrod.Tranquiliser + name = "Tranquilizer" + player = axelrod.Tranquilizer expected_classifier = { 'memory_depth': float('inf'), 'stochastic': True, @@ -181,7 +181,7 @@ class TestTranquiliser(TestPlayer): def test_init(self): - player = axelrod.Tranquiliser() + player = axelrod.Tranquilizer() self.assertEqual(player.P, 1.1) self.assertEqual(player.FD, 0) @@ -234,7 +234,7 @@ def test_score_bad(self): self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":1, "consecutive_defections":0, "ratio_FD1":5, "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) - # Given score per turn is greater than 2.25, Tranquiliser will never defect twice in a row + # Given score per turn is greater than 2.25, Tranquilizer will never defect twice in a row opponent = axelrod.MockPlayer(actions = [C] * 5) actions = [(C, C)] * 4 + [(D, C)] From d703e7c56f5b83fb9e9ffd66138f7787d4dfe591 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Wed, 23 Aug 2017 13:09:29 +0100 Subject: [PATCH 12/28] Add another test case + Pep8 Signed-off-by: Mansour Hakem --- .../tests/strategies/test_axelrod_second.py | 105 +++++++++++++----- 1 file changed, 80 insertions(+), 25 deletions(-) diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 870d86560..234df6837 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -199,71 +199,126 @@ def test_score_bad(self): opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 20 - self.versus_test(opponent, expected_actions=actions, attrs={"P":1.1, "FD":0, "consecutive_defections":20, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + self.versus_test(opponent, expected_actions=actions, attrs={"P": 1.1, + "FD": 0, + "consecutive_defections": 20, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 1, + "ratio_FD2_count": 1}) opponent = axelrod.MockPlayer([C] * 2 + [D] * 9 + [C] * 4 ) actions = [(C, C)] + [(C, C)] + [(C, D)] * 2 + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 - self.versus_test(opponent = opponent, expected_actions=actions, attrs={"P":1.8667, "FD":0, "consecutive_defections":0, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + self.versus_test(opponent = opponent, expected_actions=actions, attrs={"P": 1.8667, + "FD": 0, + "consecutive_defections": 0, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 1, + "ratio_FD2_count": 1}) # If score is between 1.75 and 2.25, may cooperate or defect opponent = axelrod.MockPlayer(actions=[D] * 8 + [C] * 5 + [D]) actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 4 # average_score_per_turn = 1.875 actions += ([(C, D)]) # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"P": 0.9203, "FD":0, "consecutive_defections":0, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"P": 0.9203, + "FD": 0, + "consecutive_defections": 0, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 1, + "ratio_FD2_count": 1}) opponent = axelrod.MockPlayer(actions=[D] * 8 + [C] * 4 + [D]) actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 # average_score_per_turn = 1.875 actions += [(D, D)] # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=10, attrs={"P": 0.891, "FD":0, "consecutive_defections":0, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + self.versus_test(opponent, expected_actions=actions, seed=10, attrs={"P": 0.891, + "FD": 0, + "consecutive_defections": 0, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 1, + "ratio_FD2_count": 1}) # If score is greater than 2.25 either cooperate or defect, if turn number <= 4; cooperate opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 4 + [(C, C)] - self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"P": 0.99, "FD":0, "consecutive_defections":0, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"P": 0.99, + "FD": 0, + "consecutive_defections": 0, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 1, + "ratio_FD2_count": 1}) opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":1, "consecutive_defections":0, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, + "FD": 1, + "consecutive_defections": 0, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 1, + "ratio_FD2_count": 1}) # Given score per turn is greater than 2.25, Tranquilizer will never defect twice in a row - opponent = axelrod.MockPlayer(actions = [C] * 5) - actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":1, "consecutive_defections":0, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + opponent = axelrod.MockPlayer(actions = [C] * 6) + actions = [(C, C)] * 4 + [(D, C), (C, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, + "FD": 2, + "consecutive_defections": 0, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 2, + "ratio_FD2_count": 1}) # Tests defection probability if score == good opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":1, "consecutive_defections":0, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, + "FD": 1, + "consecutive_defections": 0, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 1, + "ratio_FD2_count": 1}) # Ensures FD1 values are calculated opponent = axelrod.MockPlayer(actions=[C] * 6) - actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":2, "consecutive_defections":0, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":2, "ratio_FD2_count":1}) + actions = [(C, C)] * 4 + [(D, C), (C, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, + "FD": 2, + "consecutive_defections": 0, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 2, + "ratio_FD2_count": 1}) # Ensures FD2 values are calculated opponent = axelrod.MockPlayer(actions=[C] * 6) actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] + [(C, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, "FD":0, "consecutive_defections":0, "ratio_FD1":5, - "ratio_FD2":1.5, "ratio_FD1_count":2, "ratio_FD2_count":2}) + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, + "FD": 0, + "consecutive_defections": 0, + "ratio_FD1": 5, + "ratio_FD2": 1.5, + "ratio_FD1_count": 2, + "ratio_FD2_count": 2}) # Ensures scores are being counted opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 19 - self.versus_test(opponent, expected_actions=actions, attrs={"P": 1.1, "FD":0, "consecutive_defections":19, "ratio_FD1":5, - "ratio_FD2":0, "ratio_FD1_count":1, "ratio_FD2_count":1}) # Check \ No newline at end of file + self.versus_test(opponent, expected_actions=actions, attrs={"P": 1.1, + "FD": 0, + "consecutive_defections": 19, + "ratio_FD1": 5, + "ratio_FD2": 0, + "ratio_FD1_count": 1, + "ratio_FD2_count": 1}) \ No newline at end of file From 1def399b152062196e4b26f8cc5a6e32d845336f Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Wed, 23 Aug 2017 13:15:05 +0100 Subject: [PATCH 13/28] Fix doctests --- docs/tutorials/advanced/classification_of_strategies.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/advanced/classification_of_strategies.rst b/docs/tutorials/advanced/classification_of_strategies.rst index c6203e89c..d769593a8 100644 --- a/docs/tutorials/advanced/classification_of_strategies.rst +++ b/docs/tutorials/advanced/classification_of_strategies.rst @@ -47,7 +47,7 @@ strategies:: ... } >>> strategies = axl.filtered_strategies(filterset) >>> len(strategies) - 72 + 73 Or, to find out how many strategies only use 1 turn worth of memory to make a decision:: From c5838bb5c971cb440594c43bfe33066bfe5b9172 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Thu, 24 Aug 2017 20:10:08 +0100 Subject: [PATCH 14/28] Modify code to conform PEP8 standard's. Remove unnecessary code. Signed-off-by: Mansour Hakem --- axelrod/strategies/axelrod_second.py | 173 +++++++++++------- .../tests/strategies/test_axelrod_second.py | 1 - training_data.csv | 0 3 files changed, 108 insertions(+), 66 deletions(-) create mode 100644 training_data.csv diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 3a18cd0e0..dcb07c930 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -213,59 +213,86 @@ class Tranquilizer(Player): Reversed engineered by: Owen Campbell, Will Guo and Mansour Hakem. - Description given in Axelrod's "More Effective Choice in the Prisoner's Dilemma" - paper: The rule normally cooperates but is ready to defect if the other player - defects too often. Thus the rule tends to cooperate for the first dozen - or two moves if the other player is cooperating, but then it throws in a + Description given in Axelrod's "More Effective Choice in the + Prisoner's Dilemma" paper: The rule normally cooperates but + is ready to defect if the other player defects too often. + Thus the rule tends to cooperate for the first dozen or two moves + if the other player is cooperating, but then it throws in a defection. If the other player continues to cooperate, then defections become more frequent. But as long as Tranquilizer is maintaining an average payoff of at least 2.25 points per move, it will never defect - twice in succession and it will not defect more than one-quarter of the time. + twice in succession and it will not defect more than + one-quarter of the time. - Has a variable, 'FD' which can be 0, 1 or 2. It has an initial value of 0 - Has a variable 'S', which counts the consecutive number of times the opponent has played D (i.e. it is reset to 0 if the opponent plays C). It has an initial value of 0. - Has a variable, 'C', which counts the number of times the opponent Cooperates - Has a variable 'AK' which increases each time a move is played whilst in state FD = 1. It has an initial value of 1. - Has a variable 'NK' which increases each time a move is played whilst in state FD = 2. It has an initial value of 1. - Has a variable 'AD' with an initial value of 5 - Has a variable 'NO with an initial value of 0 - When FD = 0: - If the opponent's last move (JA) was Cooperate, increase the value of C by 1 - If Score (K) < 1.75 * Move Number (M), play opponent's last move - If (1.75 * M) <= K < (2.25 * M): - Calculate Probability P: - P = 0.25 + C/M - 0.25*S + (K - L)/100 + 4/M - Where L is the opponent's score so far - If Random (R) <= P: - Cooperate - Else: - Defect - If K >= (2.25 * M): - Calculate probability P: - P = 0.95 - (AD + NO - 5)/15 + 1/M**2 - J/4 - Where J is the opponent's last move - If Random (R) <= P: - Cooperate - Else: - Set FD = 1 - Defect - When FD = 1: - Set FD = 2 - Set the variable 'AD': - AD = ((AD * AK) + 3 - (3 * J) + (2 * JA) - (JA * J)) / (AK + 1) - Where JA is the strategy's last move and J is the opponent's last move (C = 0, D = 1) - Increase the value of AK by 1 - Cooperate - When FD = 2: - Set FD = 0 - Set the variable 'NO': - NO = ((NO * NK) + 3 - (3 * J) + (2 * JA) - (JA * J) / (NK + 1) - Where JA the strategy's last move and J is the opponent's last move (C = 0, D = 1) - Increase the value of NK by 1 - Cooperate + - Has a variable, 'FD' which can be 0, 1 or 2. It has an initial value of 0 + - Has a variable 'S', which counts the consecutive number of + times the opponent has played D (i.e. it is reset to 0 if the opponent + plays C). It has an initial value of 0. + - Has a variable, 'C', which counts the number of times the opponent Cooperates + - Has a variable 'AK' which increases each time a move is played whilst in state + FD = 1. It has an initial value of 1. + - Has a variable 'NK' which increases each time a move is + played whilst in state FD = 2. It has an initial value of 1. + - Has a variable 'AD' with an initial value of 5 + - Has a variable 'NO with an initial value of 0 - Tranquilizer came in 27th place in Axelrod's second torunament. + Has a variable 'NO with an initial value of 0 + + + The strategy follows the following algorithm:: + + When FD = 0: + + If the opponent's last move (JA) was Cooperate, increase the value of C by 1 + If Score (K) < 1.75 * Move Number (M), play opponent's last move + If (1.75 * M) <= K < (2.25 * M): + + Calculate Probability P: + P = 0.25 + C/M - 0.25*S + (K - L)/100 + 4/M + Where L is the opponent's score so far + If Random (R) <= P: + + Cooperate + Else: + + Defect + + If K >= (2.25 * M): + + Calculate probability P: + P = 0.95 - (AD + NO - 5)/15 + 1/M**2 - J/4 + Where J is the opponent's last move + + If Random (R) <= P: + + Cooperate + + Else: + + Set FD = 1 + Defect + + When FD = 1: + + Set FD = 2 + Set the variable 'AD': + AD = ((AD * AK) + 3 - (3 * J) + (2 * JA) - (JA * J)) / (AK + 1) + Where JA and J are the last moves of the strategy and the opponent (C=0, D=1) + Increase the value of AK by 1 + Cooperate + + When FD = 2: + + Set FD = 0 + Set the variable 'NO': + NO = ((NO * NK) + 3 - (3 * J) + (2 * JA) - (JA * J) / (NK + 1) + Where JA and J are the last moves of the strategy and the opponent (C=0, D=1) + Increase the value of NK by 1 + Cooperate + + Tranquilizer came in 27th place in Axelrod's second torunament. + Names: @@ -299,61 +326,77 @@ def __init__(self): self.dict = {C: 0, D: 1} - def update_stateFD(self, opponent): # Calculates the ratioFD values and P values, as well as sets the states of FD at the start of each turn - + def update_stateFD(self, opponent): + + """ + Calculates the ratioFD values and P values, as well as sets the + states of FD at the start of each turn + """ self.current_score = compute_final_score(zip(self.history, opponent.history)) if self.FD == 2: self.FD = 0 - self.ratio_FD2 = ((self.ratio_FD2 * self.ratio_FD2_count + 3 - 3 * self.dict[opponent.history[-1]]) + 2 * self.dict[ - self.history[-1]] - self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) / (self.ratio_FD2_count + 1) + self.ratio_FD2 = (self.ratio_FD2 * self.ratio_FD2_count) + self.ratio_FD2 += 3 - (3 * self.dict[opponent.history[-1]]) + self.ratio_FD2 += (2 * self.dict[self.history[-1]]) + self.ratio_FD2 -= self.dict[opponent.history[-1]] * self.dict[self.history[-1]] + self.ratio_FD2 /= (self.ratio_FD2_count + 1) self.ratio_FD2_count += 1 elif self.FD == 1: self.FD = 2 - self.ratio_FD1 = ((self.ratio_FD1 * self.ratio_FD1_count + 3 - 3 * self.dict[opponent.history[-1]]) + 2 * self.dict[self.history[-1]] - self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) / (self.ratio_FD1_count + 1) + self.ratio_FD1 = ((self.ratio_FD1 * self.ratio_FD1_count) + self.ratio_FD1 += 3 - (3 * self.dict[opponent.history[-1]]) + self.ratio_FD1 += 2 * self.dict[self.history[-1]] + self.ratio_FD1 -= self.dict[opponent.history[-1]] * self.dict[self.history[-1]] + self.ratio_FD1 /= (self.ratio_FD1_count + 1) self.ratio_FD1_count += 1 else: if (self.current_score[0] / (len(self.history))) >= 2.25: - self.P = .95 - ((self.ratio_FD1) + (self.ratio_FD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - (self.dict[opponent.history[-1]] / 4) + self.P = .95 - ((self.ratio_FD1) + (self.ratio_FD2) - 5) / 15 + self.P += 1 / (len(self.history) + 1 ** 2) + self.P -= (self.dict[opponent.history[-1]] / 4) self.P = round(self.P, 4) self.score = "good" elif (self.current_score[0] / (len(self.history))) >= 1.75: - self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutive_defections * .25) + (self.current_score[0] - self.current_score[1]) / 100 + (4 / (len(self.history) + 1)) + self.P = .25 + opponent.cooperations / (len(self.history)) + self.P -= (self.consecutive_defections * .25) + self.P += (self.current_score[0] - self.current_score[1]) / 100 + self.P += (4 / (len(self.history) + 1)) self.P = round(self.P, 4) self.score = "average" def strategy(self, opponent: Player) -> Action: - randomValue = random.random() # Random float between 0 and 1 to decide whether the player should defect or not + randomValue = random.random() - current_score = compute_final_score(zip(self.history, opponent.history)) # Calculates current score + current_score = compute_final_score(zip(self.history, opponent.history)) - if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquilizer cooperates + if len(self.history) == 0: return C - else: # If round number != 0, exectue the stateFD(self, opponent) function + else: Tranquilizer.update_stateFD(self, opponent) - if opponent.history[-1] == D: # Calculates number of consecutive defections + if opponent.history[-1] == D: self.consecutive_defections += 1 else: self.consecutive_defections = 0 - if self.FD != 0: # If FD != 0, then return value dependant on number of consecutive defections + if self.FD != 0: if self.consecutive_defections == 0: return C else: return D - elif (self.current_score[0] / (len(self.history))) < 1.75: # If score is too low, copy opponent + elif (self.current_score[0] / (len(self.history))) < 1.75: return opponent.history[-1] # "If you can't beat them join'em" else: - if (randomValue < self.P): # Comapares randomValue to that of the calculated variable 'P' - if self.consecutive_defections == 0: # Decides what to return (based on previous move), give randomValue < 'P' + if (randomValue < self.P): + if self.consecutive_defections == 0: return C else: return self.history[-1] else: - if self.score == "good": # If score is above 2.25 && randomValue > P, set FD = 1, and defect + if self.score == "good": self.FD = 1 - else: # If score is greater than 1.75, but lower than 2.25 while randomValue > P, defect + else: pass return D \ No newline at end of file diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 234df6837..4e630ab0d 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -5,7 +5,6 @@ import axelrod from .test_player import TestPlayer -from axelrod.interaction_utils import compute_final_score C, D = axelrod.Action.C, axelrod.Action.D diff --git a/training_data.csv b/training_data.csv new file mode 100644 index 000000000..e69de29bb From a2cfe714481f20a737491d204aa854672c82cb86 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Thu, 24 Aug 2017 20:10:08 +0100 Subject: [PATCH 15/28] Modify code to conform PEP8 standard's. Remove unnecessary code. Signed-off-by: Mansour Hakem --- axelrod/strategies/axelrod_second.py | 173 +++++++++++------- .../tests/strategies/test_axelrod_second.py | 3 +- training_data.csv | 0 3 files changed, 109 insertions(+), 67 deletions(-) create mode 100644 training_data.csv diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 3a18cd0e0..876cde5e8 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -213,59 +213,86 @@ class Tranquilizer(Player): Reversed engineered by: Owen Campbell, Will Guo and Mansour Hakem. - Description given in Axelrod's "More Effective Choice in the Prisoner's Dilemma" - paper: The rule normally cooperates but is ready to defect if the other player - defects too often. Thus the rule tends to cooperate for the first dozen - or two moves if the other player is cooperating, but then it throws in a + Description given in Axelrod's "More Effective Choice in the + Prisoner's Dilemma" paper: The rule normally cooperates but + is ready to defect if the other player defects too often. + Thus the rule tends to cooperate for the first dozen or two moves + if the other player is cooperating, but then it throws in a defection. If the other player continues to cooperate, then defections become more frequent. But as long as Tranquilizer is maintaining an average payoff of at least 2.25 points per move, it will never defect - twice in succession and it will not defect more than one-quarter of the time. + twice in succession and it will not defect more than + one-quarter of the time. - Has a variable, 'FD' which can be 0, 1 or 2. It has an initial value of 0 - Has a variable 'S', which counts the consecutive number of times the opponent has played D (i.e. it is reset to 0 if the opponent plays C). It has an initial value of 0. - Has a variable, 'C', which counts the number of times the opponent Cooperates - Has a variable 'AK' which increases each time a move is played whilst in state FD = 1. It has an initial value of 1. - Has a variable 'NK' which increases each time a move is played whilst in state FD = 2. It has an initial value of 1. - Has a variable 'AD' with an initial value of 5 - Has a variable 'NO with an initial value of 0 - When FD = 0: - If the opponent's last move (JA) was Cooperate, increase the value of C by 1 - If Score (K) < 1.75 * Move Number (M), play opponent's last move - If (1.75 * M) <= K < (2.25 * M): - Calculate Probability P: - P = 0.25 + C/M - 0.25*S + (K - L)/100 + 4/M - Where L is the opponent's score so far - If Random (R) <= P: - Cooperate - Else: - Defect - If K >= (2.25 * M): - Calculate probability P: - P = 0.95 - (AD + NO - 5)/15 + 1/M**2 - J/4 - Where J is the opponent's last move - If Random (R) <= P: - Cooperate - Else: - Set FD = 1 - Defect - When FD = 1: - Set FD = 2 - Set the variable 'AD': - AD = ((AD * AK) + 3 - (3 * J) + (2 * JA) - (JA * J)) / (AK + 1) - Where JA is the strategy's last move and J is the opponent's last move (C = 0, D = 1) - Increase the value of AK by 1 - Cooperate - When FD = 2: - Set FD = 0 - Set the variable 'NO': - NO = ((NO * NK) + 3 - (3 * J) + (2 * JA) - (JA * J) / (NK + 1) - Where JA the strategy's last move and J is the opponent's last move (C = 0, D = 1) - Increase the value of NK by 1 - Cooperate + - Has a variable, 'FD' which can be 0, 1 or 2. It has an initial value of 0 + - Has a variable 'S', which counts the consecutive number of + times the opponent has played D (i.e. it is reset to 0 if the opponent + plays C). It has an initial value of 0. + - Has a variable, 'C', which counts the number of times the opponent Cooperates + - Has a variable 'AK' which increases each time a move is played whilst in state + FD = 1. It has an initial value of 1. + - Has a variable 'NK' which increases each time a move is + played whilst in state FD = 2. It has an initial value of 1. + - Has a variable 'AD' with an initial value of 5 + - Has a variable 'NO with an initial value of 0 - Tranquilizer came in 27th place in Axelrod's second torunament. + Has a variable 'NO with an initial value of 0 + + + The strategy follows the following algorithm:: + + When FD = 0: + + If the opponent's last move (JA) was Cooperate, increase the value of C by 1 + If Score (K) < 1.75 * Move Number (M), play opponent's last move + If (1.75 * M) <= K < (2.25 * M): + + Calculate Probability P: + P = 0.25 + C/M - 0.25*S + (K - L)/100 + 4/M + Where L is the opponent's score so far + If Random (R) <= P: + + Cooperate + Else: + + Defect + + If K >= (2.25 * M): + + Calculate probability P: + P = 0.95 - (AD + NO - 5)/15 + 1/M**2 - J/4 + Where J is the opponent's last move + + If Random (R) <= P: + + Cooperate + + Else: + + Set FD = 1 + Defect + + When FD = 1: + + Set FD = 2 + Set the variable 'AD': + AD = ((AD * AK) + 3 - (3 * J) + (2 * JA) - (JA * J)) / (AK + 1) + Where JA and J are the last moves of the strategy and the opponent (C=0, D=1) + Increase the value of AK by 1 + Cooperate + + When FD = 2: + + Set FD = 0 + Set the variable 'NO': + NO = ((NO * NK) + 3 - (3 * J) + (2 * JA) - (JA * J) / (NK + 1) + Where JA and J are the last moves of the strategy and the opponent (C=0, D=1) + Increase the value of NK by 1 + Cooperate + + Tranquilizer came in 27th place in Axelrod's second torunament. + Names: @@ -299,61 +326,77 @@ def __init__(self): self.dict = {C: 0, D: 1} - def update_stateFD(self, opponent): # Calculates the ratioFD values and P values, as well as sets the states of FD at the start of each turn - + def update_stateFD(self, opponent): + + """ + Calculates the ratioFD values and P values, as well as sets the + states of FD at the start of each turn + """ self.current_score = compute_final_score(zip(self.history, opponent.history)) if self.FD == 2: self.FD = 0 - self.ratio_FD2 = ((self.ratio_FD2 * self.ratio_FD2_count + 3 - 3 * self.dict[opponent.history[-1]]) + 2 * self.dict[ - self.history[-1]] - self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) / (self.ratio_FD2_count + 1) + self.ratio_FD2 = (self.ratio_FD2 * self.ratio_FD2_count) + self.ratio_FD2 += 3 - (3 * self.dict[opponent.history[-1]]) + self.ratio_FD2 += (2 * self.dict[self.history[-1]]) + self.ratio_FD2 -= self.dict[opponent.history[-1]] * self.dict[self.history[-1]] + self.ratio_FD2 /= (self.ratio_FD2_count + 1) self.ratio_FD2_count += 1 elif self.FD == 1: self.FD = 2 - self.ratio_FD1 = ((self.ratio_FD1 * self.ratio_FD1_count + 3 - 3 * self.dict[opponent.history[-1]]) + 2 * self.dict[self.history[-1]] - self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) / (self.ratio_FD1_count + 1) + self.ratio_FD1 = self.ratio_FD1 * self.ratio_FD1_count + self.ratio_FD1 += 3 - (3 * self.dict[opponent.history[-1]]) + self.ratio_FD1 += 2 * self.dict[self.history[-1]] + self.ratio_FD1 -= self.dict[opponent.history[-1]] * self.dict[self.history[-1]] + self.ratio_FD1 /= (self.ratio_FD1_count + 1) self.ratio_FD1_count += 1 else: if (self.current_score[0] / (len(self.history))) >= 2.25: - self.P = .95 - ((self.ratio_FD1) + (self.ratio_FD2) - 5) / 15 + 1 / (len(self.history) + 1) ** 2 - (self.dict[opponent.history[-1]] / 4) + self.P = .95 - ((self.ratio_FD1) + (self.ratio_FD2) - 5) / 15 + self.P += 1 / (len(self.history) + 1 ** 2) + self.P -= (self.dict[opponent.history[-1]] / 4) self.P = round(self.P, 4) self.score = "good" elif (self.current_score[0] / (len(self.history))) >= 1.75: - self.P = .25 + opponent.cooperations / (len(self.history)) - (self.consecutive_defections * .25) + (self.current_score[0] - self.current_score[1]) / 100 + (4 / (len(self.history) + 1)) + self.P = .25 + opponent.cooperations / (len(self.history)) + self.P -= (self.consecutive_defections * .25) + self.P += (self.current_score[0] - self.current_score[1]) / 100 + self.P += (4 / (len(self.history) + 1)) self.P = round(self.P, 4) self.score = "average" def strategy(self, opponent: Player) -> Action: - randomValue = random.random() # Random float between 0 and 1 to decide whether the player should defect or not + randomValue = random.random() - current_score = compute_final_score(zip(self.history, opponent.history)) # Calculates current score + current_score = compute_final_score(zip(self.history, opponent.history)) - if len(self.history) == 0: # Assumes opponent will cooperate, hence, Tranquilizer cooperates + if len(self.history) == 0: return C - else: # If round number != 0, exectue the stateFD(self, opponent) function + else: Tranquilizer.update_stateFD(self, opponent) - if opponent.history[-1] == D: # Calculates number of consecutive defections + if opponent.history[-1] == D: self.consecutive_defections += 1 else: self.consecutive_defections = 0 - if self.FD != 0: # If FD != 0, then return value dependant on number of consecutive defections + if self.FD != 0: if self.consecutive_defections == 0: return C else: return D - elif (self.current_score[0] / (len(self.history))) < 1.75: # If score is too low, copy opponent + elif (self.current_score[0] / (len(self.history))) < 1.75: return opponent.history[-1] # "If you can't beat them join'em" else: - if (randomValue < self.P): # Comapares randomValue to that of the calculated variable 'P' - if self.consecutive_defections == 0: # Decides what to return (based on previous move), give randomValue < 'P' + if (randomValue < self.P): + if self.consecutive_defections == 0: return C else: return self.history[-1] else: - if self.score == "good": # If score is above 2.25 && randomValue > P, set FD = 1, and defect + if self.score == "good": self.FD = 1 - else: # If score is greater than 1.75, but lower than 2.25 while randomValue > P, defect + else: pass return D \ No newline at end of file diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 234df6837..ab85c996d 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -5,7 +5,6 @@ import axelrod from .test_player import TestPlayer -from axelrod.interaction_utils import compute_final_score C, D = axelrod.Action.C, axelrod.Action.D @@ -193,7 +192,7 @@ def test_init(self): self.assertEqual(player.score, None) self.current_score = 0 - def test_score_bad(self): + def test_strategy(self): # Tests whether TitForTat is played given score is below 1.75 diff --git a/training_data.csv b/training_data.csv new file mode 100644 index 000000000..e69de29bb From 18a5fb4c326401fed32eec10386a44888d01f398 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Thu, 24 Aug 2017 23:20:14 +0100 Subject: [PATCH 16/28] Fix equation in strategy Signed-off-by: Mansour Hakem --- axelrod/strategies/axelrod_second.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index d49a5e38d..36d118703 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -345,15 +345,9 @@ def update_stateFD(self, opponent): elif self.FD == 1: self.FD = 2 self.ratio_FD1 = (self.ratio_FD1 * self.ratio_FD1_count) -<<<<<<< HEAD self.ratio_FD1 += (3 - (3 * self.dict[opponent.history[-1]])) self.ratio_FD1 += (2 * self.dict[self.history[-1]]) self.ratio_FD1 -= (self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) -======= - self.ratio_FD1 += 3 - (3 * self.dict[opponent.history[-1]]) - self.ratio_FD1 += 2 * self.dict[self.history[-1]] - self.ratio_FD1 -= self.dict[opponent.history[-1]] * self.dict[self.history[-1]] ->>>>>>> f7018cc78d8c4c1b7ccc779bb1c45794e2bd6251 self.ratio_FD1 /= (self.ratio_FD1_count + 1) self.ratio_FD1_count += 1 else: From be6a9e1603fb4048ba1ac1ecbfe5e533971ae95d Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Fri, 25 Aug 2017 07:51:52 +0100 Subject: [PATCH 17/28] Fix styling --- axelrod/strategies/axelrod_second.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 36d118703..0e7a7ade8 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -217,7 +217,7 @@ class Tranquilizer(Player): Prisoner's Dilemma" paper: The rule normally cooperates but is ready to defect if the other player defects too often. Thus the rule tends to cooperate for the first dozen or two moves - if the other player is cooperating, but then it throws in a + if the other player is cooperating, but then it throws in a defection. If the other player continues to cooperate, then defections become more frequent. But as long as Tranquilizer is maintaining an average payoff of at least 2.25 points per move, it will never defect @@ -227,17 +227,16 @@ class Tranquilizer(Player): - Has a variable, 'FD' which can be 0, 1 or 2. It has an initial value of 0 - Has a variable 'S', which counts the consecutive number of - times the opponent has played D (i.e. it is reset to 0 if the opponent - plays C). It has an initial value of 0. + times the opponent has played D (i.e. it is reset to 0 if the opponent + plays C). It has an initial value of 0. - Has a variable, 'C', which counts the number of times the opponent Cooperates - Has a variable 'AK' which increases each time a move is played whilst in state - FD = 1. It has an initial value of 1. + FD = 1. It has an initial value of 1. - Has a variable 'NK' which increases each time a move is - played whilst in state FD = 2. It has an initial value of 1. + played whilst in state FD = 2. It has an initial value of 1. - Has a variable 'AD' with an initial value of 5 - Has a variable 'NO with an initial value of 0 - - Has a variable 'NO with an initial value of 0 + - Has a variable 'NO with an initial value of 0 The strategy follows the following algorithm:: From d07e85f957c67738804747a063ca2dfbf81e8bb0 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Fri, 25 Aug 2017 19:06:39 +0100 Subject: [PATCH 18/28] Change varaible names. Fix move number bug and hence modify tests. PEP8 Styling. --- axelrod/strategies/axelrod_second.py | 93 +++++----- .../tests/strategies/test_axelrod_second.py | 171 +++++++++--------- 2 files changed, 138 insertions(+), 126 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 0e7a7ade8..b3c25888c 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -227,13 +227,13 @@ class Tranquilizer(Player): - Has a variable, 'FD' which can be 0, 1 or 2. It has an initial value of 0 - Has a variable 'S', which counts the consecutive number of - times the opponent has played D (i.e. it is reset to 0 if the opponent - plays C). It has an initial value of 0. + times the opponent has played D (i.e. it is reset to 0 if the opponent + plays C). It has an initial value of 0. - Has a variable, 'C', which counts the number of times the opponent Cooperates - Has a variable 'AK' which increases each time a move is played whilst in state - FD = 1. It has an initial value of 1. + FD = 1. It has an initial value of 1. - Has a variable 'NK' which increases each time a move is - played whilst in state FD = 2. It has an initial value of 1. + played whilst in state FD = 2. It has an initial value of 1. - Has a variable 'AD' with an initial value of 5 - Has a variable 'NO with an initial value of 0 - Has a variable 'NO with an initial value of 0 @@ -295,7 +295,6 @@ class Tranquilizer(Player): Names: - - Craig Feathers: [Axelrod1980]_ - Tranquilizer: [Axelrod1980]_ """ @@ -313,19 +312,19 @@ class Tranquilizer(Player): # Initialised atributes def __init__(self): super().__init__() - self.FD = 0 + self.num_turns_after_good_defection = 0 self.consecutive_defections = 0 - self.ratio_FD1 = 5 - self.ratio_FD2 = 0 - self.ratio_FD1_count = 1 - self.ratio_FD2_count = 1 + self.one_turn_after_good_defection_ratio= 5 + self.two_turns_after_good_defection_ratio= 0 + self.one_turn_after_good_defection_ratio_count = 1 + self.two_turns_after_good_defection_ratio_count = 1 self.score = None - self.P = 1.1 + self.probability = 1.1 self.current_score = 0 self.dict = {C: 0, D: 1} - def update_stateFD(self, opponent): + def update_state(self, opponent): """ Calculates the ratioFD values and P values, as well as sets the @@ -333,35 +332,47 @@ def update_stateFD(self, opponent): """ self.current_score = compute_final_score(zip(self.history, opponent.history)) - if self.FD == 2: - self.FD = 0 - self.ratio_FD2 = (self.ratio_FD2 * self.ratio_FD2_count) - self.ratio_FD2 += 3 - (3 * self.dict[opponent.history[-1]]) - self.ratio_FD2 += (2 * self.dict[self.history[-1]]) - self.ratio_FD2 -= self.dict[opponent.history[-1]] * self.dict[self.history[-1]] - self.ratio_FD2 /= (self.ratio_FD2_count + 1) - self.ratio_FD2_count += 1 - elif self.FD == 1: - self.FD = 2 - self.ratio_FD1 = (self.ratio_FD1 * self.ratio_FD1_count) - self.ratio_FD1 += (3 - (3 * self.dict[opponent.history[-1]])) - self.ratio_FD1 += (2 * self.dict[self.history[-1]]) - self.ratio_FD1 -= (self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) - self.ratio_FD1 /= (self.ratio_FD1_count + 1) - self.ratio_FD1_count += 1 + if self.num_turns_after_good_defection == 2: + self.num_turns_after_good_defection = 0 + self.two_turns_after_good_defection_ratio = ( + ((self.two_turns_after_good_defection_ratio + * self.two_turns_after_good_defection_ratio_count) + + (3 - (3 * self.dict[opponent.history[-1]])) + + (2 * self.dict[self.history[-1]]) + - ((self.dict[opponent.history[-1]] * self.dict[self.history[-1]]))) + / (self.two_turns_after_good_defection_ratio_count + 1) + ) + + self.two_turns_after_good_defection_ratio_count += 1 + elif self.num_turns_after_good_defection == 1: + self.num_turns_after_good_defection = 2 + self.one_turn_after_good_defection_ratio = ( + (self.one_turn_after_good_defection_ratio + * self.one_turn_after_good_defection_ratio_count) + + (3 - (3 * self.dict[opponent.history[-1]])) + + (2 * self.dict[self.history[-1]]) + - (self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) + / (self.one_turn_after_good_defection_ratio_count + 1) + ) + self.one_turn_after_good_defection_ratio_count += 1 else: if (self.current_score[0] / (len(self.history))) >= 2.25: - self.P = (.95 - (((self.ratio_FD1) + (self.ratio_FD2) - 5) / 15)) - self.P += (1 / ((len(self.history) + 1) ** 2)) - self.P -= (self.dict[opponent.history[-1]] / 4) - self.P = round(self.P, 4) + self.probability = ( + (.95 - (((self.one_turn_after_good_defection_ratio) + + (self.two_turns_after_good_defection_ratio) - 5) / 15)) + + (1 / (((len(self.history))) ** 2)) + - (self.dict[opponent.history[-1]] / 4) + ) + self.probability = round(self.probability, 4) self.score = "good" elif (self.current_score[0] / (len(self.history))) >= 1.75: - self.P = .25 + opponent.cooperations / (len(self.history)) - self.P -= (self.consecutive_defections * .25) - self.P += ((self.current_score[0] - self.current_score[1]) / 100) - self.P += (4 / (len(self.history) + 1)) - self.P = round(self.P, 4) + self.probability = ( + (.25 + (opponent.cooperations / (len(self.history)))) + - (self.consecutive_defections * .25) + + ((self.current_score[0] - self.current_score[1]) / 100) + + (4 / (len(self.history))) + ) + self.probability = round(self.probability, 4) self.score = "average" def strategy(self, opponent: Player) -> Action: @@ -373,13 +384,13 @@ def strategy(self, opponent: Player) -> Action: if len(self.history) == 0: return C else: - Tranquilizer.update_stateFD(self, opponent) + Tranquilizer.update_state(self, opponent) if opponent.history[-1] == D: self.consecutive_defections += 1 else: self.consecutive_defections = 0 - if self.FD != 0: + if self.num_turns_after_good_defection != 0: if self.consecutive_defections == 0: return C else: @@ -387,14 +398,14 @@ def strategy(self, opponent: Player) -> Action: elif (self.current_score[0] / (len(self.history))) < 1.75: return opponent.history[-1] # "If you can't beat them join'em" else: - if (randomValue < self.P): + if (randomValue < self.probability): if self.consecutive_defections == 0: return C else: return self.history[-1] else: if self.score == "good": - self.FD = 1 + self.num_turns_after_good_defection = 1 else: pass return D diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index ab85c996d..eecbac989 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -182,13 +182,13 @@ def test_init(self): player = axelrod.Tranquilizer() - self.assertEqual(player.P, 1.1) - self.assertEqual(player.FD, 0) + self.assertEqual(player.probability, 1.1) + self.assertEqual(player.num_turns_after_good_defection, 0) self.assertEqual(player.consecutive_defections, 0) - self.assertEqual(player.ratio_FD1, 5) - self.assertEqual(player.ratio_FD2, 0) - self.assertEqual(player.ratio_FD1_count, 1) - self.assertEqual(player.ratio_FD2_count, 1) + self.assertEqual(player.one_turn_after_good_defection_ratio, 5) + self.assertEqual(player.two_turns_after_good_defection_ratio, 0) + self.assertEqual(player.one_turn_after_good_defection_ratio_count, 1) + self.assertEqual(player.two_turns_after_good_defection_ratio_count, 1) self.assertEqual(player.score, None) self.current_score = 0 @@ -198,126 +198,127 @@ def test_strategy(self): opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 20 - self.versus_test(opponent, expected_actions=actions, attrs={"P": 1.1, - "FD": 0, + self.versus_test(opponent, expected_actions=actions, attrs={"probability": 1.1, + "num_turns_after_good_defection": 0, "consecutive_defections": 20, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 1, - "ratio_FD2_count": 1}) + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) opponent = axelrod.MockPlayer([C] * 2 + [D] * 9 + [C] * 4 ) actions = [(C, C)] + [(C, C)] + [(C, D)] * 2 + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 - self.versus_test(opponent = opponent, expected_actions=actions, attrs={"P": 1.8667, - "FD": 0, + self.versus_test(opponent = opponent, expected_actions=actions, attrs={"probability": 2.2, + "num_turns_after_good_defection": 0, "consecutive_defections": 0, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 1, - "ratio_FD2_count": 1}) + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) # If score is between 1.75 and 2.25, may cooperate or defect opponent = axelrod.MockPlayer(actions=[D] * 8 + [C] * 5 + [D]) actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 4 # average_score_per_turn = 1.875 actions += ([(C, D)]) # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"P": 0.9203, - "FD": 0, + self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"probability": 0.9423, + "num_turns_after_good_defection": 0, "consecutive_defections": 0, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 1, - "ratio_FD2_count": 1}) + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) opponent = axelrod.MockPlayer(actions=[D] * 8 + [C] * 4 + [D]) actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 # average_score_per_turn = 1.875 actions += [(D, D)] # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=10, attrs={"P": 0.891, - "FD": 0, + self.versus_test(opponent, expected_actions=actions, seed=10, attrs={"probability": 0.9167, + "num_turns_after_good_defection": 0, "consecutive_defections": 0, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 1, - "ratio_FD2_count": 1}) + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) - # If score is greater than 2.25 either cooperate or defect, if turn number <= 4; cooperate + # If score is greater than 2.25 either cooperate or defect, if turn number <= 5; cooperate opponent = axelrod.MockPlayer(actions=[C] * 5) - actions = [(C, C)] * 4 + [(C, C)] - self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"P": 0.99, - "FD": 0, + actions = [(C, C)] * 5 + self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"probability": 1.0125, + "num_turns_after_good_defection": 0, "consecutive_defections": 0, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 1, - "ratio_FD2_count": 1}) + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) - opponent = axelrod.MockPlayer(actions=[C] * 5) - actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, - "FD": 1, - "consecutive_defections": 0, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 1, - "ratio_FD2_count": 1}) + opponent = axelrod.MockPlayer(actions=[C] * 6) + actions = [(C, C)] * 5 + [(D, C)] + self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + "num_turns_after_good_defection": 1, + "consecutive_defections": 0, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) # Given score per turn is greater than 2.25, Tranquilizer will never defect twice in a row - opponent = axelrod.MockPlayer(actions = [C] * 6) - actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, - "FD": 2, + opponent = axelrod.MockPlayer(actions = [C] * 7) + actions = [(C, C)] * 5 + [(D, C), (C, C)] + self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + "num_turns_after_good_defection": 2, "consecutive_defections": 0, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 2, - "ratio_FD2_count": 1}) + "one_turn_after_good_defection_ratio": 10, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 2, + "two_turns_after_good_defection_ratio_count": 1}) + # Tests defection probability if score == good - opponent = axelrod.MockPlayer(actions=[C] * 5) - actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, - "FD": 1, + opponent = axelrod.MockPlayer(actions=[C] * 6) + actions = [(C, C)] * 5 + [(D, C)] + self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + "num_turns_after_good_defection": 1, "consecutive_defections": 0, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 1, - "ratio_FD2_count": 1}) + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) # Ensures FD1 values are calculated - opponent = axelrod.MockPlayer(actions=[C] * 6) - actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, - "FD": 2, + opponent = axelrod.MockPlayer(actions=[C] * 7) + actions = [(C, C)] * 5 + [(D, C), (C, C)] + self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + "num_turns_after_good_defection": 2, "consecutive_defections": 0, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 2, - "ratio_FD2_count": 1}) + "one_turn_after_good_defection_ratio": 10, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 2, + "two_turns_after_good_defection_ratio_count": 1}) # Ensures FD2 values are calculated - opponent = axelrod.MockPlayer(actions=[C] * 6) - actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] + [(C, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"P": 0.99, - "FD": 0, + opponent = axelrod.MockPlayer(actions=[C] * 7) + actions = [(C, C)] * 5 + [(D, C)] + [(C, C)] + [(C, C)] + self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + "num_turns_after_good_defection": 0, "consecutive_defections": 0, - "ratio_FD1": 5, - "ratio_FD2": 1.5, - "ratio_FD1_count": 2, - "ratio_FD2_count": 2}) + "one_turn_after_good_defection_ratio": 10, + "two_turns_after_good_defection_ratio": 1.5, + "one_turn_after_good_defection_ratio_count": 2, + "two_turns_after_good_defection_ratio_count": 2}) # Ensures scores are being counted opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 19 - self.versus_test(opponent, expected_actions=actions, attrs={"P": 1.1, - "FD": 0, + self.versus_test(opponent, expected_actions=actions, attrs={"probability": 1.1, + "num_turns_after_good_defection": 0, "consecutive_defections": 19, - "ratio_FD1": 5, - "ratio_FD2": 0, - "ratio_FD1_count": 1, - "ratio_FD2_count": 1}) \ No newline at end of file + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) \ No newline at end of file From 7c2b155054c5f075588915cfd1e55f51474696ad Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Sat, 26 Aug 2017 00:44:14 +0100 Subject: [PATCH 19/28] Fix move number bug and hence modify tests. PEP8 Styling. --- axelrod/strategies/axelrod_second.py | 43 +++++++------- .../tests/strategies/test_axelrod_second.py | 58 +++++++++---------- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index b3c25888c..d1f8f3655 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -227,13 +227,13 @@ class Tranquilizer(Player): - Has a variable, 'FD' which can be 0, 1 or 2. It has an initial value of 0 - Has a variable 'S', which counts the consecutive number of - times the opponent has played D (i.e. it is reset to 0 if the opponent - plays C). It has an initial value of 0. + times the opponent has played D (i.e. it is reset to 0 if the opponent + plays C). It has an initial value of 0. - Has a variable, 'C', which counts the number of times the opponent Cooperates - Has a variable 'AK' which increases each time a move is played whilst in state - FD = 1. It has an initial value of 1. + FD = 1. It has an initial value of 1. - Has a variable 'NK' which increases each time a move is - played whilst in state FD = 2. It has an initial value of 1. + played whilst in state FD = 2. It has an initial value of 1. - Has a variable 'AD' with an initial value of 5 - Has a variable 'NO with an initial value of 0 - Has a variable 'NO with an initial value of 0 @@ -309,6 +309,7 @@ class Tranquilizer(Player): 'manipulates_state': False } + # Initialised atributes def __init__(self): super().__init__() @@ -336,42 +337,43 @@ def update_state(self, opponent): self.num_turns_after_good_defection = 0 self.two_turns_after_good_defection_ratio = ( ((self.two_turns_after_good_defection_ratio - * self.two_turns_after_good_defection_ratio_count) + * self.two_turns_after_good_defection_ratio_count) + (3 - (3 * self.dict[opponent.history[-1]])) + (2 * self.dict[self.history[-1]]) - - ((self.dict[opponent.history[-1]] * self.dict[self.history[-1]]))) + - ((self.dict[opponent.history[-1]] + * self.dict[self.history[-1]]))) / (self.two_turns_after_good_defection_ratio_count + 1) ) - self.two_turns_after_good_defection_ratio_count += 1 elif self.num_turns_after_good_defection == 1: self.num_turns_after_good_defection = 2 self.one_turn_after_good_defection_ratio = ( - (self.one_turn_after_good_defection_ratio + ((self.one_turn_after_good_defection_ratio * self.one_turn_after_good_defection_ratio_count) + (3 - (3 * self.dict[opponent.history[-1]])) + (2 * self.dict[self.history[-1]]) - - (self.dict[opponent.history[-1]] * self.dict[self.history[-1]]) + - (self.dict[opponent.history[-1]] + * self.dict[self.history[-1]])) / (self.one_turn_after_good_defection_ratio_count + 1) ) self.one_turn_after_good_defection_ratio_count += 1 else: - if (self.current_score[0] / (len(self.history))) >= 2.25: + if (self.current_score[0] / ((len(self.history)) + 1)) >= 2.25: self.probability = ( - (.95 - (((self.one_turn_after_good_defection_ratio) + (.95 - (((self.one_turn_after_good_defection_ratio) + (self.two_turns_after_good_defection_ratio) - 5) / 15)) - + (1 / (((len(self.history))) ** 2)) + + (1 / (((len(self.history))+1) ** 2)) - (self.dict[opponent.history[-1]] / 4) ) self.probability = round(self.probability, 4) self.score = "good" - elif (self.current_score[0] / (len(self.history))) >= 1.75: + elif (self.current_score[0] / ((len(self.history)) + 1)) >= 1.75: self.probability = ( - (.25 + (opponent.cooperations / (len(self.history)))) + (.25 + (opponent.cooperations / ((len(self.history)) + 1))) - (self.consecutive_defections * .25) - + ((self.current_score[0] - self.current_score[1]) / 100) - + (4 / (len(self.history))) - ) + + ((self.current_score[0] + - self.current_score[1]) / 100) + + (4 / ((len(self.history)) + 1))) self.probability = round(self.probability, 4) self.score = "average" @@ -395,10 +397,10 @@ def strategy(self, opponent: Player) -> Action: return C else: return D - elif (self.current_score[0] / (len(self.history))) < 1.75: + elif (self.current_score[0] / ((len(self.history)) + 1)) < 1.75: return opponent.history[-1] # "If you can't beat them join'em" else: - if (randomValue < self.probability): + if (randomValue <= self.probability): if self.consecutive_defections == 0: return C else: @@ -406,7 +408,6 @@ def strategy(self, opponent: Player) -> Action: else: if self.score == "good": self.num_turns_after_good_defection = 1 - else: - pass return D + \ No newline at end of file diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index eecbac989..1814634b0 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -206,9 +206,9 @@ def test_strategy(self): "one_turn_after_good_defection_ratio_count": 1, "two_turns_after_good_defection_ratio_count": 1}) - opponent = axelrod.MockPlayer([C] * 2 + [D] * 9 + [C] * 4 ) - actions = [(C, C)] + [(C, C)] + [(C, D)] * 2 + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 - self.versus_test(opponent = opponent, expected_actions=actions, attrs={"probability": 2.2, + opponent = axelrod.MockPlayer([C] * 2 + [D] * 8 + [C] * 4 ) + actions = [(C, C)] + [(C, C)] + [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 + self.versus_test(opponent = opponent, expected_actions=actions, attrs={"probability": 2.25, "num_turns_after_good_defection": 0, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -217,9 +217,9 @@ def test_strategy(self): "two_turns_after_good_defection_ratio_count": 1}) # If score is between 1.75 and 2.25, may cooperate or defect - opponent = axelrod.MockPlayer(actions=[D] * 8 + [C] * 5 + [D]) - actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 4 - # average_score_per_turn = 1.875 + opponent = axelrod.MockPlayer(actions=[D] * 7 + [C] * 5 + [D]) + actions = [(C, D)] + [(D, D)] * 6 + [(D, C)] + [(C, C)] * 4 + # average_score_per_turn = 1.77 actions += ([(C, D)]) # <-- Random self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"probability": 0.9423, "num_turns_after_good_defection": 0, @@ -229,11 +229,11 @@ def test_strategy(self): "one_turn_after_good_defection_ratio_count": 1, "two_turns_after_good_defection_ratio_count": 1}) - opponent = axelrod.MockPlayer(actions=[D] * 8 + [C] * 4 + [D]) - actions = [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 - # average_score_per_turn = 1.875 + opponent = axelrod.MockPlayer(actions=[D] * 7 + [C] * 5 + [D]) + actions = [(C, D)] + [(D, D)] * 6 + [(D, C)] + [(C, C)] * 4 + # average_score_per_turn = 1.85 actions += [(D, D)] # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=10, attrs={"probability": 0.9167, + self.versus_test(opponent, expected_actions=actions, seed=10, attrs={"probability": 0.9423, "num_turns_after_good_defection": 0, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -245,7 +245,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 5 - self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"probability": 1.0125, + self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"probability": 0.99, "num_turns_after_good_defection": 0, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -253,9 +253,9 @@ def test_strategy(self): "one_turn_after_good_defection_ratio_count": 1, "two_turns_after_good_defection_ratio_count": 1}) - opponent = axelrod.MockPlayer(actions=[C] * 6) - actions = [(C, C)] * 5 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + opponent = axelrod.MockPlayer(actions=[C] * 5) + actions = [(C, C)] * 4 + [(D, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, "num_turns_after_good_defection": 1, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -265,21 +265,21 @@ def test_strategy(self): # Given score per turn is greater than 2.25, Tranquilizer will never defect twice in a row - opponent = axelrod.MockPlayer(actions = [C] * 7) - actions = [(C, C)] * 5 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + opponent = axelrod.MockPlayer(actions = [C] * 6) + actions = [(C, C)] * 4 + [(D, C), (C, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, "num_turns_after_good_defection": 2, "consecutive_defections": 0, - "one_turn_after_good_defection_ratio": 10, + "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 2, "two_turns_after_good_defection_ratio_count": 1}) # Tests defection probability if score == good - opponent = axelrod.MockPlayer(actions=[C] * 6) - actions = [(C, C)] * 5 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + opponent = axelrod.MockPlayer(actions=[C] * 5) + actions = [(C, C)] * 4 + [(D, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, "num_turns_after_good_defection": 1, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -289,24 +289,24 @@ def test_strategy(self): # Ensures FD1 values are calculated - opponent = axelrod.MockPlayer(actions=[C] * 7) - actions = [(C, C)] * 5 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + opponent = axelrod.MockPlayer(actions=[C] * 6) + actions = [(C, C)] * 4 + [(D, C), (C, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, "num_turns_after_good_defection": 2, "consecutive_defections": 0, - "one_turn_after_good_defection_ratio": 10, + "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 2, "two_turns_after_good_defection_ratio_count": 1}) # Ensures FD2 values are calculated - opponent = axelrod.MockPlayer(actions=[C] * 7) - actions = [(C, C)] * 5 + [(D, C)] + [(C, C)] + [(C, C)] - self.versus_test(opponent, expected_actions=actions, seed=19, attrs={"probability": 0.99, + opponent = axelrod.MockPlayer(actions=[C] * 6) + actions = [(C, C)] * 4 + [(D, C), (C, C), (C, C)] + self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, "num_turns_after_good_defection": 0, "consecutive_defections": 0, - "one_turn_after_good_defection_ratio": 10, + "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 1.5, "one_turn_after_good_defection_ratio_count": 2, "two_turns_after_good_defection_ratio_count": 2}) From 45fe0a8cc08c601ed95996aaccdc79616739c8ff Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Sat, 26 Aug 2017 14:05:43 +0100 Subject: [PATCH 20/28] Remove randomValue, replace with random.random() only and hence modify seeds in test. Fix PEP8 styling conflictions and change value of initial probability --- axelrod/strategies/axelrod_second.py | 70 +++++++++---------- .../tests/strategies/test_axelrod_second.py | 18 ++--- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index d1f8f3655..714bfb61d 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -309,18 +309,16 @@ class Tranquilizer(Player): 'manipulates_state': False } - - # Initialised atributes def __init__(self): super().__init__() - self.num_turns_after_good_defection = 0 + self.num_turns_after_good_defection = 0 # equal to FD variable in Fortran code self.consecutive_defections = 0 self.one_turn_after_good_defection_ratio= 5 self.two_turns_after_good_defection_ratio= 0 self.one_turn_after_good_defection_ratio_count = 1 self.two_turns_after_good_defection_ratio_count = 1 self.score = None - self.probability = 1.1 + self.probability = float self.current_score = 0 self.dict = {C: 0, D: 1} @@ -328,59 +326,59 @@ def __init__(self): def update_state(self, opponent): """ - Calculates the ratioFD values and P values, as well as sets the - states of FD at the start of each turn + Calculates the ratio values for the one_turn_after_good_defection_ratio, + two_turns_after_good_defection_ratio and the probability values, + as well as sets the value of num_turns_after_good_defection. """ self.current_score = compute_final_score(zip(self.history, opponent.history)) if self.num_turns_after_good_defection == 2: self.num_turns_after_good_defection = 0 self.two_turns_after_good_defection_ratio = ( - ((self.two_turns_after_good_defection_ratio - * self.two_turns_after_good_defection_ratio_count) - + (3 - (3 * self.dict[opponent.history[-1]])) - + (2 * self.dict[self.history[-1]]) - - ((self.dict[opponent.history[-1]] - * self.dict[self.history[-1]]))) - / (self.two_turns_after_good_defection_ratio_count + 1) - ) + ((self.two_turns_after_good_defection_ratio + * self.two_turns_after_good_defection_ratio_count) + + (3 - (3 * self.dict[opponent.history[-1]])) + + (2 * self.dict[self.history[-1]]) + - ((self.dict[opponent.history[-1]] + * self.dict[self.history[-1]]))) + / (self.two_turns_after_good_defection_ratio_count + 1) + ) self.two_turns_after_good_defection_ratio_count += 1 elif self.num_turns_after_good_defection == 1: self.num_turns_after_good_defection = 2 self.one_turn_after_good_defection_ratio = ( - ((self.one_turn_after_good_defection_ratio - * self.one_turn_after_good_defection_ratio_count) - + (3 - (3 * self.dict[opponent.history[-1]])) - + (2 * self.dict[self.history[-1]]) - - (self.dict[opponent.history[-1]] - * self.dict[self.history[-1]])) - / (self.one_turn_after_good_defection_ratio_count + 1) - ) + ((self.one_turn_after_good_defection_ratio + * self.one_turn_after_good_defection_ratio_count) + + (3 - (3 * self.dict[opponent.history[-1]])) + + (2 * self.dict[self.history[-1]]) + - (self.dict[opponent.history[-1]] + * self.dict[self.history[-1]])) + / (self.one_turn_after_good_defection_ratio_count + 1) + ) self.one_turn_after_good_defection_ratio_count += 1 else: if (self.current_score[0] / ((len(self.history)) + 1)) >= 2.25: self.probability = ( - (.95 - (((self.one_turn_after_good_defection_ratio) - + (self.two_turns_after_good_defection_ratio) - 5) / 15)) - + (1 / (((len(self.history))+1) ** 2)) - - (self.dict[opponent.history[-1]] / 4) - ) + (.95 - (((self.one_turn_after_good_defection_ratio) + + (self.two_turns_after_good_defection_ratio) - 5) / 15)) + + (1 / (((len(self.history))+1) ** 2)) + - (self.dict[opponent.history[-1]] / 4) + ) self.probability = round(self.probability, 4) self.score = "good" elif (self.current_score[0] / ((len(self.history)) + 1)) >= 1.75: self.probability = ( - (.25 + (opponent.cooperations / ((len(self.history)) + 1))) - - (self.consecutive_defections * .25) - + ((self.current_score[0] - - self.current_score[1]) / 100) - + (4 / ((len(self.history)) + 1))) + (.25 + (opponent.cooperations / ((len(self.history)) + 1))) + - (self.consecutive_defections * .25) + + ((self.current_score[0] + - self.current_score[1]) / 100) + + (4 / ((len(self.history)) + 1)) + ) self.probability = round(self.probability, 4) self.score = "average" def strategy(self, opponent: Player) -> Action: - randomValue = random.random() - current_score = compute_final_score(zip(self.history, opponent.history)) if len(self.history) == 0: @@ -400,7 +398,7 @@ def strategy(self, opponent: Player) -> Action: elif (self.current_score[0] / ((len(self.history)) + 1)) < 1.75: return opponent.history[-1] # "If you can't beat them join'em" else: - if (randomValue <= self.probability): + if (random.random() <= self.probability): if self.consecutive_defections == 0: return C else: @@ -409,5 +407,3 @@ def strategy(self, opponent: Player) -> Action: if self.score == "good": self.num_turns_after_good_defection = 1 return D - - \ No newline at end of file diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 1814634b0..d38271f28 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -182,7 +182,7 @@ def test_init(self): player = axelrod.Tranquilizer() - self.assertEqual(player.probability, 1.1) + self.assertEqual(player.probability, float) self.assertEqual(player.num_turns_after_good_defection, 0) self.assertEqual(player.consecutive_defections, 0) self.assertEqual(player.one_turn_after_good_defection_ratio, 5) @@ -198,7 +198,7 @@ def test_strategy(self): opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 20 - self.versus_test(opponent, expected_actions=actions, attrs={"probability": 1.1, + self.versus_test(opponent, expected_actions=actions, attrs={"probability": float, "num_turns_after_good_defection": 0, "consecutive_defections": 20, "one_turn_after_good_defection_ratio": 5, @@ -233,7 +233,7 @@ def test_strategy(self): actions = [(C, D)] + [(D, D)] * 6 + [(D, C)] + [(C, C)] * 4 # average_score_per_turn = 1.85 actions += [(D, D)] # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=10, attrs={"probability": 0.9423, + self.versus_test(opponent, expected_actions=actions, seed=2, attrs={"probability": 0.9423, "num_turns_after_good_defection": 0, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -255,7 +255,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 1, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -267,7 +267,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions = [C] * 6) actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 2, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -279,7 +279,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 1, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -291,7 +291,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[C] * 6) actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 2, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -303,7 +303,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[C] * 6) actions = [(C, C)] * 4 + [(D, C), (C, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=70, attrs={"probability": 0.99, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 0, "consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -315,7 +315,7 @@ def test_strategy(self): opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 19 - self.versus_test(opponent, expected_actions=actions, attrs={"probability": 1.1, + self.versus_test(opponent, expected_actions=actions, attrs={"probability": float, "num_turns_after_good_defection": 0, "consecutive_defections": 19, "one_turn_after_good_defection_ratio": 5, From 83d61c1f5bd92c83a7f00dd6807333f40cdb657e Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Sat, 26 Aug 2017 16:32:34 +0100 Subject: [PATCH 21/28] Change initial probability value to 'None'. --- axelrod/strategies/axelrod_second.py | 2 +- axelrod/tests/strategies/test_axelrod_second.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 714bfb61d..6819e2dfe 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -318,7 +318,7 @@ def __init__(self): self.one_turn_after_good_defection_ratio_count = 1 self.two_turns_after_good_defection_ratio_count = 1 self.score = None - self.probability = float + self.probability = None self.current_score = 0 self.dict = {C: 0, D: 1} diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index d38271f28..3bc4fc8d7 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -182,7 +182,7 @@ def test_init(self): player = axelrod.Tranquilizer() - self.assertEqual(player.probability, float) + self.assertEqual(player.probability, None) self.assertEqual(player.num_turns_after_good_defection, 0) self.assertEqual(player.consecutive_defections, 0) self.assertEqual(player.one_turn_after_good_defection_ratio, 5) @@ -190,7 +190,6 @@ def test_init(self): self.assertEqual(player.one_turn_after_good_defection_ratio_count, 1) self.assertEqual(player.two_turns_after_good_defection_ratio_count, 1) self.assertEqual(player.score, None) - self.current_score = 0 def test_strategy(self): @@ -198,7 +197,7 @@ def test_strategy(self): opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 20 - self.versus_test(opponent, expected_actions=actions, attrs={"probability": float, + self.versus_test(opponent, expected_actions=actions, attrs={"probability": None, "num_turns_after_good_defection": 0, "consecutive_defections": 20, "one_turn_after_good_defection_ratio": 5, @@ -315,10 +314,11 @@ def test_strategy(self): opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 19 - self.versus_test(opponent, expected_actions=actions, attrs={"probability": float, + self.versus_test(opponent, expected_actions=actions, attrs={"probability": None, "num_turns_after_good_defection": 0, "consecutive_defections": 19, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) \ No newline at end of file + "two_turns_after_good_defection_ratio_count": 1}) + \ No newline at end of file From 8d0ef1be4ffd735dd8a5860dff517291a47e2c51 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Tue, 29 Aug 2017 15:16:39 +0100 Subject: [PATCH 22/28] Changed variable name 'consecutive_defections' to 'opponent_consecutive_defections' --- axelrod/strategies/axelrod_second.py | 12 +++++----- .../tests/strategies/test_axelrod_second.py | 24 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 6819e2dfe..369b3593d 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -312,7 +312,7 @@ class Tranquilizer(Player): def __init__(self): super().__init__() self.num_turns_after_good_defection = 0 # equal to FD variable in Fortran code - self.consecutive_defections = 0 + self.opponent_consecutive_defections = 0 self.one_turn_after_good_defection_ratio= 5 self.two_turns_after_good_defection_ratio= 0 self.one_turn_after_good_defection_ratio_count = 1 @@ -369,7 +369,7 @@ def update_state(self, opponent): elif (self.current_score[0] / ((len(self.history)) + 1)) >= 1.75: self.probability = ( (.25 + (opponent.cooperations / ((len(self.history)) + 1))) - - (self.consecutive_defections * .25) + - (self.opponent_consecutive_defections * .25) + ((self.current_score[0] - self.current_score[1]) / 100) + (4 / ((len(self.history)) + 1)) @@ -386,12 +386,12 @@ def strategy(self, opponent: Player) -> Action: else: Tranquilizer.update_state(self, opponent) if opponent.history[-1] == D: - self.consecutive_defections += 1 + self.opponent_consecutive_defections += 1 else: - self.consecutive_defections = 0 + self.opponent_consecutive_defections = 0 if self.num_turns_after_good_defection != 0: - if self.consecutive_defections == 0: + if self.opponent_consecutive_defections == 0: return C else: return D @@ -399,7 +399,7 @@ def strategy(self, opponent: Player) -> Action: return opponent.history[-1] # "If you can't beat them join'em" else: if (random.random() <= self.probability): - if self.consecutive_defections == 0: + if self.opponent_consecutive_defections == 0: return C else: return self.history[-1] diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 3bc4fc8d7..dc336b12c 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -184,7 +184,7 @@ def test_init(self): self.assertEqual(player.probability, None) self.assertEqual(player.num_turns_after_good_defection, 0) - self.assertEqual(player.consecutive_defections, 0) + self.assertEqual(player.opponent_consecutive_defections, 0) self.assertEqual(player.one_turn_after_good_defection_ratio, 5) self.assertEqual(player.two_turns_after_good_defection_ratio, 0) self.assertEqual(player.one_turn_after_good_defection_ratio_count, 1) @@ -199,7 +199,7 @@ def test_strategy(self): actions = [(C, D)] + [(D, D)] * 20 self.versus_test(opponent, expected_actions=actions, attrs={"probability": None, "num_turns_after_good_defection": 0, - "consecutive_defections": 20, + "opponent_consecutive_defections": 20, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -209,7 +209,7 @@ def test_strategy(self): actions = [(C, C)] + [(C, C)] + [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 self.versus_test(opponent = opponent, expected_actions=actions, attrs={"probability": 2.25, "num_turns_after_good_defection": 0, - "consecutive_defections": 0, + "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -222,7 +222,7 @@ def test_strategy(self): actions += ([(C, D)]) # <-- Random self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"probability": 0.9423, "num_turns_after_good_defection": 0, - "consecutive_defections": 0, + "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -234,7 +234,7 @@ def test_strategy(self): actions += [(D, D)] # <-- Random self.versus_test(opponent, expected_actions=actions, seed=2, attrs={"probability": 0.9423, "num_turns_after_good_defection": 0, - "consecutive_defections": 0, + "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -246,7 +246,7 @@ def test_strategy(self): actions = [(C, C)] * 5 self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"probability": 0.99, "num_turns_after_good_defection": 0, - "consecutive_defections": 0, + "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -256,7 +256,7 @@ def test_strategy(self): actions = [(C, C)] * 4 + [(D, C)] self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 1, - "consecutive_defections": 0, + "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -268,7 +268,7 @@ def test_strategy(self): actions = [(C, C)] * 4 + [(D, C), (C, C)] self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 2, - "consecutive_defections": 0, + "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 2, @@ -280,7 +280,7 @@ def test_strategy(self): actions = [(C, C)] * 4 + [(D, C)] self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 1, - "consecutive_defections": 0, + "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -292,7 +292,7 @@ def test_strategy(self): actions = [(C, C)] * 4 + [(D, C), (C, C)] self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 2, - "consecutive_defections": 0, + "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 2, @@ -304,7 +304,7 @@ def test_strategy(self): actions = [(C, C)] * 4 + [(D, C), (C, C), (C, C)] self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, "num_turns_after_good_defection": 0, - "consecutive_defections": 0, + "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 1.5, "one_turn_after_good_defection_ratio_count": 2, @@ -316,7 +316,7 @@ def test_strategy(self): actions = [(C, D)] + [(D, D)] * 19 self.versus_test(opponent, expected_actions=actions, attrs={"probability": None, "num_turns_after_good_defection": 0, - "consecutive_defections": 19, + "opponent_consecutive_defections": 19, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, From 059f1e8bf35cac68f366e7141cea1eb4e0f6cf72 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Tue, 29 Aug 2017 23:29:30 +0100 Subject: [PATCH 23/28] Move FD1 state code to new method called update_stochastic_state, modify probability equation and hence modify tests. --- axelrod/strategies/axelrod_second.py | 28 +++++++------ .../tests/strategies/test_axelrod_second.py | 42 +++++++++---------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 369b3593d..5e28cfb04 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -323,14 +323,13 @@ def __init__(self): self.dict = {C: 0, D: 1} - def update_state(self, opponent): + def update_cooperative_state(self, opponent): """ Calculates the ratio values for the one_turn_after_good_defection_ratio, two_turns_after_good_defection_ratio and the probability values, as well as sets the value of num_turns_after_good_defection. """ - self.current_score = compute_final_score(zip(self.history, opponent.history)) if self.num_turns_after_good_defection == 2: self.num_turns_after_good_defection = 0 @@ -356,8 +355,10 @@ def update_state(self, opponent): / (self.one_turn_after_good_defection_ratio_count + 1) ) self.one_turn_after_good_defection_ratio_count += 1 - else: - if (self.current_score[0] / ((len(self.history)) + 1)) >= 2.25: + + def update_stochastic_state(self, opponent): + + if (self.current_score[0] / ((len(self.history)) + 1)) >= 2.25: self.probability = ( (.95 - (((self.one_turn_after_good_defection_ratio) + (self.two_turns_after_good_defection_ratio) - 5) / 15)) @@ -366,9 +367,9 @@ def update_state(self, opponent): ) self.probability = round(self.probability, 4) self.score = "good" - elif (self.current_score[0] / ((len(self.history)) + 1)) >= 1.75: + elif (self.current_score[0] / ((len(self.history)) + 1)) >= 1.75: self.probability = ( - (.25 + (opponent.cooperations / ((len(self.history)) + 1))) + (.25 + ((opponent.cooperations + 1) / ((len(self.history)) + 1))) - (self.opponent_consecutive_defections * .25) + ((self.current_score[0] - self.current_score[1]) / 100) @@ -379,16 +380,17 @@ def update_state(self, opponent): def strategy(self, opponent: Player) -> Action: - current_score = compute_final_score(zip(self.history, opponent.history)) - + self.current_score = compute_final_score(zip(self.history, opponent.history)) + if len(self.history) == 0: return C else: - Tranquilizer.update_state(self, opponent) - if opponent.history[-1] == D: - self.opponent_consecutive_defections += 1 - else: - self.opponent_consecutive_defections = 0 + self.update_cooperative_state(opponent) + if opponent.history[-1] == D: + self.opponent_consecutive_defections += 1 + else: + self.opponent_consecutive_defections = 0 + self.update_stochastic_state(opponent) if self.num_turns_after_good_defection != 0: if self.opponent_consecutive_defections == 0: diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index dc336b12c..85e52a6ec 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -207,7 +207,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer([C] * 2 + [D] * 8 + [C] * 4 ) actions = [(C, C)] + [(C, C)] + [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 - self.versus_test(opponent = opponent, expected_actions=actions, attrs={"probability": 2.25, + self.versus_test(opponent = opponent, expected_actions=actions, attrs={"probability": 2.5833, "num_turns_after_good_defection": 0, "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -216,29 +216,29 @@ def test_strategy(self): "two_turns_after_good_defection_ratio_count": 1}) # If score is between 1.75 and 2.25, may cooperate or defect - opponent = axelrod.MockPlayer(actions=[D] * 7 + [C] * 5 + [D]) - actions = [(C, D)] + [(D, D)] * 6 + [(D, C)] + [(C, C)] * 4 - # average_score_per_turn = 1.77 + opponent = axelrod.MockPlayer(actions=[D] * 3 + [C] * 4 + [D] * 2) + actions = [(C, D)] + [(D, D)] * 2 + [(D, C)] + [(C, C)] * 3 + [(C, D)] actions += ([(C, D)]) # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"probability": 0.9423, + self.versus_test(opponent, expected_actions=actions, seed=0, attrs={"probability": 0.95, "num_turns_after_good_defection": 0, - "opponent_consecutive_defections": 0, + "opponent_consecutive_defections": 1, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, "two_turns_after_good_defection_ratio_count": 1}) - opponent = axelrod.MockPlayer(actions=[D] * 7 + [C] * 5 + [D]) - actions = [(C, D)] + [(D, D)] * 6 + [(D, C)] + [(C, C)] * 4 - # average_score_per_turn = 1.85 - actions += [(D, D)] # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=2, attrs={"probability": 0.9423, - "num_turns_after_good_defection": 0, - "opponent_consecutive_defections": 0, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) + opponent = axelrod.MockPlayer(actions=[D] * 3 + [C] * 4 + [D] * 2) + actions = [(C, D)] + [(D, D)] * 2 + [(D, C)] + [(C, C)] * 3 + [(C, D)] + actions += ([(D, D)]) # <-- Random + self.versus_test(opponent, expected_actions=actions, seed=17, attrs={"probability": 0.95, + "num_turns_after_good_defection": 0, + "opponent_consecutive_defections": 1, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) + + # If score is greater than 2.25 either cooperate or defect, if turn number <= 5; cooperate @@ -266,7 +266,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions = [C] * 6) actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.9778, "num_turns_after_good_defection": 2, "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -290,7 +290,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[C] * 6) actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.9778, "num_turns_after_good_defection": 2, "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, @@ -301,8 +301,8 @@ def test_strategy(self): # Ensures FD2 values are calculated opponent = axelrod.MockPlayer(actions=[C] * 6) - actions = [(C, C)] * 4 + [(D, C), (C, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, + actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] * 2 + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.8704, "num_turns_after_good_defection": 0, "opponent_consecutive_defections": 0, "one_turn_after_good_defection_ratio": 5, From b562e51cf65d3e89d9f4e083fa04921ac244eda9 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Thu, 31 Aug 2017 16:15:11 +0100 Subject: [PATCH 24/28] Restructure program, remove update_stochastic_state, modify tests --- axelrod/strategies/axelrod_second.py | 84 ++++++++----------- .../tests/strategies/test_axelrod_second.py | 64 +++++--------- 2 files changed, 56 insertions(+), 92 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 5e28cfb04..071fb25cb 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -317,8 +317,6 @@ def __init__(self): self.two_turns_after_good_defection_ratio= 0 self.one_turn_after_good_defection_ratio_count = 1 self.two_turns_after_good_defection_ratio_count = 1 - self.score = None - self.probability = None self.current_score = 0 self.dict = {C: 0, D: 1} @@ -330,6 +328,10 @@ def update_cooperative_state(self, opponent): two_turns_after_good_defection_ratio and the probability values, as well as sets the value of num_turns_after_good_defection. """ + if opponent.history[-1] == D: + self.opponent_consecutive_defections += 1 + else: + self.opponent_consecutive_defections = 0 if self.num_turns_after_good_defection == 2: self.num_turns_after_good_defection = 0 @@ -356,56 +358,38 @@ def update_cooperative_state(self, opponent): ) self.one_turn_after_good_defection_ratio_count += 1 - def update_stochastic_state(self, opponent): - - if (self.current_score[0] / ((len(self.history)) + 1)) >= 2.25: - self.probability = ( - (.95 - (((self.one_turn_after_good_defection_ratio) - + (self.two_turns_after_good_defection_ratio) - 5) / 15)) - + (1 / (((len(self.history))+1) ** 2)) - - (self.dict[opponent.history[-1]] / 4) - ) - self.probability = round(self.probability, 4) - self.score = "good" - elif (self.current_score[0] / ((len(self.history)) + 1)) >= 1.75: - self.probability = ( - (.25 + ((opponent.cooperations + 1) / ((len(self.history)) + 1))) - - (self.opponent_consecutive_defections * .25) - + ((self.current_score[0] - - self.current_score[1]) / 100) - + (4 / ((len(self.history)) + 1)) - ) - self.probability = round(self.probability, 4) - self.score = "average" - def strategy(self, opponent: Player) -> Action: - self.current_score = compute_final_score(zip(self.history, opponent.history)) - if len(self.history) == 0: return C - else: - self.update_cooperative_state(opponent) - if opponent.history[-1] == D: - self.opponent_consecutive_defections += 1 - else: - self.opponent_consecutive_defections = 0 - self.update_stochastic_state(opponent) - - if self.num_turns_after_good_defection != 0: - if self.opponent_consecutive_defections == 0: + + self.current_score = compute_final_score(zip(self.history, opponent.history)) + + self.update_cooperative_state(opponent) + if self.num_turns_after_good_defection in [1, 2]: + return C + + if (self.current_score[0] / ((len(self.history)) + 1)) >= 2.25: + probability = ( + (.95 - (((self.one_turn_after_good_defection_ratio) + + (self.two_turns_after_good_defection_ratio) - 5) / 15)) + + (1 / (((len(self.history))+1) ** 2)) + - (self.dict[opponent.history[-1]] / 4) + ) + if random.random() <= probability: return C - else: - return D - elif (self.current_score[0] / ((len(self.history)) + 1)) < 1.75: - return opponent.history[-1] # "If you can't beat them join'em" - else: - if (random.random() <= self.probability): - if self.opponent_consecutive_defections == 0: - return C - else: - return self.history[-1] - else: - if self.score == "good": - self.num_turns_after_good_defection = 1 - return D + self.num_turns_after_good_defection = 1 + return D + elif (self.current_score[0] / ((len(self.history)) + 1)) >= 1.75: + probability = ( + (.25 + ((opponent.cooperations + 1) / ((len(self.history)) + 1))) + - (self.opponent_consecutive_defections * .25) + + ((self.current_score[0] + - self.current_score[1]) / 100) + + (4 / ((len(self.history)) + 1)) + ) + if random.random() <= probability: + return C + self.num_turns_after_good_defection = 1 + return D + return opponent.history[-1] diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 85e52a6ec..1c5c6a5f6 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -182,24 +182,24 @@ def test_init(self): player = axelrod.Tranquilizer() - self.assertEqual(player.probability, None) self.assertEqual(player.num_turns_after_good_defection, 0) self.assertEqual(player.opponent_consecutive_defections, 0) self.assertEqual(player.one_turn_after_good_defection_ratio, 5) self.assertEqual(player.two_turns_after_good_defection_ratio, 0) self.assertEqual(player.one_turn_after_good_defection_ratio_count, 1) self.assertEqual(player.two_turns_after_good_defection_ratio_count, 1) - self.assertEqual(player.score, None) def test_strategy(self): + opponent = axelrod.Bully() + actions = [(C, D), (D, D), (D, C), (C, C), (C, D), (D, D), (D, C), (C, C)] + self.versus_test(opponent, expected_actions=actions) + # Tests whether TitForTat is played given score is below 1.75 opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 20 - self.versus_test(opponent, expected_actions=actions, attrs={"probability": None, - "num_turns_after_good_defection": 0, - "opponent_consecutive_defections": 20, + self.versus_test(opponent, expected_actions=actions, attrs={"num_turns_after_good_defection": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -207,9 +207,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer([C] * 2 + [D] * 8 + [C] * 4 ) actions = [(C, C)] + [(C, C)] + [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 - self.versus_test(opponent = opponent, expected_actions=actions, attrs={"probability": 2.5833, - "num_turns_after_good_defection": 0, - "opponent_consecutive_defections": 0, + self.versus_test(opponent = opponent, expected_actions=actions, attrs={"num_turns_after_good_defection": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -219,9 +217,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[D] * 3 + [C] * 4 + [D] * 2) actions = [(C, D)] + [(D, D)] * 2 + [(D, C)] + [(C, C)] * 3 + [(C, D)] actions += ([(C, D)]) # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=0, attrs={"probability": 0.95, - "num_turns_after_good_defection": 0, - "opponent_consecutive_defections": 1, + self.versus_test(opponent, expected_actions=actions, seed=0, attrs={"num_turns_after_good_defection": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -230,13 +226,11 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[D] * 3 + [C] * 4 + [D] * 2) actions = [(C, D)] + [(D, D)] * 2 + [(D, C)] + [(C, C)] * 3 + [(C, D)] actions += ([(D, D)]) # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=17, attrs={"probability": 0.95, - "num_turns_after_good_defection": 0, - "opponent_consecutive_defections": 1, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) + self.versus_test(opponent, expected_actions=actions, seed=17, attrs={"num_turns_after_good_defection": 1, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1}) @@ -244,9 +238,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 5 - self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"probability": 0.99, - "num_turns_after_good_defection": 0, - "opponent_consecutive_defections": 0, + self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"num_turns_after_good_defection": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -254,9 +246,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, - "num_turns_after_good_defection": 1, - "opponent_consecutive_defections": 0, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 1, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -266,33 +256,27 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions = [C] * 6) actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.9778, - "num_turns_after_good_defection": 2, - "opponent_consecutive_defections": 0, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 2, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 2, "two_turns_after_good_defection_ratio_count": 1}) - # Tests defection probability if score == good + # Tests cooperation after update_cooperatiove_state opponent = axelrod.MockPlayer(actions=[C] * 5) - actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.99, - "num_turns_after_good_defection": 1, - "opponent_consecutive_defections": 0, + actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 2, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, + "one_turn_after_good_defection_ratio_count": 2, "two_turns_after_good_defection_ratio_count": 1}) # Ensures FD1 values are calculated opponent = axelrod.MockPlayer(actions=[C] * 6) actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.9778, - "num_turns_after_good_defection": 2, - "opponent_consecutive_defections": 0, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 2, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 2, @@ -302,9 +286,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[C] * 6) actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] * 2 - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"probability": 0.8704, - "num_turns_after_good_defection": 0, - "opponent_consecutive_defections": 0, + self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 1.5, "one_turn_after_good_defection_ratio_count": 2, @@ -314,9 +296,7 @@ def test_strategy(self): opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 19 - self.versus_test(opponent, expected_actions=actions, attrs={"probability": None, - "num_turns_after_good_defection": 0, - "opponent_consecutive_defections": 19, + self.versus_test(opponent, expected_actions=actions, attrs={"num_turns_after_good_defection": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, From 5a2dafc15e455b98eececf349084e9e3380b6163 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Thu, 31 Aug 2017 19:28:23 +0100 Subject: [PATCH 25/28] Change docstrings, fix bug --- axelrod/strategies/axelrod_second.py | 84 ++++++++++++------- .../tests/strategies/test_axelrod_second.py | 4 +- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 071fb25cb..07d2c84db 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -212,31 +212,52 @@ class Tranquilizer(Player): Fortran strategy K67R from Axelrod's second tournament. Reversed engineered by: Owen Campbell, Will Guo and Mansour Hakem. + The strategy starts by cooperating this strategy has 3 states. - Description given in Axelrod's "More Effective Choice in the - Prisoner's Dilemma" paper: The rule normally cooperates but - is ready to defect if the other player defects too often. - Thus the rule tends to cooperate for the first dozen or two moves - if the other player is cooperating, but then it throws in a - defection. If the other player continues to cooperate, then defections - become more frequent. But as long as Tranquilizer is maintaining an - average payoff of at least 2.25 points per move, it will never defect - twice in succession and it will not defect more than - one-quarter of the time. + At the start of the strategy it updates it's states: + - It counts the number of consecutive defections by the opponent. + - If it was in state 2 it moves to state 0 and calculates the + following quantities two_turns_after_good_defection_ratio and + two_turns_after_good_defection_ratio_count. + - If it was in state 1 it moves to state 2 and calculates the + following quantities one_turn_after_good_defection_ratio and + one_turn_after_good_defection_ratio_count. + + If after this it is in state 1 or 2 then it cooperates. + + If it is in state 0 it will potentially perform 1 of the 2 + following stochastic tests: + + 1. If average score per turn is greater than 2.25 then it calculates a + value of probability: - - Has a variable, 'FD' which can be 0, 1 or 2. It has an initial value of 0 - - Has a variable 'S', which counts the consecutive number of - times the opponent has played D (i.e. it is reset to 0 if the opponent - plays C). It has an initial value of 0. - - Has a variable, 'C', which counts the number of times the opponent Cooperates - - Has a variable 'AK' which increases each time a move is played whilst in state - FD = 1. It has an initial value of 1. - - Has a variable 'NK' which increases each time a move is - played whilst in state FD = 2. It has an initial value of 1. - - Has a variable 'AD' with an initial value of 5 - - Has a variable 'NO with an initial value of 0 - - Has a variable 'NO with an initial value of 0 + probability = ( + (.95 - (((self.one_turn_after_good_defection_ratio) + + (self.two_turns_after_good_defection_ratio) - 5) / 15)) + + (1 / (((len(self.history))+1) ** 2)) + - (self.dict[opponent.history[-1]] / 4) + ) + + and will cooperate if a random sampled number is less than that value of + probability. If it does not cooperate then the strategy moves to state 1 + and defects. + + 2. If average score per turn is greater than 1.75 but less than 2.25 + then it calculates a value of probability: + + probability = ( + (.25 + ((opponent.cooperations + 1) / ((len(self.history)) + 1))) + - (self.opponent_consecutive_defections * .25) + + ((current_score[0] + - current_score[1]) / 100) + + (4 / ((len(self.history)) + 1)) + ) + + and will cooperate if a random sampled number is less than that value of + probability. If not, it defects. + + If none of the above holds the player simply plays tit for tat. The strategy follows the following algorithm:: @@ -317,11 +338,10 @@ def __init__(self): self.two_turns_after_good_defection_ratio= 0 self.one_turn_after_good_defection_ratio_count = 1 self.two_turns_after_good_defection_ratio_count = 1 - self.current_score = 0 self.dict = {C: 0, D: 1} - def update_cooperative_state(self, opponent): + def update_state(self, opponent): """ Calculates the ratio values for the one_turn_after_good_defection_ratio, @@ -363,13 +383,14 @@ def strategy(self, opponent: Player) -> Action: if len(self.history) == 0: return C - self.current_score = compute_final_score(zip(self.history, opponent.history)) - self.update_cooperative_state(opponent) + self.update_state(opponent) if self.num_turns_after_good_defection in [1, 2]: return C - - if (self.current_score[0] / ((len(self.history)) + 1)) >= 2.25: + + current_score = compute_final_score(zip(self.history, opponent.history)) + + if (current_score[0] / ((len(self.history)) + 1)) >= 2.25: probability = ( (.95 - (((self.one_turn_after_good_defection_ratio) + (self.two_turns_after_good_defection_ratio) - 5) / 15)) @@ -380,16 +401,15 @@ def strategy(self, opponent: Player) -> Action: return C self.num_turns_after_good_defection = 1 return D - elif (self.current_score[0] / ((len(self.history)) + 1)) >= 1.75: + elif (current_score[0] / ((len(self.history)) + 1)) >= 1.75: probability = ( (.25 + ((opponent.cooperations + 1) / ((len(self.history)) + 1))) - (self.opponent_consecutive_defections * .25) - + ((self.current_score[0] - - self.current_score[1]) / 100) + + ((current_score[0] + - current_score[1]) / 100) + (4 / ((len(self.history)) + 1)) ) if random.random() <= probability: return C - self.num_turns_after_good_defection = 1 return D return opponent.history[-1] diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 1c5c6a5f6..1ea21a554 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -226,7 +226,7 @@ def test_strategy(self): opponent = axelrod.MockPlayer(actions=[D] * 3 + [C] * 4 + [D] * 2) actions = [(C, D)] + [(D, D)] * 2 + [(D, C)] + [(C, C)] * 3 + [(C, D)] actions += ([(D, D)]) # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=17, attrs={"num_turns_after_good_defection": 1, + self.versus_test(opponent, expected_actions=actions, seed=17, attrs={"num_turns_after_good_defection": 0, "one_turn_after_good_defection_ratio": 5, "two_turns_after_good_defection_ratio": 0, "one_turn_after_good_defection_ratio_count": 1, @@ -262,7 +262,7 @@ def test_strategy(self): "one_turn_after_good_defection_ratio_count": 2, "two_turns_after_good_defection_ratio_count": 1}) - # Tests cooperation after update_cooperatiove_state + # Tests cooperation after update_state opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] From 6d3683f482c274b68733478e6918fdf5a6392cc9 Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Thu, 31 Aug 2017 22:57:52 +0100 Subject: [PATCH 26/28] Fix PEP8 Styling --- axelrod/strategies/axelrod_second.py | 133 +++++++-------- .../tests/strategies/test_axelrod_second.py | 160 ++++++++++-------- 2 files changed, 159 insertions(+), 134 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 07d2c84db..91bd940a0 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -208,7 +208,18 @@ class Tranquilizer(Player): """ Submitted to Axelrod's second tournament by Craig Feathers - This strategy is based on the reverse engineering of the + Description given in Axelrod's "More Effective Choice in the + Prisoner's Dilemma" paper: The rule normally cooperates but + is ready to defect if the other player defects too often. + Thus the rule tends to cooperate for the first dozen or two moves + if the other player is cooperating, but then it throws in a + defection. If the other player continues to cooperate, then defections + become more frequent. But as long as Tranquilizer is maintaining an + average payoff of at least 2.25 points per move, it will never defect + twice in succession and it will not defect more than + one-quarter of the time. + + This implementation is based on the reverse engineering of the Fortran strategy K67R from Axelrod's second tournament. Reversed engineered by: Owen Campbell, Will Guo and Mansour Hakem. @@ -218,12 +229,49 @@ class Tranquilizer(Player): - It counts the number of consecutive defections by the opponent. - If it was in state 2 it moves to state 0 and calculates the - following quantities two_turns_after_good_defection_ratio and - two_turns_after_good_defection_ratio_count. - - If it was in state 1 it moves to state 2 and calculates the - following quantities one_turn_after_good_defection_ratio and - one_turn_after_good_defection_ratio_count. + following quantities two_turns_after_good_defection_ratio and + two_turns_after_good_defection_ratio_count. + + Formula for: + + two_turns_after_good_defection_ratio: + + self.two_turns_after_good_defection_ratio = ( + ((self.two_turns_after_good_defection_ratio + * self.two_turns_after_good_defection_ratio_count) + + (3 - (3 * self.dict[opponent.history[-1]])) + + (2 * self.dict[self.history[-1]]) + - ((self.dict[opponent.history[-1]] + * self.dict[self.history[-1]]))) + / (self.two_turns_after_good_defection_ratio_count + 1) + ) + + two_turns_after_good_defection_ratio_count = + two_turns_after_good_defection_ratio + 1 + - If it was in state 1 it moves to state 2 and calculates the + following quantities one_turn_after_good_defection_ratio and + one_turn_after_good_defection_ratio_count. + + Formula for: + + one_turn_after_good_defection_ratio: + + self.one_turn_after_good_defection_ratio = ( + ((self.one_turn_after_good_defection_ratio + * self.one_turn_after_good_defection_ratio_count) + + (3 - (3 * self.dict[opponent.history[-1]])) + + (2 * self.dict[self.history[-1]]) + - (self.dict[opponent.history[-1]] + * self.dict[self.history[-1]])) + / (self.one_turn_after_good_defection_ratio_count + 1) + ) + + one_turn_after_good_defection_ratio_count: + + one_turn_after_good_defection_ratio_count = + one_turn_after_good_defection_ratio + 1 + If after this it is in state 1 or 2 then it cooperates. If it is in state 0 it will potentially perform 1 of the 2 @@ -257,60 +305,8 @@ class Tranquilizer(Player): and will cooperate if a random sampled number is less than that value of probability. If not, it defects. - If none of the above holds the player simply plays tit for tat. - - - The strategy follows the following algorithm:: - - When FD = 0: - - If the opponent's last move (JA) was Cooperate, increase the value of C by 1 - If Score (K) < 1.75 * Move Number (M), play opponent's last move - If (1.75 * M) <= K < (2.25 * M): - - Calculate Probability P: - P = 0.25 + C/M - 0.25*S + (K - L)/100 + 4/M - Where L is the opponent's score so far - If Random (R) <= P: - - Cooperate - Else: - - Defect - - If K >= (2.25 * M): - - Calculate probability P: - P = 0.95 - (AD + NO - 5)/15 + 1/M**2 - J/4 - Where J is the opponent's last move - - If Random (R) <= P: - - Cooperate - - Else: - - Set FD = 1 - Defect - - When FD = 1: - - Set FD = 2 - Set the variable 'AD': - AD = ((AD * AK) + 3 - (3 * J) + (2 * JA) - (JA * J)) / (AK + 1) - Where JA and J are the last moves of the strategy and the opponent (C=0, D=1) - Increase the value of AK by 1 - Cooperate - - When FD = 2: - - Set FD = 0 - Set the variable 'NO': - NO = ((NO * NK) + 3 - (3 * J) + (2 * JA) - (JA * J) / (NK + 1) - Where JA and J are the last moves of the strategy and the opponent (C=0, D=1) - Increase the value of NK by 1 - Cooperate - + If none of the above holds the player simply plays tit for tat. + Tranquilizer came in 27th place in Axelrod's second torunament. @@ -332,13 +328,14 @@ class Tranquilizer(Player): def __init__(self): super().__init__() - self.num_turns_after_good_defection = 0 # equal to FD variable in Fortran code - self.opponent_consecutive_defections = 0 - self.one_turn_after_good_defection_ratio= 5 - self.two_turns_after_good_defection_ratio= 0 - self.one_turn_after_good_defection_ratio_count = 1 - self.two_turns_after_good_defection_ratio_count = 1 - self.dict = {C: 0, D: 1} + self.num_turns_after_good_defection = 0 # equal to FD variable + self.opponent_consecutive_defections = 0 # equal to S variable + self.one_turn_after_good_defection_ratio= 5 # equal to AD variable + self.two_turns_after_good_defection_ratio= 0 # equal to NO variable + self.one_turn_after_good_defection_ratio_count = 1 # equal to AK variable + self.two_turns_after_good_defection_ratio_count = 1 # equal to NK variable + # All above variables correspond to those in original Fotran Code + self.dict = {C: 0, D: 1} def update_state(self, opponent): @@ -401,7 +398,7 @@ def strategy(self, opponent: Player) -> Action: return C self.num_turns_after_good_defection = 1 return D - elif (current_score[0] / ((len(self.history)) + 1)) >= 1.75: + if (current_score[0] / ((len(self.history)) + 1)) >= 1.75: probability = ( (.25 + ((opponent.cooperations + 1) / ((len(self.history)) + 1))) - (self.opponent_consecutive_defections * .25) diff --git a/axelrod/tests/strategies/test_axelrod_second.py b/axelrod/tests/strategies/test_axelrod_second.py index 1ea21a554..302c2678e 100644 --- a/axelrod/tests/strategies/test_axelrod_second.py +++ b/axelrod/tests/strategies/test_axelrod_second.py @@ -193,112 +193,140 @@ def test_strategy(self): opponent = axelrod.Bully() actions = [(C, D), (D, D), (D, C), (C, C), (C, D), (D, D), (D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions) + expected_attrs={"num_turns_after_good_defection": 0, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, + attrs=expected_attrs) # Tests whether TitForTat is played given score is below 1.75 opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 20 - self.versus_test(opponent, expected_actions=actions, attrs={"num_turns_after_good_defection": 0, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) + expected_attrs={"num_turns_after_good_defection": 0, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, + attrs=expected_attrs) opponent = axelrod.MockPlayer([C] * 2 + [D] * 8 + [C] * 4 ) - actions = [(C, C)] + [(C, C)] + [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 - self.versus_test(opponent = opponent, expected_actions=actions, attrs={"num_turns_after_good_defection": 0, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) + actions = [(C, C), (C, C)] + [(C, D)] + [(D, D)] * 7 + [(D, C)] + [(C, C)] * 3 + expected_attrs={"num_turns_after_good_defection": 0, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, + attrs=expected_attrs) # If score is between 1.75 and 2.25, may cooperate or defect + opponent = axelrod.MockPlayer(actions=[D] * 3 + [C] * 4 + [D] * 2) actions = [(C, D)] + [(D, D)] * 2 + [(D, C)] + [(C, C)] * 3 + [(C, D)] actions += ([(C, D)]) # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=0, attrs={"num_turns_after_good_defection": 0, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) + expected_attrs={"num_turns_after_good_defection": 0, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, seed=0, + attrs=expected_attrs) opponent = axelrod.MockPlayer(actions=[D] * 3 + [C] * 4 + [D] * 2) actions = [(C, D)] + [(D, D)] * 2 + [(D, C)] + [(C, C)] * 3 + [(C, D)] actions += ([(D, D)]) # <-- Random - self.versus_test(opponent, expected_actions=actions, seed=17, attrs={"num_turns_after_good_defection": 0, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) - - - - # If score is greater than 2.25 either cooperate or defect, if turn number <= 5; cooperate + expected_attrs={"num_turns_after_good_defection": 0, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, seed=17, + attrs=expected_attrs) + + """If score is greater than 2.25 either cooperate or defect, + if turn number <= 5; cooperate""" opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 5 - self.versus_test(opponent, expected_actions=actions, seed=1, attrs={"num_turns_after_good_defection": 0, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) + expected_attrs={"num_turns_after_good_defection": 0, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, seed=1, + attrs=expected_attrs) opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 4 + [(D, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 1, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) - - # Given score per turn is greater than 2.25, Tranquilizer will never defect twice in a row + expected_attrs={"num_turns_after_good_defection": 1, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, seed=89, + attrs=expected_attrs) + + """ Given score per turn is greater than 2.25, + Tranquilizer will never defect twice in a row""" opponent = axelrod.MockPlayer(actions = [C] * 6) actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 2, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 2, - "two_turns_after_good_defection_ratio_count": 1}) + expected_attrs={"num_turns_after_good_defection": 2, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 2, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, seed=89, + attrs=expected_attrs) # Tests cooperation after update_state opponent = axelrod.MockPlayer(actions=[C] * 5) actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 2, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 2, - "two_turns_after_good_defection_ratio_count": 1}) + expected_attrs={"num_turns_after_good_defection": 2, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 2, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, seed=89, + attrs=expected_attrs) # Ensures FD1 values are calculated opponent = axelrod.MockPlayer(actions=[C] * 6) actions = [(C, C)] * 4 + [(D, C), (C, C)] - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 2, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 2, - "two_turns_after_good_defection_ratio_count": 1}) - + expected_attrs={"num_turns_after_good_defection": 2, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 2, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, seed=89, + attrs=expected_attrs) + # Ensures FD2 values are calculated opponent = axelrod.MockPlayer(actions=[C] * 6) actions = [(C, C)] * 4 + [(D, C)] + [(C, C)] * 2 - self.versus_test(opponent, expected_actions=actions, seed=89, attrs={"num_turns_after_good_defection": 0, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 1.5, - "one_turn_after_good_defection_ratio_count": 2, - "two_turns_after_good_defection_ratio_count": 2}) - + expected_attrs={"num_turns_after_good_defection": 0, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 1.5, + "one_turn_after_good_defection_ratio_count": 2, + "two_turns_after_good_defection_ratio_count": 2} + self.versus_test(opponent, expected_actions=actions, seed=89, + attrs=expected_attrs) + # Ensures scores are being counted opponent = axelrod.Defector() actions = [(C, D)] + [(D, D)] * 19 - self.versus_test(opponent, expected_actions=actions, attrs={"num_turns_after_good_defection": 0, - "one_turn_after_good_defection_ratio": 5, - "two_turns_after_good_defection_ratio": 0, - "one_turn_after_good_defection_ratio_count": 1, - "two_turns_after_good_defection_ratio_count": 1}) - \ No newline at end of file + expected_attrs={"num_turns_after_good_defection": 0, + "one_turn_after_good_defection_ratio": 5, + "two_turns_after_good_defection_ratio": 0, + "one_turn_after_good_defection_ratio_count": 1, + "two_turns_after_good_defection_ratio_count": 1} + self.versus_test(opponent, expected_actions=actions, + attrs=expected_attrs) From d590ca15022f9e59e7cb50fda4968aa76e1292ab Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Sat, 2 Sep 2017 15:42:45 +0100 Subject: [PATCH 27/28] Note that strategy has been implemented. --- docs/reference/overview_of_strategies.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/overview_of_strategies.rst b/docs/reference/overview_of_strategies.rst index 5aece3062..84b4241bb 100644 --- a/docs/reference/overview_of_strategies.rst +++ b/docs/reference/overview_of_strategies.rst @@ -137,7 +137,7 @@ repository. "K64R_", "Brian Yamachi", "Not Implemented" "K65R_", "Mark F Batell", "Not Implemented" "K66R_", "Ray Mikkelson", "Not Implemented" - "K67R_", "Craig Feathers", "Not Implemented" + "K67R_", "Craig Feathers", ":class:`Tranquilizer `" "K68R_", "Fransois Leyvraz", "Not Implemented" "K69R_", "Johann Joss", "Not Implemented" "K70R_", "Robert Pebly", "Not Implemented" From 1a0ab104a682ebc17c8e5d0a3c551b7f6ff2480e Mon Sep 17 00:00:00 2001 From: Mansour Hakem Date: Sun, 3 Sep 2017 16:50:26 +0100 Subject: [PATCH 28/28] Fix grammatical errors --- axelrod/strategies/axelrod_second.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/axelrod/strategies/axelrod_second.py b/axelrod/strategies/axelrod_second.py index 91bd940a0..37dd94a6f 100644 --- a/axelrod/strategies/axelrod_second.py +++ b/axelrod/strategies/axelrod_second.py @@ -223,9 +223,9 @@ class Tranquilizer(Player): Fortran strategy K67R from Axelrod's second tournament. Reversed engineered by: Owen Campbell, Will Guo and Mansour Hakem. - The strategy starts by cooperating this strategy has 3 states. + The strategy starts by cooperating and has 3 states. - At the start of the strategy it updates it's states: + At the start of the strategy it updates its states: - It counts the number of consecutive defections by the opponent. - If it was in state 2 it moves to state 0 and calculates the @@ -343,7 +343,7 @@ def update_state(self, opponent): """ Calculates the ratio values for the one_turn_after_good_defection_ratio, two_turns_after_good_defection_ratio and the probability values, - as well as sets the value of num_turns_after_good_defection. + and sets the value of num_turns_after_good_defection. """ if opponent.history[-1] == D: self.opponent_consecutive_defections += 1 @@ -377,7 +377,7 @@ def update_state(self, opponent): def strategy(self, opponent: Player) -> Action: - if len(self.history) == 0: + if not self.history: return C