Source code for pygenalgo.operators.mutation.meta_mutator

from pygenalgo.genome.chromosome import Chromosome
from pygenalgo.operators.mutation.swap_mutator import SwapMutator
from pygenalgo.operators.mutation.random_mutator import RandomMutator
from pygenalgo.operators.mutation.shuffle_mutator import ShuffleMutator
from pygenalgo.operators.mutation.inverse_mutator import InverseMutator
from pygenalgo.operators.mutation.mutate_operator import MutationOperator


[docs] class MetaMutator(MutationOperator): """ Description: Meta-mutator, mutates the chromosome by applying randomly all other mutators (one at a time), with equal probability. NOTE: In the future the equal probabilities can be amended. """ def __init__(self, mutate_probability: float = 0.1) -> None: """ Construct a 'MetaMutator' object with a predefined probability value. :param mutate_probability: (float). """ # Call the super constructor with the provided probability value. super().__init__(mutate_probability) # NOTE: In here the mutation probabilities for each mutator are set to 1.0. self._items = (SwapMutator(1.0), RandomMutator(1.0), ShuffleMutator(1.0), InverseMutator(1.0)) # _end_def_
[docs] def mutate(self, individual: Chromosome) -> None: """ Perform the mutation operation by randomly applying another mutator. :param individual: (Chromosome). :return: None. """ # If the mutation probability is higher than # a uniformly random value, make the changes. if self.is_operator_applicable(): # Get the number of available mutators. n_operators: int = len(self.items) # Select randomly with equal probability # a mutator and call its mutation method. self.items[self.rng.integers(n_operators, dtype=int)].mutate(individual) # Increase the mutator counter. self.inc_counter()
# _end_def_ @property def all_counters(self) -> dict: """ Accessor (getter) of the application counter from all the internal mutators. This is mostly to verify that everything is working as expected. :return: a dictionary with the counter calls for all mutator methods. """ return {mut_op.__class__.__name__: mut_op.counter for mut_op in self.items} # _end_def_
[docs] def reset_counter(self) -> None: """ Sets ALL the counters to 'zero'. We have to override the super().reset_counter() method, because we have to call explicitly the reset_counter on all the internal operators. :return: None. """ # First call the super() to reset the self internal counter. super().reset_counter() # Here call explicitly the reset on each of the internal mutators. for op in self.items: op.reset_counter()
# _end_def_ # _end_class_