Source code for axelrod.strategies.frequency_analyzer

from axelrod.action import Action, actions_to_str
from axelrod.player import Player
from axelrod.strategy_transformers import (
    FinalTransformer,
    TrackHistoryTransformer,
)

C, D = Action.C, Action.D


[docs] class FrequencyAnalyzer(Player): """ A player starts by playing TitForTat for the first 30 turns (dataset generation phase). Take the matrix of last 2 moves by both Player and Opponent. While in dataset generation phase, construct a dictionary d, where keys are each 4 move sequence and the corresponding value for each key is a list of the subsequent Opponent move. The 4 move sequence starts with the Opponent move. For example, if a game at turn 5 looks like this: Opp: C, C, D, C, D Player: C, C, C, D, C d should look like this: { [CCCC]: [D], [CCDC]: [C], [DCCD]: [D] } During dataset generation phase, Player will play TitForTat. After end of dataset generation phase, Player will switch strategies. Upon encountering a particular 4-move sequence in the game, Player will look up history of subsequent Opponent move. If ratio of defections to total moves exceeds p, Player will defect. Otherwise, Player will cooperate. Could fall under "Hunter" class of strategies. More likely falls under LookerUp class of strategies. Names: - FrequencyAnalyzer (FREQ): Original by Ian Miller """ # These are various properties for the strategy name = "FrequencyAnalyzer" classifier = { "memory_depth": float("inf"), "stochastic": False, "long_run_time": False, "inspects_source": False, "manipulates_source": False, "manipulates_state": False, } def __init__(self) -> None: """ Parameters ---------- p, float The probability to cooperate """ super().__init__() self.minimum_cooperation_ratio = 0.25 self.frequency_table: dict = dict() self.last_sequence = "" self.current_sequence = ""
[docs] def strategy(self, opponent: Player) -> Action: """This is the actual strategy""" if len(self.history) > 5: self.last_sequence = ( str(opponent.history[-3]) + str(self.history[-3]) + str(opponent.history[-2]) + str(self.history[-2]) ) self.current_sequence = ( str(opponent.history[-2]) + str(self.history[-2]) + str(opponent.history[-1]) + str(self.history[-1]) ) self.update_table(opponent) # dataset generation phase if (len(self.history) < 30) or ( self.current_sequence not in self.frequency_table ): if not self.history: return C if opponent.history[-1] == D: return D return C # post-dataset generation phase results = self.frequency_table[self.current_sequence] cooperates = results.count(C) if (cooperates / len(self.history)) > self.minimum_cooperation_ratio: return C return D
def update_table(self, opponent: Player): if self.last_sequence in self.frequency_table.keys(): results = self.frequency_table[self.last_sequence] results.append(opponent.history[-1]) self.frequency_table[self.last_sequence] = results else: self.frequency_table[self.last_sequence] = [opponent.history[-1]]