def mutate(self, parent: Tree): if (self.mutation_algorithms is None) or (self.mutation_algorithms is []): return elif random.random() > self.mutation_rate: return rand_mutation_method: str = self.mutation_algorithms[random.randrange( 0, self.mutation_algorithms.__len__())] # todo not sure about correct names for these types of mutations if rand_mutation_method is "delete": # delete children underneath and attach random terminals to it self.__mutate_delete(parent) elif rand_mutation_method is "change": # change the label of the node with respect to its max_num_of_children self.__mutate_change(parent) elif rand_mutation_method is "add": # adds a whole new tree as one of its children self.__mutate_add(parent) elif rand_mutation_method is "exchange": # change the type (function to terminal and otherwise) pass # todo implement this else: raise Exception("Invalid Algorithm for Mutation") parent.is_mutated = True parent.update_tree() if parent.depth > self.max_depth: parent.reshape_max_depth(self.max_depth)
def __cross_over(self, parent_1: Tree, parent_2: Tree) -> Tree: # getting a random node from parent_2 temp_node = parent_2.get_random_node().copy() # region generating a index range for parent_1 depth_min_range = hp.GP.cross_over_min_range depth_max_range = int(hp.GP.cross_over_min_range_multiplier * parent_1.number_of_nodes_in_tree) if depth_min_range >= depth_max_range: raise Exception("Invalid Range for crossover replacement : (", depth_min_range, " , ", depth_max_range, ")") if depth_max_range is 1: depth_max_range += 1 depth_range = (depth_min_range, depth_max_range) # endregion parent_1.select_random_node_and_replace(depth_range, temp_node) # update and reshape the tree if needed parent_1.update_tree() if parent_1.depth > self.max_depth: parent_1.reshape_max_depth(self.max_depth) return parent_1