《遺傳算法(GA)的MATLAB實現》

一、案例引入

f(x)=200e0.05xsinx,x[2,2] 的最大值




二、使用MATLAB事先探測出該函數的最大值的大概位置

PS:使用MATLAB繪圖窗口中的“工具->數據遊標”即可手動探測出函數最大值所在的大致座標.

繪圖代碼:

%detect.m

x = -2:0.001:2;
y = 200*exp(-0.05*x).*sin(x);
plot(x,y)
grid on;



preGA




三、源代碼

目標函數

(注:對於優化問題中的最大值或極大值問題,可以直接將目標函數當作適應度函數)

%targetFun.m

function y = targetFun(x);

y = 200*exp(-0.05*x).*sin(x);


將一個二進制串轉換爲十進制數

%transform2To10.m

function y = transform2To10(x);

bitLength = size(x, 2);
y = x(bitLength);
for i = 1:bitLength-1
    y = y + x(bitLength-i)*power(2, i);
end


計算種羣中每個個體的染色體的適應度,結果存放在fitValue中;

計算種羣中每個個體的染色體被複制的累積概率,結果存放在cumsumP中

%fitnessFun.m

function [fitValue, cumsumP] = fitnessFun(population);

global bitLength;
global boundsBegin;
global boundsEnd;

popSize = size(population, 1); %種羣中個體的個數

for i = 1:popSize
    x = transform2To10(population(i,:));
    xx = boundsBegin + x * (boundsEnd - boundsBegin)/(power(2,bitLength)-1);
    fitValue(i) = targetFun(xx);
end

fitValue = fitValue' + 230;
fSum = sum(fitValue);
pPerPop = fitValue/fSum;

cumsumP(1) = pPerPop(1);
for i = 2:popSize
    cumsumP(i) = cumsumP(i-1) + pPerPop(i);
end


進行選擇操作(從原種羣中選擇出兩個個體的染色體),以便得到新種羣

%selectTwo.m

function selTwo = selectTwo(population, cumsumP);

for i=1:2
    r = rand;
    prand = cumsumP - r;

    j = 1;
    while prand(j)<0
        j = j + 1;
    end
    selTwo(i) = j;
end


決定在遺傳運算中是否需要進行交叉或變異過程

%ifCroIfMut.m

function p = ifCroIfMut(croOrMut);

test(1:100) = 0;
l = round(100*croOrMut);
test(1:l) = 1;
n = round(rand*99)+1;

p = test(n);


根據選擇出的兩個個體(這兩個個體在新種羣中)的染色體以及交叉概率進行交叉過程的到兩個子代染色體

%crossoverTwo.m

function cTwo = crossoverTwo(population, selTwo, pC);

bitLength = size(population, 2);

p = ifCroIfMut(pC);

if p == 1
    choice = round(rand*(bitLength-2))+1;
    cTwo(1,:) = [population(selTwo(1),1:choice) population(selTwo(2), choice+1:bitLength)];
    cTwo(2,:) = [population(selTwo(2),1:choice) population(selTwo(1), choice+1:bitLength)]; 
else
    cTwo(1,:) = population(selTwo(1),:);
    cTwo(2,:) = population(selTwo(2),:); 
end


根據選擇出的一個個體(這個個體在新種羣中)的染色體以及變異概率進行變異過程

%mutateOne.m

function new = mutateOne(old, pM);

bitLength = size(old,2);
new = old;

p = ifCroIfMut(pM);
if p == 1
    choice = round(rand*(bitLength-1)) + 1;
    new(choice) = abs(old(choice)-1);
end


主體求解代碼:

%GA.m

global bitLength;
global boundsBegin;
global boundsEnd;

bounds = [-2 2];
precision = 0.0001;
boundsBegin = bounds(:,1);
boundsEnd = bounds(:, 2);

bitLength = ceil(log2((boundsEnd - boundsBegin)'/precision));

popSize = 50;
generationN = 12;
pCrossover = 0.90;
pMutation = 0.09;

population = round(rand(popSize, bitLength));
[fitValue, cumsumP] = fitnessFun(population);

generation = 1;
while generation < generationN + 1
    for j = 1:2:popSize
        %選擇兩個個體
        selTwo = selectTwo(population, cumsumP);
        %交叉兩個個體
        cTwo = crossoverTwo(population, selTwo, pCrossover);
        cNew(j,:) = cTwo(1,:);
        cNew(j+1,:) = cTwo(2,:);
        %變異兩個個體
        mNew(j,:) = mutateOne(cNew(j,:), pMutation);
        mNew(j+1,:) = mutateOne(cNew(j+1,:), pMutation);
    end

    population = mNew;
    [fitValue, cumsumP] = fitnessFun(population);
    [fMax, nMax] = max(fitValue); %nMax爲fitValue中所有元素的最大值fMax在向量fitValue中的索引
    fMean = mean(fitValue);  %求得fitValue中所有元素的平均值

    yMax(generation) = fMax;
    yMean(generation) = fMean;
    x = transform2To10(population(nMax,:));
    xx = boundsBegin + x * (boundsEnd - boundsBegin)/(power(2,bitLength)-1);
    xMax(generation) = xx;
    generation = generation + 1;
end

generation = generation - 1;
bestPopulation = xx;
bestTargetFunValue = targetFun(xx);

figure(1);
hand1 = plot(1:generation, yMax);
set(hand1,'linestyle', '-','linewidth', 1.8,'marker', '*', 'markersize', 6);
hold on;

hand2 = plot(1:generation, yMean);
set(hand2,'color', 'r','linestyle', '-','linewidth', 1.8,'marker', 'h', 'markersize', 6);

xlabel('進化代數'); ylabel('最大/平均適應度'); xlim([1 generationN]);
legend('最大適應度', '平均適應度');

box off; hold off;



四、求解結果



GA

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章