返回顶部
首页 > 资讯 > 精选 >Go语言中怎么实现一个遗传算法
  • 602
分享到

Go语言中怎么实现一个遗传算法

2023-06-17 03:06:02 602人浏览 八月长安
摘要

这期内容当中小编将会给大家带来有关Go语言中怎么实现一个遗传算法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Go语言坚决拥护组合(composition),同时也很反对继承的做法,在网络上引起了强烈的讨

这期内容当中小编将会给大家带来有关Go语言中怎么实现一个遗传算法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

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

本文将重点介绍如何用Go语言实现遗传算法。如果你还没有参加过golang Tour,我还建议你快速看一下这门语言的介绍。

话不多说,让我们开始从代码说起吧!***个例子与我以前做过的很类似:找到一个二次的最小值。

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{}) }

我立马定义了一组设置,以便在稍后启动的算法中用到。

第二部分的GeneticAlgorithmRunner这个看起来有点奇怪。GeneticAlgorithmRunner是一个接口,询问如何生成初始种群,执行corssovers和mutataions,并对答案进行排序,以便在Population中保持***的个体,这样下一代才会更加优秀。我认为这看起来很奇怪,因为“接口”通常用于面向对象的语言,通常会要求对象实现某些特性和方法。这里没有什么差别。这一小段代码实际上是在说,它正在请求一些东西来定义这些方法的细节。我是这样做的:

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() }  func (l QuadraticGA) Sort(population []interface{}){   sort.Slice(population, func(i, j int) bool {     return calculate(population[i].(float64)) > calculate(population[j].(float64))   }) }

更奇怪的是,我从来没有提到过这些方法的接口。请记住,因为没有对象,也没有继承。QuadraticGA结构体是一个空白对象,隐式地作为GeneticAlgorithmRunner。每个必需的方法都在括号中绑定到该结构体,就像Java中的“@  override”。现在,结构体和设置需要传递给运行该算法的模块。

settings := ga.GeneticAlgorithmSettings{    PopulationSize: 5,    MutationRate: 10,    CrossoverRate: 100,    NumGenerations: 20,    KeepBestAcrossPopulation: true, }  best, err := ga.Run(QuadraticGA{}, settings)  if err != nil {    println(err) }else{    fmt.Printf("Best: x: %f  y: %f\n", best, calculate(best.(float64))) }

很简单,对吧?“QuadraticGA  {}”只是简单地创建了该结构的一个新实例,其余的则由Run()方法完成。该方法返回搜索结果和发生的任何错误,因为Go不相信try /  catch&mdash;&mdash;另一场战争作者采取了严格的设计立场。

现在来计算每个项的性能,以求二次函数求出的二次函数来求出一个新的X值的方法:

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 }

既然已经为二次实现创建了接口,那么GA本身需要完成:

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

不坏!由于人口规模只有5、20代,而且输入的范围被限制在[0 100],这一搜索就钉在了顶点上。

现在,您可能想知道为什么我定义了所有的接口方法来返回“接口{}”。这就像Go和generics一样。没有对象,因此没有对象类型返回,但是没有描述的大小的数据仍然可以在堆栈上传递。这本质上也是这个返回类型的含义:它传递一些已知的和类似的类型的对象。有了这个“泛型”,我就可以将GA移动到它自己的包中,并将相同的代码移到多个不同类型的数据上。

我们有两个输入的3D二次方程,而不是一个二维二次方程的单个输入。接口方法只需要很小的改变:

type Quad3D struct {    x, y float64 } func makeNewQuadEntry(newX, newY float64) Quad3D {    return Quad3D{       x: newX,       y: newY,    } }  func calculate3D(entry Quad3D) float64 {    return math.Pow(entry.x, 2)- 6 * entry.x + math.Pow(entry.y, 2)- 6 * entry.y + 2 }  type Quadratic3dGA struct { }  func (l Quadratic3dGA) GenerateInitialPopulation(populationSize int)[]interface{}{     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))    }) }  func quadratic3dMain(){    settings := ga.GeneticAlgorithmSettings{       PopulationSize: 25,       MutationRate: 10,       CrossoverRate: 100,       NumGenerations: 20,       KeepBestAcrossPopulation: true,    }     best, err := ga.Run(Quadratic3dGA{}, settings)    entry := best.(Quad3D)     if err != nil {       println(err)    }else{       fmt.Printf("Best: x: %f  y: %f  z: %f\n", entry.x, entry.y, calculate3D(entry))    } }

