基於實數編碼的參數自適應遺傳算法(matlab代碼)

 實數編碼的遺傳算法尋優:

遺傳算法的基本操作算子:

(1)選擇算子

      選擇算子的作用主要是避免優良基因的丟失,使得性能高的個體能以更大的概率被選中,有機會作爲父代繁殖下一代,從而提  高遺傳算法的全局收斂性及計算效率。常見的選擇算子包括輪盤賭選擇法、隨機遍歷抽樣法、局部選擇法及錦標賽選擇法等。選擇算子採用輪盤賭;

(2)交叉算子

       在遺傳算法中,交叉算子是區別於其它優化算法的本質特徵,用於組合新的個體在解空間中快速有效地進行搜索,同時也降低了對有效模式的破壞程度,起到全局搜索尋優的效果。交叉算子直接影響着遺傳算法的最終搜索效果,一定程度上決定了其發展前景。

其中alpha爲參數,0<alpha<1

(3)變異算子

      羣體基因的多樣性是保證遺傳算法尋找到全局最優解的前提條件,然而在進化過程中,遺傳選擇操作削弱了羣體的多樣性,上述交叉算子只有滿足一定的條件才能保持羣體的多樣性,而變異操作則是保持羣體多樣性的有效算子,所以變異操作算子的選取也是必不可少的。變異尺度自適應變化的變異算子在進化初期採用較大的變異尺度來保持羣體的多樣性,而在後期變異尺度將逐漸縮小以提高局部微調能力。本文在此基礎上做些改進,改進後的變異算子具有原有算子的優點,且操作上比原有算子簡單方便,有效地加快遺傳算法的收斂速度,具體如下:

可以看出s(t) 決定了變異空間的大小,在迭代的初期,變異空間較大,在迭代的後期,變異空間縮小,算法的局部尋優能力變強。

變異算子參考文獻:   [1] 管小豔. 實數編碼下遺傳算法的改進及其應用[D].重慶大學,2012.

參數自適應:

交叉概率Pc和變異概率Pm是遺傳算法的兩個重要的參數,這兩個參數決定了每個個體進行交叉或者變異操作的概率。

 

自適應算子參考文獻:

[2] M. Srinivas and L. M. Patnaik, "Adaptive probabilities of crossover and mutation in genetic algorithms," in IEEE Transactions on Systems, Man, and Cybernetics, vol. 24, no. 4, pp. 656-667, April 1994.doi: 10.1109/21.286385

上述部分翻譯自文獻[2]

按照論文描述,對算法的復現如下:

% 測試函數圖像
% 測試函數圖像
% 改進的自適應遺傳算法:
% 參考文獻:[7] M. Srinivas and L. M. Patnaik, "Adaptive probabilities of crossover and mutation in genetic algorithms," 
%              in IEEE Transactions on Systems, Man, and Cybernetics, vol. 24, no. 4, pp. 656-667, April 1994.
%              doi: 10.1109/21.286385
clc;
clear all;
mode = 'Schaffer';
% mode = 'self_define';
if strcmp(mode, 'Schaffer')
    figure(1)
    x = -4:0.1:4;
    y = -4:0.1:4;
    [X,Y] = meshgrid(x,y);
    % Z = 3*cos(X.*Y)+X+Y.^2;
    Z = 0.5-((sin(sqrt(X.^2+Y.^2)).^2)-0.5)./(1+0.001.*(X.^2+Y.^2)).^2;
    surf(X,Y,Z);
    title('Schaffer Function');
    xlabel('X-軸');
    ylabel('Y-軸');
    zlabel('Z-軸');
    
    figure(2);
    contour(X, Y, Z, 8);
    title('Schaffer函數等高線');
    xlabel('X-軸');
    ylabel('Y-軸');
end

if strcmp(mode, 'self_define')
    figure(1);
    x = -4:0.1:4;
    y = -4:0.1:4;
    [X,Y] = meshgrid(x,y);
    % Z = 100.*(Y-X.^2).^2+(1-X).^2;
    Z = (cos(X.^2+Y.^2)-0.1)./(1+0.3*(X.^2+Y.^2).^2)+3;
    surf(X,Y,Z);
    %title('Rosen Brock valley Function');
    title('Self define Function');
    xlabel('X-軸');
    ylabel('Y-軸');
    zlabel('Z-軸');
