文章目录

  • 解决以下问题
  • 0 主函数
  • 1.初始化
  • 2 计算目标函数值
  • 3 计算适应度函数
  • 4 选择
  • 5 交叉
  • 7 求出每一代 中最大得适应值及其个体
  • 主函数:
  • **处理最小值问题:**

这篇文章是目前为止我写的最认真的一篇博客。主要涉讲解了遗传算法的编程。关于理论基础详见博客推荐第一篇。
遗传算法博客推荐第一篇理解:遗传算法详解GA,适合初学者.

遗传算法博客推荐第二篇编程:遗传算法(Genetic Algorithm)原理详解和matlab代码解析实现及对应gaot工具箱实现代码.

在开始之前推荐先看完上述两篇遗传算法讲解博客,是很厉害的前辈们写的,写的通俗易懂,但是matlab的版本更新,关于遗传算法的工具箱也更新,如果使用里面的函数会出现问题。
第二篇博客中在不调用库的情况下,自己搭建的遗传算法,网上查了其他的写的基本大同小异。但是关于以下几个问题没有详细的解释。

解决以下问题

  1. 源程序有一点点的小错误,进行了修正。
  2. 关于不同的取值范围和精度要求,如何设定字符串长度,以及一部分进制转换。
  3. 在文中对于处理最小值问题只简单的提了一句取导数,实际改写程序中并不是那么简单。

为了方便可读性,这里先展示一遍原始程序,以下程序摘自前文中提到的第二篇博客。

0 主函数

% 下面举例说明遗传算法 %
% 求下列函数的最大值 %
% f(x)=x+10*sin(5x)+7*cos(4x) x∈[0,10] %
% 将 x 的值用一个10位的二值形式表示为二值问题,一个10位的二值数提供的分辨率是每为 (10-0)/(2^10-1)≈0.01
% 将变量域 [0,10] 离散化为二值域 [0,1023], x=0+10*b/1023, 其中 b 是 [0,1023] 中的一个二值数。 %
% %
%--------------------------------------------------------------------------------------------------------------%
%--------------------------------------------------------------------------------------------------------------% 2.0 主程序
%遗传算法主程序
%Name:genmain05.m
%要求精度不大于0.01,
clear
clc
popsize=20;                         %群体大小
chromlength=10;                  %字符串长度(个体长度)
pc=0.6;                                %交叉概率,只有在随机数小于pc时,才会产生交叉
pm=0.001;                           %变异概率pop=initpop(popsize,chromlength);               %随机产生初始群体
for i=1:2000                                                        %20为遗传代数[objvalue]=calobjvalue(pop);                  %计算目标函数fitvalue=calfitvalue(objvalue);                 %计算群体中每个个体的适应度[newpop]=selection(pop,fitvalue);                 %选择[newpop1]=crossover(newpop,pc);               %交叉[newpop2]=mutation(newpop1,pm);               %变异[objvalue]=calobjvalue(newpop2);                 %计算目标函数fitvalue=calfitvalue(objvalue);                       %计算群体中每个个体的适应度[bestindividual,bestfit]=best(newpop2,fitvalue);     %求出群体中适应值最大的个体及其适应值y(i)=bestfit;                                                              %返回的 y 是自适应度值,而非函数值x(i)=decodechrom(bestindividual,1,chromlength)*10/1023;      %将自变量解码成十进制pop=newpop2;
end
fplot('x+10*sin(5*x)+7*cos(4*x)',[0 10])
hold on
plot(x,y,'r*')
hold on[z ,index]=max(y);             %计算最大值及其位置
x5=x(index)                     %计算最大值对应的x值
ymax=z

1.初始化

主函数中调用,生成20个个体,按照精度要求选择染色体的长度
initpop.m

% 2.1初始化(编码)
% initpop.m函数的功能是实现群体的初始化,popsize表示群体的大小,chromlength表示染色体的长度(二值数的长度),
% 长度大小取决于变量的二进制编码的长度(在本例中取10位)。%初始化
function pop=initpop(popsize,chromlength)
pop=round(rand(popsize,chromlength)); % rand随机产生每个单元为 {0,1} 行数为popsize,列数为chromlength的矩阵,% round对矩阵的每个单元进行圆整四舍五入。这样产生的初始种群。

2 计算目标函数值

calobjvalue.m函数的功能是实现目标函数的计算,其公式采用本文示例仿真,可根据不同优化问题予以修改。

