Source code for desdeo_emo.recombination.biogp_mutation

import numpy as np
from random import choice, sample


[docs]def mutate(offspring, individuals, params, *args): """Perform BioGP mutation functions. Standard mutation: Randomly select and regrow a subtree of an individual. Small mutation: Randomly select a node within a tree and replace it with either a function of the same arity, or another value from the terminal set. Mono parental: Randomly swap two subtrees within the same individual. Parameters ---------- offspring : list List of individuals to mutate. individuals : list List of all individuals. params : dict Parameters for breeding. If None, use defaults. """ prob_mut = params.get("prob_mutation", 0.3) prob_stand = 1 / 3 * prob_mut prob_point = 1 / 3 * prob_mut prob_mono = prob_mut - prob_stand - prob_point prob_replace = prob_mut r = np.random.rand() for ind in offspring: if r <= prob_stand: # Standard mutation # # This picks a random subtree anywhere within the tree rand_node = choice(ind.nodes[1:]) tree = ind.grow_tree(method="grow", depth=rand_node.depth, ind=rand_node) rand_node.value = tree.value rand_node.roots = tree.roots # This picks a whole subtree at depth=1 under the linear node # rand_subtree = np.random.randint(len(ind.roots)) # del ind.roots[rand_subtree] # ind.grow_tree(method="grow", ind=ind) ind.nodes = ind.get_sub_nodes() elif r <= prob_point + prob_stand: # Small mutation for node in ind.nodes[1:]: if np.random.rand() < prob_replace and callable(node.value): value = choice(node.function_set) while node.value.__code__.co_argcount != value.__code__.co_argcount: value = choice(node.function_set) node.value = value elif np.random.rand() < prob_replace: node.value = choice(node.terminal_set) ind.nodes = ind.get_sub_nodes() elif r <= prob_mono + prob_point + prob_stand: # Mono parental swap_nodes = sample(ind.nodes[1:], 2) tmp_value = swap_nodes[0].value tmp_roots = swap_nodes[0].roots swap_nodes[0].value = swap_nodes[1].value swap_nodes[0].roots = swap_nodes[1].roots swap_nodes[1].value = tmp_value swap_nodes[1].roots = tmp_roots ind.nodes = ind.get_sub_nodes() else: pass
[docs]class BioGP_mutation: def __init__(self, probability_mutation: float): self.probability_mutation: float = probability_mutation self.probability_stand = probability_mutation / 3 self.probability_point = probability_mutation / 3 self.probability_mono = probability_mutation / 3 self.probability_replace = probability_mutation
[docs] def do(self, offspring): r = np.random.rand() for ind in offspring[:, 0]: if r <= self.probability_stand: # Standard mutation # # This picks a random subtree anywhere within the tree rand_node = choice(ind.nodes[1:]) tree = ind.grow_tree( method="grow", depth=rand_node.depth, ind=rand_node ) rand_node.value = tree.value rand_node.roots = tree.roots # This picks a whole subtree at depth=1 under the linear node # rand_subtree = np.random.randint(len(ind.roots)) # del ind.roots[rand_subtree] # ind.grow_tree(method="grow", ind=ind) ind.nodes = ind.get_sub_nodes() elif r <= self.probability_point + self.probability_stand: # Small mutation for node in ind.nodes[1:]: if np.random.rand() < self.probability_replace and callable( node.value ): value = choice(node.function_set) while ( node.value.__code__.co_argcount != value.__code__.co_argcount ): value = choice(node.function_set) node.value = value elif np.random.rand() < self.probability_replace: node.value = choice(node.terminal_set) ind.nodes = ind.get_sub_nodes() elif r <= self.probability_mutation: # Mono parental swap_nodes = sample(ind.nodes[1:], 2) tmp_value = swap_nodes[0].value tmp_roots = swap_nodes[0].roots swap_nodes[0].value = swap_nodes[1].value swap_nodes[0].roots = swap_nodes[1].roots swap_nodes[1].value = tmp_value swap_nodes[1].roots = tmp_roots ind.nodes = ind.get_sub_nodes() else: pass return np.asarray(offspring)