摘要:遺傳算法物競天擇,適者生存,遺傳算法就是借鑒生物體自然選擇和自然遺傳機(jī)制的隨機(jī)搜索算法。隨機(jī)生成的基因適應(yīng)度的最大值隨機(jī)生成,適應(yīng)度函數(shù)計算種群中所有對象的適應(yīng)度及總和,并對超出的基因進(jìn)行懲罰。
此為《算法的樂趣》讀書筆記,我用javascript(ES6)重新實(shí)現(xiàn)算法。
遺傳算法“物競天擇,適者生存”,遺傳算法就是借鑒生物體自然選擇和自然遺傳機(jī)制的隨機(jī)搜索算法。算法的關(guān)鍵點(diǎn)有:基因的選擇與編碼、適應(yīng)度評估函數(shù)與三個遺傳算子(選擇、交叉和變異)的設(shè)計。
0-1背包問題有一個背包,最多承重為C=150的物品,現(xiàn)在有7個物品,編號為1~7,重量分別是w=[35,30,60,50,40,10,25],價值分別是p=[10,40,30,50,35,40,30],現(xiàn)在從這7個物品中選擇一個或多個裝入背包,要求在物品總重量不超過C的前提下,所裝入的物品總價值最高。
代碼及思路該算法采用屬性序列方式對基因編碼,遺傳算子則使用了比例選擇模式、多點(diǎn)交叉和均勻變異三種方式,麻雀雖小,五臟具全。
變量定義var C = 150 //背包最大承重 var WEIGHT = [35,30,60,50,40,10,25] //物品重量 var POWER = [10,40,30,50,35,40,30] //物品價值 var LEN = 7 //基因長度 var maxPower = 0 //保存最大值方案 var maxGene = [] var maxi = 0; //最大值最初出現(xiàn)的進(jìn)化代數(shù) const POPMAX = 32, //種群數(shù)量 P_XOVER = 0.8, //遺傳概率 P_MUTATION = 0.15, //變異概率 MAXGENERATIONS = 20 //總的進(jìn)化代數(shù) var pop = [] //種群所有對象基因編碼
基因由7件物品狀態(tài)組成,1表示裝入,0表示不裝入;每個個體除了基因外,還有適應(yīng)度、選擇概率和積累選擇概率。類定義如下:
class Gene{ constructor(gene){ this.gene = gene; //基因,數(shù)組 this.fitness = 0; this.rf = 0; this.cf = 0; } }種群初始化
每個個體選擇隨機(jī)的基因,使用0,1隨機(jī)數(shù)直接填充gene數(shù)組。因?yàn)檫@個具體問題規(guī)模較小,在選擇時我丟棄了適應(yīng)度較高的方案,以此來更好的測試算法的效果。
function initGenes(){ let count = 0, maxFit = 100; //隨機(jī)生成的基因適應(yīng)度的最大值 while(count < POPMAX){ let tmp = [],pall = 0; for(let j = 0; j適應(yīng)度函數(shù) 計算種群中所有對象的適應(yīng)度及總和,并對超出C的基因進(jìn)行“懲罰”。
function envaluateFitness(max){ //max參數(shù)只是用來記錄進(jìn)化代數(shù) let totalFitness = 0; for(let i=0; i選擇算子函數(shù)C){ //基因不符合要求,適應(yīng)降到1,讓其自然淘汰 pop[i].fitness = 1; }else{ if(pop[i].fitness > maxPower){ //保存階段最優(yōu)值 maxPower = pop[i].fitness; maxGene = __.cloneDeep(pop[i].gene); //使用lodash庫 maxi = max; } } totalFitness += pop[i].fitness } return totalFitness; } 采用簡單的輪盤賭方式進(jìn)行選擇,首先計算種群中所有個體的選擇概率和累積概率,然后利用隨機(jī)數(shù)進(jìn)行“輪盤賭”,挑出幸運(yùn)者作為新種群。這里有個坑,lodash的cloneDeep直接克隆pop會有問題,出現(xiàn)怪異問題,難道是我的對象層次太深,求解!
function selectBetter(totalFitness){ let lastCf = 0; let newPop = [] for(let i = 0; i交叉算子函數(shù)= pop[j].cf && p < pop[j+1].cf){ newPop[i] = pop[j+1]; break; } } } } pop = [] //種群替換,坑在這,直接 pop=__.cloneDeep(newPop)不對,高手給解釋下,誰研究過lodash的源碼? for(let i=0; i< newPop.length; i++){ pop.push(__.cloneDeep(newPop[i])) } } 交叉算子采用多點(diǎn)交叉策略,對兩個隨機(jī)選中的個體基因進(jìn)行交換,基因交換的位置和個數(shù)都是隨機(jī)的,使得新個體的基因更具有隨機(jī)性。
function crossover(){ let first = -1; for(let i=0; i變異算子函數(shù) 變異算子采用均勻變異的策略,選中個體基因變異的個數(shù)與位置都是隨機(jī)選擇的。
function mutation(){ for(let i=0; i算法主流程 主流程很簡單,幾乎是線性的。
initGenes(); var f = envaluateFitness(0) for(let i=0; i總結(jié)" + maxGene.join(",")); 以前一直覺得遺傳算法很神秘,因此仔細(xì)研究了一下,覺得算法的效果很大程度上取決于各種參數(shù)的設(shè)定。另外,也許進(jìn)化過程中出現(xiàn)過最優(yōu)值,但最后的種群中也不一定會有最優(yōu)值存在。真是能用其它方法可以解決時最好不用它,呵呵!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/79264.html
摘要:編碼需要將問題的解編碼成字符串的形式才能使用遺傳算法。遺傳算子遺傳算法有個最基本的操作選擇,交叉,變異。實(shí)驗(yàn)發(fā)現(xiàn),比較大的種群的規(guī)模并不能優(yōu)化遺傳算法的結(jié)果。災(zāi)變遺傳算法的局部搜索能力較強(qiáng),但是很容易陷入局部極值。 一、遺傳算法進(jìn)化論背景知識 作為遺傳算法生物背景的介紹,下面內(nèi)容了解即可: 種群(Population):生物的進(jìn)化以群體的形式進(jìn)行,這樣的一個群體稱為種群。 個體:組成...
摘要:是一個遺傳算法框架,這里是它的簡介。最小化問題使用負(fù)值的的最大化問題用正值。略種群種群橫線個體。這個種群是直接使用和函數(shù)來初始化的。個體之間分布在網(wǎng)格中每個格子包含一個個體。調(diào)用將會返回一個種群,個體是使用兩個索引可獲得的。 DEAP是一個python遺傳算法框架,這里是它的簡介。DEAP documentation今天整理一下DEAP的概覽,大體了解一下它的流程。初學(xué),不嚴(yán)謹(jǐn),僅作為...
閱讀 2559·2021-11-22 09:34
閱讀 3538·2021-11-15 11:37
閱讀 2340·2021-09-13 10:37
閱讀 2104·2021-09-04 16:40
閱讀 1563·2021-09-02 15:40
閱讀 2456·2019-08-30 13:14
閱讀 3325·2019-08-29 13:42
閱讀 1902·2019-08-29 13:02