Skip to content

Commit 2b14c9f

Browse files
committed
Adding MutateTransform
- Can pass either a prob and single player OR a distribution and list of players. - Tests for simple deterministic cases - Docs
1 parent cae2ffd commit 2b14c9f

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

axelrod/strategy_transformers.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import inspect
1010
import random
1111
from types import FunctionType
12+
from numpy.random import choice
1213

1314
from .actions import Actions, flip_action
1415
from .random_ import random_choice
@@ -239,6 +240,31 @@ def apology_wrapper(player, opponent, action, myseq, opseq):
239240
ApologyTransformer = StrategyTransformerFactory(apology_wrapper,
240241
name_prefix="Apologizing")
241242

243+
244+
def mutate_wrapper(player, opponent, action, probability, m_player):
245+
""""""
246+
247+
# If a single probability, player is passed
248+
if type(probability) in [float, int]:
249+
m_player = [m_player]
250+
probability = [probability]
251+
252+
# If a probability distribution, players is passed
253+
if type(probability) == type(m_player) is list:
254+
mutate_prob = sum(probability) # Prob of mutation
255+
if mutate_prob > 0:
256+
# Distribution of choice of mutation:
257+
normalised_prob = [prob / float(mutate_prob)
258+
for prob in probability]
259+
if random.random() < mutate_prob:
260+
p = choice(m_player, p=normalised_prob)()
261+
p.history = player.history
262+
return p.strategy(opponent)
263+
264+
return action
265+
266+
MutateTransformer = StrategyTransformerFactory(mutate_wrapper, name_prefix="Mutated")
267+
242268
# Strategy wrappers as classes
243269

244270
class RetaliationWrapper(object):
@@ -260,6 +286,7 @@ def __call__(self, player, opponent, action, retaliations):
260286
RetaliationTransformer = StrategyTransformerFactory(
261287
RetaliationWrapper(), name_prefix="Retaliating")
262288

289+
263290
class RetaliationUntilApologyWrapper(object):
264291
"""Enforces the TFT rule that the opponent pay back a defection with a
265292
cooperation for the player to stop defecting."""

axelrod/tests/unit/test_strategy_transformers.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,53 @@ def test_apology(self):
212212
p1.play(p2)
213213
self.assertEqual(p1.history, [D, D, C, D, D, C])
214214

215+
def test_mutate(self):
216+
"""Tests the MutateTransformer."""
217+
probability = 1
218+
MD = MutateTransformer(probability, axelrod.Cooperator)(axelrod.Defector)
219+
220+
p1 = MD()
221+
p2 = axelrod.Cooperator()
222+
for _ in range(5):
223+
p1.play(p2)
224+
self.assertEqual(p1.history, [C, C, C, C, C])
225+
226+
probability = 0
227+
MD = MutateTransformer(probability, axelrod.Cooperator)(axelrod.Defector)
228+
229+
p1 = MD()
230+
p2 = axelrod.Cooperator()
231+
for _ in range(5):
232+
p1.play(p2)
233+
self.assertEqual(p1.history, [D, D, D, D, D])
234+
235+
# Decorating with list and distribution
236+
237+
# Decorate a cooperator putting all weight on other strategies that are
238+
# 'nice'
239+
probability = [.3, .2, 0]
240+
strategies = [axelrod.TitForTat, axelrod.Grudger, axelrod.Defector]
241+
MD = MutateTransformer(probability, strategies)(axelrod.Cooperator)
242+
243+
p1 = MD()
244+
# Against a cooperator we see that we only cooperate
245+
p2 = axelrod.Cooperator()
246+
for _ in range(5):
247+
p1.play(p2)
248+
self.assertEqual(p1.history, [C, C, C, C, C])
249+
250+
# Decorate a cooperator putting all weight on Defector
251+
probability = [0, 0, 1]
252+
strategies = [axelrod.TitForTat, axelrod.Grudger, axelrod.Defector]
253+
MD = MutateTransformer(probability, strategies)(axelrod.Cooperator)
254+
255+
p1 = MD()
256+
# Against a cooperator we see that we only cooperate
257+
p2 = axelrod.Cooperator()
258+
for _ in range(5):
259+
p1.play(p2)
260+
self.assertEqual(p1.history, [D, D, D, D, D])
261+
215262
def test_deadlock(self):
216263
"""Test the DeadlockBreakingTransformer."""
217264
# We can induce a deadlock by alterting TFT to defect first

0 commit comments

Comments
 (0)