def parse_config(cls, param_dict): return DefaultClassConfig(param_dict, [ ConfigParameter('elitism', int, 0), ConfigParameter('survival_threshold', float, 0.2), ConfigParameter('min_species_size', int, 2), ConfigParameter('fitness_min_divisor', float, 1.0) ])
def parse_config(cls, param_dict): return DefaultClassConfig(param_dict, [ConfigParameter('max_num_states', int, 5), ConfigParameter('elitism', int, 0), ConfigParameter('survival_threshold', float, 0.2), ConfigParameter('min_species_size', int, 2) ])
def get_config_params(self): default_name, opt_name, rate_name = self.config_item_names() return [ ConfigParameter(default_name, str), ConfigParameter(opt_name, list), ConfigParameter(rate_name, float) ]
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._params = [ ConfigParameter('num_inputs', int), ConfigParameter('num_outputs', int), ConfigParameter('num_initial_states', int), ConfigParameter('max_num_states', int, 1000), # Note the default. ConfigParameter('state_add_prob', float), ConfigParameter('state_delete_prob', float), ConfigParameter('transition_add_prob', float), ConfigParameter('transition_delete_prob', float), ConfigParameter('compatibility_disjoint_coefficient', float), ConfigParameter('compatibility_difference_coefficient', 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)) self.node_indexer = self.num_initial_states
def __init__(self, params): super().__init__(params) _params = [ConfigParameter('num_hidden_per_layer', list), ConfigParameter('connectivity', float)] for p in _params: setattr(self, p.name, p.interpret(params)) self.num_hidden_per_layer = [int(i) for i in self.num_hidden_per_layer] self.num_layers = len(self.num_hidden_per_layer) + 2
def __init__(self, params): StateMachineGenomeConfig.__init__(self, params) additional_params = [ConfigParameter('genome_source', str), ConfigParameter('fixed_section', str)] self._params.extend(additional_params) for p in additional_params: setattr(self, p.name, p.interpret(params))
def parse_config(cls, param_dict: Dict[str, str]) -> DefaultClassConfig: return DefaultClassConfig( param_dict, [ ConfigParameter("elitism", int, 0), ConfigParameter("survival_threshold", float, 0.2), ConfigParameter("min_species_size", int, 2), ], )
def __init__(self, params): _my_params = [ ConfigParameter("node_mutate_prob", float), ConfigParameter("conn_mutate_prob", float) ] for p in _my_params: setattr(self, p.name, p.interpret(params)) super().__init__(params)
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
class CircuitGenomeConfig(object): __params = [ ConfigParameter('num_inputs', int), ConfigParameter('num_outputs', int), 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) ] 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() # Gather configuration data from the gene classes. self.__params += CircuitNodeGene.get_config_params() self.__params += CircuitConnectionGene.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)] def save(self, f): write_pretty_params(f, self, self.__params)
def parse_config(cls, param_dict): """ add init and min distance in config. :param param_dict: parameter dictionary. :return: config. """ return DefaultClassConfig(param_dict, [ ConfigParameter('init_distance', float, 5), ConfigParameter('min_distance', float, 0.2), ConfigParameter('correlation_rate', float, -0.5), ConfigParameter('search_count', int, 1), ConfigParameter('cluster_method', str, "kmeans++") ])
class GRUGenomeConfig(DefaultGenomeConfig): gru_params = [ConfigParameter('gru_prob', float)] def __init__(self, *args, **kwargs): DefaultGenomeConfig.__init__(self, *args, **kwargs) params = kwargs['params'] for p in self.gru_params: self._params.append(p) setattr(self, p.name, p.interpret(params))
def __init__(self, params): # Create full set of available activation functions. ################### change acc to the config file in the end ############3 self._params = [ ConfigParameter('num_inputs', int), ConfigParameter('num_outputs', int), ConfigParameter('num_hidden', int), ConfigParameter('compatibility_disjoint_coefficient', float), ConfigParameter('compatibility_weight_coefficient', float), ConfigParameter('node_add_prob', float), ConfigParameter('node_delete_prob', float), ConfigParameter('single_structural_mutation', bool, 'false'), ConfigParameter('structural_mutation_surer', str, 'default') ] # Gather configuration data from the gene classes. self.node_gene_type = params['node_gene_type'] self._params += self.node_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 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 parse_config(cls, param_dict): """Parse the speciation parameter values Args: param_dict (dict): A dictionary of parameter values. Returns: DefaultClassConfig: The speciation configuration. """ return DefaultClassConfig( param_dict, [ConfigParameter('compatibility_threshold', float)])
def parse_config(cls, param_dict): """Parses the stagnation configuration parameters. Config Parameters: species_fitness_func (str): The function (mean, max) for aggregating the fitnesses of the members of each species. max_stagnation (int): The maximum number of generations a species can stall for before being deemed stagnant. species_elitism (int): The minimum number of species that should be retained. TODO: Refactor `species_elitism` as `min_species` Args: param_dict: ... Returns: DefaultClassConfig: ... """ return DefaultClassConfig(param_dict, [ ConfigParameter('species_fitness_func', str, 'mean'), ConfigParameter('max_stagnation', int, 15), ConfigParameter('species_elitism', int, 0) ])
def __init__(self, params): """Creates a new ReproductionConfig object. Args: params (dict): A dictionary of config parameters and values. """ self._params = [ ConfigParameter('mutate_only_prob', float), ConfigParameter('crossover_avg_prob', float), ConfigParameter('crossover_only_prob', float), ConfigParameter('inter_species_crossover_prob', float), ConfigParameter('num_elites', int), ConfigParameter('survival_threshold', float), ConfigParameter('elitism_threshold', int) ] # Use the configuration data to interpret the supplied parameters for p in self._params: setattr(self, p.name, p.interpret(params))
def __init__(self, params={}): self._params = [ ConfigParameter('novelty_search_enabled', bool, 'false'), ConfigParameter('pop_knn_neighbours', int, '0'), ConfigParameter('archive_knn_neighbours', int, '0'), ConfigParameter('threshhold', float, '0'), ConfigParameter('behavior_exclusion_type', list), 'None', ConfigParameter('behavior_exclusion_value', list), 'None' ] self.novelty_search_enabled = params.get('novelty_search_enabled', False) self.pop_knn_neighbours = params.get('pop_knn_neighbours', None) self.archive_knn_neighbours = params.get('archive_knn_neighbours', None) self.threshhold = params.get('threshhold', None) self.behavior_exclusion_type = params.get('behavior_exclusion_type', None) self.behavior_exclusion_value = params.get('behavior_exclusion_value', None)
def parse_config(cls, param_dict): return DefaultClassConfig( param_dict, [ConfigParameter('compatibility_threshold', float)])
class _GymNeatConfig(object): ''' A class for helping Gym work with NEAT ''' __params = [ ConfigParameter('pop_size', int), ConfigParameter('fitness_criterion', str), ConfigParameter('fitness_threshold', float), ConfigParameter('reset_on_extinction', bool), ConfigParameter('no_fitness_termination', bool, False) ] def __init__(self, args, layout=None): # Check config file exists if not os.path.isfile(args.configfile): print('No such config file: %s' % os.path.abspath(args.configfile)) exit(1) # Use default NEAT settings self.genome_type = neat.DefaultGenome self.reproduction_type = neat.DefaultReproduction self.species_set_type = neat.DefaultSpeciesSet self.stagnation_type = neat.DefaultStagnation parameters = ConfigParser() with open(args.configfile) as f: if hasattr(parameters, 'read_file'): parameters.read_file(f) else: parameters.readfp(f) self.node_names = {} try: names = parameters['Names'] for idx, name in enumerate(eval(names['input'])): self.node_names[-idx - 1] = name for idx, name in enumerate(eval(names['output'])): self.node_names[idx] = name except Exception: pass param_list_names = [] for p in self.__params: if p.default is None: setattr(self, p.name, p.parse('NEAT', parameters)) else: try: setattr(self, p.name, p.parse('NEAT', parameters)) except Exception: setattr(self, p.name, p.default) warnings.warn( 'Using default %s for %s' % (p.default, p.name), DeprecationWarning) param_list_names.append(p.name) # Bozo filter for missing sections self.check_params(args.configfile, parameters, 'NEAT') self.check_params(args.configfile, parameters, 'Gym') # Get number of episode repetitions gympar = parameters['Gym'] env_name = gympar['environment'] self.reps = int(gympar['episode_reps']) # Make gym environment form name in command-line arguments env = _gym_make(env_name) # Get input/output layout from environment, or from layout for Hyper if layout is None: num_inputs = env.observation_space.shape[0] if _is_discrete(env): num_outputs = env.action_space.n else: num_outputs = env.action_space.shape[0] else: num_inputs, num_outputs = layout # Parse type sections. genome_dict = dict(parameters.items(self.genome_type.__name__)) genome_dict['num_inputs'] = num_inputs genome_dict['num_outputs'] = num_outputs self.genome_config = self.genome_type.parse_config(genome_dict) stagnation_dict = dict(parameters.items(self.stagnation_type.__name__)) self.stagnation_config = \ self.stagnation_type.parse_config(stagnation_dict) self.species_set_dict = \ dict(parameters.items(self.species_set_type.__name__)) self.species_set_config = \ self.species_set_type.parse_config(self.species_set_dict) self.reproduction_dict = \ dict(parameters.items(self.reproduction_type.__name__)) self.reproduction_config = \ self.reproduction_type.parse_config(self.reproduction_dict) # Store environment name for saving results self.env_name = env_name # Get number of generations and random seed from config; # use defaults if missing neatpar = parameters['NEAT'] self.ngen = self.get_with_default(neatpar, 'generations', lambda s: int(s), None) self.seed = self.get_with_default(neatpar, 'seed', lambda s: int(s), None) self.checkpoint = self.get_with_default(neatpar, 'checkpoint', lambda s: bool(s), False) # Set random seed (including None) random.seed(self.seed) # Set max episode steps from spec in __init__.py self.max_episode_steps = env.spec.max_episode_steps # Store environment for later self.env = env # Track evaluations self.current_evaluations = 0 self.total_evaluations = 0 # Support novelty search self.novelty = _GymNeatConfig.parse_novelty(args.configfile) \ if args.novelty else None # Store config parameters for subclasses self.params = parameters # For debugging self.gen = 0 # Default to non-recurrent net self.activations = 1 def eval_net_mean(self, net, genome): return (self.eval_net_mean_novelty(net, genome) if self.is_novelty() else self.eval_net_mean_reward(net, genome)) def eval_net_mean_reward(self, net, genome): reward_sum = 0 total_steps = 0 for _ in range(self.reps): reward, steps = eval_net(net, self.env, activations=self.activations, seed=self.seed, max_episode_steps=self.max_episode_steps) reward_sum += reward total_steps += steps return reward_sum / self.reps, total_steps def eval_net_mean_novelty(self, net, genome): reward_sum = 0 total_steps = 0 # No behaviors yet behaviors = [None] * self.reps for j in range(self.reps): reward, behavior, steps = self.eval_net_novelty(net, genome) reward_sum += reward behaviors[j] = behavior total_steps += steps return reward_sum / self.reps, behaviors, total_steps def eval_net_novelty(self, net, genome): env = self.env env.seed(self.seed) state = env.reset() steps = 0 is_discrete = _is_discrete(env) total_reward = 0 while steps < self.max_episode_steps: # Support recurrent nets for k in range(self.activations): action = net.activate(state) # Support both discrete and continuous actions action = (np.argmax(action) if is_discrete else action * env.action_space.high) state, reward, done, info = env.step(action) behavior = info['behavior'] # Accumulate reward, but not novelty total_reward += reward if done: break steps += 1 env.close() # Return total reward and final behavior return total_reward, behavior, steps def save_genome(self, genome): name = self.make_name(genome) net = FeedForwardNetwork.create(genome, self) pickle.dump((net, self.env_name), open('models/%s.dat' % name, 'wb')) _GymNeatConfig.draw_net(net, 'visuals/%s-network' % name, self.node_names) def is_novelty(self): return self.novelty is not None def make_name(self, genome, suffix=''): return '%s%s%+010.3f' % \ (self.env_name, suffix, genome.actual_fitness) def get_with_default(self, params, name, fun, default): return fun(params[name]) if name in params else default def check_params(self, filename, params, section_name): if not params.has_section(section_name): self.error('%s section missing from configuration file %s' % (section_name, filename)) def error(self, msg): print('ERROR: ' + msg) exit(1) @staticmethod def draw_net(net, filename, node_names): # Create PDF using PUREPLES function draw_net(net, filename=filename, node_names=node_names) # Delete text os.remove(filename) @staticmethod def eval_genome(genome, config): ''' The result of this function gets assigned to the genome's fitness. ''' net = FeedForwardNetwork.create(genome, config) return config.eval_net_mean(net, genome) @staticmethod def parse_novelty(cfgfilename): novelty = None parameters = ConfigParser() with open(cfgfilename) as f: if hasattr(parameters, 'read_file'): parameters.read_file(f) else: parameters.readfp(f) try: names = parameters['Novelty'] novelty = Novelty(eval(names['k']), eval(names['threshold']), eval(names['limit']), eval(names['ndims'])) except Exception: print('File %s has no [Novelty] section' % cfgfilename) exit(1) return novelty
def get_config_params(self): default_name, rate_name = self.config_item_names() return [ ConfigParameter(default_name, bool), ConfigParameter(rate_name, float) ]
class DefaultGenomeConfig(object): __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) ] 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() # 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 parse_config(cls, param_dict: Dict[str, str]) -> DefaultClassConfig: return DefaultClassConfig(param_dict, [ ConfigParameter('species_fitness_func', str, 'mean'), ConfigParameter('max_stagnation', int, 15), ConfigParameter('species_elitism', int, 0) ])
class NeatConfig(object): ''' Replaces neat.Config to support Novelty Search. ''' __params = [ConfigParameter('pop_size', int), ConfigParameter('fitness_criterion', str), ConfigParameter('fitness_threshold', float), ConfigParameter('reset_on_extinction', bool), ConfigParameter('no_fitness_termination', bool, False)] def __init__(self, genome_type, reproduction_type, species_set_type, stagnation_type, config_file_name, env_name, layout_dict, seed, novelty=False): # Check that the provided types have the required methods. assert hasattr(genome_type, 'parse_config') assert hasattr(reproduction_type, 'parse_config') assert hasattr(species_set_type, 'parse_config') assert hasattr(stagnation_type, 'parse_config') self.genome_type = genome_type self.reproduction_type = reproduction_type self.species_set_type = species_set_type self.stagnation_type = stagnation_type self.env_name = env_name self.seed = seed if not os.path.isfile(config_file_name): raise Exception('No such config file: %s' % os.path.abspath(config_file_name)) parameters = ConfigParser() with open(config_file_name) as f: if hasattr(parameters, 'read_file'): parameters.read_file(f) else: parameters.readfp(f) self.node_names = {} try: names = parameters['Names'] for idx, name in enumerate(eval(names['input'])): self.node_names[-idx-1] = name for idx, name in enumerate(eval(names['output'])): self.node_names[idx] = name except Exception: pass # NEAT configuration if not parameters.has_section('NEAT'): raise RuntimeError('NEAT section missing from configuration file.') param_list_names = [] for p in self.__params: if p.default is None: setattr(self, p.name, p.parse('NEAT', parameters)) else: try: setattr(self, p.name, p.parse('NEAT', parameters)) except Exception: setattr(self, p.name, p.default) warnings.warn('Using default %s for %s' % (p.default, p.name), DeprecationWarning) param_list_names.append(p.name) param_dict = dict(parameters.items('NEAT')) unknown_list = [x for x in param_dict if x not in param_list_names] if unknown_list: if len(unknown_list) > 1: raise UnknownConfigItemError( 'Unknown (section NEAT) configuration items:\n' + '\n\t'.join(unknown_list)) raise UnknownConfigItemError( 'Unknown (section NEAT) configuration item %s' % format(unknown_list[0])) # Parse type sections. genome_dict = dict(parameters.items(genome_type.__name__)) # Add layout (input/output) info for key in layout_dict: genome_dict[key] = layout_dict[key] self.genome_config = genome_type.parse_config(genome_dict) species_set_dict = dict(parameters.items(species_set_type.__name__)) self.species_set_config = \ species_set_type.parse_config(species_set_dict) stagnation_dict = dict(parameters.items(stagnation_type.__name__)) self.stagnation_config = stagnation_type.parse_config(stagnation_dict) reproduction_dict = dict(parameters.items(reproduction_type.__name__)) self.reproduction_config = \ reproduction_type.parse_config(reproduction_dict) # Support novelty search self.novelty = _parse_novelty(config_file_name) if novelty else None # Store config parameters for subclasses self.params = parameters # For debugging self.gen = 0 # Default to non-recurrent net self.activations = 1 def save_genome(self, genome): name = self.make_name(genome) net = FeedForwardNetwork.create(genome, self) pickle.dump((net, self.env_name), open('models/%s.dat' % name, 'wb')) _GymNeatConfig.draw_net(net, 'visuals/%s' % name, self.node_names) def is_novelty(self): return self.novelty is not None def get_actual_fitness(self, genome): return genome.actual_fitness if self.is_novelty() else genome.fitness def make_name(self, genome, suffix=''): return '%s%s%+010.3f' % \ (self.env_name, suffix, self.get_actual_fitness(genome))
def __init__(self, params): """Creates a new GenomeConfig object. Args: params (dict): A dictionary of config parameters and values. """ # Create full set of available activation functions self.activation_defs = ActivationFunctionSet() self._params = [ ConfigParameter('num_inputs', int), ConfigParameter('num_outputs', int), ConfigParameter('num_biases', int), ConfigParameter('initial_conn_prob', float), ConfigParameter('activation_func', str), ConfigParameter('compatibility_disjoint_coefficient', float), ConfigParameter('compatibility_weight_coefficient', float), ConfigParameter('normalise_gene_dist', bool), ConfigParameter('feed_forward', bool), ConfigParameter('conn_add_prob', float), ConfigParameter('node_add_prob', float), ConfigParameter('weight_mutate_prob', float), ConfigParameter('weight_replace_prob', float), ConfigParameter('weight_init_power', float), ConfigParameter('weight_perturb_power', float), ConfigParameter('weight_min_value', float), ConfigParameter('weight_max_value', float), ConfigParameter('gene_disable_prob', float) ] # Use the configuration data to interpret the supplied parameters for p in self._params: setattr(self, p.name, p.interpret(params))
def get_config_params(self): return [ConfigParameter(n, float) for n in self.config_item_names()]
def get_config_params(self): return [ ConfigParameter(self.config_item_name(n), self._config_items[n][0], self._config_items[n][1]) for n in iterkeys(self._config_items) ]
class CustomConfig: """A simple custom config container for user-configurable parameters of NEAT. To include additional top-level parameters, specify them in __params. """ # Only modify this ######################################################### __params = [ ConfigParameter('pop_size', int), ConfigParameter('fitness_criterion', str), ConfigParameter('fitness_threshold', float, math.inf), ConfigParameter('reset_on_extinction', bool), ConfigParameter('no_fitness_termination', bool, False), ConfigParameter('num_episodes', int), ConfigParameter('num_runs', int), ConfigParameter('checkpoint_interval', int), ConfigParameter('max_generations', int) ] ############################################################################ def __init__(self, genome_type, reproduction_type, species_set_type, stagnation_type, filename): # Check that the provided types have the required methods. assert hasattr(genome_type, 'parse_config') assert hasattr(reproduction_type, 'parse_config') assert hasattr(species_set_type, 'parse_config') assert hasattr(stagnation_type, 'parse_config') self.genome_type = genome_type self.reproduction_type = reproduction_type self.species_set_type = species_set_type self.stagnation_type = stagnation_type if not os.path.isfile(filename): raise Exception('No such config file: ' + os.path.abspath(filename)) parameters = ConfigParser() with open(filename) as f: if hasattr(parameters, 'read_file'): parameters.read_file(f) else: parameters.readfp(f) # NEAT configuration if not parameters.has_section('NEAT'): raise RuntimeError( "'NEAT' section not found in NEAT configuration file.") param_list_names = [] for p in self.__params: if p.default is None: setattr(self, p.name, p.parse('NEAT', parameters)) else: try: setattr(self, p.name, p.parse('NEAT', parameters)) except Exception: setattr(self, p.name, p.default) warnings.warn( "Using default {!r} for '{!s}'".format( p.default, p.name), DeprecationWarning) param_list_names.append(p.name) param_dict = dict(parameters.items('NEAT')) unknown_list = [ x for x in iterkeys(param_dict) if not x in param_list_names ] if unknown_list: if len(unknown_list) > 1: raise UnknownConfigItemError( "Unknown (section 'NEAT') configuration items:\n" + "\n\t".join(unknown_list)) raise UnknownConfigItemError( "Unknown (section 'NEAT') configuration item {!s}".format( unknown_list[0])) # Parse type sections. genome_dict = dict(parameters.items(genome_type.__name__)) self.genome_config = genome_type.parse_config(genome_dict) species_set_dict = dict(parameters.items(species_set_type.__name__)) self.species_set_config = species_set_type.parse_config( species_set_dict) stagnation_dict = dict(parameters.items(stagnation_type.__name__)) self.stagnation_config = stagnation_type.parse_config(stagnation_dict) reproduction_dict = dict(parameters.items(reproduction_type.__name__)) self.reproduction_config = reproduction_type.parse_config( reproduction_dict) def save(self, filename): with open(filename, 'w') as f: f.write( '# The `NEAT` section specifies parameters particular to the NEAT algorithm\n' ) f.write( '# or the experiment itself. This is the only required section.\n' ) f.write('[NEAT]\n') write_pretty_params(f, self, self.__params) f.write('\n[{0}]\n'.format(self.genome_type.__name__)) self.genome_type.write_config(f, self.genome_config) f.write('\n[{0}]\n'.format(self.species_set_type.__name__)) self.species_set_type.write_config(f, self.species_set_config) f.write('\n[{0}]\n'.format(self.stagnation_type.__name__)) self.stagnation_type.write_config(f, self.stagnation_config) f.write('\n[{0}]\n'.format(self.reproduction_type.__name__)) self.reproduction_type.write_config(f, self.reproduction_config)
def parse_config(cls, param_dict: Dict[str, str]) -> DefaultClassConfig: return DefaultClassConfig( param_dict, [ConfigParameter("compatibility_threshold", float)])
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('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('inc_depth_prob', float), ConfigParameter('inc_breadth_prob', float), ConfigParameter('single_structural_mutation', bool, 'false'), ConfigParameter('structural_mutation_surer', str, 'default'), ConfigParameter('initial_connection', str, 'full_direct') ] # 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 parse_config(cls, param_dict): return DefaultClassConfig(param_dict, [ ConfigParameter('species_fitness_func', str, 'mean'), ConfigParameter('stagnation_split_interval', int, 15) ])