|
1 | | -// The maze solving experiments based on NEAT methodology with Novelty Search and Fitness based optimization |
| 1 | +// Package maze provides the maze solving experiments based on NEAT methodology with Novelty Search and Fitness |
| 2 | +// based optimization. |
2 | 3 | package maze |
3 | 4 |
|
4 | 5 | import ( |
5 | 6 | "fmt" |
6 | | - "github.com/yaricom/goNEAT/neat" |
7 | | - "github.com/yaricom/goNEAT/neat/genetics" |
8 | | - "github.com/yaricom/goNEAT/neat/network" |
9 | | - "github.com/yaricom/goNEAT_NS/neatns" |
| 7 | + "github.com/yaricom/goNEAT/v2/neat" |
| 8 | + "github.com/yaricom/goNEAT/v2/neat/genetics" |
| 9 | + "github.com/yaricom/goNEAT/v2/neat/network" |
| 10 | + "github.com/yaricom/goNEAT_NS/v2/neatns" |
10 | 11 | "math" |
11 | 12 | ) |
12 | 13 |
|
@@ -42,18 +43,29 @@ func histDiff(left, right []float64) float64 { |
42 | 43 | func mazeSimulationEvaluate(env *Environment, org *genetics.Organism, record *AgentRecord, pathPoints []Point) (*neatns.NoveltyItem, bool, error) { |
43 | 44 | nItem := neatns.NewNoveltyItem() |
44 | 45 |
|
| 46 | + // get Organism phenotype's network depth |
| 47 | + netDepth, err := org.Phenotype.MaxActivationDepthFast(1) // The max depth of the network to be activated |
| 48 | + if err != nil { |
| 49 | + neat.WarnLog(fmt.Sprintf( |
| 50 | + "Failed to estimate maximal depth of the network:\n%s\nUsing default depth: %d", |
| 51 | + org.Genotype, netDepth)) |
| 52 | + } |
| 53 | + neat.DebugLog(fmt.Sprintf("Network depth: %d for organism: %d\n", netDepth, org.Genotype.Id)) |
| 54 | + if netDepth == 0 { |
| 55 | + neat.DebugLog(fmt.Sprintf("ALERT: Network depth is ZERO for Genome: %s", org.Genotype)) |
| 56 | + } |
| 57 | + |
45 | 58 | // initialize maze simulation's environment specific to the provided organism - this will be a copy |
46 | 59 | // of primordial environment provided |
47 | | - orgEnv, err := mazeSimulationInit(*env, org) |
| 60 | + orgEnv, err := mazeSimulationInit(*env, org, netDepth) |
48 | 61 | if err != nil { |
49 | 62 | return nil, false, err |
50 | 63 | } |
51 | 64 |
|
52 | | - // do specified amount of time steps emulations or while exit not found |
| 65 | + // do a specified amount of time steps emulations or while exit not found |
53 | 66 | steps := 0 |
54 | 67 | for i := 0; i < orgEnv.TimeSteps && !orgEnv.ExitFound; i++ { |
55 | | - err := mazeSimulationStep(orgEnv, org) |
56 | | - if err != nil { |
| 68 | + if err = mazeSimulationStep(orgEnv, org, netDepth); err != nil { |
57 | 69 | return nil, false, err |
58 | 70 | } |
59 | 71 | // store agent path points at given sample size |
@@ -100,88 +112,58 @@ func mazeSimulationEvaluate(env *Environment, org *genetics.Organism, record *Ag |
100 | 112 |
|
101 | 113 | // To initialize the maze simulation within provided environment copy and for given organism. |
102 | 114 | // Returns new environment for simulation against given organism |
103 | | -func mazeSimulationInit(env Environment, org *genetics.Organism) (*Environment, error) { |
104 | | - |
105 | | - // get Organism phenotype's network depth |
106 | | - netDepth, err := org.Phenotype.MaxDepth() // The max depth of the network to be activated |
107 | | - if err != nil { |
108 | | - if err != network.NetErrDepthCalculationFailedLoopDetected { |
109 | | - return nil, err |
110 | | - } else { |
111 | | - neat.InfoLog(fmt.Sprintf("Network loop detected, using default depth: %d for organism: %d\n", |
112 | | - netDepth, org.Genotype.Id)) |
113 | | - } |
114 | | - } |
115 | | - neat.DebugLog(fmt.Sprintf("Network depth: %d for organism: %d\n", netDepth, org.Genotype.Id)) |
116 | | - if netDepth == 0 { |
117 | | - neat.DebugLog(fmt.Sprintf("ALERT: Network depth is ZERO for Genome: %s", org.Genotype)) |
118 | | - } |
119 | | - |
| 115 | +func mazeSimulationInit(env Environment, org *genetics.Organism, netDepth int) (*Environment, error) { |
120 | 116 | // flush the neural net |
121 | | - if _, err = org.Phenotype.Flush(); err != nil { |
| 117 | + if _, err := org.Phenotype.Flush(); err != nil { |
122 | 118 | neat.ErrorLog("Failed to flush phenotype") |
123 | 119 | return nil, err |
124 | 120 | } |
125 | 121 | // update the maze |
126 | | - err = env.Update() |
127 | | - if err != nil { |
| 122 | + if err := env.Update(); err != nil { |
128 | 123 | neat.ErrorLog("Failed to update environment") |
129 | 124 | return nil, err |
130 | 125 | } |
131 | 126 |
|
132 | 127 | // create neural net inputs from environment |
133 | | - inputs, err := env.GetInputs() |
134 | | - if err != nil { |
| 128 | + if inputs, err := env.GetInputs(); err != nil { |
135 | 129 | return nil, err |
136 | | - } |
137 | | - |
138 | | - // load into neural net |
139 | | - if err = org.Phenotype.LoadSensors(inputs); err != nil { |
| 130 | + } else if err = org.Phenotype.LoadSensors(inputs); err != nil { // load into neural net |
140 | 131 | return nil, err |
141 | 132 | } |
142 | 133 |
|
143 | 134 | // propagate input through the phenotype net |
144 | 135 |
|
145 | | - // Relax phenotype net and get output |
146 | | - if _, err = org.Phenotype.Activate(); err != nil && err != network.NetErrExceededMaxActivationAttempts { |
147 | | - neat.ErrorLog("Failed to activate network init 1") |
| 136 | + // Use depth to ensure full relaxation |
| 137 | + if _, err := org.Phenotype.ForwardSteps(netDepth); err != nil && err != network.ErrNetExceededMaxActivationAttempts { |
| 138 | + neat.ErrorLog(fmt.Sprintf("Failed to activate network at simulation init: %s", err)) |
148 | 139 | return nil, err |
149 | 140 | } |
150 | 141 |
|
151 | | - // use depth to ensure relaxation at each layer |
152 | | - for relax := 0; relax <= netDepth; relax++ { |
153 | | - if _, err = org.Phenotype.Activate(); err != nil && err != network.NetErrExceededMaxActivationAttempts { |
154 | | - neat.ErrorLog("Failed to activate network init 2") |
155 | | - return nil, err |
156 | | - } |
157 | | - } |
158 | | - |
159 | 142 | return &env, nil |
160 | 143 | } |
161 | 144 |
|
162 | 145 | // To execute a time step of the maze simulation evaluation within given Environment for provided Organism |
163 | | -func mazeSimulationStep(env *Environment, org *genetics.Organism) error { |
| 146 | +func mazeSimulationStep(env *Environment, org *genetics.Organism, netDepth int) error { |
164 | 147 | // get simulation parameters as inputs to organism's network |
165 | 148 | if inputs, err := env.GetInputs(); err != nil { |
166 | 149 | return err |
167 | 150 | } else if err = org.Phenotype.LoadSensors(inputs); err != nil { |
168 | 151 | neat.ErrorLog("Failed to load sensors") |
169 | 152 | return err |
170 | 153 | } |
171 | | - _, err := org.Phenotype.Activate() |
172 | | - if err != nil && err != network.NetErrExceededMaxActivationAttempts { |
173 | | - neat.ErrorLog("Failed to activate network simulation") |
| 154 | + if _, err := org.Phenotype.ForwardSteps(netDepth); err != nil && err != network.ErrNetExceededMaxActivationAttempts { |
| 155 | + neat.ErrorLog(fmt.Sprintf("Failed to activate network at simulation init: %s", err)) |
174 | 156 | return err |
175 | 157 | } |
176 | 158 |
|
177 | 159 | // use the net's outputs to change heading and velocity of maze agent |
178 | | - if err = env.ApplyOutputs(org.Phenotype.Outputs[0].Activation, org.Phenotype.Outputs[1].Activation); err != nil { |
| 160 | + if err := env.ApplyOutputs(org.Phenotype.Outputs[0].Activation, org.Phenotype.Outputs[1].Activation); err != nil { |
179 | 161 | neat.ErrorLog("Failed to apply outputs") |
180 | 162 | return err |
181 | 163 | } |
182 | 164 |
|
183 | 165 | // update the environment |
184 | | - if err = env.Update(); err != nil { |
| 166 | + if err := env.Update(); err != nil { |
185 | 167 | neat.ErrorLog("Failed to update environment") |
186 | 168 | return err |
187 | 169 | } |
|
0 commit comments