1
- from random import random , gauss , choice
2
1
import os
2
+ from random import random , gauss , choice
3
3
4
- from neat .genome import DefaultGenome , FFGenome
5
- from neat import activation_functions
4
+ from neat .activations import ActivationFunctionSet
5
+ from neat . genome import DefaultGenome
6
6
from neat .reproduction import DefaultReproduction
7
7
from neat .stagnation import DefaultStagnation
8
8
13
13
14
14
aggregation_function_defs = {'sum' : sum , 'max' : max , 'min' : min }
15
15
16
+
16
17
class Config (object ):
17
18
'''
18
19
A simple container for all of the user-configurable parameters of NEAT.
@@ -29,14 +30,81 @@ class Config(object):
29
30
30
31
allowed_connectivity = ['unconnected' , 'fs_neat' , 'fully_connected' , 'partial' ]
31
32
32
- def __init__ (self , filename = None ):
33
+ def __init__ (self ):
34
+ # Initialize type registry with default implementations.
33
35
self .registry = {'DefaultStagnation' : DefaultStagnation ,
34
36
'DefaultReproduction' : DefaultReproduction ,
35
- 'DefaultGenome' : DefaultGenome ,
36
- 'FFGenome' : FFGenome }
37
+ 'DefaultGenome' : DefaultGenome }
37
38
self .type_config = {}
38
- if filename is not None :
39
- self .load (filename )
39
+
40
+ # Phenotype configuration
41
+ self .input_nodes = 0
42
+ self .output_nodes = 0
43
+ self .hidden_nodes = 0
44
+ self .initial_connection = 'unconnected'
45
+ self .connection_fraction = None
46
+ self .max_weight = 30.0
47
+ self .min_weight = - 30.0
48
+ self .weight_stdev = 1.0
49
+ self .activation_functions = ['sigmoid' ]
50
+ self .aggregation_functions = ['sum' ]
51
+
52
+ # Genetic algorithm configuration
53
+ self .pop_size = 150
54
+ self .max_fitness_threshold = - 0.05
55
+ self .prob_add_conn = 0.5
56
+ self .prob_add_node = 0.1
57
+ self .prob_delete_conn = 0.1
58
+ self .prob_delete_node = 0.05
59
+ self .prob_mutate_bias = 0.05
60
+ self .bias_mutation_power = 2.0
61
+ self .prob_mutate_response = 0.5
62
+ self .response_mutation_power = 0.1
63
+ self .prob_mutate_weight = 0.5
64
+ self .prob_replace_weight = 0.02
65
+ self .weight_mutation_power = 0.8
66
+ self .prob_mutate_activation = 0.0
67
+ self .prob_mutate_aggregation = 0.0
68
+ self .prob_toggle_link = 0.01
69
+ self .reset_on_extinction = True
70
+
71
+ # genotype compatibility
72
+ self .compatibility_threshold = 3.0
73
+ self .excess_coefficient = 1.0
74
+ self .disjoint_coefficient = 1.0
75
+ self .weight_coefficient = 0.4
76
+
77
+ stagnation_type_name = 'DefaultStagnation'
78
+ self .stagnation_type = self .registry [stagnation_type_name ]
79
+ # TODO: Look up the default type configuration from a static method on the type?
80
+ self .type_config [stagnation_type_name ] = {'species_fitness_func' : 'mean' ,
81
+ 'max_stagnation' : 15 }
82
+
83
+ reproduction_type_name = 'DefaultReproduction'
84
+ self .reproduction_type = self .registry [reproduction_type_name ]
85
+ # TODO: Look up the default type configuration from a static method on the type?
86
+ self .type_config [reproduction_type_name ] = {'elitism' : 1 ,
87
+ 'survival_threshold' : 0.2 }
88
+
89
+ genome_type_name = 'DefaultGenome'
90
+ self .genome_type = self .registry [genome_type_name ]
91
+ # TODO: Look up the default type configuration from a static method on the type?
92
+ self .type_config [genome_type_name ] = {}
93
+
94
+ # Gather statistics for each generation.
95
+ self .collect_statistics = True
96
+ # Show stats after each generation.
97
+ self .report = True
98
+ # Save the best genome from each generation.
99
+ self .save_best = False
100
+ # Time in minutes between saving checkpoints, None for no timed checkpoints.
101
+ self .checkpoint_time_interval = None
102
+ # Time in generations between saving checkpoints, None for no generational checkpoints.
103
+ self .checkpoint_gen_interval = None
104
+
105
+ # Create full set of available activation functions.
106
+ # TODO: pick a better name for this member, it's too confusing alongside activation_functions.
107
+ self .available_activations = ActivationFunctionSet ()
40
108
41
109
def load (self , filename ):
42
110
if not os .path .isfile (filename ):
@@ -76,7 +144,7 @@ def load(self, filename):
76
144
77
145
# Verify that specified activation functions are valid.
78
146
for fn in self .activation_functions :
79
- if not activation_functions .is_valid (fn ):
147
+ if not self . available_activations .is_valid (fn ):
80
148
raise Exception ("Invalid activation function name: {0!r}" .format (fn ))
81
149
82
150
# Genetic algorithm configuration
@@ -123,28 +191,26 @@ def load(self, filename):
123
191
self .genome_type = self .registry [genome_type_name ]
124
192
self .type_config [genome_type_name ] = parameters .items (genome_type_name )
125
193
126
- # Gather statistics for each generation.
127
- self .collect_statistics = True
128
- # Show stats after each generation.
129
- self .report = True
130
- # Save the best genome from each generation.
131
- self .save_best = False
132
- # Time in minutes between saving checkpoints, None for no timed checkpoints.
133
- self .checkpoint_time_interval = None
134
- # Time in generations between saving checkpoints, None for no generational checkpoints.
135
- self .checkpoint_gen_interval = None
194
+ def set_input_output_sizes (self , num_inputs , num_outputs ):
195
+ self .input_nodes = num_inputs
196
+ self .output_nodes = num_outputs
197
+ self .input_keys = [- i - 1 for i in range (self .input_nodes )]
198
+ self .output_keys = [i for i in range (self .output_nodes )]
199
+
200
+ def save (self , filename ):
201
+ pass
136
202
137
- def register (self , typeName , typeDef ):
203
+ def register (self , type_name , type_def ):
138
204
"""
139
205
User-defined classes mentioned in the config file must be provided to the
140
206
configuration object before the load() method is called.
141
207
"""
142
- self .registry [typeName ] = typeDef
208
+ self .registry [type_name ] = type_def
143
209
144
- def get_type_config (self , typeInstance ):
145
- return dict (self .type_config [typeInstance .__class__ .__name__ ])
210
+ def get_type_config (self , type_instance ):
211
+ return dict (self .type_config [type_instance .__class__ .__name__ ])
146
212
147
- # TODO: Factor out these mutation methods into a separate class.
213
+ # TODO: Factor out these mutation methods into a separate class?
148
214
def new_weight (self ):
149
215
return gauss (0 , self .weight_stdev )
150
216
0 commit comments