遗传算法,其本质上是一种进化算法,相比其他的算法应用范围比较广泛,特别是对于一些非线性、多模型、多目标的函数优化问题,用其他的优化方法较难求解,而遗传算法可以方便的得到较好的结果。不过正如我在PSO粒子群算法的文章中说道,每种算法的应用场景往往和所应用的问题相关,对于特定的问题,某一种优化算法可能展现出其他算法所达不到的效果。

       想必遗传算法的原理大家都大概了解,这里就不过多赘述,总之也是一种在迭代中不断进化,探索,想最优情况靠近的一种迭代算法。遗传算法包括三个基本操作:选择、交叉和变异。不同改进的遗传算法,往往都是在这三个基本操作上进行改进。

       本文给出的是基本的遗传算法程序,同样也是引自龚纯的这本《精通MATLAB最优计算》,用于求取优化函数的最大值,当然求最小值的情况只需更改目标函数的正负即可。要注意的是,本算法是遗传算法的最基本的格式,只能用于解决一维无约束的优化问题。由于略去了很多操作的原理比如编码操作、轮盘赌选择策略、交叉方法,变异方法等,我在代码上加了详细的备注,由于代码本身并不复杂,需要的读者自己阅读一下即可理解。下面给出基本遗传算法函数的调用格式:

function [xv,fv]=myGA(fitness,a,b,NP,NG,Pc,Pm,eps)

        fitness是待优化函数,调用时可以自己编写后使用句柄调用,随后会举例展示调用的方法。除此之外的参数的意义分别是:

a:自变量下界;

b:自变量上界;

NP:种群大小;

Pc:杂交概率;

Pm:变异概率;

eps:自变量离散精度;

xm:目标函数取最大值时的自变量值;

fv:目标函数的最大值。

基本遗传算法的程序为:

function [xv,fv]=myGA(fitness,a,b,NP,NG,Pc,Pm,eps)

%待优化的目标函数:fitness
%自变量下界:a
%自变量上界:b
%种群个体数:NP
%最大进化代数:NG
%杂交概率:Pc
%变异概率:Pm
%自变量离散精度:eps
%目标函数取最小值时的自变量值:xm
%目标函数的最小值:fv

L = ceil(log2((b-a)/eps+1));               %根据离散精度,确定二进制编码需要的码长
x = zeros(NP,L);                           %NP行L列的全零矩阵
for i=1:NP
    x(i,:) = Initial(L);                   %种群初始化
    fx(i) = fitness(Dec(a,b,x(i,:),L));    %个体适应值
end
for k=1:NG
    sumfx = sum(fx);                       %所有个体适应值之和
    Px = fx/sumfx;                         %所有个体的选择概率
    PPx = 0;
    PPx(1) = Px(1);
    for i=2:NP                             %从第二个开始
        PPx(i) = PPx(i-1) + Px(i);         %轮盘赌策略的概率累加
    end
    for i=1:NP
        sita = rand();                     %sita是0,1之间的随机数
        for n=1:NP
            if sita <= PPx(n)
                SelFather = n;             %根据轮盘赌策略确定的父亲
                break;
            end
        end
        Selmother = floor(rand()*(NP-1))+1;%随机选择母亲
        posCut = floor(rand()*(L-2))+1;   %随机群定交叉点
        r1 = rand();                       %r1为0,1之间随机数
        if r1<=Pc                          %如果r1小于杂交概率,交叉
            nx(i,1:posCut) = x(SelFather,1:posCut);           %将切点前编码替换为父亲的
            nx(i,(posCut+1):L) = x(Selmother,(posCut+1):L);   %将切点后编码替换为母亲的
            r2 = rand();                   %r2为0,1之间随机数
            if r2<=Pm                      %如果r2小于变异概率,变异
            posMut = round(rand()*(L-1)+1);%随机确定变异位
            nx(i,posMut) = ~nx(i,posMut);  %变异位编码取非
            end
        else
            nx(i,:) = x(SelFather,:);      %若r1不小于杂交概率,则将该个体替换为父亲的编码
    end
end
x = nx;
for i=1:NP
    fx(i) = fitness(Dec(a,b,x(i,:),L));     %子代适应值
end
end
fv = -inf;
for i=1:NP
    fitx = fitness(Dec(a,b,x(i,:),L));
    if fitx > fv                            %取个体中的最好值作为最终结果
        fv = fitx;                          %fv为最优解的函数值
        xv = Dec(a,b,x(i,:),L);             %xv为最优解的编码
    end
end
function result = Initial(length)           %初始化函数
for i=1:length
    r = rand();
    result(i) = round(r);
end
    function y = Dec(a,b,x,L)               %二进制编码转换为十进制编码
        base = 2.^((L-1):-1:0);
        y = dot(base,x);
        y = a+y*(b-a)/(2^L-1);

       再次提醒,本程序是最基本的遗传算法程序,只能解决一维无约束的优化问题,若对于多目标问题,其实上文的PSO算法可以完成,或者在本文的遗传算法上做一些更改,之后我也会更新多目标情况下的遗传算法程序。下面举例展示本程序的调用方法,首先将待优化的目标函数在MATLAB中写成函数的形式:

function F = fitness(x)

 F = x^3-60*x^2+900*x+100;

       现在用刚刚的遗传算法代码求该函数的最大值,设置自变量的范围是0-30,可以直接在命令行调用,其调用格式为:

[xv,fv] = myGA(@fitness,0,30,50,100,0.9,0.04,0.01)

运行结果为:

xv =

   10.3223

fv =

   4.0969e+03

       遗传算法求得的结果的精度一方面与离散精度有关,另一方面与个体数目有关,离散精度决定了遗传算法能得到的最大精度,个体数目越大, 求得的结果精度越有可能达到离散精度。同样的迭代次数越大,也越有可能找到更优的解,不过也有可能陷入到局部最优中,所以需要适当的调整杂交概率与变异概率的大小。