学点数模-2——遗传算法
今天来学习一下遗传算法,其实相关的代码已经找到了,但是想先学一下,因为我发现我有些地方不能纯看代码看懂。还是得辅佐一下。
说白了就是模拟生物进化的,那么我们先构建一个模拟生物进化的模型,
首先,我们可以想象一下,
1.有三十只兔子在某一块地皮上,这就是初始种群。
2.这三十只兔子会相互繁育下一代,这之中会产生基因的交叉,即父母的染色体各取一条。还会产生染色体变异
3.产生的下一代还会不断的产生基因的交换与变异
4.物竞天择——因为某一个特定的规则,这个兔子活了下来,这里会复杂一点
我们可以简单思考一下,即使是物竞天择了、也不止是强壮的兔子活了下来,还有一些兔子侥幸活了下来。所以我们如果在模型里进行的话,简单来说,就是这个兔子的强壮程度决定了他活下去的概率。并且,这个兔子的强壮程度还会决定它的染色体会更优先被选中,即更容易发生交换(变异是无时无刻的,没有选择的)
在解释了一下遗传算法的基础思想之后,我们还要提一嘴
遗传算法,本质上还是在寻找最优解,它也是模拟的种群遗传去寻找最优解的。跟上次的模拟退火是一样的,目的上并没有区别。
1,相关的函数及解释
适应度函数(fitness function)
这个函数是基于你所添加的判断去计算适应度的。比方说,你想计算一个完全没有规律的函数的最优解,那么所有兔子越偏向优解的,越具有适应度。适应度函数就取决于你想要计算最优解的函数
选择函数(selection)
选择函数指的是种群选择度,是来源于适应度的,适应度越高,其越会被选择,当然这是概率层面更高,并非适应度低就完全不行。
染色体交叉与变异
理论上,将染色体转为二进制是最正规的,但是其本身是“像”而非好用(个人理解),我们正常使用,用浮点数就完全ok,当然,浮点数是有弊端的,不像二进制那种随意交换,我们可以选择把重点放在变异
染色体变异则是我们可想而知的东西。比方说,这个染色体的浮点数编码是1.1,2.5,4.6,之后发生变异,这个变异可以大也可以小,可以增也可以减,这些都可以,但是由于刚开始计算为了尽快到达尽量优解,而后期想要更为精确的到达最优解,我们可以动态规划变异,即刚开始变异步幅大,后期变异步幅小,可以在种群繁衍几十次之后修改,动态就好。
main.m
function main() clear; clc; %种群大小 popsize=100; %二进制编码长度 chromlength=10; %交叉概率 pc = 0.6; %变异概率 pm = 0.001; %初始种群 pop = initpop(popsize,chromlength); objvalue = cal_objvalue(pop); fitvalue = objvalue; for i = 1:100 %选择操作 newpop = selection(pop,fitvalue); %交叉操作 newpop = crossover(newpop,pc); %变异操作 newpop = mutation(newpop,pm); %更新种群 pop = newpop; %计算适应度值(函数值) objvalue = cal_objvalue(pop); fitvalue = objvalue; %寻找最优解 [bestindividual,bestfit] = best(pop,fitvalue); x2 = binary2decimal(bestindividual); x1 = binary2decimal(newpop); y1 = cal_objvalue(newpop); if mod(i,10) == 0 figure; fplot('10*sin(5*x)+7*abs(x-5)+10',[0 10]); hold on; plot(x1,y1,'*'); size(x1) title(['iteration times 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);
initpop.m
%初始化种群大小 %输入变量: %popsize:种群大小 %chromlength:染色体长度-->>转化的二进制长度 %输出变量: %pop:种群 function pop=initpop(popsize,chromlength) pop = round(rand(popsize,chromlength)); %rand(3,4)生成3行4列的0-1之间的随机数 % rand(3,4) % % ans = % % 0.8147 0.9134 0.2785 0.9649 % 0.9058 0.6324 0.5469 0.1576 % 0.1270 0.0975 0.9575 0.9706 %round就是四舍五入 % round(rand(3,4))= % 1 1 0 1 % 1 1 1 0 % 0 0 1 1 %所以返回的种群就是每行是一个个体,列数是染色体长度
二进制转十进制binary2decimal.m(我认为浮点数也是够的,不过找的源码懒得改了.)
%二进制转化成十进制函数 %输入变量: %二进制种群 %输出变量 %十进制数值 function pop2 = binary2decimal(pop) [px,py]=size(pop); for i = 1:py pop1(:,i) = 2.^(py-i).*pop(:,i); end %sum(.,2)对行求和,得到列向量 temp = sum(pop1,2); pop2 = temp*10/1023;
计算适应度函数cal_objvalue.m
%计算函数目标值 %输入变量:二进制数值 %输出变量:目标函数值 function [objvalue] = cal_objvalue(pop) x = binary2decimal(pop); %转化二进制数为x变量的变化域范围的数值 objvalue=10*sin(5*x)+7*abs(x-5)+10;
选择新个体selection.m
%如何选择新的个体 %输入变量:pop二进制种群,fitvalue:适应度值 %输出变量:newpop选择以后的二进制种群 function [newpop] = selection(pop,fitvalue) %构造轮盘 [px,py] = 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
交叉crossover.m
%交叉变换 %输入变量:pop:二进制的父代种群数,pc:交叉的概率 %输出变量:newpop:交叉后的种群数 function [newpop] = crossover(pop,pc) [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
变异mutation.m
%关于编译 %函数说明 %输入变量:pop:二进制种群,pm:变异概率 %输出变量:newpop变异以后的种群 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; elseif newpop(i,mpoint) == 1 newpop(i,mpoint) = 0; end else newpop(i,:) = pop(i,:); end end
选择最优个体best.m
%求最优适应度函数 %输入变量:pop:种群,fitvalue:种群适应度 %输出变量:bestindividual:最佳个体,bestfit:最佳适应度值 function [bestindividual bestfit] = best(pop,fitvalue) [px,py] = size(pop); bestindividual = pop(1,:); bestfit = fitvalue(1); for i = 2:px if fitvalue(i)>bestfit bestindividual = pop(i,:); bestfit = fitvalue(i); end end
以上源码来自遗传算法介绍并附上Matlab代码 - 知乎 (zhihu.com) 这篇文章源码注释写的非常非常好,给我自己也学习一下。
本文来自博客园,作者:逆世混沌,转载请注明原文链接:https://www.cnblogs.com/nish1hundun/p/17029995.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步