遺傳演算法回溯
1. 數學建模常用模型有哪些
1、蒙特卡羅演算法,該演算法又稱隨機性模擬演算法,是通過計算機模擬來解決問題的演算法。
2、數據擬合、參數估計、插值等數據處理演算法。
3、線性規劃、整數規劃、多元規劃、二次規劃等規劃類問題。
4、圖論算包括最短路、網路流、二分圖等演算法,涉及到圖論的問題用這些方法解決。
5、動態規劃、回溯搜索、分治演算法、分支定界等計算機演算法。
6、最優化理論的三大非經典演算法:模擬退火法、神經網路、遺傳演算法。
7、網格演算法和窮舉法,這兩者都是暴力搜索最優點的演算法,在很多競賽題中有所應用。
8、數值分析演算法,比如方程組求解、矩陣運算、函數積分等演算法就需要額外編寫庫函數進行調用。
2. 哪裡有0—1背包演算法各種方法的總結啊,包括動態規劃、貪心、回溯、分支界限等等
我記得以前有一篇180頁的pascal演算法,我用delphi實現了其中一部分,這些演算法都相當有用,但是也是超難,我啃回溯啃了5天。動態規劃在分類步驟比較小的情況下用,遞歸太常用了,回溯就是循環的遞歸(解決迴路嵌套問題),枚舉只有情況有限的時候一個個列舉出來,貪心就是不求最佳,找一個滿足添加的結果就行
3. 基於遺傳演算法的疊前地震波形反演構建虛擬井曲線
羅文造1楊紹國2王英民3
(1.廣州海洋地質調查局 廣州 510760;2.成都理工大學 成都 610059;3.中國石油大學(北京)北京 102200)
第一作者簡介:羅文造,男,1969年出生,高級工程師,主要從事地球物理技術方法研究。
摘要 疊前地震波形反演能夠提供詳細的地下地層特徵,但由於其計算量大、數據和模型之間的非線性、目標函數的多極值和反演結果的多解性使疊前地震反演的實施成為一大難點。本文通過疊前和疊後混合反演技術採用遺傳演算法實現了深海無井地震反演。遺傳演算法思想簡單、易於實現和使用、具有隱含並行性和全局搜索能力等優點,基於遺傳演算法的疊前地震波形反演得到了與井中實際數據基本吻合的速度和密度數據。
關鍵詞 疊前反演 遺傳演算法 虛擬井
1 前言
地震反演分為疊前反演和疊後反演。一般疊前反演方法所得到的物理特性與疊後反演方法相比提供了更詳細的地下地層特徵。疊前反演解析度高,但速度慢、穩定性差,現處於研究階段,距大規模生產應用還有一定距離。疊後反演雖然解析度要低一些,但速度快、穩定性好,可滿足大規模生產應用的需要。
疊前地震波形反演所面臨的難題在於:①計算量和數據量非常龐大;②數據和模型之間高度非線性;③目標函數具有多個極小值;④反演結果具有多解性,可能存在多個模型與地震數據匹配良好(Sen等,1991)。非線性、非唯一性和大計算量交織在一起,使疊前地震波形反演的難度很大。但它對儲層岩性和所含流體的高解析度,對油氣勘探開發技術研究人員來說具有較大的吸引力。針對疊前地震波形反演所面臨的難題,近十年來,有許多地球物理工作者進行了大量的探索,取得了重要的研究成果,這些進展基本上解決了疊前地震波形反演所面臨的高度非線性和局部極小值問題;但對非唯一性和大計算量的問題沒得到很好解決。為此,有些學者採用了一種折中的辦法,即疊前和疊後混合反演的辦法,首先在一些控制點進行精細的疊前地震波形反演構建虛擬井曲線,然後以虛擬井作為控制信息進行疊後反演(Mallick,2000)。疊前和疊後混合反演的辦法利用了疊前反演解析度高,疊後反演速度快、穩定性好的優點,克服了各自的缺點,成為目前的一個研究亮點。特別對於深海無井的情況,具有很好的應用前景。本文採用疊前和疊後混合反演的辦法實現深海無井地震反演,其關鍵是疊前地震波形反演構建虛擬井曲線方法的研究。
2 遺傳演算法基本原理
遺傳演算法(Genetic Algorithm,簡稱GA)是美國Michigan大學的John H.Holland在60年代提出的,目的是把自然界的自適應機理應用於計算機系統的設計。目前,遺傳演算法作為一種有效的全局尋優自適應概率演算法,由於其演算法思想簡單、易於實現、易於使用、具有隱含並行性和全局搜索能力等優點,且對很多優化問題能夠較容易地得到令人滿意的解,在自適應控制、組合優化、模式識別、機器學習、人工智慧、地球物理反演、管理決策等涉及優化計算問題的領域得到了廣泛的應用,且影響越來越大。
盡管遺傳演算法在解決復雜非線性優化問題中具有獨特的優勢,但它本身也有局限性,其突出的一個弱點就是收斂性能差,尤其對於多參數、超大解空間的優化問題,其收斂速度有時讓人很難接受,這在一定程度上制約了GA的使用和發展(Sen等,1992)。採用GA求解高維、多約束、多目標的優化問題仍是一個沒有很好解決的課題,它的進展將會推動GA在許多工程領域的應用。
遺傳演算法是一種基於自然選擇和基因遺傳學原理的隨機搜索演算法,但又不同於一般隨機搜索演算法。它是通過將待尋優的模型空間的參數進行編碼,並用隨機選擇作為工具來引導搜索過程向著更高效的方向發展,其計算簡單、功能強大(Mallick,1995)。具有以下特點:
1)GA是對要尋優參數的編碼進行操作,而不是對參數本身;
2)GA是從「群體」(多個初始點)出發開始的並行操作,可以有效地防止搜索過程收斂於局部是優解,是一種全局尋優的方法,且計算速度較快;
3)GA採用目標函數來確定基因遺傳的概率,對問題的依賴性較小,適用范圍更廣;
4)GA的操作均採用隨機概率的方式,減少人為干預對結果的影響;
5)GA以隨機選擇來引導搜索過程,是一種啟發式的搜索方法,搜索效率更高;
6)GA適合於大規模復雜問題的優化,如地震反演問題。
遺傳演算法運算的原理簡單,只涉及參數編碼的復制和部分編碼的交換和變異操作,標准GA只包括選擇、交叉和變異三種基本操作:
(1)選擇(Selection)/再生(Reproction)
選擇是根據群體成員的適應度值fi,對群體成員進行復制的過程。其按照一定的概率選擇優秀成員並復制保留下來,體現「適者生存」的自然規律。
選擇運算有許多方法,最簡單的方法是採用輪盤賭法。該方法根據群體中各成員的適應度,計算適應概率fpi,適應度越大,適應概率越大。
(2)基因交換(Crossover)/重組(Recombination)
基因交換或重組由兩步構成,一是匹配,即對再生的群體成員做隨機匹配;二是交換匹配成員的基因,即對每對匹配成員,按照隨機概率Pc選擇隨機位置,將兩成員的編碼進行交換或重組。經過再生所得的新群體中並沒有新成員,也就是在搜索空間中沒有得到新的搜索點。而按隨機概率進行基因交換後,新群體中既有上一代的優秀成員,又有由優秀成員交叉後產生的新成員,得到的新搜索點。根據生物遺傳的「雜交優勢」規律,這種新成員應該優於原成員。
(3)基因變異(mutation)
基因變異的目的是在搜索過程中,不斷引入新的信息量,以免再生和交換的遺傳過程中丟失潛在的有用遺傳物質。基因變異實際上是對群體成員的基因按小概率Pm擾動而使其發生變化,以補充新的信息。
遺傳演算法求解優化問題的基本思路:
(1)確定目標函數
目標函數(Objects)是刻畫最優解的標准,也是適度計算的依據。一般是以計算值與觀測值之間的擬合程度或誤差大小為標準的。
(2)指定問題參數的搜索范圍
給定每一個模型參數的取值范圍,對任一參數x給出[Xmin,Xmax)。實際上是問題解空間搜索精度的描述,其決定了搜索空間的大小,精度越高,離散化的搜索空間越大。
(3)模型參數編碼
由於GA運算是對模型參數的編碼進行的。編碼方式有多種,常用的有二進制編碼和十進制編碼。
(4)初始群體的產生
給定群體成員數n,用隨機生成的方法獲取n個群體成員構成初始群體;
(5)遺傳計算
① 求取適應度值
適應度值是直接由目標函數轉換計算出來的。對最小化問題可用
指數轉換:
南海地質研究.2006
i=1,…,n
其中:Objects[i]為第i個成員的目標函數值;σ為群體目標函數值的方差;Fitness[i]為第i個成員的適應度值。
② 再生
計算再生概率:
南海地質研究.2006
Ps[0]=0;
南海地質研究.2006
i=1,…,n
生成[0,1]隨機數r,如果Ps[i-1]≤r<Ps[i]則第i個成員獲得再生。
③ 交叉
將群體成員兩兩配對,組成n/2對母本,並按概率Pc進行交叉;即產生[0,1]隨機數r,如果r<=Pc,則在一隨機位置交換兩個母本的編碼;否則不變。
④ 變異
對每一個新成員,按概率Pm進行基因的隨機突變,即產生[0,1]隨機數r,如果r<=Pm,則在一隨機位置改變該成員的編碼,由1變0,或由0變1。
遺傳演算法對問題的求解是通過對尋優參數空間進行編碼,從多點出發,採用隨機選擇作為工具來引導搜索過程向著更高效的方向發展,是一種普適性的搜索方法(Mallick,1999)。由於在搜索過程中使用了其父輩的適應度函數值作為啟發知識,因此又是一種啟發式搜索方法。這種搜索方法,對於簡單的多極值優化問題可能會產生好的效果。盡管如此,GA對於多參數復雜非線性問題收斂速度還是過慢(Xia等,1998)。
就遺傳演算法本身而言,提高其收斂速度的關鍵在於合理的適合問題特點的遺傳編碼方法、適應度函數及變換方法、遺傳運算元、演算法參數的設置和選取。
3 基於遺傳演算法的疊前地震波形反演
採用GA疊前地震波形反演估算彈性參數。疊前反演在角道集上進行,以便減少計算工作量。疊前資料預處理包括:角道集抽取、疊前去噪、壓制多次波和高精度速度分析等方。GA疊前地震波形反演的技術路線如圖1。
圖1 GA疊前地震波形反演框圖
Fig.1 The flow chart of pre-stack seismic waveform inversion by means of GA
其演算法如下:
1)准備初始模型、地震記錄Seis等數據
由高精度速度分析構建初始模型,地震記錄Seis為角道集地震記錄。
2)確定地質模型參數及參數搜索范圍和搜索間隔
3)對模型參數編碼。根據搜索范圍的搜索間隔,先確定各參數可能取得的不同值的個數,為節省空間對所有參數進行整數編碼。
4)生成擬合模型的初始隨機總體P,假設生成了n個隨機模型
由X=Xmin+Code×Dx,對Vp,Vs和ρ三個參數nt個樣點用隨機生成的方式生成整數碼產生要求的樣本量。
5)計算各模型的合成地震記錄Syni。
合成地震記錄採用Zoeppritz方程計算。
6)比較Syni與Seis,計算並保存目標函數值
觀測記錄與合成記錄之間的匹配程度稱為模型的擬合度(Inger等,1992),如果隨機模型與實際情況相差很遠,由觀測記錄計算得到的角道集與相應的合成角道集匹配就會很差。相反如果所選隨機模型接近實際情況,從而使由觀測記錄計算得到的角道集與相應的合成角道集能很好地匹配。
南海地質研究.2006
i=1,…,n
其中:n為群體樣本數;從理論上說,點越多,搜索效率應該越高。但實際上增加搜索點,也高增加了遺傳計算的計算量。因此解決實際問題時,根據問題的性質及解空間的大小,做適當選擇。在計算時,由於遺傳計算量相對較大,選擇了較小的群體。為便於操作和增加程序的適應能力,採用人機交互輸入的方式選擇8到32間的偶整數。
Nt=nt×angles;
nt:地震道時間取樣點數;
angles:角道集所選角度個數。
seis[j]:觀測記錄角道集
Syn[j][i]:第i個群體成員的合成記錄角道集
7)根據目標函數值對P做再生、交叉、變異操作,更新P生成新的隨機總體;
8)如果滿足結束條件,結束並輸出結果;否則重復5)至8)直到結束。
4 疊前地震波形反演的實施
針對地震波反演問題這種多參數、復雜非線性問題的特點採用了如下技術措施:
(1)編碼方法
對多參數、復雜非線性問題,其編碼的優劣直接影響計算效率。為此採用了整數編碼方案有效降低碼的長度,加快計算速度。參數編碼採用整數編碼,方法如下:
參數值=參數最小值+碼值×參數搜索精度;
碼值=(參數值-參數最小值)/參數搜索精度;
即:Dx=(Xmax-Xmin)/Codemax
X=Xmin+Code×Dx
Code=(X-Xmin)/Dx
(2)適應度函數
適應度函數是由目標函數轉換而得的用以刻劃個體適應生存能力的函數。對極小值問題一般採用指數變換,但這種變換是一種均勻變換,在計算後期當群體中各樣本目標函數值接近時,為增加優秀個體在再生時被選中的可能性,從而加快演算法收斂,選擇採用了S函數做疊加變換。
開始時使用指數變換:
南海地質研究.2006
i=1,…,n
其中:Objects[i]為第i個成員的目標函數值;σ為群體目標函數值的方差;Fitness[i]為第i個成員的適應度值。
當群體中樣本目標函數值接近時使用S函數變換:
南海地質研究.2006
用於在遺傳迭代計算後期,當群體各樣本適應度很接近時,以指數形式放大平均適應度以上的樣本適應度差異,縮小平均適應度以下的樣本適應度的差異,以便更好地選擇優秀個體(Sen,2001)。
式中:x對應用不同樣本的原適應度值;y為變換後的適應度值;θ0為所有樣本的平均適應度。a>0表示用於控制放大比例參數,越大對平均值以上的部分放大越明顯。b>0表示調節系數,當a=1時,可取b為8到10;b太大達不到對接近最大值處的適應度的放大,b較小時可用線性變換取代。
南海地質研究.2006
當然為達到上述目的,也可使用其它函數,選擇使用S函數,一是因為S變換的連續性,可使大於平均值的適應度放大,而使小於平均值的適應度縮小。二是基於前人的經驗增加優秀個體在再生時被選中的可能性,從而加快演算法收斂。
(3)演算法過程
一般GA在計算時採用的是上一代的適應度作為啟發函數再生後進行的隨機啟發搜索方法。為提高演算法速度在實際處理中除使用上一代的適應度,還充分利用了優秀的隔代遺傳的信息作為啟發信息,參與遺傳過程的計算。採用一種有限深度回溯搜索的方法,避免了迭代計算的反復,從而加快了計算收斂速度。事實上,在超大解空間中,某一代的遺傳性能往往很難決定最終結果的好壞。另外,在交叉中每對成員交叉變換使用兩次概率選擇方法,即先選成員對,再選參數,且每個參數分別選擇,這樣可以有效地增加搜索能力。
5 試算效果實例分析
圖2給出了理論地震記錄的基於遺傳演算法的疊前地震波形反演的實例。圖中展示了反演縱波速度和實際井中速度曲線,反演橫波速度和實際井中速度曲線,反演密度和實際井中密度曲線,理論地震角道集記錄和反演結果的合成角道集記錄。基於遺傳演算法疊前反演結果與井中實際數據基本吻合,理論地震角道集記錄和反演結果的合成角道集記錄吻合非常好。
圖2 基於遺傳演算法的疊前地震波形反演實例
Fig.2 A case for GA based pre-stack seismic waveform inversion
圖中從左到右為反演縱波速度和實際井中速度曲線,反演橫波速度和實際井中速度曲線,反演密度和實際井中密度曲線,5°理論地震角道集記錄和反演結果的合成角道集記錄,10°理論地震角道集記錄和反演結果的合成角道集記錄,15°理論地震角道集記錄和反演結果的合成角道集記錄,20°理論地震角道集記錄和反演結果的合成角道集記錄
參考文獻
Inger L,and Rosen B.1992.Genetic algorithms and very fast simulated annealing:A comparision,Math.Comput.Modelling,16,87~100
Mallick S.1995.Model-based inversion of amplitude-variation-with-offset data using a genetic algorithm,Geophysics,52,1355~1364
Mallick S.1999.Some practical aspects of prestack waveform inversion using a genetic algorthm:An example from the east Texas Woodbine gas sand,Geophysics,64,326~336
Mallick S.2000.Hybrid seismic inversion:A reconnaissance tool for deepwater exploration.The Leading Edge,19,1230~1237
Sen M K,and Stoffa P L.1991.Nonlinear one-dimensional seismic waveform inversion using simulated annealing,Geophysics,56,1624~1638
Sen M K,and Stoffa P L.1992.Rapid sampling of model space using genetic algorithms:Examples from seismic waveform inversion,Geophys.J.Internat.,108,281~292
Sen M K.2001.Pre-stack waveform inversion:Current status and future direction,Institute for Geophysics
Xia G,Sen M K,and Stoffa P L.1998.1-D elastic waveform inversion:A divide-and-conquer approach,Geophysics,63,1670~1684
The construction of pseudo-well logs by inversion of pre-stack seismic waveform based on genetic algorithm
Luo Wenzao1Yang Shaoguo2Wang Yingmin3
(1.Guangzhou Marine Geological Survey,Guangzhou,510760;2.Cheng University Sciences and Technologies,Cheng,610059;3.China Petroleum University,Beijing,102200)
Abstract:The inversion of pre-stack seismic waveform is capable of providing the detailed character of subsurface stratigraphy.But its large scale of calculation,the non-linear relationship between data and model,multi-pole of objective functions and its multi-resolution has resulted in the difficulty of its operation.The seismic inversion without well constrained in the deep sea has been realized by hybrid inversion of pre-and post-inversion.The genetic algorithm is simple,easy to realizing and using with the character of latent paralleling and global searching capability.The inversion of pre-stack seismic waveform based on genetic algorithm gives the velocity and density which consists basically with those from the wells.
Key Words:Pre-stack inversion Genetic algorithm Pseudo-well
4. 數學建模需要掌握哪些編程語言和技術
數學建模需要掌握MATLAB、Python、SAS、Lingo等編程語言。
5. 數學建模的應用范圍有多大
例如給你一些數據讓你分析一個城市的經濟發展水平,或者給出數據讓你選擇有價證券,亦或分析壟斷行業的價格與服務。需要用到數據統計模型和優化模型。不會涉及很深的專業知識,也不必刻意去了解多少經濟方面的知識,要知道中國數學建模大賽是全國各高校各專業學生皆可參加的競賽。你只要了解並且能夠熟練運用數學建模的幾種基本模型就可以(建模時也就用這幾種模型,就算過多的運用專業知識也未必得高分,因為這個競賽比的是把實際問題抽象成數學問題的能力,而非專業技巧)。
這幾種基本模型有:優化模型、微分方程模型、統計模型、概率模型、圖論模型、決策模型。
在這幾種模型中貫穿著以下幾種演算法(下面我就復制粘貼了):
1、蒙特卡羅演算法(該演算法又稱隨機性模擬演算法,是通過計算機模擬來解決問題的算
法,同時可以通過模擬可以來檢驗自己模型的正確性,是比賽時必用的方法)
2、數據擬合、參數估計、插值等數據處理演算法(比賽中通常會遇到大量的數據需要
處理,而處理數據的關鍵就在於這些演算法,通常使用Matlab作為工具)
3、線性規劃、整數規劃、多元規劃、二次規劃等規劃類問題(建模競賽大多數問題
屬於最優化問題,很多時候這些問題可以用數學規劃演算法來描述,通常使用Lindo、
Lingo軟體實現)
4、圖論演算法(這類演算法可以分為很多種,包括最短路、網路流、二分圖等演算法,涉
及到圖論的問題可以用這些方法解決,需要認真准備)
5、動態規劃、回溯搜索、分治演算法、分支定界等計算機演算法(這些演算法是演算法設計
中比較常用的方法,很多場合可以用到競賽中)
6、最優化理論的三大非經典演算法:模擬退火法、神經網路、遺傳演算法(這些問題是
用來解決一些較困難的最優化問題的演算法,對於有些問題非常有幫助,但是演算法的實
現比較困難,需慎重使用)
7、網格演算法和窮舉法(網格演算法和窮舉法都是暴力搜索最優點的演算法,在很多競賽
題中有應用,當重點討論模型本身而輕視演算法的時候,可以使用這種暴力方案,最好
使用一些高級語言作為編程工具)
8、一些連續離散化方法(很多問題都是實際來的,數據可以是連續的,而計算機只
認的是離散的數據,因此將其離散化後進行差分代替微分、求和代替積分等思想是非
常重要的)
9、數值分析演算法(如果在比賽中採用高級語言進行編程的話,那一些數值分析中常
用的演算法比如方程組求解、矩陣運算、函數積分等演算法就需要額外編寫庫函數進行調
用)
10、圖象處理演算法(賽題中有一類問題與圖形有關,即使與圖形無關,論文中也應該
要不乏圖片的,這些圖形如何展示以及如何處理就是需要解決的問題,通常使用Matlab
進行處理)
我今年9月份要參加數學建模,希望和你相互交流,共同進步!
6. cet-4網考模擬系統怎麼用
進真題演練,伺服器地址寫211.161.1.5,先注冊個號再進入,是模擬的,所以不一定打真實信息,但要記住用戶名和密碼啊···
1 自動組卷演算法比較
實現自動組卷是CET-4在線模擬考試系統的核心。隨機抽取法和回溯試探法是過去經常被使用的自動組卷演算法,但都存在著嚴重的不足。隨機抽取法具有很大的隨意性和不確定性。回溯試探法雖然組捲成功率遠遠高於隨機抽取法,但其組卷效率並不高。遺傳演算法是在結合以上兩種演算法基礎上所得到的一種新的改進演算法,它是一種並行的、能夠有效優化的演算法[1],具有簡單通用、魯棒性強、全局尋優、收斂速度快等特點。
2 遺傳演算法的基本步驟
遺傳演算法的基本步驟主要包括編碼、初始化群體、適應度計算、選擇、交叉和變異。
3 基於遺傳演算法組卷的關鍵技術
將遺傳演算法應用於組卷,關鍵技術就在於遺傳演算法的基本步驟在組卷中的實現。
3.1 編碼方案
7. 線性演算法是指什麼樣演算法請舉幾個例子。類似於進化演算法就是指遺傳演算法,人工免疫演算法等。
這里說的線性演算法應該是從時間復雜度方面來說的,相對於進化演算法的話。
即在線性時間或 Ο(n)時間內能求得問題最優解的演算法,統稱為線性演算法。比如說動態規劃法、分治法、回溯法、遞歸法等。
供參考
8. 遺傳演算法,回溯演算法,貪心演算法以及動態規劃是什麼通俗點
回溯就是不斷的嘗試各種可能,貪心就是一直往下走,拿最優的,答案不一定就是全局最優。動態規劃就是枚舉最優的子狀態得到當前狀態...具有階段性,答案保證是全局最優的。但用空間換時間
9. 遺傳演算法求解背包問題的程序
1樓的不是遺傳演算法吧!
剛好做過這個遺傳演算法解背包問題的論文,給你回答啦~~獨家哦,分數要給偶~~
1、程序開發環境
開發環境:Visual C++6.0 (把Fortran程序改為VC)
操作系統:Windows 2003 Professional
2、程序性能對比
運行時間與加速比(如表1所示)
進程數p(個) 1 2 4
運行時間t(秒) 129s 78s 38s
加速比s 1.65 3.38
表1、運行時間與加速比
3、程序運行結果:
實例數據:
假設物體的重量Weight、物體的收益Profit和背包的容量Contain 分別為:
Weight={ 80,82,85,70,72, 70,66,50,55,25 ,
50,55,40,48,50, 32,22,60,30,32 ,
40,38,35,32,25, 28,30,22,50,30 ,
45,30,60,50,20 , 65,20,25,30,10 ,
20,25,15,10,10 , 10,4, 4, 2, 1 }
Profit={ 220,208,198,192,180, 180,165,162,160,158,
155,130,125,122,120 , 118,115,110,105,101,
100,100,98, 96, 95, 90, 88, 82, 80, 77 ,
75, 73, 72, 70, 69, 66, 65, 63, 60, 58,
56, 50, 30, 20, 15, 10, 8, 5, 3, 1}
Contain=1000,
如何選擇哪些物品裝入該背包可使得在背包的容量約束限制之內所裝物品的總價值最大?
傳統的演算法(動態規劃、遞歸回溯法和貪心演算法所得結果:
總價值為3077 , 總重量為999。
2001年張鈴,張鈸教授在計算機學報上發表的《佳點集遺傳演算法》所得結果
總價值為3103, 總重量為1000。
我們演算法所得結果: 總價值為3103, 總重量為1000。
我們所求得最優解的個體分配情況為:
11010 10111 10110 11011 01111 11101 00001 01001 10000
01000
演算法 最大迭代次數 總價值為 總重量為
傳統的演算法 400 3077 999
佳點集演算法 70 3103 1000
遺傳演算法 75 3103 1000
// knapsack.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <AfxWin.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <conio.h>
#include <stdio.h>
// 重要常量參數
#define popsize 200 //種群的規模
#define pc 0.618 //雜交概率
#define pm 0.03 //變異概率
#define lchrom 50 //染色體長度
#define maxgen 1000 //最大進化代數
struct population
{
unsigned int chrom[lchrom]; //染色體
double weight; //背包重量
double fitness; //適應度
unsigned int parent1,parent2,cross; //雙親、交叉點
};
//新生代種群、父代種群
struct population oldpop[popsize],newpop[popsize];
//背包問題中物體重量、收益、背包容量
int weight[lchrom],profit[lchrom],contain;
//種群的總適應度、最小、最大、平均適應度
double sumfitness,minfitness,maxfitness,avgfitness;
//計算適應度時使用的 懲罰函數系數
double alpha;
//一個種群中最大和最小適應度的個體
int minpop,maxpop;
/* 讀入背包信息,並且計算懲罰函數系數 */
void read_infor()
{
FILE *fp;
int j;
//獲取背包問題信息文件
if ((fp=fopen("knapsack.txt","r"))==NULL)
{
//讀取文件失敗
AfxMessageBox("The file is not found",MB_OK,NULL);
return;
}
//讀入物體收益信息
for (j=0;j<lchrom;j++)
{
fscanf(fp,"%d",&profit[j]);
}
//讀入物體重量信息
for (j=0;j<lchrom;j++)
{
fscanf(fp,"%d",&weight[j]);
}
//讀入背包容量
fscanf(fp,"%d",&contain);
fclose(fp);
}
//根據計算的個體重量,判斷此個體是否該留在群體中
double cal_weight(unsigned int *chr)
{
int j;
double pop_weight;//背包重量
pop_weight=0;
for (j=0;j<lchrom;j++)
{
pop_weight=pop_weight+(*chr)*weight[j];
chr++;
}
return pop_weight;
}
/* 種群中個體適應度計算*/
double cal_fit(unsigned int *chr)
{
int j;
double pop_profit;//適應度
pop_profit=0;
// pop_weight=0;
for (j=0;j<lchrom;j++)
{
pop_profit=pop_profit+(*chr)*profit[j];
// pop_weight=pop_weight+(*chr)*weight[j];
chr++;
}
return pop_profit;
}
/* 群體適應度的最大最小值以及其他信息 */
void statistics(struct population *pop)
{
int i;
double tmp_fit;
sumfitness=pop[0].fitness;
minfitness=pop[0].fitness;
minpop=0;
maxfitness=pop[0].fitness;
maxpop=0;
for (i=1;i<popsize;i++)
{
//計算種群的總適應度
sumfitness=sumfitness+pop[i].fitness;
tmp_fit=pop[i].fitness;
//選擇種群中最大適應度的個體
if ((tmp_fit>maxfitness)&&((int)(tmp_fit*10)%10==0))
{
maxfitness=pop[i].fitness;
maxpop=i;
}
//選擇種群中最小適應度的個體
if (tmp_fit<minfitness)
{
minfitness=pop[i].fitness;
minpop=i;
}
//計算平均適應度
avgfitness=sumfitness/(float)popsize;
}
// printf("\nthe max pop = %d;",maxpop);
// printf("\nthe min pop = %d;",minpop);
// printf("\nthe sumfitness = %f\n",sumfitness);
}
//報告種群信息
void report(struct population *pop,int gen)
{
int j;
int pop_weight=0;
printf("the generation is %d.\n",gen); //輸出種群的代數
//輸出種群中最大適應度個體的染色體信息
printf("The population's chrom is: \n");
for (j=0;j<lchrom;j++)
{
if (j%5==0)
{ printf(" ");}
printf("%1d",pop[maxpop].chrom[j]);
}
//輸出群體中最大適應度
printf("\nThe population's max fitness is %d.",(int)pop[maxpop].fitness);
printf("\nThe knapsack weight is %d.\n\n",(int)pop[maxpop].weight);
}
/* 生成初始種群 */
void initpop()
{
int i,j,ispop;
double tmpWeight;
//變數用於判斷是否為滿足條件的個體
ispop=false;
//生成popsize個種群個體
for(i=0;i<popsize;i++)
{
while (!ispop)
{
for(j=0;j<lchrom;j++)
{
oldpop[i].chrom[j]=rand()%2; //隨機生成個體的染色體
oldpop[i].parent1=0; //雙親
oldpop[i].parent2=0;
oldpop[i].cross=0; //交叉點
}
//選擇重量小於背包容量的個體,即滿足條件
tmpWeight=cal_weight(oldpop[i].chrom);
if (tmpWeight<=contain)
{
oldpop[i].fitness=cal_fit(oldpop[i].chrom);
oldpop[i].weight=tmpWeight;
oldpop[i].parent1=0;
oldpop[i].parent2=0;
oldpop[i].cross=0;
ispop=true;
}
}
//此個體可以加入到種群中
ispop=false;
}
}
/* 遺傳操作 */
//概率選擇試驗
int execise(double probability)
{
double pp;
//如果生成隨機數大於相應的概率則返回真,否則試驗不成功
pp=(double)(rand()%20001/20000.0);
if (pp<=probability) return 1;
return 0;
}
// 選擇進行交叉操作的個體
int selection(int pop)
{
double wheel_pos,rand_Number,partsum;
int parent;
//賭輪法選擇
rand_Number=(rand()%2001)/2000.0;
wheel_pos=rand_Number*sumfitness; //賭輪大小
partsum=0;
parent=0;
do{
partsum=partsum+oldpop[parent].fitness;
parent=parent+1;
} while (partsum<wheel_pos && parent<popsize);
return parent-1;
}
/* 交叉操作 */
int crossover(unsigned int *parent1,unsigned int *parent2,int i)
{
int j,cross_pos;
if (execise(pc))
{
//生成交叉位置0,1,...(lchrom-2)
cross_pos=rand()%(lchrom-1);
}
else cross_pos=lchrom-1;
for (j=0;j<=cross_pos;j++)
{ //保留復制;
//包括在概率選擇不成功時,父體完全保留
newpop[i].chrom[j]=parent1[j];
}
for(j=cross_pos+1;j<=(lchrom-1);j++)
{
//從交叉點開始交叉
newpop[i].chrom[j]=parent2[j];
}
//記錄交叉位置
newpop[i].cross=cross_pos;
return 1;
}
/* 變異操作 */
int mutation(unsigned int alleles)
{
if (execise(pm))
{
if (alleles)
alleles=0;
else alleles=1;
}
//返回變異值,或者返回原值
return alleles;
}
/* 群體更新 */
void generation()
{
unsigned int i,j,mate1,mate2;
double tmpWeight;
int ispop;//記錄是否是符合條件的個體
i=0;
while (i<popsize)
{
ispop=false;
while (!ispop)
{
//選擇
mate1=selection(i);
mate2=selection(i+1);
//交叉
crossover(oldpop[mate1].chrom,oldpop[mate2].chrom,i);
//變異
for (j=0;j<lchrom;j++)
{
newpop[i].chrom[j]=mutation(newpop[i].chrom[j]);
}
//選擇重量小於背包容量的個體,即滿足條件
tmpWeight=cal_weight(newpop[i].chrom);
if (tmpWeight<=contain)
{
newpop[i].fitness=cal_fit(newpop[i].chrom);
newpop[i].weight=tmpWeight;
newpop[i].parent1=mate1;
newpop[i].parent2=mate2;
ispop=true;
}
}
//此個體可以加入到種群中
i=i+1;
}
}
void main(int argc, char* argv[])
{
int gen,oldmaxpop,k;
double oldmax;
read_infor();//讀入背包信息
gen=0;
srand( (unsigned)time( NULL ) );//置隨機種子
initpop();
memcpy(&newpop,&oldpop,popsize*sizeof(struct population));
statistics(newpop);//統計新生種群的信息
report(newpop,gen);
while(gen<maxgen)
{
gen=gen+1;
if (gen%100==0)
{
srand( (unsigned)time( NULL ) );//置隨機種子
}
oldmax=maxfitness;
oldmaxpop=maxpop;
generation();
statistics(newpop); //統計新生代種群信息
//如果新生代種群中個體的最大適應度小於老一代種群
//個體的最大適應度,則保存老一代種群個體的最大適應度
//否則報告新生代的最大適應度
if (maxfitness<oldmax)
{
for(k=0;k<lchrom;k++)
newpop[minpop].chrom[k]=oldpop[oldmaxpop].chrom[k];
newpop[minpop].fitness=oldpop[oldmaxpop].fitness;
newpop[minpop].parent1=oldpop[oldmaxpop].parent1;
newpop[minpop].parent2=oldpop[oldmaxpop].parent2;
newpop[minpop].cross=oldpop[oldmaxpop].cross;
statistics(newpop);
}
else if (maxfitness>oldmax)
{
report(newpop,gen);
}
//保存新生代種群的信息到老一代種群信息空間
memcpy(&oldpop,&newpop,popsize*sizeof(struct population));
}
printf("It is over.");
getch();
}