遺傳算法(一)基本遺傳算法(SGA)及MATLAB源碼

遺傳算法(Genetic Algorithm)是常用的智能算法的一種,遺傳算法GA(Genetic Algorithm)入門知識梳理 對GA進行了詳盡的基本介紹,其結尾附的七個鏈接也讓人很有啓發。本文附上自己對遺傳算法的學習理解與代碼實現。

//挖坑


根據遺傳算法基礎知識,寫出僞代碼如下:

Initialization();
while less than maximum iterations
    Crossover(parent, pCross) -> childrenCross
    Mutation(parent, pMutation) -> childrenMutate
    [childrenCross; cihldrenMutate] -> children
    Calculate the fitness of children
    select(children) -> parent
    if Satisfy terminal condition
        break
    end
end

整體思路可以說是比較簡單,生成種羣->交叉、變異->遺傳(自然選擇)->下一代。生成種羣需要一定的編碼技巧(挖坑,以後填)。


下面給出具體MATLAB代碼實現:

%%
%編碼方式: 基本二進制編碼
%Input:     FitFunc:    Any function
%           pCrossover: probability of crossover, default 0.5
%           pMutation:  probability of mutation,  default 0.04
%           GroupNum:   number of individuals of the virtual group, default 30
%           MaxIter:    maximum iterations
%           MaxRepeat:  (optional)determine the convergence standard 判斷收斂
%parent.fitness
%parent.chrom

function Result = MyGA(FitFunc, pCrossover, pMutation, GroupNum, MaxIter, MaxRepeat)
    %Default parameters
    if nargin < 6
        MaxRepeat = 10;
        if nargin < 5
            MaxIter = 1000;
            if nargin < 4
                GroupNum = 50;
                if nargin < 3
                    pMutation = 0.04;
                    if nargin < 2
                        pCrossover = 0.5;
                    end
                end
            end
        end
    end

    Result  =  [];
    epsilon =  1e-5;
    iter    =  0;
    iRepeat =  1;
    bit     =  22;
    thisMax =  0;
    parent  =  InitGroup(GroupNum, FitFunc, bit);   %Generate initial population
    while iter < MaxIter
        children1 = Crossover(parent, pCrossover/iter^0.1);  %Return crossovered chromes
        children.chrom = [];
        children.fitness = [];
        children.chrom = Mutation([parent.chrom; children1], pMutation/iter^0.1);
        children.fitness = CalcFit(children.chrom, FitFunc, bit);
        children = select(children, GroupNum);
        parent = children;
        iter = iter + 1;
        %parent.chrom;
        %[m, I] = max(parent.fitness)
        if (thisMax-max(parent.fitness))/max(parent.fitness) < epsilon
            iRepeat = iRepeat + 1;
        else 
            iRepeat = 1;
        end
        thisMax = max(parent.fitness);
        disp(thisMax)
        Result = [Result; thisMax];
    end
end

%Encoding method: 普通二進制編碼
function parent = InitGroup(GroupNum, FitFunc, bit)
    parent.fitness = [];
    parent.chrom = [];
    for i = 1:GroupNum
        item = dec2bin(fix(rand*2^bit));
        while size(item, 2) < bit
           item = ['0', item];
        end
        parent.chrom = [parent.chrom; item];
    end
    parent.fitness = CalcFit(parent.chrom, FitFunc, bit);
end

%User Define 自定義解碼方式
function Decode = Decoding(Population, bit)
    Decode = bin2dec(Population) * 2 / (2^bit)+1;
end

%Calculate Fitness
function Fitness = CalcFit(Population, Fun, bit)
    DecodedPop = Decoding(Population, bit);
    Fitness = Fun(DecodedPop);
end

%roulette selcting method
function newPop = select(parent, PopNum)
    %Add: The best survive?
    cumFit = cumsum(parent.fitness)/sum(parent.fitness);
    %[M, I] = max(parent.fitness);
    %newPop.chrom(1,:) = parent.chrom(I, :);
    %newPop.fitness = parent.fitness(I);
    for i = 1 : PopNum
         index = find (cumFit - rand > 0);
         newPop.chrom(i,:) = parent.chrom(index(1),:);
         newPop.fitness(i) = parent.fitness(index(1));
    end
end

function childrenChrom = Crossover(parent, pCrossover)
    [PopNum, bit] = size(parent.chrom);
    childrenChrom = [];
    %[M, I] = max(parent.fitness);
    %childrenChrom = parent.chrom(I, :); %Parent with highest fitness
    for i = 1 : PopNum/2
        RandCross = rand(1);
        if RandCross < pCrossover
            i = fix(rand(1)*PopNum + 1);
            j = fix(rand(1)*PopNum + 1);
            while i == j
                i = fix(rand(1)*PopNum + 1);
                j = fix(rand(1)*PopNum + 1);
            end 
            BreakPoint = fix(rand(1)*bit + 1);
            temp = parent.chrom(i, 1:BreakPoint);
            parent.chrom(i, 1:BreakPoint) = parent.chrom(j, 1:BreakPoint);
            parent.chrom(j, 1:BreakPoint) = temp;
            childrenChrom = [childrenChrom; parent.chrom(i, :); parent.chrom(j, :)];
        end
    end
end

function childrenChrom = Mutation(chrom, pMutation)
    [PopNum, bit] = size(chrom);
    childrenChrom = chrom;
    for i = 1:PopNum
        for j = 1:bit
            if rand < pMutation
                childrenChrom(i, j) = '1'-childrenChrom(i, j)+'0';
            end
        end
    end   
end

解幾個簡單的例子

簡單一元函數

y=x×sin(x)

[1,3] 區間上,用MATLAB求得在x=2.0288 時函數有最大值1.8197

a

此函數在指定區間上只有一個最大值,用遺傳算法可以很容易地得到結果。

MyGA(@myFun)

其中myFun爲上文所述的函數,即爲遺傳算法中的適應度函數。

MyGA(@myFun);
    1.8185
    1.8123
    1.8184
    1.8193
    1.8193
    1.8193
    1.8193
    1.8195
    1.8196
    1.8196
    1.8196
    1.8196
    1.8196
    1.8196
    1.8194
    1.8196
    1.8196
    1.8196
    1.8197
    1.8196
    1.8196
    1.8196
    1.8197
    1.8197
iter =
    25

隨機選擇一組輸出如上所示。其中定義算法收斂的相對誤差限epsilon爲1×103

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