// Evolve implements the inner loop of the evolutionary algorithm. // The population calls the Evolve method of each genome, in parallel. Then, // each receiver returns a value to replace it in the next generation. A global // selector object synchronises replacement among the parallel parents. func (ack *ackley) Evolve(suitors ...evo.Genome) evo.Genome { for i := 0; i < 7; i++ { // Creation: // We create the child genome from recycled memory when we can. var child ackley child.gene = vectors.Get().(real.Vector) child.steps = vectors.Get().(real.Vector) // Crossover: // Select two parents at random. // Uniform crossover of object parameters. // Arithmetic crossover of strategy parameters. mom := suitors[rand.Intn(len(suitors))].(*ackley) dad := suitors[rand.Intn(len(suitors))].(*ackley) real.UniformX(child.gene, mom.gene, dad.gene) real.ArithX(1, child.steps, mom.steps, dad.steps) // Mutation: Evolution Strategy // Lognormal scaling of strategy parameters. // Gausian perturbation of object parameters. child.steps.Adapt() child.steps.LowBound(precision) child.gene.Step(child.steps) child.gene.HighBound(bounds) child.gene.LowBound(-bounds) // Replacement: (40,280) // Each child is added to the global selection pool. selector.Put(&child) } // Finally, block until all parallel calls have added their children to the // selection pool and return one of the selected replacements. return selector.Get() }
func TestArithX(t *testing.T) { mom := []float64{0, 0} dad := []float64{1, -1} child := []float64{0, 0} real.ArithX(1, child, mom, dad) a := 0 < child[0] && child[0] < 1 b := -1 < child[1] && child[1] < 0 c := child[0] == -child[1] if !a || !b || !c { t.Fail() } }