def _calculate_possible_inputs_when_adding_connection( genome: Genome, out_node_key: int, config: BaseConfiguration): # all nodes possible_input_keys_set = set(genome.node_genes.keys()).union( set(genome.get_input_nodes_keys())) # no connection between two output nodes possible_input_keys_set -= set(genome.get_output_nodes_keys()) if config.feed_forward: # avoid self-recurrency possible_input_keys_set -= {out_node_key} # pass # REMOVE POSSIBLE CONNECTIONS possible_connection_set = set( itertools.product(list(possible_input_keys_set), [out_node_key])) # remove already existing connections: don't duplicate connections possible_connection_set -= set(genome.connection_genes.keys()) # remove possible connections that introduce cycles possible_connection_set = \ ArchitectureMutation._remove_connection_that_introduces_cycles(genome=genome, possible_connection_set=possible_connection_set) # # remove possible connections that introduce multihop jumps # possible_connection_set = \ # Mutation._remove_connection_that_introduces_multihop_jumps(genome=genome, # possible_connection_set=possible_connection_set) if len(possible_connection_set) == 0: return [] possible_input_keys_set = list(zip(*list(possible_connection_set)))[0] return possible_input_keys_set
def plot_genome_network(genome: Genome, filename='./network.png', view=True): return plot_network(nodes=list(genome.node_genes.keys()), edges=list(genome.connection_genes.keys()), input_nodes=genome.get_input_nodes_keys(), output_nodes=genome.get_output_nodes_keys(), filename=filename, view=view)
def generate_genome_given_graph(graph, connection_weights): genome = Genome(key='foo') unique_node_keys = [] input_nodes = [] for connection in graph: for node_key in connection: if node_key not in unique_node_keys: unique_node_keys.append(node_key) if node_key < 0: input_nodes.append(node_key) input_nodes = set(input_nodes) unique_node_keys = list( set(unique_node_keys + genome.get_output_nodes_keys()) - input_nodes) nodes = {} for node_key in unique_node_keys: node = NodeGene(key=node_key).random_initialization() node.set_mean(0) node.set_std(STD) nodes[node_key] = node connections = {} for connection_key, weight in zip(graph, connection_weights): connection = ConnectionGene(key=connection_key) connection.set_mean(weight) connection.set_std(STD) connections[connection_key] = connection genome.connection_genes = connections genome.node_genes = nodes return genome
def _remove_connection_that_introduces_multihop_jumps( genome: Genome, possible_connection_set: set) -> set: output_node_keys = genome.get_output_nodes_keys() input_node_keys = genome.get_input_nodes_keys() connections_to_remove = [] for connection in possible_connection_set: connections = list(genome.connection_genes.keys()) + [connection] if adds_multihop_jump(connections=connections, output_node_keys=output_node_keys, input_node_keys=input_node_keys): connections_to_remove.append(connection) possible_connection_set -= set(connections_to_remove) return possible_connection_set
def _get_available_nodes_to_be_deleted(self, genome: Genome): available_nodes = set(genome.node_genes.keys()) - set( genome.get_output_nodes_keys()) return list(available_nodes)
def transform_genome_to_layers(genome: Genome) -> dict: layers = dict() nodes = genome.node_genes connections = genome.connection_genes nodes_per_layer = calculate_nodes_per_layer( links=list(connections.keys()), input_node_keys=genome.get_input_nodes_keys(), output_node_keys=genome.get_output_nodes_keys()) layer_indices = list(nodes_per_layer.keys()) layer_indices.sort() for layer_index in layer_indices[:-1]: original_nodes_in_layer = nodes_per_layer[layer_index] layer = LayerBuilder(nodes=nodes, connections=connections, layer_node_keys=original_nodes_in_layer, nodes_per_layer=nodes_per_layer, layer_counter=layer_index) \ .create() \ .get_layer() layers[layer_index] = layer # enrich layers for layer_counter, layer in layers.items(): # logger.debug(f'Layer: {layer_counter}') # add needed indices for node_key in layer.external_input_keys: index = None for layer_2 in layers.values(): if node_key in layer_2.original_input_keys: index = (layer_2.key, layer_2.input_keys.index(node_key)) break assert index is not None layer.indices_of_needed_nodes.append(index) layer.needed_nodes[node_key] = index # add indices to cache for node_key in layer.original_input_keys: for layer_2 in layers.values(): if node_key in layer_2.external_input_keys: index = layer.input_keys.index(node_key) # add if not in list if index not in layer.indices_of_nodes_to_cache: layer.indices_of_nodes_to_cache.append(index) if len(layer.indices_of_needed_nodes) > 1: needed_node_keys = list(layer.needed_nodes.keys()) needed_node_keys.sort() sorted_indices_of_needed_nodes = [] for node_key in needed_node_keys: sorted_indices_of_needed_nodes.append( layer.needed_nodes[node_key]) assert len(sorted_indices_of_needed_nodes) == len( layer.indices_of_needed_nodes) layer.indices_of_needed_nodes = sorted_indices_of_needed_nodes logger.debug(f'Indices to cache: {layer.indices_of_nodes_to_cache}') logger.debug( f'Indices needed from cache: {layer.indices_of_needed_nodes}') return layers