diff --git a/axelrod/moran.py b/axelrod/moran.py index b5e3ffbe8..0cd102aad 100644 --- a/axelrod/moran.py +++ b/axelrod/moran.py @@ -122,20 +122,12 @@ def __init__( self._random = RandomGenerator(seed=seed) self._bulk_random = BulkRandomGenerator(self._random.random_seed_int()) self.set_players() - # Build the set of mutation targets - # Determine the number of unique types (players) - keys = set([str(p) for p in players]) - # Create a dictionary mapping each type to a set of representatives - # of the other types - d = dict() - for p in players: - d[str(p)] = p - mutation_targets = dict() - for key in sorted(keys): - mutation_targets[key] = [ - v for (k, v) in sorted(d.items()) if k != key - ] - self.mutation_targets = mutation_targets + + # Dedupe initial players as mutation targets + initial_players_by_name = { + player.name: player for player in self.initial_players + } + self.mutation_targets = [pi for pi in initial_players_by_name.values()] if interaction_graph is None: interaction_graph = complete_graph(len(players), loops=False) @@ -218,16 +210,15 @@ def mutate(self, index: int) -> Player: return self.players[index].mutate() # Assuming mutation_method == "transition" - if self.mutation_rate > 0: - # Choose another strategy at random from the initial population - r = self._random.random() - if r < self.mutation_rate: - s = str(self.players[index]) - j = self._random.randrange(0, len(self.mutation_targets[s])) - p = self.mutation_targets[s][j] - return p.clone() - # Just clone the player - return self.players[index].clone() + if self._random.random() > self.mutation_rate: + # Just clone the player + return self.players[index].clone() + + # Choose another strategy at random from the initial population + player = None + while player is None or str(player) == str(self.players[index]): + player = self._random.choice(self.mutation_targets) + return player.clone() def death(self, index: int = None) -> int: """