"""Customised configuration module with additional user-configurable parameters.
Modifies the config object in the default NEAT-Python config module to include
the following additional parameters:
- `num_episodes`: the number of episodes each genome/agent should be
evaluated for.
- `num_runs`: the number of evolutionary runs to perform.
- `checkpoint_interval`: the number of generations between checkpoint saves.
- `max_generations`: the maximum number of generations for each evolutionary
run.
"""
from __future__ import print_function
import os
import warnings
import math
try:
from configparser import ConfigParser
except ImportError:
from configparser import SafeConfigParser as ConfigParser
from neat.config import ConfigParameter, UnknownConfigItemError, write_pretty_params
from neat.six_util import iterkeys
[docs]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)
[docs] 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)