摘要
遺傳算法(Genetic Algorithm, GA)是模擬達爾文生物進化論的自然選擇和遺傳學機理的生物進化過程的計算模型,是一種通過模擬自然進化過程搜索最優解的方法。
本文在遺傳算法的模式理論的基礎上,用Matlab程序實現了遺傳算法,實現了5個二維單目標函數優化和解決了20個城市的旅行商問題。並對各種參數對結果的影響進行了數學分析,通過實驗研究了應用中的遺傳算法性能影響因素。
二維單目標函數優化過程中,基本可以每次都達到全局最優解,並可以在1000代以內收斂,實驗結果顯示其收斂速度快,結果直觀,性能好。
在TSP問題中,通過修改代碼中選擇函數、交叉函數的選型,解決了陷入局部最優問題,使得最終達到全局最優,且路徑圖不交叉。
本文整體方案仍然處於實驗的階段,離解決實際問題還有很大的差距。遺傳算法的應用在日后必定會越來越成熟,同時這一領域也具有很大的發展空間。
關鍵詞:遺傳算法 二維單目標函數優化 Matlab TSP
目錄
-
緒論
1.1 課程背景
自然計算(Nature Inspired Computation),具有模仿自然界特點,通常是一類具有自適應、自組織、自學習能力的模型與算法,能夠解決傳統計算方法難於解決的各種復雜問題。
從自然計算角度看,每種自然計算方法都對應一種實際的啟發源,要將啟發源中所包含的內在的特殊規律,如生物進化規律、離子進出細胞膜的規律等,利用數學或邏輯符號建模描述成一種特殊計算過程。以自然界包括生命、生物及生態系統,物理與化學,經濟以及社會文化系統等,特別是生物體的功能、特點和作用機理為基礎,研究其中所蘊含的豐富的信息處理機制,抽取相應的計算模型,設計相應的算法,研制革新計算系統,並在各相關領域加以應用[1]。
自然計算,是智能計算的一部分,自然計算的應用涉及領域很廣,在復雜優化問題求解、優化調度控制與故障診斷、智能控制與機器人控制、智能交通、智能建築、計算機集成制造、智能電網、數據挖掘、模式識別、網絡通信與信息安全、工業設計優化、社會經濟、金融與管理、生態環境、生物醫學醫葯、新能源與新材料、航空航天與軍事等領域均有應用。
自然計算的內容一般包括:人工神經網絡,遺傳算法,免疫算法,人工內分沁系統,蟻群算法,粒子群算法以及膜計算等等。
其中,遺傳算法(Genetic Algorithm, GA)是模擬達爾文生物進化論的自然選擇和遺傳學機理的生物進化過程的計算模型,是一種通過模擬自然進化過程搜索最優解的方法。
其主要特點是直接對結構對象進行操作,不存在求導和函數連續性的限定;具有內在的隱並行性和更好的全局尋優能力;采用概率化的尋優方法,不需要確定的規則就能自動獲取和指導優化的搜索空間,自適應地調整搜索方向。
遺傳算法以一種群體中的所有個體為對象,並利用隨機化技術指導對一個被編碼的參數空間進行高效搜索。其中,選擇、交叉和變異構成了遺傳算法的遺傳操作;參數編碼、初始群體的設定、適應度函數的設計、遺傳操作設計、控制參數設定五個要素組成了遺傳算法的核心內容。
1.2 國內外研究概述
遺傳算法是由美國的密歇根大學的Holland教授於1975年在他的專著《自然界和人工系統的適應性》中首先提出的,它是一類借鑒生物界自然選擇和自然遺傳機制的隨機搜索算法[2]。
在此之后,遺傳算法的研究都以理論為主,直到第—屆世界遺傳算法大會在Pizibao召開后,遺傳算法開始被逐步投入到實際運用中。1990年以后,遺傳算法迅速發展,在學術研究的理論和應用領域都是一顆新星。當然,人們在對遺傳算法有了一定的理論基礎后,更熱衷於對於其應用的研究。
遺傳算法的應用領域主要有以下幾個分支:
1、基於遺傳算法的機器學習;
2、遺傳算法和Fuzzy Reasoning、Neural Network、Chaos Theory等其它智能計算理論相輔相成的發展;
3、遺傳算法對於並行計算的研究有重大意義;
4、對人工生命的研究影響意義非凡,人工生命就是用計算機模擬生命的遺傳、繁殖現象;
5、遺傳算法和進化策略以及進化規划的互相滲透。
除此之外,還有幾件事在遺傳算法的發展中起到了至關重要的作用。1991年D.Whitey教授在研究旅行商問題時,提出了交叉算子的概念,並且通過實驗進行了驗證。還有D.H.Ackley提出的SIGH算法,即是著名的隨機迭代遺傳爬山法,主要采用隨機概率的思想,進行選舉產生下一代。
參考文獻[1]在前人研究的基礎上,分析了遺傳算法研究方面發表在EI源刊上的文章分布情況,分別從研究內容和應用領域兩個方面進行了統計。從研究內容來看,內容涉及物種多樣性、測試函數、遺傳算子、參數確定等研究內容的文章占較大數量;從應用領域來看,針對遺傳算法在生產調度及機器人學方面進行研究的文章占多數,在自動控制、組合優化和圖像處理方面的研究也占很大一部分比例。有關遺傳算法在函數優化、機器學習、人工生命、數據挖掘及遺傳編程方面研究所涉及的文章不是很多。
總而言之,遺傳算法的終極目標是為人類呈現一種全新的思維模式,帶來真正的計算革命。
1.3 本文的主要研究內容
本文主要分析了遺傳算法的運行機理,查閱了相關的參考文獻和應用算法,闡述了作者對於遺傳算法的原理與應用的理解。並通過實踐,將遺傳算法有效應用於函數優化和旅行商問題(即TSP問題Traveling Salesman Problem)的分析中,研究了遺傳算法在函數優化和解決TSP問題的應用中的性能,並在MATLAB環境中的實現了遺傳算法求解函數優化問題和TSP問題,繪制了相關的結果展示曲線,並對結果進行了一定的分析,提出了改進的思路。
1.3 本文的組織結構
以下是本文的主要內容安排:
第一章 緒論,主要介紹了本論文的研究背景與研究意義,簡單說明了現階段該領域的發展狀況。
第二章 相關理論與技術。介紹了遺傳算法的基本算法流程,分別提出了遺傳算法應用於函數優化和TSP問題的解決思路和理論依據。同時在本章的后半部分還介紹了遺傳算法在以上兩個領域近幾年來的發展情況。
第三章 算法的實現與實驗結果的分析。實現了算法並進行了實驗測試,並探討了評估模型的各項指標。
第四章 總結和展望。對本文提出的模型與算法進行總結,指出了目前存在的問題,並對下一步研究方向進行討論。
-
相關理論與技術
遺傳算法是模擬達爾文生物進化論的自然選擇和遺傳學機理的生物進化過程的計算模型,是一種通過模擬自然進化過程搜索最優解的方法。模擬自然選擇和自然遺傳過程中發生的繁殖、交叉和基因突變現象,在每次迭代中都保留一組候選解,並按某種指標從解群中選取較優的個體,利用遺傳算子(選擇、交叉和變異)對這些個體進行組合,產生新一代的候選解群。重復此過程,直到滿足某種收斂指標為止。
這個過程將導致種群像自然進化一樣的后生代種群比前代更加適應於環境,末代種群中的最優個體經過解碼,可以作為問題近似最優解。與傳統的啟發式優化搜索算法相比,遺傳算法的主要本質特征在於群體搜索策略和簡單的遺傳算子。群體搜索使遺傳算法得以突破領域搜索的限制,可以實現整個解空間上的分布式信息采集和探索;遺傳算子僅僅利用適應值度量作為運算指標進行隨機操作,降低了一般啟發式算法在搜索過程中對人機交互的依賴。
圖1.1 標准遺傳算法流程圖
遺傳算法通常實現方式為一種計算機模擬,是計算數學中用於解決最佳化的搜索算法。對於一個最優化問題,一定數量的候選解(稱為個體)可抽象表示為染色體,使種群向更好的解進化。傳統上,解用二進制表示(即0和1的串),但也可以用實數編碼等其他表示方法。進化從完全隨機個體的種群開始,之后一代一代發生。在每一代中評價整個種群的適應度,從當前種群中隨機地選擇多個個體(基於它們的適應度),通過自然選擇和突變產生新的生命種群,該種群在算法的下一次迭代中成為當前種群。
相關概念的類比見下列表:
-
群體: 搜索空間的一組有效解;
-
種群: 選擇得到的新群體;
-
染色體: 優化問題的可行解的編碼串;
-
基因: 染色體的一個編碼單元;
-
適配值: 染色體的適應值;
-
交叉: 染色體交換部分基因得到的新染色體;
-
變異: 染色體某些基因的數值改變;
-
進化結束:算法結束,算法收斂。
2.1 遺傳算法步驟簡介
編碼和產生初始群體
染色體一般被表達為簡單的字符串或數字串,不過也有其他的依賴於特殊問題的表示方法適用,這一過程稱為編碼。根據問題選擇相應的編碼方法,並隨機產生一個確定長度的N個染色體組成的初始群體。常用的編碼方式如下:
二進制編碼方法是使用二值符號集{0,1},它所構成的個體基因型是一個二進制編碼符號串。二進制編碼符號串的長度與問題所要求的求解精度有關。
優點是簡單。無論是編碼還是解碼操作都非常方便和快捷;方便交叉和變異;符合最小字符集編碼原則。缺點是不適合連續函數的優化問題,局部搜索能力差;連續的數值之間有時候存在海明距離大的問題。例如63和64對應的二進制分別是0111111和1000000。(連續數值對應的二進制數7位全都不同)對於高精度的問題,變異后可能會出現遠離最優解的情況,表現型不穩定。
實數編碼方法,個體基因值用某范圍內的一個實數來表示。編碼長度等於決策變量的個數。
優點是精度高,適用於連續變量問題,避免了海明懸崖問題;適用於表示范圍比較大的數值,適合空間較大的一串算搜索;降低了計算復雜性,提升效率;便於遺傳算法與經典優化方法的混合使用;便於設計針對問題的專門知識的知識型遺傳算子;便於處理復雜的決策變量約束條件,適合於組合優化問題。
排列編碼方法,排列編碼主要針對一些特殊問題。將有限集合的元素盡心排列。假如集合內有m個元素,那么就有m!個排列組合。
優點是對於NPhard問題,m較大,窮舉法失效,這時就可以用遺傳算法。常見的應用有旅行商(TSP)問題、作業調度(job-scheduling)問題以及資源調度(resource-scheduling)問題等。
本文中在
產生初始化種群是在可行域內產生若干個可行解,采用隨機初始化的方法。算法隨機生成一定數量的個體,可能出現比較極端的情況,但是大概率情況下,這些使用隨機數函數產生的可行解,在可行域內是均勻分布的。有時候操作者也可以干預這個隨機產生過程,以提高初始種群的質量。
設計適應度函數
個體的適應度(fitness)指的是個體在種群生存的優勢程度度量,用於區分個體的"好與壞"。適應度使用適應度函數(fitness function)來進行計算。適應度函數也叫評價函數,主要是通過個體特征從而判斷個體的適應度。對群體中的每一個染色體計算它的適應度的一般過程:
-
對個體編碼串進行解碼處理后,可得到個體的表現型。
-
由個體的表現型可計算出對應個體的目標函數值。
-
根據最優化問題的類型,由目標函數值按一定的轉換規則求出個體的適應度。
在設計適應度函數的時候,應滿足以下要求:單值、連續、非負、最大化、合理、一致性、計算量盡可能小、通用新盡可能強等。
在每一代中,都會評價每一個體,並通過計算適應度函數得到適應度數值。按照適應度排序種群個體,適應度高的在前面。這里的"高"是相對於初始的種群的低適應度而言。
設計收斂准則[5],開始搜索
初始的數據可以通過這樣的選擇過程組成一個相對優化的群體。之后,被選擇的個體進入交叉過程。這個過程是通過選擇和繁殖完成,其中繁殖包括交叉和突變,產生下一代個體並組成種群。
一代一代向增加整體適應度的方向發展,直到滿足收斂准則或者達到迭代次數。因為總是更常選擇最好的個體產生下一代,而適應度低的個體逐漸被淘汰掉。
一般收斂准則有以下幾種:
-
進化次數限制;
-
計算耗費的資源限制(例如計算時間、計算占用的內存等 ) ;
-
一個個體已經滿足最優值的條件,即最優值已經找到;
-
適應度已經達到飽和,繼續進化不會產生適應度更好的個體;
-
人為干預;
-
以及以上兩種或更多種的組合。
交叉操作
一般的遺傳算法都有一個交叉概率(又稱為交叉概率),范圍一般是0.6~1,這個交叉概率反映兩個被選中的個體進行交叉的概率。例如,交叉概率為0.8,則80%的"父代"會產生子代。每兩個個體通過交叉產生兩個新個體,代替原來的個體,而不交叉的個體則保持不變。交叉的兩個父代染色體相互交換,從而產生兩個新的染色體。
本文中使用單點交叉的方法,第一個個體前半段是父親的染色體,后半段是母親的,第二個個體則正好相反。不過這里的半段並不是真正的一半,交叉的位置叫做交叉點,也是隨機產生的,可以是染色體的任意位置。
變異操作
通過突變產生新的"子"個體。一般遺傳算法都有一個固定的較小的變異概率,一般取0.0001-0.1,這代表變異發生的概率。根據這個概率,新個體的染色體隨機的突變,突變后的個體和未產生突變的個體一起,形成新的群體。
本文采用的方法是隨機改變染色體的一個字節(0變到1,或者1變到0)。
選擇操作
選擇則是根據新個體的適應度進行,但同時不意味着完全以適應度高低為導向,因為單純選擇適應度高的個體將可能導致算法快速收斂到局部最優解而非全局最優解,我們稱之為早熟。作為折中,遺傳算法依據原則。適應度越高,被選擇的機會越高,而適應度低的,被選擇的機會就低。
帶選擇、交叉、變異的標准遺傳算法並不一定收斂於全局最優解。在實際的應用過程中,要對各種參數進行適當的改進,才能使遺傳算法具有良好的收斂性能。
2.2 遺傳算法解決函數優化問題
函數優化問題是遺傳算法的經典應用領域,也是對遺傳算法進行性能評價的常用算例[3]。在使用遺傳算法解決函數優化問題中,本文使用基本的遺傳算法解決了二位測試函數的優化問題。
在使用遺傳算法解決函數優化問題的時候,算法的主要部分如下:
在編碼過程中,采用了二進制編碼方式,由於上述函數兩個變量x與y的取值范圍都是相同的且是對稱的,並且變量的取值區間也都不大,因此采用同樣的編碼長度。x與y均使用20位二進制進行編碼。
設定搜索次數為N,程序完成N次搜索之后取出最優適應函數值、最優值對應的個體編碼。N的值隨不同函數調整。
計算的是每個個體之前所有個體的選擇概率之和,相當於概率論中的概率分布函數F(x)。
設計適應度函數Fit(x)時可以對目標函數稍作調整,使得Fit(x)越大,證明個體越好。在這里,簡單進行舉例,當需要控制更優秀的個體的適應度更大時,相關調整的方法如下:
由於本文中要針對5個不同的單目標函數優化問題編寫代碼,在初步使用Matlab繪制出函數的三維圖像之后,發現函數優化過程均需要求得函數在可行域中的最小值,因此代碼部分和適應度函數設計部分可以統一。
因此本文在設計適應度函數時,設計的規則是Fit(x)大多數為目標函數的倒數,Fit(x)越大,證明個體越好。
2.3 遺傳算法解決TSP問題
旅行商問題,即TSP問題(Traveling Salesman Problem)又譯為旅行推銷員問題、貨郎擔問題,是數學領域中著名問題之一。
假設有一個旅行商人要拜訪n個城市,他必須選擇所要走的路徑,路徑的限制是每個城市只能拜訪一次,而且最后要回到原來出發的城市。路徑的選擇目標是要求得的路徑路程為所有路徑之中的最小值。
一個商人欲到20個城市推銷商品,每兩個城市i和j之間的距離為,如何選擇一條道路使得商人每個城市走一遍后回到起點且所走路徑最短?
設定搜索次數為G,程序完成G次進化之后取出最短路徑,畫出相關圖像。
這時隨機選擇兩個交叉位置a和b,比如說a=3,b=6,那么交叉的片段為:
然后將父代2的交叉片段移動到父代1的前面,將父代1的交叉片段移動到父代2的前面,則這兩個父代個體變為:
然后從前到后把第2個重復的基因位刪除掉,我們先把兩個父代個體中重復的基因位標記出來:
比如說有6個城市,當前解為123456,我們隨機選擇兩個位置,然后將這兩個位置上的元素進行交換。
比如說,交換2和5兩個位置上的元素,則交換后的解為153426。
有6個城市,當前解為123456,我們隨機選擇兩個位置,然后將這兩個位置之間的元素進行逆序排列。
比如說,逆轉2和5之間的所有元素,則逆轉后的解為154326。
有6個城市,當前解為123456,我們隨機選擇兩個位置,然后將這第一個位置上的元素插入到第二個元素后面。
比如說,第一個選擇2這個位置,第二個選擇5這個位置,則插入后的解為134526。
在變異操作中,我們將以上三種操作賦予不同的權重,然后采用輪盤賭的方式選擇究竟使用哪個操作。
一個個體的目標函數值就是該個體的總距離,比如說一個個體為213,那么這個個體的總距離=21之間的距離+13之間的距離+32之間的距離(從3出發還需要返回起始點2)。
而一個個體的適應度值是其目標函數值的倒數。因為總距離越小說明這個個體質量越好,所以適應度值越大就說明這個個體質量越好。
3.1解決二維單目標函數優化算法設計及結果分析
由於本文中要針對5個不同的單目標函數優化問題編寫代碼,在初步使用Matlab繪制出函數的三維圖像之后,發現函數優化過程均需要求得函數在可行域中的最小值,因此代碼部分和適應度函數設計部分可以統一。
a)初始化:設置進化代數計數器i=0,設置最大進化代數N,隨機生成num個個體作為初始群體P(0)。
d)交叉運算:將單點交叉算子作用於群體。
e)變異運算:將變異算子作用於群體。
群體P(t)經過選擇、交叉、變異運算之后得到下一代群體P(t+1)。
f)終止條件判斷:若i=N,則以進化過程中所得到的具有最大適應度個體作為最優解輸出,終止計算。
-
對於二維球形函數:
在編碼過程中,x與y均使用20位二進制進行編碼,編碼總位數40位。隨機產生10個初始種群。
設定搜索次數為N=5000,程序完成N次搜索之后取出最優適應函數值、最優值對應的個體編碼。
在進行函數優化的時候,采用單點交叉的方法,交叉概率。對於交配后新種群中個體的每一位基因,根據變異概率隨機決定該基因是否進行變異,選擇時采用輪盤賭選擇方法。
設計目標函數使得Fit(x)= 越大,證明個體越好。
圖3.1.1 函數1優化過程中目標函數最優值變化
由上圖可以看到,優化過程中函數的值一直在隨機變化,但是最優值確實在變小。
編寫代碼將全局最優值結果打印出來,其中"bestJ"對應的是目標函數的最優值,"bestStr對應的是最優個體基因的編碼串,"besta"與"bestb"分別對應取最優值時x和y的取值(基因串解碼的結果)。並將結果在函數圖像中繪制出來。
圖3.1.2 函數一最優點位置圖及計算機結果
算法得到的目標函數在可行域內的最優解為(-0.078,0.011),最佳目標函數值為0.0062,近似等於可行域內最小目標函數值。
-
對於De-Jong函數:
在編碼過程中,x與y均使用20位二進制進行編碼,編碼總位數40位。設定搜索次數為N=10000,單點交叉的方法,交叉概率。對於交配后新種群中個體的每一位基因,根據變異概率隨機決定該基因是否進行變異,選擇時采用輪盤賭選擇方法。
設計目標函數使得Fit(x)= 越大,證明個體越好。
同上述函數,編寫代碼將全局最優值結果打印出來,並將結果在函數圖像中繪制出來。
圖3.2.1 函數2優化過程中目標函數值變化
由上圖可以看到,優化過程中函數的值一直在隨機變化,但是目標函數的最優值確實在變小。
圖3.2.2 函數2最優點位置圖及計算結果
算法得到的目標函數在可行域內的最優解為(0.9683,0.9320),最佳函數值為0.0042,近似等於可行域內最小目標函數值。
-
對於Goldstein--price函數:
在編碼過程中,x與y均使用20位二進制進行編碼,編碼總位數40位。設定搜索次數為N=1000,單點交叉的方法,交叉概率。對於交配后新種群中個體的每一位基因,根據變異概率隨機決定該基因是否進行變異,選擇時采用輪盤賭選擇方法。
設計目標函數,由於函數有一部分值比0小,而適應度函數一定是正的,因此,此時根據函數值的取值范圍,設計適應度函數為
Fit(x)=
使得適應度函數值越大,目標函數值越小,證明個體越好。
圖3.3.1 函數3優化過程中目標函數值變化
同上述函數,編寫代碼將全局最優值結果打印出來,並將結果在函數圖像中繪制出來。這里對部分變量名進行了修改,"bestF"對應目標函數的最優值,"bestx"與"besty"分別對應取最優值時x和y的取值(基因串解碼的結果)。並將結果在函數圖像中繪制出來。
圖3.3.2 函數3最優點位置圖及計算結果
算法得到的目標函數在可行域內的最優解為(-1.9480,-1.8363),最佳目標函數值為-4.4464*106,近似等於可行域內最小目標函數值。
-
對於Himmelbaut函數:
在編碼過程中,x與y均使用20位二進制進行編碼,編碼總位數40位。設定搜索次數為N=1000,單點交叉的方法,交叉概率。對於交配后新種群中個體的每一位基因,根據變異概率隨機決定該基因是否進行變異,選擇時采用輪盤賭選擇方法。
設計目標函數使得Fit(x)=越大,證明個體越好。
圖3.4.1 函數4優化過程中目標函數值變化及最優點計算結果
同上述函數,編寫代碼將全局最優值結果打印出來,並將結果在函數圖像中繪制出來。從函數4優化過程中適應度值函數的變化過程可以看出,在進化臨近1000次的時候,目標函數值有一個較大的降低,達到最優值2.26,因此猜測此時並未達到全局最優解。
決定再次訓練,多進化幾個輪次,觀察目標函數值是否會再變小一點。將進化終止條件調整到5000次,重復進行實驗,得到如下結果:
圖3.4.2 函數4再次優化過程中目標函數值變化
此時的最優值下降到了0.0886,相比之前得到的局部最優值2.26得到了很多優化。因此可以判定,增加進化次數有助於函數得到全局的最優值。
圖3.4.3 函數4最優點位置圖及計算結果
算法得到的目標函數在可行域內的最優解為(-2.8554,3.1432),最佳目標函數值為0.0886,近似等於可行域內最小目標函數值。
-
對於函數Six-hump cameback函數
在編碼過程中,x與y均使用20位二進制進行編碼,編碼總位數40位。設定搜索次數為N=1000,單點交叉的方法,交叉概率。對於交配后新種群中個體的每一位基因,根據變異概率隨機決定該基因是否進行變異,選擇時采用輪盤賭選擇方法。
設計目標函數使得適應度函數Fit(x)= 越大,證明個體越好。
圖3.5.1 函數5優化過程中目標函數值變化
同上述函數,編寫代碼將全局最優值結果打印出來,並將結果在函數圖像中繪制出來。
圖3.5.2 函數5最優點位置圖及計算結果
算法得到的目標函數在可行域內的最優解為(-0.0757,0.6992),最佳目標函數值為-1.0294,近似等於可行域內最小目標函數值。
-
解決TSP問題算法設計及結果分析
前期准備:首先在程序中導入20個城市的坐標,根據坐標計算出任意兩個城市之間的距離的距離矩陣。同時根據城市的坐標繪制出城市的分布圖。
圖3.6.1 20城市的坐標分布圖
種群初始化:解決TSP問題過程中個體編碼方法為排列編碼。對於20個城市的TSP問題,編碼為1~20的整數的隨機排列。
初始化的參數有種群規模、染色體基因個數(即城市的個數)、最大遺傳代數、交叉概率、變異概率。
隨機選擇一個種群,繪制出其對應的城市連線線路圖。
圖3.6.2 20城市初始化編碼的路徑圖
適應值函數:由於之前已經計算出任意兩個城市之間的距離,因此每個染色體(即n個城市的隨機排列)可計算出總路徑長度,作為目標函數。因此可將一個隨機全排列的總距離的倒數作為適應度函數,即距離越短,適應度函數越好,滿足TSP要求。
交叉操作:本文算法采用OX交叉操作,隨機選擇兩個個體,在對應位置交換若干個基因片段,同時保證每個個體依然是1~20的隨機排列,防止進入局部收斂。
變異操作:將變異算子作用於群體,並通過以上運算得到下一代群體。
選擇操作:采用賭輪選擇機制,使適應度較大(優良)個體有較大的存在機會,而適應度較小(低劣)的個體繼續存在的機會也較小。
保留每代最優個體,算出目標函數值,繪制目標函數值的進化曲線。
圖3.6.3 TSP問題目標函數值進化曲線
可以看到,隨着進化代數的增加,總距離的值不斷下降,說明遺傳算法可以解決TSP問題。
編寫代碼計算出優化后的最短距離和畫出最短路徑圖。
圖3.6.4 優化后的最短距離和最短路徑圖
由於遺傳算法具有隨機性,在同等參數下,程序計算出的最小路徑可能會存在差別,如下圖:
圖3.6.5 同一代碼同參數不同輸出結果
此時種群規模為200,進化代數為1000。為了加深對於遺傳算法的理解,我進行了不同種群規模的實驗,染色體基因個數(即城市的個數)、最大遺傳代數、交叉概率、變異概率結果如下圖:
種群規模=50
種群規模=500
圖3.6.6種群規模不同時的不同輸出結果
由運行結果可知當種群規模較小時(50個個體)得到TSP的最短路徑長度均小於全局的最短路徑長度。
因此,可以推斷,在最大遺傳代數足夠的情況下,群體個數M參數不宜過小,設置較小,雖然降低了計算量,但是同時降低了每次進化中群體包含更多較好染色體的能力。
也不宜過大,若設置較大,一次進化所覆蓋的模式較多,可以保證群體的多樣性,從而提高算法的搜索能力,但是由於群體中染色體的個數較多,勢必增加算法的計算量,降低了算法的運行效率。
同時,在種群規模為200,其他參數不變,改變最大遺傳代數后,得到結果如下圖:
最大遺傳代數=500
最大遺傳代數=100
圖3.6.7 改變最大遺傳代數后的結果圖
由以上結果圖可知,最大遺傳代數不宜太小,否則可能還沒有找到最優值,算法就停止了搜索。
同理也進行了交叉概率、變異概率對結果的影響的一系列實驗,得出以下結論:
影響着算法的運行效率,但其大小對得出的最短路徑長度的大小並沒有直接的影響,不能保證其最優性。Pc的取值為0.4~0.99時效果較好。
的值不宜過大,最好取0.001-0.1。因為變異對已找到的較優解具有一定的破壞作用,如果的值太大,可能會導致算法目前所處的較好的搜索狀態倒退回原來較差的情況。
在TSP問題中,一開始編寫的代碼,即使加大迭代次數到5000,也不能解決的最短路徑的交叉問題,使得最終得到的最短路徑值比較大。陷入了局部最優。通過修改代碼中選擇函數、交叉函數的選型,解決了問題,使得最終得到的最短路徑值更小,且路徑圖不交叉。
圖3.6.8 未改良的算法運行結果
-
總結與展望
4.1 總結
本文在遺傳算法的模式理論的基礎上,用Matlab程序實現了遺傳算法,並對各種參數對結果的影響進行了數學分析,通過實驗研究了應用中的遺傳算法性能影響因素。
在二維單目標函數優化過程中,雖然函數有很多局部最優,但加大迭代次數后,也基本可以每次都達到全局最優解,並可以在1000代以內收斂,實驗結果顯示其收斂速度快,結果直觀,性能好。
在TSP問題中,通過修改代碼中選擇函數、交叉函數的選型,解決了局部最優問題,使得最終達到全局最優,且路徑圖不交叉。
理解了遺傳算法的獨有特點:
-
從問題解的串集開始搜索,而不是從單個解開始。這是遺傳算法與傳統優化算法的極大區別。傳統優化算法是從單個初始值迭代求最優解的;容易誤入局部最優解。遺傳算法從串集開始搜索,覆蓋面大,利於全局擇優。
-
遺傳算法同時處理群體中的多個個體,即對搜索空間中的多個解進行評估,減少了陷入局部最優解的風險,同時算法本身易於實現並行化。
-
遺傳算法基本上不用搜索空間的知識或其它輔助信息,而僅用適應度函數值來評估個體,在此基礎上進行遺傳操作。適應度函數不僅不受連續可微的約束,而且其定義域可以任意設定。這一特點使得遺傳算法的應用范圍大大擴展。
-
遺傳算法不是采用確定性規則,而是采用概率的變遷規則來指導他的搜索方向。
-
具有自組織、自適應和自學習性。遺傳算法利用進化過程獲得的信息自行組織搜索時,適應度大的個體具有較高的生存概率,並獲得更適應環境的基因結構。
本次大作業完成的過程並沒有想象中的順利,遇到了很多問題。一開始參考網絡上的開源代碼,但是結果並不理想。在重新仔細研究了一遍遺傳算法后,對於基因長度的選擇,選擇算子,交叉算子等相關內容有了更深刻的認識。
在之后針對每個函數進行優化時,多次嘗試了不同的參數值,對於參數的選擇以及不同參數對於算法性能的影響有了更全面的了解。
4.2 展望
本文在運用遺傳算法求解問題時,選擇參數經驗較少,需要通過查閱資料獲得相關最優參數取值范圍。同時我也在反思這種經驗主義或盲目性,遺傳算法是否可以和梯度下降算法自適應學習率一樣,自主動態調整參數?能否結合直觀的參數關系圖和統計分析,以尋找解決函數優化問題的最優交叉和變異率的組合參數的有效方法。
在二維單目標函數初始化的時候,可以不隨機產生初始編碼值,而是依據先驗經驗,在更小的最優解可能出現的局部區域展開更加細致的搜索。
算法本身也可以采用動態自適應技術,在進化過程中自動調整算法控制參數和編碼精度,比如使用模糊自適應法。
旅行商問題是一類經典的組合最優化問題,在理論研究和實際應用領域具有重要的研究價值。傳統的遺傳算法GA在求解TSP問題時容易出現早熟和陷入局部最優等現象(實驗過程中曾遇到過)。
為此查閱了很多資料,得知了一些優化方法:一種基於協同進化的遺傳算法(CEGA)用於解決GA算法的缺陷[10]。實驗結果表明,所提出的算法[10]在解決TSP問題時,具有收斂速度快、容易跳出局部最優等特點,相較其他GA算法具有更好的性能。除此之外還有一種基於自適應層次譜聚類與遺傳優化的算法求解大規模TSP算法[8],一種自適應遺傳算法,變異率自適應,提高了算法的收斂速度【12】。
總之,通過本次大作業,我對於遺傳算法有了更加深入的認識。同時,也完成了一系列的相關實驗,提高了代碼能力。但是在實驗中碰到的問題也讓我明白,本次大作業只是一個開始,遺傳算法的魅力遠不止此,可以提升、可以探索的空間還相當的大。本文整體方案仍然處於實驗的階段,離解決實際問題還有很大的差距。
遺傳算法的應用在日后必定會越來越成熟,同時這一領域也具有很大的發展空間,在未來我也將投入更多的精力在這個方面,也期望未來可以取得更高的成就。
參考文獻
-
自然計算的研究綜述[J]. 電子學報, 2012, 40(3):548-558.
https://wenku.baidu.com/view/59ef836e590216fc700abb68a98271fe910eaf92.html
-
馬永傑, 雲文霞,MA Yong-jie, YUN Wen-xia- 《計算機應用研究》2012年4期
-
蔣冬初. 遺傳算法及其在函數優化問題中的應用研究[D].湖南大學,2004.
-
石麗娟. 遺傳算法求解函數優化問題的Matlab實現. 福建電腦, 2010年6期
-
王輝, 徐曉英. 基於遺傳算法收斂特性的停機准則[J]. 武漢理工大學學報(交通科學與工程版), 2012, 36(005):1091-1094.
-
王輝, 徐曉英基於遺傳算法收斂特性的停機准則. 《武漢理工大學學報(交通科學與工程版)》 2012年05期
-
李慶,魏光村,高蘭,仇國華,肖新光.用於求解TSP問題的遺傳算法改進[J].軟件導刊,2020,19(03):116-119.
-
楊彩虹,楊明.基於自適應層次譜聚類與遺傳優化的TSP算法[J].雲南師范大學學報(自然科學版),2020,40(01):44-51.
-
遺傳算法交叉算子的性能研究,益陽師專學報2002.19(3):26-28
-
王震,劉瑞敏,朱陽光,王梟.一種求解TSP問題的改進遺傳算法[J].電子測量技術,2019,42(23):91-96.
-
遺傳算法的收斂性分析,湖南教育學院學報2002.20(4):285-288
-
劉景鑫,李林林,李治華,張耘赫.一種求解旅行商問題的基於外部存檔的自適應遺傳算法[J].計算機時代,2019(07):51-53.
-
遺傳算法在實際應用中的性能分析,吉首大學學報2003.24(3):12-14
-
遺傳算法並行機理分析,海南大學學報2004.22(4):331-335
-
遺傳算法在求解函數優化中的最優化參數研究2005年4月
附錄
任務一:遺傳算法計算函數最優值代碼
一共五個函數,都是求最小值,因此只需要修改適應度函數的表達式、目標函數的表達式、可行域的范圍,和調整交叉概率、變異概率、進化次數等參數即可。
主函數
%%%%%%%%%%%%%%%遺傳算法解決函數優化問題%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%six-hump函數%%%%%%%%%%%%%%%%
clear all; %清除所有變量
close all; %清圖
clc; %清屏
%%%%%%%%%%%%初始化參數%%%%%%%%%%%%%%%%%%%%%%%
Pc=0.9; %交叉概率
Pm=0.01; %變異概率
N=1000;%迭代次數
Num=40;%編碼總位數
Num1=20;%x編碼位數
a1=-5; %x下限
b1=5; %x上限
a2=-5; %y下限
b2=5; %y上限
%%%%%%%%%%%%%%%%%%%%隨機生成初始字符串%%%%%%%%%%%%%%%%%%%%%
for i=1:10 %生成10個長度為Num的隨機0/1字符串
a = round(rand(1,Num)*1);
a = num2str(a);
a(a==' ')=[];
s{i}=a;
end
%%%%%%%%%%%%進化過程,迭代N次后結束%%%%%%%%%%%%%
for i=1:N
s1=s;
for j=1:10
J(j)=fitness(s1{j});
end
s = crossover(Pc,s,J); %交叉
s = mutation(Pm,s); %變異
s = selection(s,J); %選擇
for j=1:10
J(j)=fitness(s{j});
end
[mi,I]=min(J);
TempMin(i)=mi;
Minstr{i}=s{I};
best(i)=min(TempMin);
end
%%%%%%%%%%%%%%%%%%%%%畫出優化圖線%%%%%%%%%%%%%%%%%%%%%
figure();
t=1:N;
hold on
plot(t,best,'r',t,TempMin,'k');
[mi,I]=min(TempMin);
bestF=min(TempMin)%打印最優值目標函數值
bestStr=Minstr{I}%打印最優值的編碼串
x1=bestStr(1:Num1);
x2=bestStr(Num1+1:Num);
n=bin2dec(x1);
m=bin2dec(x2);
bestx=a1+[(b1-a1)*n/(2^Num1-1)] %打印出最佳x值
besty=a2+[(b2-a2)*m/(2^(Num-Num1)-1)] %打印出最佳y值
%%%%%%%%%%%畫出函數圖像,並標出最優值點%%%%%%%%%%%%%%%%%%
figure();
x1=linspace(-5,5,20);
x2=linspace(-5,5,20);
[x,y]=meshgrid(x1,x2);
for i=20:-1:1
for j=20:-1:1
ax=x(i,j);
by=y(i,j);
z(i,j)=4*ax^2+2.1*ax^4+(1/3)*ax^6+ax*by-4*by^2+4*by^4;
end
end
surf(x,y,z);
hold on;
plot3(bestx,besty,bestF, 'ro');title('最優值在原始函數的位置圖');
適應度值函數
%%%%%%%%%%%%%%%%計算目標函數%%%%%%%%%%%%%%%%
function y=fitness(b)
a1=-5; %x下限
b1=5; %x上限
a2=-5; %y下限
b2=5; %y上限
Num=40;%編碼總位數
Num1=20;%x編碼位數
x1=b(1:Num1);
x2=b(Num1+1:Num);
n=bin2dec(x1);
m=bin2dec(x2);
ax=a1+[(b1-a1)*n/(2^Num1-1)];
by=a2+[(b2-a2)*m/(2^(Num-Num1)-1)];
y=4*ax^2+2.1*ax^4+(1/3)*ax^6+ax*by-4*by^2+4*by^4;
單點交叉函數
%%%%%%%%%%%%%%%%%單點交叉函數%%%%%%%%%%%%%%%%%%
function y=crossover(Pc,s,J)
Num=40;%編碼總位數
Num1=20;%x編碼位數
for i=1:10
if Pc>rand(1)
j=randi(10,1);
k=randi(10,1);
if j~=k
S1 = s{j};
S2 = s{k};
h = randi([2,Num-1],1);
new1 = [S1(1:h),S2(h+1:Num)];
new2 = [S2(1:h),S1(h+1:Num)];
s{j}=new1;
s{k}=new2;
end
end
end
y=s;
輪盤賭選擇函數
%%%%%%%%%%%%%%%%%輪盤賭選擇函數%%%%%%%%%%%%%%%%%
function y=selection(s,J)
F = sum(J);
for j=1:10
p(j)=J(j)/F;
end
LJ=zeros(1,20);
LJ(1)=p(1);
for i=2:10
LJ(i)=LJ(i-1)+p(i);
end
for i=1:10
sjs=rand(1);
for j=1:9
if LJ(j)>sjs
live{i}=s{j};
break;
end
if LJ(j)<=sjs&&sjs<LJ(j+1)
live{i}=s{j+1};
break;
end
end
end
y=live;
end
變異函數
%%%%%%%%%%%%%%%%%%%%%%%%%變異函數%%%%%%%%%%%%%%%%%%%%%%%
function y=mutation(Pm,s)
Num=40;%編碼總位數
Num1=20;%x編碼位數
for i=1:10
for j=1:Num
if Pm>rand(1)
S=s{i};
mid=str2num(S(j));
mid=1-mid;
S(j)=num2str(mid);
s{i}=S;
end
end
end
y=s;
任務二:遺傳算法計算TSP最短路徑代碼
主函數
%%%%%%%%%%%%%%%%%%遺傳算法解決TSP問題%%%%%%%%%%%%%%%%%
clear all; %清除所有變量
close all; %清圖
clc; %清屏
C=[
5.294 1.558;
4.268 3.622;
4.719 2.774;
4.185 2.230;
0.915 3.861;
4.771 6.041;
1.524 2.871;
3.447 2.111;
3.718 3.665;
2.649 2.556;
4.399 1.194;
4.660 2.949;
1.232 6.440;
5.036 0.244;
2.710 3.140;
1.072 3.454;
5.855 6.203;
0.194 1.862;
1.762 2.693;
2.682 6.097;
]; %20個城市坐標
N=size(C,1); %TSP問題的規模,即城市數目
D=zeros(N); %任意兩個城市距離間隔矩陣
%%%%%%%%%%%%%求任意兩個城市距離間隔矩陣%%%%%%%%%%%%%%%%%%%%%
for i=1:N
for j=1:N
D(i,j)=((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2)^0.5;
end
end
NP=200; %種群規模
G=1000; %最大遺傳代數
f=zeros(NP,N); %用於存儲種群
F=[]; %種群更新中間存儲
for i=1:NP
f(i,:)=randperm(N); %隨機生成初始種群
end
R=f(1,:); %存儲最優種群
len=zeros(NP,1); %存儲路徑長度
fitness=zeros(NP,1); %存儲歸一化適應值
gen=0;
%%%%%%%隨機選擇一個種群,畫出所有城市坐標,對應各城市之間的連線%%%%%%%%%%%
R=f(1,:);
figure(1);
scatter(C(:,1),C(:,2),'rx');
figure(2);
plot_route(C,R);
%%%%%%%%%%%遺傳算法循環%%%%%%%%%%%%%%%%%%
while gen<G
%%%%%%%%%%%%%%%%%計算路徑長度%%%%%%%%%%%%%%%%%%%%%
for i=1:NP
len(i,1)=D(f(i,N),f(i,1));
for j=1:(N-1)
len(i,1)=len(i,1)+D(f(i,j),f(i,j+1));
end
end
maxlen=max(len); %最長路徑
minlen=min(len); %最短路徑
%%%%%%%%%%%%%%%%%%%%更新最短路徑%%%%%%%%%%%%%%%%%%%
rr=find(len==minlen);
R=f(rr(1,1),:);
%%%%%%%%%%%計算歸一化適應值%%%%%%%%%%%%%%%%%%%%
for i=1:length(len)
fitness(i,1)=(1-((len(i,1)-minlen)/(maxlen-minlen+0.001)));
end
%%%%%%%%%%%%%%%%%%%選擇操作%%%%%%%%%%%%%%%%%%%%%%%
nn=0;
for i=1:NP
if fitness(i,1)>=rand
nn=nn+1;
F(nn,:)=f(i,:);
end
end
[aa,bb]=size(F);
while aa<NP
nnper=randperm(nn);
A=F(nnper(1),:);
B=F(nnper(2),:);
%%%%%%%%%%%%%%%%交叉操作%%%%%%%%%%%%%%%%%%%
W=ceil(N/10); %交叉點個數
p=unidrnd(N-W+1); %隨機選擇交叉范圍,從p到p+W
for i=1:W
x=find(A==B(p+i-1));
y=find(B==A(p+i-1));
temp=A(p+i-1);
A(p+i-1)=B(p+i-1);
B(p+i-1)=temp;
temp=A(x);
A(x)=B(y);
B(y)=temp;
end
%%%%%%%%%%%%%%%%%%%%%變異操作%%%%%%%%%%%%%%%%%%%
p1=floor(1+N*rand());
p2=floor(1+N*rand());
while p1==p2
p1=floor(1+N*rand());
p2=floor(1+N*rand());
end
tmp=A(p1);
A(p1)=A(p2);
A(p2)=tmp;
tmp=B(p1);
B(p1)=B(p2);
B(p2)=tmp;
F=[F;A;B];
[aa,bb]=size(F);
end
if aa>NP
F=F(1:NP,:); %保持種群規模為n
end
f=F; %更新種群
f(1,:)=R; %保留每代最優個體
clear F;
gen=gen+1
Rlength(gen)=minlen;
end
figure
for i=1:N-1
plot([C(R(i),1),C(R(i+1),1)],[C(R(i),2),C(R(i+1),2)],'bo-');
hold on;
end
plot([C(R(N),1),C(R(1),1)],[C(R(N),2),C(R(1),2)],'ro-');
title(['優化最短距離:',num2str(minlen)]);
figure
plot(Rlength)
xlabel('迭代次數')
ylabel('目標函數值')
title('適應度進化曲線')
繪圖函數
%連點畫圖函數 plot_route.m
function plot_route(a,R)
scatter(a(:,1),a(:,2),'rx');
hold on;
plot([a(R(1),1),a(R(length(R)),1)],[a(R(1),2),a(R(length(R)),2)]);
hold on;
for i=2:length(R)
x0=a(R(i-1),1);
y0=a(R(i-1),2);
x1=a(R(i),1);
y1=a(R(i),2);
xx=[x0,x1];
yy=[y0,y1];
plot(xx,yy);
hold on;
end
end