GA遗传算法Matlab版本实例注释

关于我对GA遗传算法的理解:

刚开始只听说过遗传算法的时候,听到这个名字就感觉好牛掰的样子。然后看了一本叫做《MATLAB智能算法30个案例分析》的书,学习了GA遗传算法,然而学完了之后知道我的第一感觉是什么?那就是真特么扯淡,哈哈哈!这特么不就是瞎碰,瞎猫碰上死耗子,碰上了最优解就碰上了,碰不上不就得到个不知道差多少的解吗?不过存在即合理仔细想想能发明这个算法的人还是很值得尊敬的。好了来说说我的理解,首先遗传算法当然是模拟生物进化优胜劣汰的法则了,它最大的优点就是不要你去寻找解,而只需要你作为上帝去否决那些你认为不好的解,最终留下来的就是最优解(或者次优解)了

首先来解释一下几个名词:

1. 染色体,一条染色体对应的就是你需要求的一个解,例如你需要求一个三元四次的复杂方程的极小值,那么你的一个结当然包含三个数(因为是三元嘛,当然是三个未知 数啦),假设是x,y,z。那么你的一条染色体就包含三个数,类似于一个向量[x  y  z]。类似的如果你的一个解只有一个数,那么一条染色体就只包含一个数。

2. 基因,咱们都是理科生,当然知道染色体是由基因组成的,上面说到了[x  y  z]对应的是一条染色体,那么自然组成x  , y , z的就是基因喽,这里我们就要说到编码了,一般 我们会将染色体进行编码,假设使用的是二进制编码,那么我们用二进制0和1将[x  y  z]横着写成一排,那么是不是就是遗传0和1。那么这些0和1就是基因了。

3. 交叉,交叉也是跟生物里面学的一样,就是两条染色体并排的时候相对应的那一段交叉接起来

4. 变异,变异就是基因中某个bit的0变成了1,或者1变成了0,几率很小。当然在算法中是我们让它变异的。

5. 压差,在下面的例子中,有个词语叫“压差”,之前网上都没找到明白的解释,其实说的那么高端,压差就是指你把本来0~255之间的数按照某种算法映射到1~10的话,那么 压差就是指这个1~10了,其实就是归一化之后的范围。

6. 适应度,上面说到优胜劣汰,我们作为上帝需要指定一个规则,怎么样的算是优秀,什么样的算是劣质,说让谁淘汰就让谁淘汰,比如说我们求一个方程的极小值,那么 我们当然是将每条染色体的值带入到方程中,求得的值越小就越优秀,越大就越劣质喽。那么我们就要淘汰那些使得方程值大的染色体,通过交叉编译来补充那些被淘汰 染色体的位置。

7. 适应度函数,适应度函数顾名思义就是用来计算适应度的函数,这个函数的定义很重要,但是总得来说只要保证越符合我们要求的,得出来的值(适应度)越大理论上就 可以接受,至于好不好另说。

8. 种群,就是若干个染色体组成种群。


接下来就说说GA遗传算法的步骤:

下面这个用matlab写的例子就是一个求极值问题,求方程y = sin(10*pi*x)/x , x属于[1,2] , 的极值


clc;

clear all;
close all;
figure(1);
hold on;
lb = 1; ub = 2; %这个值是自变量的范围,在这个范围内求解
ezplot('sin(10*pi*X)/X',[lb,ub]); %第一个参数表示的是方程,y的计算公式,画出图像
xlabel('自变量/X');
ylabel('函数值/Y');


NIND = 40;  %初始化40个解,每一个解代表的是一条染色体,这条染色体就代表的是一个x的值
MAXGEN = 20; %最大遗传代数
PRECT = 20; %染色体精度,也就是一个个体的基因数(2进制数长度),也就是用多少个bit表示一个x的值
GGAP = 0.95; %代沟,表示每一代从种群中选择多少个体到下一代
px = 0.7;   %染色体交叉几率,具体自己写的话不知道这个概率怎么用的,不过matlab中作为参数直接带入就好了
pm = 0.01;  %染色体变异几率,具体自己写的话不知道这个概率怎么用的,不过matlab中作为参数直接带入就好了
trace = zeros(2,MAXGEN);%初始化为0
FieldD = [PRECT;lb;ub;1;0;1;1]; % PRECT:2进制位数 lb:范围下限 ub:表示范围上限 
                                % 1:二进制编码 0:表示用算术刻度 1:表示包含左边界 1:表示包含右边界
Chrom = crtbp(NIND,PRECT); %随机产生初始解


gen = 0;%遗传代数
X = bs2rv(Chrom , FieldD); %根据区域描述器,自动将2进制编码转化成指定范围内的实数值
                        %得出的X是一个长度为40的列向量


