Ejemplo n.º 1
0
 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)
                                ])
Ejemplo n.º 3
0
 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)
     ]
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
 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
Ejemplo n.º 6
0
    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))
Ejemplo n.º 7
0
 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),
         ],
     )
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
    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++")
        ])
Ejemplo n.º 12
0
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))
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
    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)])
Ejemplo n.º 15
0
    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)
        ])
Ejemplo n.º 16
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))
Ejemplo n.º 17
0
    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)
Ejemplo n.º 18
0
 def parse_config(cls, param_dict):
     return DefaultClassConfig(
         param_dict, [ConfigParameter('compatibility_threshold', float)])
Ejemplo n.º 19
0
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
Ejemplo n.º 20
0
 def get_config_params(self):
     default_name, rate_name = self.config_item_names()
     return [
         ConfigParameter(default_name, bool),
         ConfigParameter(rate_name, float)
     ]
Ejemplo n.º 21
0
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)
Ejemplo n.º 22
0
 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)
     ])
Ejemplo n.º 23
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))
Ejemplo n.º 24
0
    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))
Ejemplo n.º 25
0
 def get_config_params(self):
     return [ConfigParameter(n, float) for n in self.config_item_names()]
Ejemplo n.º 26
0
 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)
     ]
Ejemplo n.º 27
0
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)
Ejemplo n.º 28
0
 def parse_config(cls, param_dict: Dict[str, str]) -> DefaultClassConfig:
     return DefaultClassConfig(
         param_dict, [ConfigParameter("compatibility_threshold", float)])
Ejemplo n.º 29
0
    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
Ejemplo n.º 30
0
 def parse_config(cls, param_dict):
     return DefaultClassConfig(param_dict, [
         ConfigParameter('species_fitness_func', str, 'mean'),
         ConfigParameter('stagnation_split_interval', int, 15)
     ])