end

clc;
clearvars -except mode;

r = 0.2;
b = 3;
NP=400;
% Pc=0.65;   % 將Pc,Pm參數改進爲自適應參數
% Pm=0.20;
G=520;    %        記得改
D=2;    % 變量個數

k1 = 1;
k3 = 1;

k2 = 0.5;
k4 = 0.5;

X_min=-4;
X_max=4;
Y_min=-4;
Y_max=4;
% optimization_trace = [];    % 三維數組, 行,列,葉
for count_1=1:NP  % 產生初始解
    temp1 = X_min+rand()*(X_max-X_min);
    temp2 = Y_min+rand()*(Y_max-Y_min);
    x(count_1,:) = [temp1,temp2];
end

save_pic_cnt = 1;
A = figure(3);

for gen=1:G
    %pause(0.2);
    if rem(gen, 100)==1
        scatter(x(:,1), x(:, 2));
        axis([-4, 4, -4, 4]);
        title(['第', num2str(gen), '次迭代']);
        xlabel('變量X');
        ylabel('變量Y');
        base_path = 'C:\Users\18811\Desktop\graph\';
        cnt = num2str(save_pic_cnt);
        tail_path = '.jpg';
        frame = getframe(A);
        im=frame2im(frame);
        path_img = [base_path, cnt, tail_path];
        % imwrite(im, path_img);
        % save_x(:, :, save_pic_cnt) = x;
        save_pic_cnt = save_pic_cnt + 1;
    end

    % scatter(0, 0, 'o', 'r');
    for count_2=1:NP
        fitness(count_2)=func(x(count_2,:), mode);
    end
    %[fitness_min,index0] = min(fitness);
    %fitness_max = max(fitness);
    [fitness_max,index0] = max(fitness);
    fitness_average = sum(fitness)/(length(fitness));  % 種羣的平均值
    collect_fit_average(gen) = fitness_average;   % 保存適應度的平均值
    collect_fitmax_subtract_fit_average(gen) = fitness_max - fitness_average;  % 保存f_max-f_average ;
    fitness_min = min(fitness);
    best_indiv = x(index0,:);  % 最優的個體
    % optimization_trace(gen,: , global_count) = best_indiv;
    % best_solution(gen) = fitness_min;
    best_solution(gen) = fitness_max;
    % 計算歸一化的適應度值
    fitness = (fitness - fitness_min)/(fitness_max - fitness_min);
    fitness_sum = sum(fitness);
    fitness = fitness./fitness_sum;
    fitness = cumsum(fitness);  

    % 選擇算子:
    ms = sort(rand(NP,1));
    fiti = 1;
    newi = 1;
    while newi<=NP
        if ms(newi)<fitness(fiti)
            clone_x(newi,:) = x(newi,:);
            newi = newi + 1;
        else
            fiti = fiti + 1;
        end
    end
    clone_x = clone_x(1:NP, :);
    % 進行交叉,變異操作
    % count=0;
    for count=1:2:NP
        % 自適應計算Pc.
        % 選區兩個交叉的個體的較大的適應度值
        if fitness(count)>=fitness(count+1)
            fitness_selected = fitness(count);
        else
            fitness_selected = fitness(count+1);
        end
        % 計算Pc
        if fitness_selected >= fitness_average
            Pc = k1*(fitness_max-fitness_selected)/(fitness_max-fitness_average);
        else
            Pc = k3;
        end
        collect_Pc(gen, count) = Pc;   % 保存Pc的值
        temp_cross = rand();
        if temp_cross < Pc
            % 交叉算子   注:這種交叉算子效果更好
            temp_alpha = 0.6;  
            cross_x(count,:) = temp_alpha*clone_x(count,:)+(1-temp_alpha)*clone_x(count+1,:);
            cross_x(count+1,:) = temp_alpha*clone_x(count+1,:)+(1-temp_alpha)*clone_x(count,:);
            % 改進的交叉算子  參考文獻:管小豔. 實數編碼下遺傳算法的改進及其應用[D].重慶大學,2012.   注:但這種交叉算子實際的效果不理想
            % temp_gama = rand();
            % temp_alpha = 0.98;
            % cross_x(count,:) = temp_alpha*clone_x(count,:)+(1-temp_alpha)*clone_x(count+1,:)+temp_gama*(clone_x(count,:)-clone_x(count+1,:));
            % cross_x(count+1,:) = temp_alpha*clone_x(count+1,:)+(1-temp_alpha)*clone_x(count,:)+temp_gama*(clone_x(count,:)-clone_x(count+1,:));
        else
            cross_x(count,:)=clone_x(count,:);
            cross_x(count+1,:)=clone_x(count+1,:);
        end
        % 邊界條件檢查
        if cross_x(count,1)>X_max || cross_x(count,1)<X_min || cross_x(count,2)>Y_max || cross_x(count,2)<Y_min
                temp1 = X_min+rand()*(X_max-X_min);
                temp2 = Y_min+rand()*(Y_max-Y_min);
                cross_x(count,:) = [temp1,temp2];
        end
    end
    cross_x = cross_x(1:NP,:);
    %   cross_x爲完成交叉的個體;
    % 變異操作
    for count=1:1:NP
        % 計算Pm
        if fitness(count)>=fitness_average
            Pm = k2*(fitness_max-fitness(count))/(fitness_max-fitness_average);
        else
            Pm = k4;
        end
        collect_Pm(gen,count) = Pm;     %  保存Pm的值
        temp_mutation=rand();
        if temp_mutation<Pm
            %mutation_x(count,:) = (1+0.01).*cross_x(count,:);       %這種變異算子效果不理想
            % 變異算子   參考文獻:管小豔. 實數編碼下遺傳算法的改進及其應用[D].重慶大學,2012       
            mutation_pos = randi(D);
            if mutation_pos==1
                low = X_min;
                high = X_max;
            else
                low = Y_min;
                high = Y_max;
            end
            s_t(gen) = 1-r^((1-gen/G)^b);
            new_low = cross_x(count, mutation_pos)-s_t(gen)*(cross_x(count, mutation_pos)-low);
            new_high = cross_x(count, mutation_pos)+s_t(gen)*(high-cross_x(count, mutation_pos));
            mutation_x(count, :) = cross_x(count, :);
            mutation_x(count, mutation_pos) = new_low+rand()*(new_high-new_low);
            if mutation_x(count,1)>X_max || mutation_x(count,1)<X_min || mutation_x(count,2)>Y_max || mutation_x(count,2)<Y_min
                temp1 = X_min+rand()*(X_max-X_min);
                temp2 = Y_min+rand()*(Y_max-Y_min);
                mutation_x(count,:) = [temp1,temp2];
            end
        else
            mutation_x(count,:) = cross_x(count,:);
        end        
    end
    %邊界條件處理
    x=mutation_x(1:NP, :);
    x(1,:)= best_indiv;
end
%% 作圖
figure(4)
plot(best_solution);
%hold on;
xlabel('進化代數');
ylabel('適應度值');
title('適應度進化曲線');

figure(5);
plot(collect_fitmax_subtract_fit_average);
title('f_{max}-f_{average}曲線');
xlabel('進化代數');
ylabel('f_{max}-f_{average}');

% function f=func(buf)
%     f=0.5-((sin(sqrt(buf(1).^2+buf(2).^2)).^2)-0.5)./(1+0.001.*(buf(1).^2+buf(2).^2)).^2;
% end

function f=func(buf, md)
    if strcmp(md, 'Schaffer')
        f=0.5-((sin(sqrt(buf(1).^2+buf(2).^2)).^2)-0.5)./(1+0.001.*(buf(1).^2+buf(2).^2)).^2;
    end
    
    if strcmp(md,'self_define')
        % f = 100*(buf(2)-buf(1).^2).^2+(1-buf(1)).^2;
        f = (cos(buf(1).^2+buf(2).^2)-0.1)./(1+0.3*(buf(1).^2+buf(2).^2).^2)+3;
    end
end

測試函數:

Schaffer函數:

運行結果:

種羣的分佈變化:

 

-----------------------------------------------------分割線----------------------------------------------------

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