% 2.2.3 计算目标函数值
% calobjvalue.m函数的功能是实现目标函数的计算,其公式采用本文示例仿真,可根据不同优化问题予以修改。
%遗传算法子程序
%Name: calobjvalue.m
%实现目标函数的计算,将 二值域 中的数转化为 变量域的数
function [objvalue]=calobjvalue(pop)
temp1=decodechrom(pop,1,10);   %将pop每行转化成十进制数
x=temp1*10/1023;                         %在精度不大于0.01时,最小整数为1023,即需要10位二进制
objvalue=x+10*sin(5*x)+7*cos(4*x);   %计算目标函数值

decodechrom.m
(主要针对多个变量时候的一条染色体拆分,此处的例子不用拆分,pop1=pop)

% 2.2.2 将二进制编码转化为十进制数(2)
% decodechrom.m函数的功能是将染色体(或二进制编码)转换为十进制,参数spoint表示待解码的二进制串的起始位置
% (对于多个变量而言,如有两个变量,采用20为表示,每个变量10位,则第一个变量从1开始,另一个变量从11开始。本例为1),
% 参数1ength表示所截取的长度(本例为10)。
%遗传算法子程序
%Name: decodechrom.m
%将二进制编码转换成十进制function pop2=decodechrom(pop,spoint,length)          %1  10
pop1=pop(:,spoint:spoint+length-1);
pop2=decodebinary(pop1);                                           %将pop每行转换成十进制值,结果是20*1的矩阵

decodebinary.m


%产生 [2^n 2^(n-1) ... 1] 的行向量,然后求和,将二进制转化为十进制
function pop2=decodebinary(pop)
[px,py]=size(pop);                   %求pop行和列数
for i=1:py
pop1(:,i)=2.^(py-i).*pop(:,i);
end
pop2=sum(pop1,2);                 %求pop1的每行之和

3 计算适应度函数

calfitvalue.m

为了计算后续概率,把小于0的目标函数值设为0

% 2.3 计算个体的适应值
%遗传算法子程序
%Name:calfitvalue.m
%计算个体的适应值
function fitvalue=calfitvalue(objvalue)[px,py]=size(objvalue);                   %目标值有正有负
for i=1:pxif objvalue(i)>0                    temp=objvalue(i);          elsetemp=0.0;endfitvalue(i)=temp;
end
fitvalue=fitvalue';

4 选择

轮盘法选择。
原理如下
下面以轮盘赌选择为例给大家讲解一下:

假如有5条染色体,他们的适应度分别为5、8、3、7、2。

那么总的适应度为:F = 5 + 8 + 3 + 7 + 2 = 25。

那么各个个体的被选中的概率为:

α1 = ( 5 / 25 ) * 100% = 20%=0.2

α2 = ( 8 / 25 ) * 100% = 32%=0.32

α3 = ( 3 / 25 ) * 100% = 12%=0.12

α4 = ( 7 / 25 ) * 100% = 28%=0.28

α5 = ( 2 / 25 ) * 100% = 8%=0.08

怎么用代码实现呢?
思想:

把α1-α5,按比例顺序,放到长度为1的一维的线上,开始随机数生成。
理解成向线上随机撒一个点。撒到哪一段就是选择了哪个个体。

eg:
点到0.25时候,处在α1之后,在α2段,所以α2个体被选择一次。
再随机生成0.55,在α3段,所以α3个体被选择一次。

为了便于排序,先把点生成好,按顺序排列,从小到大的进行比较。
即如下代码:

selection.m

function [newpop]=selection(pop,fitvalue)
totalfit=sum(fitvalue);                   %求适应值之和
fitvalue=fitvalue/totalfit;                %单个个体被选择的概率
fitvalue=cumsum(fitvalue);            %如 fitvalue=[1 2 3 4],则 cumsum(fitvalue)=[1 3 6 10],不明白为什么要累加
[px,py]=size(pop);                       %20*10
ms=sort(rand(px,1));                   %从小到大排列
fitin=1;
newin=1;
while newin<=px                          %选出20个新个体,有重复情况,和上面介绍的方法不太一样if(ms(newin))<fitvalue(fitin)newpop(newin,:)=pop(fitin,:);newin=newin+1;elsefitin=fitin+1;end
end

5 交叉

单点交叉,以0.6的概率对相邻的两个个体染色体随机选择交叉,并随机选择交叉的位置。

crossover.m