而不是到处都是float64s,任何地方都可以通过Quad3D的条目;每一个都有一个X和一个Y值。对于创建的每个条目,都使用contructor  makeNewQuadEntry创建。Run()方法中的代码都没有更改。

当它运行时,我们得到这个输出:

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

很接近了!

哦,我忘了说走快了!在Java中执行此操作时,即使使用相同的设置,也会有明显的等待时间。在一个相对较小的范围内求解二次方程并不是很复杂,但它对一个人来说是值得注意的。

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

func main() {    beforeQuadTime := time.Now()    quadraticMain()    afterQuadTime := time.Since(beforeQuadTime)    fmt.Printf("%d\n", afterQuadTime)     before3dQuadTime := time.Now()    quadratic3dMain()    after3dQuatTime := time.Since(before3dQuadTime)    fmt.Printf("%d\n", after3dQuatTime) }

边注:我能说我很高兴我们是一个开发者社区,让他们从过去的错误中走出来,并把综合的时间模块和包构建成一种语言吗?Java 8  +拥有它们,python拥有它们,并拥有它们。这使我开心。

现在的输出:

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

那“近乎瞬间”的感觉是我想要传达的,现在我们有了很难的数字。136,876看起来很大,但要在纳秒内报告时间。

重申一遍:纳秒。不是几毫秒,我们都习惯了在互联网时代或者其他像Python和Java这样的通用语言;纳秒。1/1,000,000毫秒。

这意味着我们在不到一毫秒的时间里找到了一个使用遗传算法来搜索答案的二次方程的答案。这句话,“该死的瞬间”似乎很合适,不是吗?这包括打印到终端。

那么,要计算更密集的东西呢?在我展示一种寻找好的梦幻足球lineups的方法之前,我在Fanduel上使用。这包括从电子表格中读取数据,制作和过滤lineups,并进行更复杂的交叉和突变。强制寻找***解决方案可能需要超过75,000年(至少使用我当时使用的Python)。

我不需要再检查所有的细节,你可以自己去看代码,但我会在这里显示输出:

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 D: Philadelphia Eagles - 10.777778 K: Phil Dawson - 7.444444 16,010,182

上述就是小编为大家分享的Go语言中怎么实现一个遗传算法了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网精选频道。

--结束END--

本文标题: Go语言中怎么实现一个遗传算法

