亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Golang > 正文

Go語言實現遺傳算法的實例代碼

2020-04-01 19:01:45
字體:
來源:轉載
供稿:網友

在沒介紹正文之前先給大家補充點go語言基本知識及實例。

Go 語言教程

Go 是一個開源的編程語言,它能讓構造簡單、可靠且高效的軟件變得容易。

Go是從2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持開發,后來還加入了Ian Lance Taylor, Russ Cox等人,并最終于2009年11月開源,在2012年早些時候發布了Go 1穩定版本?,F在Go的開發已經是完全開放的,并且擁有一個活躍的社區。

Go 語言特色

簡潔、快速、安全
并行、有趣、開源
內存管理、v數組安全、編譯迅速

Go 語言用途

Go 語言被設計成一門應用于搭載 Web 服務器,存儲集群或類似用途的巨型中央服務器的系統編程語言。

對于高性能分布式系統領域而言,Go 語言無疑比大多數其它語言有著更高的開發效率。它提供了海量并行的支持,這對于游戲服務端的開發而言是再好不過了。

第一個 Go 程序

接下來我們來編寫第一個 Go 程序 hello.go(Go 語言源文件的擴展是 .go),代碼如下:

實例

package mainimport "fmt"func main() {  fmt.Println("Hello, World!")}

執行以上代碼輸出

$ go run hello.go Hello, World!

好了,正文開始。

出于好玩的心態,我決定學習一下Go語言。我認為學習新語言最好的方法就是深入學習,并且盡可能多犯錯誤。這樣做雖然可能會很慢,但是可以確保在后面的過程中再也不會出現編譯的錯誤。

Go語言與我習慣的其他語言不同。Go更喜歡自己單獨實現,而其他像Java這類語言更喜歡繼承。其實在Go語言里面根本沒有繼承這種概念,因為它壓根就沒有對象這一說法。比如說C語言,它有結構體,但是沒有類。但是這樣它還是可以有像“構造者”這樣的常見思想和設計模式(一種在這種情況下有序地產生結構體的方式)。

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”?,F在,結構體和設置需要傳遞給運行該算法的模塊。

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——另一場戰爭作者采取了嚴格的設計立場。

現在來計算每個項的性能,以求二次函數求出的二次函數來求出一個新的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.994695136,876Best: x: 3.891671 y: 4.554884 z: -12.7872594,142,778

那“近乎瞬間”的感覺是我想要傳達的,現在我們有了很難的數字。136,876看起來很大,但要在納秒內報告時間。

重申一遍:納秒。不是幾毫秒,我們都習慣了在互聯網時代或者其他像Python和Java這樣的通用語言;納秒。1/1,000,000毫秒。

這意味著我們在不到一毫秒的時間里找到了一個使用遺傳算法來搜索答案的二次方程的答案。這句話,“該死的瞬間”似乎很合適,不是嗎?這包括打印到終端。

那么,要計算更密集的東西呢?在我展示一種尋找好的夢幻足球lineups的方法之前,我在Fanduel上使用。這包括從電子表格中讀取數據,制作和過濾lineups,并進行更復雜的交叉和突變。強制尋找最佳解決方案可能需要超過75,000年(至少使用我當時使用的Python)。

我不需要再檢查所有的細節,你可以自己去看代碼,但我會在這里顯示輸出:

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

哦,是的!現在看來這是一個很好的陣容!它只需要16毫秒就能找到。

現在,這個遺傳算法可以改進了。與C一樣,當將對象傳遞給方法時,將在堆棧上復制對象(讀取數據)。隨著對象大小的增長,最好不要反復復制它們,而是要在堆中創建它們,并在周圍傳遞指針。目前,我將把它作為未來的工作。

Go也被用coroutines和信道的原生支持編寫,利用多個內核來解決一個問題,比過去簡單多了,相比于單核時代的其他語言來說,這是一個巨大的優勢。我想要增強這個算法來使用這些工具,但這也必須留給以后的工作。

我很享受學習的過程。對于我來說,用組合而不是繼承來考慮工程解決方案是很困難的,因為我已經習慣了8年以上的時間,也是我學會編程的方式。但是每種語言和方式都有各自的優點和缺點;每一種語言在我的工具中都是不同的工具。對于任何擔心嘗試的人,不要。有一個駝峰(更像是一個減速帶),但你很快就會克服它,走上成功之路。

還有一些我喜歡的東西,我喜歡其他語言,主要是一組基本的函數方法來操作數據。我需要一個lambda函數和方法來映射、減少和篩選數據的數組或部分。設計人員反對功能實現的理由是,代碼應該總是簡單、易于閱讀和編寫,并且這與for循環是可實現的。我認為,映射、過濾和減少通常更容易讀和寫,但這是一場已經在肆虐的戰爭中的爭論。

盡管我與一些開發人員的觀點存在分歧,以及我必須考慮解決問題的不同方式,但Go真的是一種很好的語言。我鼓勵大家在學習一兩門語言后再試一試。它很快就成為了最流行的語言之一,有很多原因可以解釋為什么。我期待著在未來更多地使用它。

總結

