matlab优化算法之遗传算法(含代码)【数学建模】

87b955e5db6edfef1e146e875fd48eca.png

前言:上一篇文章中我们学习的模拟退火算法是通过模拟物体的物理退火过程得以实现的,今天我们要学习的遗传算法则是通过模拟生物学中物种的进化过程来实现的!

一、遗传算法的基本原理

生物进化选择物种:

“ 物竞天择,适者生存 ” 生动地描述了自然的选择残酷性。能够很好适应当前环境的生物不仅生存了下来,还把它体内的优质“基因”留给了下一代。继承优质基因的“下一代们”不断的适应着新的环境,环境又不断的选择新的适合生存的物种。如此交替循环,经过数代的发展,最终留下来的生物一定是最适合当前环境的!

遗传算法寻找最优解:

遗传算法借鉴了达尔文的生物进化理论和孟德尔的遗传定律,使用“适者生存”的原则,在潜在的解决方案中逐次产生一个近似最优解的方案。在遗传算法的每一代中,根据个体的适应度值进行选择,并根据遗传学法则产生新一代的个体。在这个过程中种群中的个体适应度不断增强,得到解也不断接近最优解!

efe7abffae96bf8caa720b1a560f8311.png

二、遗传算法的实现

2.1 具体实现步骤:

(1) 根据具体问题确定可行解域,确定一种编码方法,能用数值串或字符串表示 可行解域的每一解。 

(2) 确定一个度量好坏的依据,它用一函数表示,叫做适应度函数。 

(3)确定进化参数群体规模 N 、交叉概率 pc 、变异概率 pm 

2.2遗传算法的一些基本概念:

