遗传算法是由John Holland与其同事、学生在20世纪60年代末70年代初提出来的算法,是模拟自然界生物遗传所得的算法,所以它具有很高的智能性,在处理复杂非线性的工程问题时,体现了很大优势,能保证其快速精确地收敛到所需要的精度,能达到工程所需要的结果。
遗传算法原理
遗传算法是根据生物进化论演化而来.它的工作原理是,产生一个原始种群,通过达尔文提出的优胜劣汰的自然原则,把不适应环境的个体淘汰,留下适应的个体,通过一代代的繁衍,不断的选择(selection),交叉(crossover),变异(muta-tion),最后得到可以完全适应所需环境的个体,而这个个体就是我们所要求的解.具体说来可分以下步骤:
1)产生初始种群,初始化相关参数,包括最大遗传代数(maxgen)、种群规模(sizepop)、交叉概率、变异概率以及个体上下限,计算初始适应度值(fitness),得到初始种群的最佳个体(bestchrom)及其适应度值(bestfitness).
2)for i= 1 to maxgen.循环执行第3到第5步.
3)对每一代的种群进行选择、交叉、变异.
4)计算每一代所产生的新种群适应度值fitness.
5)根据fitness来判断是否得到所需的解.
6)得出全局的bestchrom以及bestfitness.
通过实验我们发现,遗传算法对初始值的要求不是很高,只需给出大致的范围即可求解,而何选择适当的fitness函数对结果能否收敛且达到所需精度非常重要。
遗传算法的组成
遗传算法可以定义为一个八元组
式中:C表示个体的编码方法,可分为浮点编码和二进制编码;E表示个体适应度评价函数,它在遗传算法中起环境的作用,是选择的依据;P0表示初始群体;M表示初始群体的大小,一般为20~ 100;phi表示选择算子,选择方法主要有轮盘选择法、随机遍历抽样、波尔兹曼选择法、锦标赛选择法等;Γ表示交叉算子,主要有离散交叉、中间交叉、线性交叉、单点交叉、多点交叉等; 表示变异算子,主要有边界变异、非均衡变异、多重均衡变异等;T表示算法的终止条件,可以规定最大遗传代数或最小偏差等条件来终止遗传算法,一般情况下,最大代数可取为100~ 500.
其间完整的过程解释:确定编码方式,对问题的解进行编码;初始化种群(种群中每一个个体均编码完成);评价种群中的个体(采用适应度函数进行评估,位串的解码值,目标函数值,目标函数值向适应值映射,适应值调整);判断是否满足要求(满足结束迭代,获取最优解,不满足继续进行迭代过程);进行遗传操作:选择、交叉、变异;产生新的一代种群;继续进行评价种群的个体。
遗传算法实操
该案例参考了目前为止看到比较清楚明白的一篇文章[遗传算法介绍-]。(https://blog.youkuaiyun.com/weixin_30352645/article/details/98830852)
首先,用matlab绘制了想求解函数的图象
接下来要做的是,用遗传算法求解最大值。
function main()
%主函数,初始化
%此处显示详细说明
%种群大小
popsize=100;
%二进制编码长度
chromlength=10
%交叉概率
pc=0.6;
%变异概率
pm=0.001;
%初始种群
pop=initpop(popsize,chromlength);
for i = 1:100
%计算适应度值(函数值)
objvalue=cal_objvalue(pop);
fitvalue=objvalue;
%选择操作
newpop=selection(pop,fitvalue);
%交叉操作
newpop=crossover(newpop,pc);
%变异操作
newpop=mutation(newpop,pm);
%更新种群
pop=newpop;
%寻找最优解
[bestindividual,bestfit]=best(pop,fitvalue);
x2=binary2decimal(bestindividual);
x1=binary2decimal(newpop);
y1 = cal_objvalue(newpop);
if mod(i,10) == 0 %绘图,没什么用
figure;
fplot(@(x)10.*sin(5*x)+7.*abs(x-5)+10);
hold on;
plot(x1,y1,'*');
title(['迭代次数为n=' num2str(i)]);
%plot(x1,y1,'*');
end
end
fprintf('The best X is --->>%5.2f\n',x2);
fprintf('The best Y is --->>%5.2f\n',bestfit);
function pop=initpop(popsize,chromlength)
%初始化种群大小
%输入变量:
%popsize:种群大小
%chromlength:染色体长度-->>转化的二进制长度
%输出变量:
%pop:种群
pop=round(rand(popsize,chromlength)); %返回的每行是一个个体
function pop2=binary2decimal(pop)
%二进制转化成十进制函数
%输入变量:
%二进制种群
%输出变量
%十进制数值
[px,py]=size(pop);
for i=1:py
pop(:,i)=2.^(py-i).*pop(:,i);
end
%sum(.,2)对行求和,得到列向量
temp=sum(pop,2);
pop2=temp*10/1023;
function[objvalue]=cal_objvalue(pop)
%计算函数目标值,输入:二进制,输出:目标函数值
x=binary2decimal(pop);
%转化二进制数为x变量的变化域范围的数值
objvalue=10*sin(5*x)+7*abs(x-5)+10;
function [newpop]=selection(pop,fitvalue)
%选择新的个体,构造轮盘
[px,~] = size(pop);
totalfit = sum(fitvalue);
p_fitvalue = fitvalue/totalfit;
p_fitvalue = cumsum(p_fitvalue);%概率求和排序
ms = sort(rand(px,1));%从小到大排列
fitin = 1;
newin = 1;
while newin<=px
if(ms(newin))<p_fitvalue(fitin)
newpop(newin,:)=pop(fitin,:);
newin = newin+1;
else
fitin=fitin+1;
end
end
function [newpop] = crossover(pop,pc)
%交叉变换,输入:pop 二进制的父代种群数 pc:交叉概率
%输出:newpop:交叉后的种群数
[px,py] = size(pop);
newpop = ones(size(pop));
for i = 1:2:px-1
if(rand<pc)
cpoint = round(rand*py);
newpop(i,:) = [pop(i,1:cpoint),pop(i+1,cpoint+1:py)];
newpop(i+1,:) = [pop(i+1,1:cpoint),pop(i,cpoint+1:py)];
else
newpop(i,:) = pop(i,:);
newpop(i+1,:) = pop(i+1,:);
end
end
function [newpop] = mutation(pop,pm)
%变异
[px,py] = size(pop);
newpop = ones(size(pop));
for i = 1:px
if(rand<pm)
mpoint = round(rand*py);
if mpoint <= 0
mpoint = 1;
end
newpop(i,:) = pop(i,:);
if newpop(i,mpoint) == 0
newpop(i,mpoint) = 1;
else newpop(i,mpoint)==1
newpop(i,mpoint) = 0;
end
else newpop(i,:) = pop(i,:);
end
end
%求最优适应度函数
%输入变量:pop:种群,fitvalue:种群适应度
%输出变量:bestindividual:最佳个体,bestfit:最佳适应度值
function [bestindividual,bestfit] = best(pop,fitvalue)
[px,~] = size(pop);
bestindividual = pop(1,:);
bestfit = fitvalue(1);
for i = 2:px
if fitvalue(i)>bestfit
bestindividual = pop(i,:);
bestfit = fitvalue(i);
end
end
遗传算法优缺点
优点:编码、解码操作简单易行;交叉、变异等遗传操作便于实现;合最小字符集编码原则;利用模式定理对算法进行理论分析。
缺点:对于一些连续函数的优化问题,由于其随机性使得其局部搜索能力较差,如对于一些高精度的问题,当解迫近于最优解后,由于其变异后表现型变化很大,不连续,所以会远离最优解,达不到稳定。
这个案例只是初步掌握了遗传算法原理,具体怎样真正寻找到最优解,还需要其他小技巧。