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 __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 compare_state_outcomes(genome, sensor_input_file): # This function evaluates the difference of the states by running it on a randomly generated set # input values and reporting the distance between the output vectors of the states. # Load the randomly generated sensor inputs with open(sensor_input_file, 'r') as csv_file: csv_reader = csv.reader(csv_file, quoting=csv.QUOTE_NONNUMERIC) sensor_vectors = [row for row in csv_reader] # Evaluate the sensor inputs on each genome. state_differences = dict() activations = ActivationFunctionSet() aggregations = AggregationFunctionSet() for enc_state1 in itervalues(genome.states): state1 = State(1, enc_state1.weights, enc_state1.biases, aggregations.get(enc_state1.aggregation), activations.get(enc_state1.activation)) for enc_state2 in itervalues(genome.states): key_pair = (enc_state1.key, enc_state2.key) if key_pair[0] != key_pair[1] and key_pair not in state_differences \ and key_pair[::-1] not in state_differences: state2 = State(2, enc_state2.weights, enc_state2.biases, aggregations.get(enc_state2.aggregation), activations.get(enc_state2.activation)) output_pairs = [(state1.activate(inputs), state2.activate(inputs)) for inputs in sensor_vectors] distances = [ np.average( np.abs( np.array(output_pair[0]) - np.array(output_pair[1]))) for output_pair in output_pairs ] state_differences[key_pair] = np.average(distances), np.std( distances) return state_differences
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 __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
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
import matplotlib.pyplot as plt import numpy as np from neat.activations import ActivationFunctionSet x = np.linspace(-5.0, 5.0, 5000) afs = ActivationFunctionSet() for n, f in afs.functions.items(): plt.figure(figsize=(4, 4)) plt.plot(x, [f(i) for i in x]) plt.title(n) plt.grid() plt.xlim(-2, 2) plt.ylim(-2, 2) plt.gca().set_aspect(1) plt.savefig('activation-{0}.png'.format(n)) plt.close()
def __init__( self, params: Dict[str, Union[str, Type[DefaultNodeGene], Type[DefaultConnectionGene]]], ) -> None: # parameters self.conn_delete_prob: float = 0 self.node_delete_prob: float = 0 self.compatibility_disjoint_coefficient: float = 0 self.compatibility_weight_coefficient: float = 0 self.conn_add_prob: float = 0 self.feed_forward: bool = True self.node_add_prob: float = 0 self.num_inputs: int = 0 self.num_hidden: int = 0 self.num_outputs: int = 0 self.single_structural_mutation: bool = False self.node_gene_type: DefaultNodeGene self.connection_gene_type: DefaultConnectionGene # Create full set of available activation functions. self.activation_defs: ActivationFunctionSet = ActivationFunctionSet() # ditto for aggregation functions - name difference for backward compatibility self.aggregation_function_defs: AggregationFunctionSet = ( AggregationFunctionSet()) self.aggregation_defs: AggregationFunctionSet = self.aggregation_function_defs self._params: List[ConfigParameter] = [ 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("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: Type[DefaultNodeGene] = params["node_gene_type"] self._params += self.node_gene_type.get_config_params() self.connection_gene_type: Type[DefaultConnectionGene] = params[ "connection_gene_type"] self._params += self.connection_gene_type.get_config_params() # Use the configuration data to interpret the supplied parameters. # `num_inputs`, `num_outputs`などGenomeに関するプロパティを型を解釈してクラスメンバに実数値を設定する 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: List[int] = [-i - 1 for i in range(self.num_inputs)] self.output_keys: List[int] = [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: Optional[count] = None