以上所述是小編給大家介紹的Go語言實現遺傳算法的實例代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲**2019国产| 亚洲毛茸茸少妇高潮呻吟| 欧美中文字幕视频| 性视频1819p久久| 日韩av网址在线观看| 欧美大全免费观看电视剧大泉洋| 中文字幕国产精品久久| 国产91对白在线播放| 日韩av在线资源| 亚洲欧美激情在线视频| xxx欧美精品| 日韩av一区在线| 成人免费网站在线观看| 在线色欧美三级视频| 国产精品十八以下禁看| 一区二区三区 在线观看视| 国产精品视频26uuu| 日韩精品999| 亚洲老板91色精品久久| 欧美日韩综合视频网址| 亚洲性无码av在线| 精品成人久久av| 日韩免费在线免费观看| 在线日韩精品视频| 国产精品久久久久久久久久久久久| 26uuu另类亚洲欧美日本一| 久久男人av资源网站| 中文字幕日韩精品有码视频| 日韩少妇与小伙激情| 欧美—级高清免费播放| 一本色道久久88综合日韩精品| 国产在线视频91| 一区二区三区亚洲| 国产欧美日韩中文字幕| www.欧美精品一二三区| 国产成人精品网站| 亚洲国产三级网| 91在线观看免费| 日韩高清免费观看| 成人国产精品久久久久久亚洲| 91精品国产综合久久香蕉的用户体验| 精品国产999| 亚洲成av人影院在线观看| 欧美在线视频在线播放完整版免费观看| 色偷偷88888欧美精品久久久| 国产在线a不卡| 91精品国产高清自在线看超| 欧美激情xxxx性bbbb| 成人精品一区二区三区| 亚洲精品视频在线观看视频| 国产综合久久久久| 黑人巨大精品欧美一区二区免费| 亚洲国产成人一区| 精品国产91乱高清在线观看| 国产成人精品综合| 欧美成人午夜剧场免费观看| 久久中文久久字幕| 97久久超碰福利国产精品…| 欧美巨乳美女视频| 欧美一级淫片aaaaaaa视频| 91探花福利精品国产自产在线| 欧美夜福利tv在线| 亚洲国产精品va| 亚洲女人天堂色在线7777| 成人黄色片网站| 国产一区二区三区毛片| 日韩一区二区在线视频| 成人精品网站在线观看| 国产精品专区一| 久久精品小视频| 国产成人免费91av在线| 91在线观看免费网站| 国产精品精品国产| 亚洲成人xxx| 大胆欧美人体视频| 岛国av在线不卡| 亚洲国产日韩欧美在线99| 欧美成年人视频网站| 亚洲aⅴ男人的天堂在线观看| 色综合色综合网色综合| 久久精品视频一| 深夜福利日韩在线看| 国产一区二区三区在线看| 尤物yw午夜国产精品视频明星| 亚洲国产91精品在线观看| 日韩一级黄色av| 久久人人爽人人爽人人片av高清| 久久人人爽国产| 亚洲精品美女在线观看| 另类少妇人与禽zozz0性伦| 亚洲视频在线免费观看| 日韩在线中文视频| 欧美丰满老妇厨房牲生活| 国产三级精品网站| 欧美在线影院在线视频| 精品国产美女在线| 精品国产乱码久久久久久婷婷| 欧美激情a在线| 国产精品香蕉在线观看| 亚洲无亚洲人成网站77777| 97色在线播放视频| 国产精品嫩草影院久久久| 日韩av电影在线免费播放| 欧美精品福利在线| 日韩欧美黄色动漫| 欧美最猛性xxxxx(亚洲精品)| 久久在线免费视频| 色综合男人天堂| 成年人精品视频| 亚洲精品日韩丝袜精品| 国产精品综合网站| 91精品啪在线观看麻豆免费| 欧美专区第一页| 日韩在线视频中文字幕| 热久久美女精品天天吊色| 国产精品人成电影在线观看| 亚洲国产福利在线| 国产精品揄拍一区二区| 91精品综合久久久久久五月天| 欧美成人亚洲成人| 亚洲精品综合久久中文字幕| 在线成人免费网站| 国产精品久久久999| 中文字幕一精品亚洲无线一区| 亚洲欧美一区二区三区四区| 国产一区二区日韩精品欧美精品| 久久精品夜夜夜夜夜久久| 最近2019年好看中文字幕视频| 91高清视频在线免费观看| 55夜色66夜色国产精品视频| 精品免费在线观看| 成人网在线免费看| 日韩不卡在线观看| 欧美电影在线观看高清| 欧美激情亚洲自拍| 激情成人在线视频| 免费不卡欧美自拍视频| 日韩av影视在线| 欧洲日本亚洲国产区| 欧美香蕉大胸在线视频观看| 热re91久久精品国99热蜜臀| 精品欧美国产一区二区三区| 一区二区欧美亚洲| 久久精品国产清自在天天线| 欧美第一淫aaasss性| 一本一本久久a久久精品综合小说| 亚洲女人天堂网| 国产一区私人高清影院| 欧美激情第一页xxx| 亚洲国产精品小视频| 欧美自拍视频在线| 亚洲精品自在久久| 中文字幕亚洲专区| 精品国产一区二区三区久久狼黑人| 日韩精品在线免费观看| 91精品久久久久久久久久| 精品福利视频导航| 成人午夜激情免费视频| 97久久超碰福利国产精品…| 亚洲片在线观看| 成人午夜黄色影院| 亚洲大胆人体在线| 国产激情999| 亚洲精品免费一区二区三区|