// Copyright 2023 wanderer // SPDX-License-Identifier: GPL-3.0-or-later package ga // mutation strategies iota consts. const ( best1Exp = iota rand1Exp randtoBest1Exp ) // mutations. func clipVals(mutant []float64) []float64 { for i := range mutant { switch { case mutant[i] < 0: mutant[i] = 0 case mutant[i] > 1: mutant[i] = 1 } } return mutant } // mutate performs the mutation of choice and returns the mutant. func mutate(mutStrategy int, currentIndividual PopulationIndividual, genChamp ChampionIndividual, pop *Population, donors ...PopulationIndividual) []float64 { var mutant []float64 dim := pop.Dimen curF := pop.CurF champ := genChamp.X curX := currentIndividual.CurX switch mutStrategy { case best1Exp: mutant = mutBest1Exp(dim, curF, champ, donors...) case rand1Exp: mutant = mutRand1Exp(dim, curF, donors...) case randtoBest1Exp: mutant = mutRandtoBest1Exp(dim, curF, champ, curX, donors...) default: return nil } // return mutant with values clipped to <0;1>. return clipVals(mutant) } func mutBest1Exp(dim int, curF float64, champ []float64, donors ...PopulationIndividual) []float64 { mutant := make([]float64, dim) for i := 0; i < dim; i++ { // mutant[i] = curF + (bestF*(donors[1].CurX[i]) - donors[2].CurX[i]) mutant[i] = champ[i] + (curF*(donors[1].CurX[i]) - donors[2].CurX[i]) } return mutant } func mutRand1Exp(dim int, curF float64, donors ...PopulationIndividual) []float64 { mutant := make([]float64, dim) for i := 0; i < dim; i++ { // tmp[n] = popold[r1][n] + curF*(popold[r2][n]-popold[r3][n]); mutant[i] = donors[0].CurX[i] + curF*(donors[1].CurX[i]-donors[2].CurX[i]) } return mutant } func mutRandtoBest1Exp(dim int, curF float64, champ, currentIndividual []float64, donors ...PopulationIndividual) []float64 { mutant := make([]float64, dim) for i := 0; i < dim; i++ { mutant[i] += currentIndividual[i] + (curF*champ[i] - currentIndividual[i]) + (curF * (donors[0].CurX[i] - donors[1].CurX[i])) } return mutant }