def mutate_add_node(self, genome: Genome) -> bool: if len(genome.connection_gene_list) == 0: return False genome.last_mutation = "Add node" connection_to_replace = numpy.random.choice( genome.connection_gene_list) genome.connection_gene_list.remove(connection_to_replace) neuron_id = 0 if connection_to_replace.inno_id in self.connection_replaced: neuron_id = self.connection_replaced[connection_to_replace.inno_id] else: neuron_id = self.next_neuron_innovation() self.connection_replaced[connection_to_replace.inno_id] = neuron_id new_neuron = NeuronGene( neuron_id, self.activation_fn_library.get_random_function(), NeuronType.HIDDEN) self.neuron_innovation[new_neuron.inno_id] = new_neuron new_connection1 = self.create_connection(connection_to_replace.from_id, neuron_id, connection_to_replace.weight) new_connection2 = self.create_connection(neuron_id, connection_to_replace.to_id, 1.0) from_neuron = genome.neuron_gene_dict[connection_to_replace.from_id] to_neuron = genome.neuron_gene_dict[connection_to_replace.to_id] from_neuron.target_neurons.remove(to_neuron) to_neuron.source_neurons.remove(from_neuron) new_neuron.target_neurons.append( genome.neuron_gene_dict[connection_to_replace.to_id]) new_neuron.source_neurons.append( genome.neuron_gene_dict[connection_to_replace.from_id]) genome.neuron_gene_dict[new_neuron.inno_id] = new_neuron genome.neuron_gene_list.append(new_neuron) from_neuron.target_neurons.append(new_neuron) to_neuron.source_neurons.append(new_neuron) genome.connection_gene_list.append(new_connection1) genome.connection_gene_list.append(new_connection2) return True
def mutate_weights(self, genome: Genome) -> bool: num_connection_mutation: float = numpy.sin( random.random() * (numpy.pi / 2)) * len(genome.connection_gene_list) connections_to_mutate: List[ConnectionGene] = random.sample( genome.connection_gene_list, int(num_connection_mutation)) for conn in connections_to_mutate: conn.weight = numpy.clip( conn.weight + (random.random() - 0.5), -self.genome_params.connection_weight_range, self.genome_params.connection_weight_range) genome.last_mutation = "Mutate weights" return num_connection_mutation > 0
def mutate_delete_connection(self, genome: Genome) -> bool: if len(genome.connection_gene_list) < 2: return False connection_to_delete: ConnectionGene = random.choice( genome.connection_gene_list) from_neuron = genome.neuron_gene_dict[connection_to_delete.from_id] to_neuron = genome.neuron_gene_dict[connection_to_delete.to_id] from_neuron.target_neurons.remove(to_neuron) to_neuron.source_neurons.remove(from_neuron) genome.connection_gene_list.remove(connection_to_delete) genome.last_mutation = "Delete" return True
def mutate_add_connection(self, genome: Genome) -> bool: neuron_count = len(genome.neuron_gene_list) hidden_output_neuron_count = neuron_count - self.input_count input_bias_hidden_neuron_count = neuron_count - self.output_count genome.last_mutation = "Add" if self.genome_params.feed_forward_only: for attempts in range(5): source_neuron_idx = random.randint( 0, input_bias_hidden_neuron_count - 1) if self.input_count + self.output_count > source_neuron_idx >= self.input_count: source_neuron_idx += self.output_count target_neuron_idx = self.input_count + random.randint( 0, hidden_output_neuron_count - 1) if source_neuron_idx == target_neuron_idx: target_neuron_idx += 1 if target_neuron_idx == neuron_count: continue source_neuron = genome.neuron_gene_list[source_neuron_idx] target_neuron = genome.neuron_gene_list[target_neuron_idx] if target_neuron.type == NeuronType.BIAS or target_neuron in source_neuron.target_neurons or genome.is_connection_cyclic( source_neuron.inno_id, target_neuron.inno_id): continue self.mutate_add_create_connection(genome, source_neuron, target_neuron) return True else: for attempts in range(5): source_neuron_idx = random.randint(0, neuron_count - 1) target_neuron_idx = self.input_count + random.randint( 0, hidden_output_neuron_count - 1) source_neuron = genome.neuron_gene_list[source_neuron_idx] target_neuron = genome.neuron_gene_list[target_neuron_idx] self.mutate_add_create_connection(genome, source_neuron, target_neuron) return True