基因编码(将优化的变量转化为基因的组合表达形式,常见的编码形式有二进制和十进制两种:

二进制编码:

用二进制编码的形式表示实数。

如:用“000000” 到“111111”表示实数[0,63],编码“000000”表示“0”,编码“000001”表示“1”。当然二进制编码不仅可以表示整数,还可以表示小数。

具体步骤是,先把二进制编码表示为整数,然后在把整数映射到要表示的区间。如要用“000000” 到“111111”表示[0,10],“000000”表示0,“000001”表示0.15873,“000010”表示0.31746,相邻两个值的跳跃值约10/63≈0.15873

十进制编码

用实数进行编码

种群大小N:为便于计算,一般来说,每一代群体的个体数目都取相等。群体规模越大、越容 易找到最优解,但由于受到计算机的运算能力的限制,群体规模越大,计算所需要的时间也相应的增加

遗传概率Pm:又称交叉概率。得到种群中的优质个体后,以某一概率(遗传概率)交换他们之间的部分染色体。遗传概率控制着交叉操作,较大的交叉概率可以增强遗传算法开辟新的搜索领域,但对解的破坏性较大,一般取0.25~1

变异概率Pc:对群体中的每一个个体以某一概率(变异概率)把一小部分基因改变为等位基因。变异能保持群体的多样性,防止重要基因丢失,但变异概率不宜太大,一般取0.001~0.1

适应度函数

用来评价个体优劣的数学函数,一般由目标函数映射成适应度函数,或直接由目标函数来表示个体的适应度

选择遗传个体

根据个体的适应度,按照一定的规则或方法,从第i代个体中选择出出一些优良的个体遗传到i+1代中。选择的个体数为每代种群的个数N。主要有两种选择方法。

直接选择:按照适应度排序,选择适应度最靠前的那部分个体。

概率选择选择法(“轮盘赌”):一种基于比例的选择,利用各个个体适应度所占比例的大小决定其子孙保留的可能性。若某个个体的 i  的适应度为b74e13e391b901a613dfa003293c3572.png,种群大小为N,则它被选择的概率为:

19d1506b5cbde5867f13daeec1e3cfbd.png

2.3算法流程图:

e8ba8d48c00f00ff213ea383c0d96d75.png

三、遗传算法的改进

遗传算法对全局最优解具有强大的搜索能力,但标准遗传算法的局部能力搜索能力相对较差,且容易较早的收敛。所以在处理很多问题时常常和其他算法如模拟退火、禁忌搜索算法、改良圈等其他算法一起使用。

四、遗传算法的应用实例一:寻找函数的极值

问题:寻找下面函数在[0,20]的最大值。

61ee4ce163a1b5816780c98b0e35109a.png

4.1实现步骤:

基因编码:我们用20位的二进制来表示[0,20],相邻两个值之间的跳跃值为:

20/(2^20) ≈0.000002

选择遗传个体:轮盘赌选择

4.2 结果

我们可以看到函数在[0,20]区域内大约在X = 19的位置取得最大值,我们用遗传算法来求解。

b3dee6a165ee7eb660e7decd09e1177d.png

可以看到,大约在11代的时候就能找到最优解,可见遗传算法的强大之处。

e2a21efb10071bcae7eb4695f137a749.png

注:实现代码见文末

五、遗传算法的应用实例二:解决TSP问题

当然,寻找函数的极值还是不能凸显出遗传算法的强大之处。检验优化算法还是得用TSP 来检验,并且这次的城市数量我们也上升到了130个

当然了,只有遗传算法还是不太够滴!所以在遗传算法的基础上,我们又添加了改良圈算法来产生初始解。

5.2 实现步骤:

基因编码

采用十进制编码,用随机数列7619381523b0468a5ab120157b343e1d.png作为染色体,其中 0 < Ci< 1 (i =2,3,n-1),C1 = 0,Cn = 1。每一个随机序列都和种群中的一个个体相对应,再按升序排列。例如一个10目标问题的一个染色体为[0, 0.23, 0.82, 0.45, 0.74, 0.87, 0.11, 0.56, 0.69, 0.78, 0.52, 1]的路径为:[ 1 7 2 4 11 8 9 5 10 3 6 12]

改良圈算法产生初始解:

对于初始解:

5ef0322898a37c95ce8f1f26813f518d.png

交换U和V之间的顺序:

9ce03b1d67924986cfeaea522092994d.png

计算产生的函数差:

58274f3f491e98ef08710edba326a647.png

869e36f210dbd6c060c27b5d68acfe53.png < 0,修改后的路径作为新路径,继续修改,若1f90588a05d31fd99cd0ed198b7f6388.png>0,z则沿用当前的路径继续修改。

结果:

8c1d41eeb2856d0f18464ad5b37e76ab.png

寻找函数的极值源代码

clc,clear
N = 50;
L = 20;
pc =0.8;
pm =0.1;
g =100;
xs =20;
xx =0;
f = round(rand(N,L));
for k =1:g
    for i = 1:N
        u =f (i,:);
        m = 0;
        for j =1:L
            m = u(j)*2^(j-1)+m;
        end
        x(i) = xx + m*(xs-xx)/(2^L-1);
        fit(i) = func1(x(i));
    end
    maxfit = max(fit);
    minfit = min(fit);
    rr = find(fit==maxfit);
    fbest = f(rr(1,1),:);
    xbest = x(rr(1,1));
    fit = (fit-minfit)/(maxfit-minfit);


    %轮盘赌赋值操作
    sum_fit = sum(fit);
    fitvaule  = fit./sum_fit;
    fitvaule = cumsum(fitvaule);
    ms = sort(rand(N,1));
    fiti = 1;
    newi = 1;
    while newi <= N
        if (ms(newi)) < fitvaule(fiti)
            nf(newi,:) = f(fiti,:);
            newi = newi +1;
        else
            fiti = fiti +1;
        end
    end


    %概率交差操作
    for i = 1:2:N   %选择两个优秀个体
        p = rand;
        if p <pc
            q = round(rand(1,L));
            for j =1:L
                if q(j) == 1
                    temp = nf(i+1,j);
                    nf(i+1,j) = nf(i,j);
                    nf(i,j) = temp;
                end
            end
        end
    end


    %变异操作
    i =1;
    while i <= round(N*pm)
        h = randi(N);
        for j = 1:round(L*pm)
            g = randi(L);
            nf(h,g) = ~nf(h,g);
        end
        i = i+1;
    end


    f = nf;
    f(1,:) =fbest;
    value(k) = maxfit;
end
xbest;
xx = 0:0.1:20;
y =  sin(2*xx)+cos(3*xx)+xx;
figure
plot(xx,y)
figure
plot(value)
function result = func1(x)
fit = sin(2*x)+cos(3*x)+x;
result = fit;
end

遗传算法求解TSP问题源代码

clc,clear
%导入数据
aa = readmatrix('TSP数据-2.csv');
sj = aa([1:129],[3,4]);
dl =[sj(1,1),sj(1,2)];
sj=[sj;dl];
[n1 ,n2]= size(sj);
sj=sj*pi/180;
d=ones(n1);%计算距离矩阵
for i =1:n1
    for j=1:n1
        mp=cos(sj(i,1)-sj(j,1))*cos(sj(i,2))*cos(sj(j,2))+sin(sj(i,2))*sin(sj(j,2));
        d(i,j)=6370*acos(mp);
    end
end


L=130;%基因链长度
N=50;%种群数量
G=100;%代数
Pc=0.1;%变异概率
Pm=0.9;%交叉概率




%通过改良圈算法选取优良父代 A
J = zeros(N,L);%开辟空间存储初始种群
for k=1:N %产生初始种群,种群数量为N个
    c=randperm(L-2); %产生初始染色体
    c1=[1,c+1,L];
    flag=1;
    while flag>0
        flag=0;
        for m=1:L-3
            for n=m+2:L-1
                if d(c1(m),c1(n))+d(c1(m+1),c1(n+1))<d(c1(m),c1(m+1))+d(c1(n),c1(n+1))
                    flag=1;
                    c1(m+1:n)=c1(n:-1:m+1);
                end
            end
        end
    end
    J(k,c1)=1:L;
end
%计算改良圈初始产生路径的解
pathss = J;
temp1 = 0;
for i=1:(L-1)
    temp1 = temp1+d(pathss(1,i),pathss(1,i+1));
end


fprintf('计算改良圈初始产生路径的长度:%8.2f\n',temp1)


J=J/L;
J(:,1)=0;J(:,L)=1;
%遗传算法实现过程
A=J;
for k=1:G %产生 0~1 间随机数列进行编码
    B=A;
    c=randperm(N);
    %交配产生子代 B
    for i=1:2:N
        p = rand;
        if p<Pm
            F=2+floor((L-2)*rand(1));
            temp=B(c(i),F:L);
            B(c(i),F:L)=B(c(i+1),F:L);
            B(c(i+1),F:L)=temp;
        end
    end


    %变异产生子代 C
    by=find(rand(1,N)<Pc);%依概率Pc选择变异个体
    if isempty(by)
        by=floor(N*rand(1))+1;
    end
    C=A(by,:);
    L3=length(by);
    for j=1:L3
        bw=2+floor((L-2)*rand(1,3));
        bw=sort(bw);
        C(j,:)=C(j,[1:bw(1)-1,bw(2)+1:bw(3),bw(1):bw(2),bw(3)+1:L]);
    end


    %在父代和子代中选择优良品种作为新的父代
    G=[A;B;C];
    TL=size(G,1);
    [dd,IX]=sort(G,2);temp = zeros(1,TL);
    for j=1:TL
        for i=1:(L-1)
            temp(j)=temp(j)+d(IX(j,i),IX(j,i+1));
        end
    end
    [DZ,IZ]=sort(temp);
    A=G(IZ(1:N),:);
end
path=IX(1,:);
fprintf('旅行商经过路径的长度:%8.2f\n',DZ(1))
sj=sj*180/pi;
xx=sj(path,1);yy = sj( path,2);
plot(xx,yy,'- *') %画出巡航路径
text(sj(1,1),sj(1,2),'中心城市','color','r')%标注数据中心点

最后感谢大家的阅读,初来乍到,不周之处请多包涵。如有问题,欢迎在本文下方留言讨论。

如需本文完整程序文件,请加matlab编程爱好者②群获取,在群文件matlab爱好者公众号数据及程序文件夹下的matlab优化算法之遗传算法TSP数据

参考资料:

[1] 司守奎《数学建模算法与程序》

[2] 姜启源,谢金星,叶俊《数学建模》

[3] 包子阳,余继周《智能优化算法及其MATLAB实例》

封面图片:由 Arek Socha 在Pixabay上发布

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
简单的遗传算法,计算函数最值. function ga_main() % 遗传算法程序 % n-- 种群规模% ger-- 迭代次数% pc--- 交叉概率% pm-- 变异概率 % v-- 初始种群(规模为n)% f-- 目标函数值% fit-- 适应度向量 % vx-- 最优适应度值向量% vmfit-- 平均适应度值向量 clear all; close all; clc;%清屏 tic;%计时器开始计时 n=20;ger=100;pc=0.65;pm=0.05;%初始化参数 %以上为经验值,可以更改。 % 生成初始种群 v=init_population(n,22); %得到初始种群,22串长,生成20*22的0-1矩阵 [N,L]=size(v); %得到初始规模行,列 disp(sprintf('Number of generations:%d',ger)); disp(sprintf('Population size:%d',N)); disp(sprintf('Crossover probability:%.3f',pc)); disp(sprintf('Mutation probability:%.3f',pm)); %sprintf可以控制输出格式 % 待优化问题 xmin=0;xmax=9; %变量X范围 f='x+10*sin(x.*5)+7*cos(x.*4)'; % 计算适应度,并画出初始种群图形 x=decode(v(:,1:22),xmin,xmax);"位二进制换成十进制,%冒号表示对所有行进行操作。 fit=eval(f);%eval转化成数值型的 %计算适应度 figure(1);%打开第一个窗口 fplot(f,[xmin,xmax]);%隐函数画图 grid on;hold on; plot(x,fit,'k*');%作图,画初始种群的适应度图像 title('(a)染色体的初始位置');%标题 xlabel('x');ylabel('f(x)');%标记轴 % 迭代前的初始化 vmfit=[];%平均适应度 vx=[]; %最优适应度 it=1; % 迭代计数器 % 开始进化 while it<=ger %迭代次数 0代 %Reproduction(Bi-classist Selection) vtemp=roulette(v,fit);%复制算子 %Crossover v=crossover(vtemp,pc);%交叉算子 %Mutation变异算子 M=rand(N,L)<=pm;%这里的作用找到比0.05小的分量 %M(1,:)=zeros(1,L); v=v-2.*(v.*M)+M;%两个0-1矩阵相乘后M是1的地方V就不变,再乘以2. NICE!!确实好!!!把M中为1的位置上的地方的值变反 %这里是点乘 %变异 %Results x=decode(v(:,1:22),xmin,xmax);%解码,求目标函数值 fit=eval(f); %计算数值 [sol,indb]=max(fit);% 每次迭代中最优目标函数值,包括位置 v(1,:)=v(indb,:); %用最大值代替 fit_mean=mean(fit); % 每次迭代中目标函数值的平均值。mean求均值 vx=[vx sol]; %最优适应度值 vmfit=[vmfit fit_mean];%适应度均值 it=it+1; %迭代次数计数器增加 end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值