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]]