# Go语言如何实现遗传算法

Go语言与我习惯的其他语言不同。Go更喜欢自己单独实现，而其他像Java这类语言更喜欢继承。其实在Go语言里面根本没有继承这种概念，因为它压根就没有对象这一说法。比如说C语言，它有结构体，但是没有类。但是这样它还是可以有像“构造者”这样的常见思想和设计模式（一种在这种情况下有序地产生结构体的方式）。

Go语言坚决拥护组合（composition），同时也很反对继承的做法，在网络上引起了强烈的讨论，同时也让人们重新思考了语言该往哪个方向发展。所以，从这个角度来看，Go语言与其它语言的差别可能也没有那么大。

type GeneticAlgorithmSettings struct {
PopulationSize int
MutationRate int
CrossoverRate int
NumGenerations int
KeepBestAcrossPopulation bool
}

type GeneticAlgorithmRunner interface {
GenerateInitialPopulation(populationSize int) []interface{}
PerformCrossover(individual1, individual2 interface{}, mutationRate int) interface{}
PerformMutation(individual interface{}) interface{}
Sort([]interface{})
}


type QuadraticGA struct {}

func (l QuadraticGA) GenerateInitialPopulation(populationSize int) []interface{}{
initialPopulation := make([]interface{}, 0, populationSize)
for i:= 0; i < populationSize; i++ {
initialPopulation = append(initialPopulation, makeNewEntry())
}
return initialPopulation
}

func (l QuadraticGA) PerformCrossover(result1, result2 interface{}, _ int) interface{}{
return (result1.(float64) + result2.(float64)) / 2
}

func (l QuadraticGA) PerformMutation(_ interface{}, _ int) interface{}{
return makeNewEntry()
}

sort.Slice(population, func(i, j int) bool {
return calculate(population[i].(float64)) > calculate(population[j].(float64))
})
}


settings := ga.GeneticAlgorithmSettings{
PopulationSize: 5,
MutationRate: 10,
CrossoverRate: 100,
NumGenerations: 20,
KeepBestAcrossPopulation: true,
}

if err != nil {
println(err)
}else{
fmt.Printf("Best: x: %f  y: %f\n", best, calculate(best.(float64)))
}


func makeNewEntry() float64 {
return highRange * rand.Float64()
}

func calculate(x float64) float64 {
return  math.Pow(x, 2) - 6*x + 2 // minimum should be at x=3
}


func Run(geneticAlgoRunner GeneticAlgorithmRunner, settings GeneticAlgorithmSettings) (interface{}, error){

population := geneticAlgoRunner.GenerateInitialPopulation(settings.PopulationSize)

geneticAlgoRunner.Sort(population)

bestSoFar := population[len(population) - 1]

for i:= 0; i < settings.NumGenerations; i++ {

newPopulation := make([]interface{}, 0, settings.PopulationSize)

if settings.KeepBestAcrossPopulation {
newPopulation = append(newPopulation, bestSoFar)
}

// perform crossovers with random selection
probabilisticListOfPerformers := createStochasticProbableListOfIndividuals(population)

newPopIndex := 0
if settings.KeepBestAcrossPopulation{
newPopIndex = 1
}
for ; newPopIndex < settings.PopulationSize; newPopIndex++ {
indexSelection1 := rand.Int() % len(probabilisticListOfPerformers)
indexSelection2 := rand.Int() % len(probabilisticListOfPerformers)

// crossover
newIndividual := geneticAlgoRunner.PerformCrossover(
probabilisticListOfPerformers[indexSelection1],
probabilisticListOfPerformers[indexSelection2], settings.CrossoverRate)

// mutate
if rand.Intn(101) < settings.MutationRate {
newIndividual = geneticAlgoRunner.PerformMutation(newIndividual)
}

newPopulation = append(newPopulation, newIndividual)
}

population = newPopulation

// sort by performance
geneticAlgoRunner.Sort(population)

// keep the best so far
bestSoFar = population[len(population) - 1]

}

return bestSoFar, nil
}

func createStochasticProbableListOfIndividuals(population []interface{}) []interface{} {

totalCount, populationLength:= 0, len(population)
for j:= 0; j < populationLength; j++ {
totalCount += j
}

probableIndividuals := make([]interface{}, 0, totalCount)
for index, individual := range population {
for i:= 0; i < index; i++{
probableIndividuals = append(probableIndividuals, individual)
}
}

return probableIndividuals
}


Best: x: 3.072833 y: -6.994695


type Quad3D struct {
x, y float64
}
x: newX,
y: newY,
}
}

return math.Pow(entry.x, 2)- 6 * entry.x + math.Pow(entry.y, 2)- 6 * entry.y + 2
}

}

initialPopulation := make([]interface{}, 0, populationSize)
for i:= 0; i < populationSize; i++ { initialPopulation = append(initialPopulation, makeNewQuadEntry(makeNewEntry(), makeNewEntry())) } return initialPopulation } func (l Quadratic3dGA) PerformCrossover(result1, result2 interface{}, mutationRate int) interface{}{ r1Entry, r2Entry := result1.(Quad3D), result2.(Quad3D) return makeNewQuadEntry((r1Entry.x + r2Entry.x) / 2, (r1Entry.y + r2Entry.y) / 2,) } func (l Quadratic3dGA) PerformMutation(_ interface{}) interface{}{ return makeNewQuadEntry(makeNewEntry(), makeNewEntry()) } func (l Quadratic3dGA) Sort(population []interface{}){ sort.Slice(population, func(i, j int) bool { return calculate3D(population[i].(Quad3D)) > calculate3D(population[j].(Quad3D))
})
}

settings := ga.GeneticAlgorithmSettings{
PopulationSize: 25,
MutationRate: 10,
CrossoverRate: 100,
NumGenerations: 20,
KeepBestAcrossPopulation: true,
}

if err != nil {
println(err)
}else{
fmt.Printf("Best: x: %f  y: %f  z: %f\n", entry.x, entry.y, calculate3D(entry))
}
}


Best: x: 3.891671 y: 4.554884 z: -12.787259


Go是本地编译的，比如C。当二进制执行时，它似乎马上就吐出一个答案。这里有一个简单的方法来度量每次运行的执行时间:

func main() {

fmt.Printf("%d\n", after3dQuatTime)
}


Best: x: 3.072833 y: -6.994695
136,876
Best: x: 3.891671 y: 4.554884 z: -12.787259
4,142,778


Best: 121.409960:, \$58100
QB: Aaron Rodgers - 23.777778
RB: Latavius Murray - 15.228571
RB: DeMarco Murray - 19.980000
WR: Kelvin Benjamin - 11.800000
WR: Stefon Diggs - 14.312500
WR: Alshon Jeffery - 9.888889
TE: Connor Hamlett - 8.200000
K: Phil Dawson - 7.444444
16,010,182


Go也被用coroutines和信道的原生支持编写，利用多个内核来解决一个问题，比过去简单多了，相比于单核时代的其他语言来说，这是一个巨大的优势。我想要增强这个算法来使用这些工具，但这也必须留给以后的工作。

• 本文已收录于以下专栏：

举报原因： 您举报文章：Go语言如何实现遗传算法 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)