ObjV = sin(10*pi*X)./X ;%“./”表示为阵列操作,非矩阵运算,得出的也是一个长度为40的列向量,适应度值
                        %经过上一步,X已经为列向量,所以ObjV也是列向量了
while gen<MAXGEN
    
    %ranking : 根据适应度值,使用ranking()得出各自的入选率(适应度)
    %第一个参数:注意ObjV必须是列向量(这是ranking函数要求的),表示需要计算适应度的种群,
    %第二个参数:一个有两个标量的向量,第一个标量可以认为总为2,同时代表压差的上限
    %           第二个标量有两重意义,如果为0表示线性排序,如果为1表示非线性排序,
    %           同时它代表压差的下限。返回得到的FitnV会是一个长度跟ObjV相同的列向量
    %           ,他们之间的值是一一对应的,FitnV中较大的表示适应度的值对应ObjV中较
    %           较小的值。但是FitnV中的顺序并非是有序的,顺序跟ObjV中的每个值得顺序
    %           是一样的。
    %第三个参数:表示种群中子种群的数量
    FitnV = ranking(ObjV,[2,0],1);
    
    %select : 通过计算得到的适应度值,从原始种群Chrom中筛选一些不符合要求的个体得到
    %           新的种群返回个SelCh
    %第一个参数:表示选择筛选的策略,sus表示随机平均选择 ,还可以是rws表示轮盘赌选择
    %第二个参数:表示原始的需要被筛选的种群
    %第三个参数:表示这个种群对应的适应度
    %第四个参数:表示代沟,也就是说从Chrom中选择多少百分比的个体到下一代,这里为0.95
    %           也就是说从Chrom中选择Chrom*0.95个个体进入下一代,有0.05的染色体被淘汰
    SelCh = select('sus',Chrom,FitnV,GGAP); %这就是优胜劣汰的过程
                                            
    SelCh = recombin('xovsp',SelCh,px); %交叉基因函数 ,xovsp或者recdis表示交叉策略 , px表示染色体交叉几率
    SelCh = mut(SelCh,pm);              %变异函数 ,pm表示编译几率
    X = bs2rv(SelCh , FieldD);
    ObjVSel = sin(10*pi*X)./X;
    
    %reins : 将子代个体插入到父代种群中,代替那些不合适的父代个体
    %第一个参数:表示父代种群
    %第二个参数:子代种群
    %第三个参数:指明Chrom,SelCh中子种群个数,每个子种群必须有相同的大小
    %第四个参数:其实是一个有两个元素的向量,在这里相当于[1,1] ,第一个标量表示用什么策略将子代
    %           将子代插入父代种群,如果为0表示用随机均匀选择,如果为1表示根据适应度进行选择;
    %           第二个标量表示子代种群插入父代,占百分比,可以是[0,1]之间的标量,如果缺省表示
    %           默认值为1
    %第五个参数:基于适应度重插入(也就是第四个参数为1)的时候这个参数是必须的,Objv包含Chrom中
    %           个体的目标值(也就是根据公式计算得到的值比如上面的sin(10*pi*X)./X得到的值)。
    %           这是因为基于适应度的方法,得到适应度必须是根据目标值来确定适应度,所以这里必须
    %           要带入目标值。
    %第六个参数:如果子代的个体数量大于将要插入父代的个体数量,那么这个参数是必须的,因为待插入
    %           的个数多余需要插入的个数,那么必然存在有一部分不能插入,那么淘汰那一部分个体,是
    %           根据子代种群的个体适应度来决定的,淘汰掉适应度底的个体,那么得到个体的适应度就需
    %           要子种群的各个个体的目标值来计算。
    [Chrom,ObjV] = reins(Chrom , SelCh , 1 , 1 , ObjV , ObjVSel)
                              
    X = bs2rv(Chrom , FieldD);
    gen = gen + 1;
    
    %min : 返回向量ObjV的最小值,Y记录ObjV中每一列的最小值,I记录每一列的最小值的行号
    [Y,I] = min(ObjV)
    trace(1,gen) = X(I);
    trace(2,gen) = Y;
end


plot(trace(1,:),trace(2,:),'bo');
grid on;
plot(X,ObjV,'b*');
hold off;
figure(2);
plot(1:MAXGEN,trace(2,:));
grid on;
xlabel('遗传代数');
ylabel('解的变化');
title('进化过程');
bestY = trace(2,end);
bestX = trace(1,end);
fprintf(['最优解:\nX = ', num2str(bestX), '\nY = ' , num2str(bestY) , '\n']);





  • 20
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值