class DefaultGenomeConfig(object): """Sets up and holds configuration information for the DefaultGenome class.""" allowed_connectivity = [ 'unconnected', 'fs_neat_nohidden', 'fs_neat', 'fs_neat_hidden', 'full_nodirect', 'full', 'full_direct', 'partial_nodirect', 'partial', 'partial_direct' ] def __init__(self, params): # Create full set of available activation functions. self.activation_defs = ActivationFunctionSet() # ditto for aggregation functions - name difference for backward compatibility self.aggregation_function_defs = AggregationFunctionSet() self.aggregation_defs = self.aggregation_function_defs self._params = [ ConfigParameter('num_inputs', int), ConfigParameter('num_outputs', int), ConfigParameter('num_hidden', int), ConfigParameter('feed_forward', bool), ConfigParameter('no_output_loopbacks', bool), ConfigParameter('compatibility_disjoint_coefficient', float), ConfigParameter('compatibility_weight_coefficient', float), ConfigParameter('conn_add_prob', float), ConfigParameter('conn_delete_prob', float), ConfigParameter('node_add_prob', float), ConfigParameter('node_delete_prob', float), ConfigParameter('single_structural_mutation', bool, 'false'), ConfigParameter('structural_mutation_surer', str, 'default'), ConfigParameter('initial_connection', str, 'unconnected') ] # Gather configuration data from the gene classes. self.node_gene_type = params['node_gene_type'] self._params += self.node_gene_type.get_config_params() self.connection_gene_type = params['connection_gene_type'] self._params += self.connection_gene_type.get_config_params() # Use the configuration data to interpret the supplied parameters. for p in self._params: setattr(self, p.name, p.interpret(params)) # By convention, input pins have negative keys, and the output # pins have keys 0,1,... self.input_keys = [-i - 1 for i in range(self.num_inputs)] self.output_keys = [i for i in range(self.num_outputs)] self.connection_fraction = None # Verify that initial connection type is valid. # pylint: disable=access-member-before-definition if 'partial' in self.initial_connection: c, p = self.initial_connection.split() self.initial_connection = c self.connection_fraction = float(p) if not (0 <= self.connection_fraction <= 1): raise RuntimeError( "'partial' connection value must be between 0.0 and 1.0, inclusive." ) assert self.initial_connection in self.allowed_connectivity # Verify structural_mutation_surer is valid. # pylint: disable=access-member-before-definition if self.structural_mutation_surer.lower() in [ '1', 'yes', 'true', 'on' ]: self.structural_mutation_surer = 'true' elif self.structural_mutation_surer.lower() in [ '0', 'no', 'false', 'off' ]: self.structural_mutation_surer = 'false' elif self.structural_mutation_surer.lower() == 'default': self.structural_mutation_surer = 'default' else: error_string = "Invalid structural_mutation_surer {!r}".format( self.structural_mutation_surer) raise RuntimeError(error_string) self.node_indexer = None def add_activation(self, name, func): self.activation_defs.add(name, func) def add_aggregation(self, name, func): self.aggregation_function_defs.add(name, func) def save(self, f): if 'partial' in self.initial_connection: if not (0 <= self.connection_fraction <= 1): raise RuntimeError( "'partial' connection value must be between 0.0 and 1.0, inclusive." ) f.write('initial_connection = {0} {1}\n'.format( self.initial_connection, self.connection_fraction)) else: f.write('initial_connection = {0}\n'.format( self.initial_connection)) assert self.initial_connection in self.allowed_connectivity write_pretty_params( f, self, [p for p in self._params if 'initial_connection' not in p.name]) def get_new_node_key(self, node_dict): if self.node_indexer is None: self.node_indexer = count(max(list(node_dict)) + 1) new_id = next(self.node_indexer) assert new_id not in node_dict return new_id def check_structural_mutation_surer(self): if self.structural_mutation_surer == 'true': return True elif self.structural_mutation_surer == 'false': return False elif self.structural_mutation_surer == 'default': return self.single_structural_mutation else: error_string = "Invalid structural_mutation_surer {!r}".format( self.structural_mutation_surer) raise RuntimeError(error_string)
class DefaultGenomeConfig(object): allowed_connectivity = ['unconnected', 'fs_neat', 'full', 'partial'] aggregation_function_defs = { 'sum': sum, 'max': max, 'min': min, 'product': product } def __init__(self, params): # Create full set of available activation functions. self.activation_defs = ActivationFunctionSet() self.activation_options = params.get('activation_options', 'sigmoid').strip().split() self.aggregation_options = params.get('aggregation_options', 'sum').strip().split() self._params = [ ConfigParameter('num_inputs', int), ConfigParameter('num_outputs', int), ConfigParameter('num_hidden', int), ConfigParameter('feed_forward', bool), ConfigParameter('compatibility_disjoint_coefficient', float), ConfigParameter('compatibility_weight_coefficient', float), ConfigParameter('conn_add_prob', float), ConfigParameter('conn_delete_prob', float), ConfigParameter('node_add_prob', float), ConfigParameter('node_delete_prob', float) ] # Gather configuration data from the gene classes. self.node_gene_type = params['node_gene_type'] self._params += self.node_gene_type.get_config_params() self.connection_gene_type = params['connection_gene_type'] self._params += self.connection_gene_type.get_config_params() # Use the configuration data to interpret the supplied parameters. for p in self._params: setattr(self, p.name, p.interpret(params)) # By convention, input pins have negative keys, and the output # pins have keys 0,1,... self.input_keys = [-i - 1 for i in range(self.num_inputs)] self.output_keys = [i for i in range(self.num_outputs)] self.connection_fraction = None # Verify that initial connection type is valid. self.initial_connection = params.get('initial_connection', 'unconnected') if 'partial' in self.initial_connection: c, p = self.initial_connection.split() self.initial_connection = c self.connection_fraction = float(p) if not (0 <= self.connection_fraction <= 1): raise Exception( "'partial' connection value must be between 0.0 and 1.0, inclusive." ) assert self.initial_connection in self.allowed_connectivity def add_activation(self, name, func): self.activation_defs.add(name, func) def save(self, f): if 'partial' in self.initial_connection: if not (0 <= self.connection_fraction <= 1): raise Exception( "'partial' connection value must be between 0.0 and 1.0, inclusive." ) f.write('initial_connection = {0} {1}\n'.format( self.initial_connection, self.connection_fraction)) else: f.write('initial_connection = {0}\n'.format( self.initial_connection)) assert self.initial_connection in self.allowed_connectivity write_pretty_params(f, self, self._params) def get_new_node_key(self, node_dict): if not hasattr(self, 'node_indexer'): self.node_indexer = Indexer(max(list(iterkeys(node_dict))) + 1) new_id = self.node_indexer.get_next() assert new_id not in node_dict return new_id