% 2.5 交叉
% 交叉(crossover),群体中的每个个体之间都以一定的概率 pc 交叉,即两个个体从各自字符串的某一位置
% (一般是随机确定)开始互相交换,这类似生物进化过程中的基因分裂与重组。例如,假设2个父代个体x1,x2为:
% x1=0100110
% x2=1010001
% 从每个个体的第3位开始交叉,交又后得到2个新的子代个体y1,y2分别为:
% y1=0100001
% y2=1010110
% 这样2个子代个体就分别具有了2个父代个体的某些特征。利用交又我们有可能由父代个体在子代组合成具有更高适合度的个体。
% 事实上交叉是遗传算法区别于其它传统优化方法的主要特点之一。
%遗传算法子程序
%Name: crossover.m
%交叉function [newpop]=crossover(pop,pc)          %pc=0.6
[px,py]=size(pop);
newpop=ones(size(pop));
for i=1:2:px-1                                             %步长为2,是将相邻的两个个体进行交叉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)];elsenewpop(i,:)=pop(i,:);newpop(i+1,:)=pop(i+1,:);end
end

7 求出每一代 中最大得适应值及其个体

best.m

% 2.7 求出群体中最大得适应值及其个体
%遗传算法子程序
%Name: best.m
%求出第 t 代群体中适应值最大的值
function [bestindividual,bestfit]=best(pop,fitvalue)
[px,py]=size(pop);
bestindividual=pop(1,:);
bestfit=fitvalue(1);
for i=2:pxif fitvalue(i)>bestfitbestindividual=pop(i,:);bestfit=fitvalue(i);end
end

以下为原始程序结果,看似最后也迭代到了峰值的地方

于是我就把他的改成自己要用的程序,然后发现这里里面存在一些细节不是很对,虽然最后结果是看着蛮对的。

首先我对整套程序进行一下复盘,下面是上传到github的代码,可以和解释一起看。

Genetic-Algorithm-max

主函数:

  1. 随机产生初始群体,程序中设置种群大小20,设置字符串长度为10。
    遗传算法有4个参数需要提前设定,一般在以下范围内进行设置:
    (1)群体大小:20~100
    (2)遗传算法的终止进化代数:100~500
    (3)交叉概率:0.4~0.99
    (4)变异概率:0.0001~0.1
    上诉4个参数的设置原因见此博客
    设置字符串长度为10:
    (1)为什么设置成10:此题是对于0-10的数,要求精度小于0.01,所以至少要能表达1000种可能,在2进制中表达1000种可能的最小位数是10位,10位可以表达1024个数,每个数的大小小于0.01。
    (2)其他情况下如何设置:上诉是表示了精度小于某个值,如果要求精度刚好为一个值呢?我想到的一个办法是,仍然需要取到大于精度的所需表达的所有情况,但是在目标函数取值的地方做一个过滤,将范围之外但是2进制能表达的范围,设置成最小值(求最大值的情况下)。
    (3)针对上诉描述举个例子会更好,比如题目要求整数,范围在0-20000之间。那么我们肯定要选取15位的二进制,2^15=32768>20000,但是我们每个字符串的长度表示的范围却是0-32768,所以我在目标函数计算的函数中加入一个限制,在0-20000之外的数值就取最小值。
    欢迎大家的评论区提出更好的想法。
  2. 随机产生初始群体(基因):initpop.m 简单来说就是先随机产生种群大小*字符串长度的数组,其中数组中每个数为整数。
  3. 遗传算法迭代开始
  4. 计算目标函数(基因的表现型):首先每行的二进制都代表一个个体,计算目标函数需要把二进制先转换成十进制,并进行转换,代入目标函数计算目标函数值。
  5. 计算个体适应值(个体对环境的适应能力):这里把小于0的值去掉了,目的是为了下一步自然选择做准备,如果出现小于0的目标值,会导致下一步出现逻辑错误。
  6. 计算自然选择后新的群体(自然选择):先把上一步中计算得到的个体对环境的适应能力fitvalue,进行归一化处理,将使得全部概率之和为1,然后将概率从小到大按顺序排序。然后生成一个群体的随机数,当随机数在属于概率中,则新的群体中对应的数即为原始的个体。(好像表述的不太清楚,简单的来说就是进行选择,随机将高适应能力的个体留下来)。
  7. 交叉,变异:这里我也没仔细研究,能用就行,反正就是实现和染色体的交叉变异相似的过程。
  8. 对选择交叉变异后的群体重新计算目标函数以及个体适应度,并找出适应度最高的个体,保存对应个体及其适应度。并选择交叉变异后的群体赋值给初始群体,重新再开始遗传。

处理最小值问题:

两种情况:是否目标函数值存在负数。
1、如果不存在负数:可以采用取倒数的操作,实现求最小值

2、如果存在负数:可以采用取反的操作,实现求最小值

不论是取反还是取倒数最后计算最小值时,都记得要取回来。

