Example #1
0
// 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.
func Evolve(current evo.Genome, matingPool []evo.Genome) evo.Genome {
	// Selection:
	// Select each parent using a simple random binary tournament
	mom := sel.BinaryTournament(matingPool...).(*tsp)
	dad := sel.BinaryTournament(matingPool...).(*tsp)

	// Crossover:
	// Edge recombination
	child := &tsp{gene: pool.Get().([]int)}
	perm.EdgeX(child.gene, mom.gene, dad.gene)

	// Mutation:
	// There is an n% chance for the gene to have n random swaps
	// and an n% chance to undergo n steps of a greedy 2-opt hillclimber
	for rand.Float64() < 0.1 {
		perm.RandSwap(child.gene)
	}
	for rand.Float64() < 0.1 {
		child.TwoOpt()
	}

	// Replacement:
	// Only replace if the child is better or equal
	if current.Fitness() > child.Fitness() {
		return current
	}
	return child
}
Example #2
0
// Evolution implements the body of the evolution loop.
func Evolution(q evo.Genome, suitors []evo.Genome) evo.Genome {
	// Crossover:
	// We're implementing a diffusion model. For each member of the population,
	// we receive a small mating pool containing only our neighbors. We choose
	// a mate using a random binary tournament and create a child with
	// partially mapped crossover.
	mom := q.(*queens)
	dad := sel.BinaryTournament(suitors...).(*queens)
	child := &queens{gene: make([]int, len(mom.gene))}
	perm.PMX(child.gene, mom.gene, dad.gene)

	// Mutation:
	// Perform n random swaps where n is taken from an exponential distribution.
	// mutationCount := math.Ceil(rand.ExpFloat64() - 0.5)
	for i := float64(0); i < 5; i++ {
		j := rand.Intn(len(child.gene))
		k := rand.Intn(len(child.gene))
		child.gene[j], child.gene[k] = child.gene[k], child.gene[j]
	}

	// Replacement:
	// Only replace if the child is better or equal.
	if q.Fitness() > child.Fitness() {
		return q
	}
	return child
}