赞
踩
上一篇博文写了遗传算法的主要思路,然后摸索了一下工具箱什么的,今天就把代码这个坑先填上。
顺序就按照上一篇博文里面写的步骤来:
问题描述:采用遗传算法和非线性规划的方法求解如下函数的极小值:
其中的变量都在0~0.9π之间。
该函数的最小值为-2,最小值位置为(π/2,π/2,π/2,π/2,π/2)。
1. 先是写适应度函数
个体的适应度是适应度函数值的倒数,上一篇博文中已经用红色字标注出来了,函数值越小的个体,适应度值越大,个体越优。
所以,代码如下:
- function y = fun(x)
- y = -5 * sin(x(1))*sin(x(2))*sin(x(3))*sin(x(4))*sin(x(5))-
- sin(5*x(1))*sin(5*x(2))*sin(5*x(3))*sin(5*x(4))*sin(5*x(5))+8;
其实所谓的适应度函数就是题目所要求的函数,适应度的话,就在下面的程序中取1/y。
2. 选择操作
方法选用的是轮盘赌(一个for循环,取随机),然后组成新的种群。
- function ret = select(individuals,sizepop)
- %individuals input :种群信息
- %sizepop input :种群规模
- %opts input :选择方法
- %ret input :重组的种群
- individuals.fitness = 1./(individuals.fitness);
- sunmfitness = sum (individuals.fitness); %求适应度的总和
- sumf = individuals.fitness./sumfitness; %求每个函数值适应度的占比
- index = []; %建立一个序列
-
- for i = 1:sizepop; %开始轮盘赌
- pick = rand; %这里把rand(0-1的随机数)理解成百分比比较好,作为一个概率的比较标准
- while pick == 0
- pick = rand;
- end
- for j = 1:sizepop
- pick = pick - sumf(j);
- if pick<0
- index = [index j]; %这里其实就是进行pick和sumf的对比,
- %如果pick比sumf小,就放入序列
- break;
- end
- end
- end
-
- individuals.chrom = individuals.chrom(index,:);
- individuals.fitness = individuals.fitness(index);
- ret = individuals;
轮盘赌的想法就是模拟自然选择,把值的大小换算成面积,用随机值来模拟指针,值越大,选中的概率也就越大。
这里可能不是很好理解,在知乎上有很多大佬解读过轮盘赌的方法,比我这个更详细,可以去观摩。毕竟我这个算法只针对这道题。
3. 交叉操作
函数就不解释了,贴个链接:https://blog.csdn.net/zhangqimo/article/details/105292845
- function ret = Cross(pcross,lenchrom,chrom,sizepop,bound)
-
- %pcross input :交叉概率
- %lenchrom input :%染色体长度
- %chrom input :%染色体群
- %sizepop input :种群规模
- %ret output :交叉后的染色体
-
- for i = 1 : sizepop
- pick = rand(1,2);
-
- while prod(pick) == 0 %prod函数是求矩阵元素的积
- pick = rand(1,2);
- end
-
- index = ceil(pick.*sizepop);
- pick = rand;
- while pick = 0;
- pick = rand;
- end
-
- if pick > pcross %如果大于交叉互换的概率就继续进行操作
- continue;
- end
-
- flag = 0;
- while flag == 0
- pick = rand;
- while pick == 0
- pick = rand;
- end
-
- pos = ceil(pick.*sum(lenchrom)); %随机选择交叉位置(选择第几个变量进行互换)
- pick = rand; %交叉开始
- v1 = chrom(index(1),pos);
- v2 = chrom(index(2),pos);
- chrom(index(1),pos) = pick * v2 + (1-pick) *v1;
- chrom(index(2),pos) = pick * v2 + (i-pick) *v2; %交叉结束
-
- flag1 = test(lenchrom,bound,chrom(index(1),:),fcode); %bound为自变量取值的约
- %束,该函数检验可行性
- flag2 = test(lenchrom,bound,chrom(index(2),:),fcode);
-
- if flag1 * flag2 ==0
- flag = 0;
- else flag = 1;
- end %如果都不行,则重新交叉
- end
- end
- ret = chrom;
4. 变异操作
是从种群中随机选择一个个体,按一定概率变异得到新个体。
- function ret = Mutation(pmutation,lenchrom,chrom,sizepoppop,bound)
-
- %pcross input :变异概率
- %lenchrom input :染色体长度
- %chrom input :染色体群
- %sizepop input :种群规模
- %pop input :当前种群的进化代数和最大的进化代数信息
- %ret output :变异后的染色体
-
- for i = 1 : sizepop
- pick = rand; %随机选
- while pick == 0
- pick = rand;
- end
- index = ceil(pick * sizepop)
-
- pick = rand;
- if pick > pmutation
- continue;
- end
- flag = 0;
- while flag == 0;
- pick = rand;
- while pick == 0;
- pick == 0;
- end
- pos = ceil(pick * sum(lenchrom));
- v = chrom(i,pos);
- v1 = v - bound(pos,1)
- v2 = bound(pos,2) - v;
- pick = rand;
- %从这里开始变异
- if pick>0.5
- delta = v2*(1-pick^((1-pop(1)/pop(2))^2);
- chrom(i,pos) = v + delta;
- else
- delta = v1*(1 - pick^((1-pop(1)/pop(2))^2));
- chrom(i,pos) = v-delta;
- end
- flag = test(lenchrom,bound,chrom(i,:),fcode);
- end
- end
- end
- ret = chrom;
5. 主程序
遗传算法基本上就是:随机初始化——计算种群适应度,找最优——选择——交叉——变异——寻优——判断结束条件。
具体代码为:
心态有点炸,码的代码被猫一脚踹没了。心情好了更。
更新:主程序
- clc
- clear
-
- maxgen = 100; %迭代次数
- sizepop = 10; %种群规模
- pcross = [0.5]; %交叉概率
- pmutation = [0.05]; %变异概率
- lenchrom = [1 1 1 1 1]; %变量长度
- bound = [0 0.5*pi;0 0.5*pi;0 0.5*pi;0 0.5*pi;0 0.5*pi];
-
- %初始化(个体)
- individuals = struct('fitness',zeros(1,sizepop),'chrom',[]);
- avgfitness = []; %平均适应度
- bestfitness = []; %最佳适应度
- bestchrom = []; %最佳染色体
-
- %初始化(种群)
- for i = 1 : sizepop
- individuals.chrom(i,:) = Code(lenchrom,bound);
- x = individuals.chrom(i,:);
- individuals.fitness(i) = fun(x);
- end
-
- %找最优
- [bestfitness bestindex] = min(individuals.fitness);
- bestchrom = individuals.chrom(bestindex,:);
- avgfitness = sum(individuals.fitness)/sizepop;
- trace=[]; %记录每一代数值
-
- %进化
- for i = 1 :maxgen
- %选择
- individuals = Select(individuals,sizepop);
- avgfitness = sum(individuals.fitness)/sizepop;
- %交叉
- individuals.chrom = Cross(pcross,lenchrom,individuals.chrom,sizepop,bound);
- %变异
- individuals.chrom = Mutation(pmutation,lenchrom,individuals.chrom,sizepop,[i maxgen],bound);
-
- %以5代为界限,用求得数值作为初始值进行非线性寻优
- if mod(i,5) == 0
- individuals.chrom = nonlinear(individuals.chrom,sizepop);
- end
-
- %计算适应度
- for j = 1:sizepop
- x = individuals.chrom(j,:)
- individuals.fitness(j) = fun(x);
- end
-
- %求最优值所在位置
- [newbestfitness,newbestindex] = min(individuals.fitness);
-
- %与上一轮进化求得最优值对比,若更优,则替换
- if bestfitness > newbestfitness
- bestfitness = newbestfitness;
- bestchrom = individuals.chrom(newbestindex,:);
- end
-
- avgfitness = sum(individuals.fitness)/sizepop;
- trace = [trace;avgfitness bestfitness]; %每一代数据记录
- end
6. 非线性寻优
这里得调用工具箱里的fmincon
- function ret = nonlinear(chrom,sizepop)
- for i = 1 : sizepop
- x = fmincon(inline('-5 * sin(x(1))*sin(x(2))*sin(x(3))*sin(x(4))*sin(x(5))-
- sin(5*x(1))*sin(5*x(2))*sin(5*x(3))*sin(5*x(4))*sin(5*x(5))'),
- chrom(i,:)',[],[],[],[],[0 0 0 0 0].[2.874 2.874 2.874 2.874 2.874]);
- ret(i,:)=x';
- end
以上就是代码的全部了。
鬼知道我保存了几遍,不得不感叹一句,猫主子的脚是厉害,每次刚好踩到Alt+F4.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。