算法系列——遗传算法matlab编程详解相关推荐

  1. 汽车理论matlab编程,汽车理论课后作业matlab编程详解(带注释)[试题学习]

    <汽车理论课后作业matlab编程详解(带注释)[试题学习]>由会员分享,可在线阅读,更多相关<汽车理论课后作业matlab编程详解(带注释)[试题学习](11页珍藏版)>请在 ...

  2. 汽车理论matlab编程,汽车理论课后作业matlab编程详解带注释[10页]

    <汽车理论课后作业matlab编程详解带注释[10页]>由会员分享,可在线阅读,更多相关<汽车理论课后作业matlab编程详解带注释[10页](11页珍藏版)>请在读根文库上搜 ...

  3. 汽车理论课后习题matlab程序,汽车理论课后作业matlab编程详解(带注释).doc

    汽车理论课后作业matlab编程详解(带注释) 1.3matlab程序: (1)%驱动力-行驶阻力平衡图%货车相关参数. m=3880;g=9.8;nmin=600;nmax=4000;G=m*g;i ...

  4. Java经典算法四十例编程详解+程序实例

    JAVA经典算法40例 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: ...

  5. 汽车理论matlab编程,汽车理论课后作业matlab编程详解(带注释)

    1.3matlab程序: (1) %驱动力-行驶阻力平衡图 %货车相关参数. m=3880; g=9.8; nmin=600; nmax=4000; G=m*g; ig=[5.56 2.769 1.6 ...

  6. 免疫算法(IA)MatLab代码详解

    CSDN编辑器里面没有MATLAB选项,所以我为了注释更清楚,用的是//,大家不要被误解了呀,算法看代码就好了 1 免疫算法的精髓 生物免疫系统:动态性免疫.自适应免疫 免疫算法-保证信息的无害性.有 ...

  7. Java高并发编程详解系列-Java线程入门

    根据自己学的知识加上从各个网站上收集的资料分享一下关于java高并发编程的知识点.对于代码示例会以Maven工程的形式分享到个人的GitHub上面.   首先介绍一下这个系列的东西是什么,这个系列自己 ...

  8. 并发编程系列之volatile关键字详解

    并发编程系列之volatile关键字详解 1.volatile是什么? 首先简单说一下,volatile是什么?volatile是Java中的一个关键字,也是一种同步机制.volatile为了保证变量 ...

  9. [进阶] --- Python3 异步编程详解(史上最全篇)

    [进阶] - Python3 异步编程详解:https://blog.csdn.net/lu8000/article/details/45025987 参考:http://aosabook.org/e ...

  10. RxJS 系列之二 - Observable 详解

    查看新版教程,请访问前端修仙之路 RxJS 系列目录 RxJS 系列之一 - Functional Programming 简介 RxJS 系列之二 - Observable 详解 (本文) RxJS ...

最新文章

  1. 每日记载内容总结44
  2. OAM 深入解读:使用 OAM 定义与管理 Kubernetes 内置 Workload
  3. js中text方法是啥意识_一盏茶的时间,快速捕获JS中常用的方法(细心整理,持续更新ing)...
  4. 外挂学习之路(6)--- 选怪call
  5. 新手手册:Pytorch分布式训练
  6. android 双层饼图_python:给表格加上双层饼图,让同事的图表黯然失色
  7. 使用Mac终端设置alias常用别名,以git提交为例
  8. MySql 应用语句
  9. 强大的PHP给图片加水印
  10. windows、Linux下nginx搭建集群
  11. spring.net与OracleODP结合时发生的版本问题
  12. ps图层组快捷键 一次打开或关闭所有的顶级图层组
  13. 2.2TextCNN
  14. 极客星球 | Unity3D插件模板化探索
  15. Vmware 8里运行冒险岛097——提取Vmware Tools源文件
  16. iOS中日本日历、佛教日历取date的问题
  17. java消除噪声数据,高光谱图像去噪相关资源汇总(常用对比算法+数据集+评价指标)...
  18. 云计算概念_云计算的概念
  19. 计算机网络 | 实验二 WINPCWP编程
  20. echarts pie饼图的使用(初级版包括设置百分比)

热门文章

  1. c++ 时间轮与时间堆定时器
  2. 中山大学本科偏微分方程试题
  3. 计算机怎么删除表格,怎么快速删除电脑word文档中不想要的表格
  4. 离散数学及其应用 前言
  5. 使用dockerfile搭建java运行环境
  6. 单片机原理与c语言程序设计付先成版答案,单片机原理与C语言程序设计
  7. matlab前馈仿真,前馈-反馈控制系统的具体分析及其MATLAB/Simulink.PDF
  8. 固定资产管理流程步骤
  9. 产品读书《认知盈余》
  10. 海信信号机后台服务器配置,海信自适应交通信号控制系统解决方案