本文链接: https://lsjlt.com/news/286956.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Go语言中怎么实现一个遗传算法
    这期内容当中小编将会给大家带来有关Go语言中怎么实现一个遗传算法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Go语言坚决拥护组合(composition),同时也很反对继承的做法,在网络上引起了强烈的讨...
    99+
    2023-06-17
  • C#中怎么实现一个遗传算法
    这篇文章给大家介绍C#中怎么实现一个遗传算法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。C#遗传算法实现代码:using System;  using System.Colle...
    99+
    2023-06-17
  • Python中怎么实现一个遗传算法框架
    本篇文章给大家分享的是有关Python中怎么实现一个遗传算法框架,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。算法特点以决策变量的编码作为运算对象,使得优化过程借鉴生物学中的概...
    99+
    2023-06-17
  • Python中怎么实现一个简单遗传算法
    今天就跟大家聊聊有关Python中怎么实现一个简单遗传算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。遗传算法遗传算法是模仿自然选择过程的优化算法。 他们没有使用"数学技...
    99+
    2023-06-16
  • Python怎么实现遗传算法
    这篇文章给大家分享的是有关Python怎么实现遗传算法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。(一)问题遗传算法求解正方形拼图游戏(二)代码#!/usr/bin/env python# ...
    99+
    2023-06-21
  • matlab遗传算法怎么实现
    要实现遗传算法(Genetic Algorithm)的MATLAB代码,可以按照以下步骤进行: 初始化种群:生成包含若干个个体(...
    99+
    2023-10-22
    matlab
  • 怎么用python代码实现遗传算法
    要使用Python代码实现遗传算法,可以按照以下步骤进行操作:1. 定义问题:首先,需要明确要解决的问题是什么,例如优化问题、寻找最...
    99+
    2023-10-10
    python
  • java遗传算法路径优化怎么实现
    要实现Java遗传算法路径优化,您可以按照以下步骤进行: 定义遗传算法的基本元素:染色体、个体、种群等。染色体表示一条路径,个体...
    99+
    2023-10-22
    java
  • C语言中怎样实现一个排序算法
    本篇文章给大家分享的是有关C语言中怎样实现一个排序算法,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。冒泡排序  冒泡排序(英语:BubbleS...
    99+
    2024-04-02
  • Python实现遗传算法(虚拟机中运行)
    目录(一)问题(二)代码(三)运行结果(四)结果描述(一)问题 遗传算法求解正方形拼图游戏 (二)代码 #!/usr/bin/env python # -*- coding: u...
    99+
    2024-04-02
  • Go语言怎么实现Snowflake雪花算法
    这篇文章主要介绍了Go语言怎么实现Snowflake雪花算法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。雪花算法雪花算法的原始版本是scala版,用于生成分布式ID(纯数字...
    99+
    2023-06-15
  • 使用Go语言实现一个基本的算术运算器
    Go语言是一种开源的、静态类型的编译型语言,以其简洁、高效和易于扩展的特性而受到广泛关注和使用。本文将介绍如何使用Go语言编写一个简单的四则运算计算器,并提供具体的代码示例。首先,我们需要定义几个基本的数据结构来表示运算表达式和操作符。我们...
    99+
    2023-12-23
    Go语言 计算器 四则运算
  • 使用R语言怎么实现一个随机森林算法
    这篇文章给大家介绍使用R语言怎么实现一个随机森林算法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。R语言包“randomForest”用于创建随机森林。安装R包在R语言控制台中使用以下命令安装软件包。 您还必须安装相关...
    99+
    2023-06-15
  • Go语言实现Snowflake雪花算法
    目录介绍 雪花算法 UUID 数据库自增主键Redis Snowflake 实现原理 代码实现 实现步骤 代码实现 每次放长假的在家里的时候,总想找点简单的例子来看看实现原理,这次我...
    99+
    2024-04-02
  • 怎么使用Go语言来实现密码算法
    这篇“怎么使用Go语言来实现密码算法”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用Go语言来实现密码算法”文章吧。首...
    99+
    2023-07-05
  • C++中怎么实现一个 kmp算法
    本篇文章给大家分享的是有关C++中怎么实现一个 kmp算法,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。C++ kmp算法模板参数说明const T *source 待匹配的字...
    99+
    2023-06-17
  • Java中怎么实现一个TFIDF算法
    这篇文章给大家介绍Java中怎么实现一个TFIDF算法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。算法介绍最近要做领域概念的提取,TFIDF作为一个很经典的算法可以作为其中的一步处理。计算公式比较简单,如下:预处理由...
    99+
    2023-06-02
  • 针对VNPY策略遗传算法优化怎样写了一个类GeneticOptimizeStrategy
    这篇文章将为大家详细讲解有关针对VNPY策略遗传算法优化怎样写了一个类GeneticOptimizeStrategy,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。写了一个类,GeneticO...
    99+
    2023-06-02
  • 如何在Go语言中实现常用的算法?
    Go语言是一种快速、简单、可靠的编程语言,它已经成为了云计算、网络编程、大数据等领域的热门语言。在软件开发过程中,算法是一个不可或缺的部分。本文将介绍如何在Go语言中实现常用的算法。 一、排序算法 1.冒泡排序 冒泡排序是一种简单的排序算法...
    99+
    2023-06-17
    教程 编程算法 numy
  • GO语言中如何实现数组操作算法?
    GO语言是一种快速、高效、并发编程语言,它可以运行于跨平台的环境中。GO语言中的数组操作算法是编程中常用的操作之一,下面将详细介绍GO语言中如何实现数组操作算法。 一、数组的定义和初始化 定义数组和初始化数组是数组操作算法的起点,GO语言中...
    99+
    2023-10-03
    对象 数组 编程算法
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作