遗传算法

1.前言

遗传算法是一种基于生物界自然群体遗传进化机制的自适应全局优化概率搜索算法。它与传统算法不同,不依赖梯度信息,而是通过模拟自然进化过程来搜索最优解。

例子:兔子的遗传进化

有人说,现代医学阻碍了人类的进化?你怎么看?

2.发展历程

遗传算法由密歇根大学的约翰·霍兰德和他的同事于二十世纪六十年代在对细胞自动机(英文:cellular automata)进行研究时率先提出。在二十世纪八十年代中期之前,对于遗传算法的研究还仅仅限于理论方面,直到在匹兹堡召开了第一届世界遗传算法大会。随着计算机计算能力的发展和实际应用需求的增多,遗传算法逐渐进入实际应用阶段。1989年,纽约时报作者约翰·马科夫写了一篇文章描述第一个商业用途的遗传算法--进化者(英文:Evolver)。之后,越来越多种类的遗传算法出现并被用于许多领域中,财富杂志500强企业中大多数都用它进行时间表安排、数据分析、未来趋势预测、预算、以及解决很多其他组合优化问题。

3.应用领域

4.适用问题

全局最优化问题(用其他优化方法较难求解,通常选择GA和LINGO)

5.算法详解

刚才说到了遗传算法的来源与基础,下面我们来具体说一说生物进化与遗传算法名词的对应关系。

5.1 对应关系

生物进化

遗传算法

环境

适应函数

适者生存

适应函数值最大的解被保留的概率最大

个体

问题的一个解

染色体

解的编码

基因

编码的元素

种群

根据适应函数选择的一组解

交叉(交配)

以一定的方式由双亲产生后代的过程

变异

编码的某些分量发生变化的过程

了解了上面的对应关系之后,我们再一起来看遗传算法究竟是怎么实现的。

5.2 算法思想

遗传算法是从代表问题可能潜在解集的一个种群(population)

开始的,而一个种群则由经过基因编码(coding)的一定数目的个体(individual)组成。每个个体实际上是染色体(chromosome)带有特征的实体。为了简化,往往采用二进制编码。对种群反复进行选择(selection)、交叉(crossover)、变异(mutation)操作,估计各个体的适应值(fitness),根据”适者生存、优胜劣汰”的进化规则,产生最好的种群,使适应性好的个体比适应性差的个体有更多的繁殖机会。最后把末代种群中的最优个体经过解码(decoding),可以获得满足要求的最优解。

5.3流程图描述

5.4 伪代码描述

(1) 随机产生初始种群;

(2) 计算种群体中每个个体的适应度值,判断是否满足停

止条件,若不满足,则转第(3)步,否则转第(7)步;

(3) 按由个体适应值所决定的某个规则选择将进入下一代

的个体;

(4) 按交叉概率Pc进行交叉操作,生产新的个体;

(5) 按变异概率Pm进行变异操作,生产新的个体;

(6) 输出种群中适应度值最优的染色体作为问题的满意解

或最优解。

  • Ø 具体讲解

遗传算法的具体实现

问题

如何进行编码?

如何产生初始种群?

如何定义适应函数?

如何进行遗传操作(复制、交叉、变异)?

如何产生下一代种群?

如何定义停止准则?

6.例题解析

6.1 例1:求解多变量多约束非线性规划问题

求解以下问题的解

函数图像:

解法:

      这题属于规划类问题,我们可以用LINGO来求解。

(1)  在LINGO中求解:

那么在遗传算法里面我们要怎么样去解决它呢?

(2)  在MATLAB中求解(GA工具箱求解):

这里使用到的是MATLAB自带的GA工具箱,即GADS工具箱。

遗传工具箱共有四大版本,分别是

英国Sheffield《genetic arithmetic toolbox》(GATBX遗传算法工具箱)

中国陈益《simple genetic algorithms laboratory》(SGALAB简单遗传算法实验室)

美国NCSU-IE《Genetic Algorithm Optimization Tool》(GAOT遗传算法优化工具箱)

美国MathWorks《Genetic Algorithm and Direct Search Toolbox 》(GADS遗传算法和直接搜索工具箱)

6.2 例2:求解最值问题

求解以下问题

函数图像为

最大值大约在x=1.5附近取得。

(1)   在LINGO中求解:

(2)  在MATLAB中求解:

第一种方法:使用GA工具箱

注意:GA工具箱默认求最小值!若要求最大值,需要加上负号!

代码实现如下:

%主程序代码,本程序采用遗传算法接力进化,
%将上次进化结束后得到的最终种群作为下次输入的初始种群
%主程序代码,
clc;
close all;
clear all; % 进化的代数
T=50;
% 初始的种群
options=gaoptimset('Generations',T);
[x,fval,reason,output,final_pop]=ga(@fitnessfun,1,options); %进行第二次接力进化
options1=gaoptimset('Generations',T,'InitialPopulation',final_pop,'PlotFcns',@gaplotbestf);
[x,fval,reason,output,final_pop]=ga(@fitnessfun,1,options1); Bestx=x
BestFval=-fval % 适应度函数
function f = fitnessfun(x)
if(x<-2|x>2)
f=100;
else
f=-200*exp(-0.05*x)*sin(x);
end
end

生成结果如下:

要点:适应度函数的选取

第二种方法:使用GA工具箱GUI(有可能在将来的版本中移除)

这里我给大家实际演示一下。

要点

第三种方法:自定义实现遗传算法

接下来就步入正题了,因为工具箱提供的功能有限,很多时候不能很好地满足我们的需要,那我们怎么自己实现一个遗传算法呢?

代码实现如下:

%主程序代码,本程序采用遗传算法接力进化,
%将上次进化结束后得到的最终种群作为下次输入的初始种群
clc;
close all;
clear all; %进化的代数
T=100;
optionsOrigin=gaoptimset('Generations',T);
[x,fval,reason,output,finnal_pop]=ga(@fitnessfun,2,optionsOrigin); %进行第二次接力进化
options1=gaoptimset('Generations',T,'InitialPopulation',finnal_pop,'PlotFcns',@gaplotbestf);
[x,fval,reason,output,finnal_pop,trace]=ga(@fitnessfun,2,options1); Bestx=x
BestFval=fval % 适应度函数
function f = fun(x)
g1=1.5+x(1)*x(2)-x(1)-x(2);
g2=-x(1)*x(2)-10;
if (g1>0|g2>0)
f=100;
else
f=exp(x(1))*(4*x(1)^2+2*x(2)^2+4*x(1)*x(2)+2*x(2)+1);;
end
end %主程序:
%用遗传算法求解y=200*exp(-0.05*x).*sin(x)在[-2 2]区间上的最大值
clc;
clear all;
close all; global BitLength
global boundsbegin
global boundsend
bounds=[-2 2];%一维自变量的取值范围
precision=0.0001; %运算精度
boundsbegin=bounds(:,1);
boundsend=bounds(:,2);
%计算如果满足求解精度至少需要多长的染色体
BitLength=ceil(log2((boundsend-boundsbegin)' ./ precision));
popsize=50; %初始种群大小 Generationnmax=100; %最大代数
pcrossover=0.90; %交配概率
pmutation=0.09; %变异概率
%产生初始种群
population=round(rand(popsize,BitLength));
%计算适应度,返回适应度Fitvalue和累积概率cumsump
[Fitvalue,cumsump]=fitnessfun(population);
Generation=1;
while Generation<Generationnmax+1
for j=1:2:popsize
%选择操作
seln=selection(population,cumsump);
%交叉操作
scro=crossover(population,seln,pcrossover);
scnew(j,:)=scro(1,:);
scnew(j+1,:)=scro(2,:);
%变异操作
smnew(j,:)=mutation(scnew(j,:),pmutation);
smnew(j+1,:)=mutation(scnew(j+1,:),pmutation);
end
population=smnew; %产生了新的种群
%计算新种群的适应度
[Fitvalue,cumsump]=fitnessfun(population);
%记录当前代最好的适应度和平均适应度
[fmax,nmax]=max(Fitvalue);
fmean=mean(Fitvalue);
ymax(Generation)=fmax;
ymean(Generation)=fmean;
%记录当前代的最佳染色体个体
x=transform2to10(population(nmax,:));
%自变量取值范围是[-2 2],需要把经过遗传运算的最佳染色体整合到[-2 2]区间
xx=boundsbegin+x*(boundsend-boundsbegin)/(power((boundsend),BitLength)-1);
xmax(Generation)=xx;
Generation=Generation+1
end
Generation=Generation-1;
Bestpopulation=xx
Besttargetfunvalue=targetfun(xx)
%绘制经过遗传运算后的适应度曲线。一般地,如果进化过程中种群的平均适应度与最大适
%应度在曲线上有相互趋同的形态,表示算法收敛进行得很顺利,没有出现震荡;在这种前
%提下,最大适应度个体连续若干代都没有发生进化表明种群已经成熟。
figure(1);
hand1=plot(1:Generation,ymax);
set(hand1,'linestyle','-','linewidth',1.8,'marker','*','markersize',6)
hold on; hand2=plot(1:Generation,ymean);
set(hand2,'color','r','linestyle','-','linewidth',1.8,...
'marker','h','markersize',6)
xlabel('进化代数');ylabel('最大/平均适应度');xlim([1 Generationnmax]);
legend('最大适应度','平均适应度');
box off;hold off; %子程序:新种群交叉操作,函数名称存储为crossover.m
function scro=crossover(population,seln,pc);
BitLength=size(population,2);
pcc=IfCroIfMut(pc); %根据交叉概率决定是否进行交叉操作,1则是,0则否
if pcc==1
chb=round(rand*(BitLength-2))+1; %在[1,BitLength-1]范围内随机产生一个交叉位
scro(1,:)=[population(seln(1),1:chb) population(seln(2),chb+1:BitLength)];
scro(2,:)=[population(seln(2),1:chb) population(seln(1),chb+1:BitLength)];
else
scro(1,:)=population(seln(1),:);
scro(2,:)=population(seln(2),:);
end %子程序:计算适应度函数, 函数名称存储为fitnessfun
function [Fitvalue,cumsump]=fitnessfun(population);
global BitLength
global boundsbegin
global boundsend
popsize=size(population,1); %有popsize个个体
for i=1:popsize
x=transform2to10(population(i,:)); %将二进制转换为十进制
%转化为[-2,2]区间的实数
xx=boundsbegin+x*(boundsend-boundsbegin)/(power((boundsend),BitLength)-1);
Fitvalue(i)=targetfun(xx); %计算函数值,即适应度
end
%给适应度函数加上一个大小合理的数以便保证种群适应值为正数
Fitvalue=Fitvalue'+230;
%计算选择概率
fsum=sum(Fitvalue);
Pperpopulation=Fitvalue/fsum;
%计算累积概率
cumsump(1)=Pperpopulation(1);
for i=2:popsize
cumsump(i)=cumsump(i-1)+Pperpopulation(i);
end
cumsump=cumsump'; %子程序:新种群变异操作,函数名称存储为mutation.m
function snnew=mutation(snew,pmutation);
BitLength=size(snew,2);
snnew=snew;
pmm=IfCroIfMut(pmutation); %根据变异概率决定是否进行变异操作,1则是,0则否
if pmm==1
chb=round(rand*(BitLength-1))+1; %在[1,BitLength]范围内随机产生一个变异位
snnew(chb)=abs(snew(chb)-1);
end %子程序:判断遗传运算是否需要进行交叉或变异, 函数名称存储为IfCroIfMut.m
function pcc=IfCroIfMut(mutORcro);
test(1:100)=0;
l=round(100*mutORcro);
test(1:l)=1;
n=round(rand*99)+1;
pcc=test(n); %子程序:新种群选择操作, 函数名称存储为selection.m
function seln=selection(population,cumsump);
%从种群中选择两个个体
for i=1:2
r=rand; %产生一个随机数
prand=cumsump-r;
j=1;
while prand(j)<0
j=j+1;
end
seln(i)=j; %选中个体的序号
end %子程序:将2进制数转换为10进制数,函数名称存储为transform2to10.m
function x=transform2to10(Population);
BitLength=size(Population,2);
x=Population(BitLength);
for i=1:BitLength-1
x=x+Population(BitLength-i)*power(2,i);
end %子程序:对于优化最大值或极大值函数问题,目标函数可以作为适应度函数
%函数名称存储为targetfun.m
function y=targetfun(x); %目标函数
y=200*exp(-0.05*x).*sin(x);

生成结果如下:

遗传算法详解(LINGO及MatlabGA工具箱求解实现)的更多相关文章

  1. 遗传算法详解及c++实现

    1.什么是遗传算法? 遗传算法是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法.遗传算法是从代表问题可能潜在的解集的一个种群开始的,而一 ...

  2. 利用python求解物理学中的双弹簧质能系统详解

    利用python求解物理学中的双弹簧质能系统详解 本文主要给大家介绍了关于利用python求解物理学中双弹簧质能系统的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 物理的 ...

  3. 详解用python实现简单的遗传算法

    详解用python实现简单的遗传算法 今天整理之前写的代码,发现在做数模期间写的用python实现的遗传算法,感觉还是挺有意思的,就拿出来分享一下. 首先遗传算法是一种优化算法,通过模拟基因的优胜劣汰 ...

  4. libsvm的安装,数据格式,常见错误,grid.py参数选择,c-SVC过程,libsvm参数解释,svm训练数据,libsvm的使用详解,SVM核函数的选择

    直接conda install libsvm安装的不完整,缺几个.py文件. 第一种安装方法: 下载:http://www.csie.ntu.edu.tw/~cjlin/cgi-bin/libsvm. ...

  5. 用Advanced Installer制作DotNetBar for Windows Forms 12.0.0.1_冰河之刃重打包版详解

    关于 DotNetBar for Windows Forms 12.0.0.1_冰河之刃重打包版 --------------------11.8.0.8_冰河之刃重打包版-------------- ...

  6. JS逗号运算符的用法详解

    逗号运算符的用法详解 注意: 一.由于目前正在功读JavaScript技术,所以这里拿JavaScript为例.你可以自己在PHP中试试. 二.JavaScript语法比较复杂,因此拿JavaScri ...

  7. Dancing Link 详解(转载)

    Dancing Link详解: http://www.cnblogs.com/grenet/p/3145800.html Dancing Link求解数独: http://www.cnblogs.co ...

  8. ArcGIS中的北京54和西安80投影坐标系详解

    ArcGIS中的北京54和西安80投影坐标系详解 1.首先理解地理坐标系(Geographic coordinate system),Geographic coordinate system直译为地理 ...

  9. kmp算法详解

    转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...

随机推荐

  1. USACO Humble Numbers

    USACO  Humble Numbers 这题主要是两种做法,第一种是比较常(jian)规(dan)的-------------用pq(priority_queue)维护,每次取堆中最小值(小根堆) ...

  2. MySQL_执行计划详细说明

          1 简要说明 id 表格查询的顺序编号. 降序查看,id相同的从上到下查查看. id可以为null ,当table为( union ,m,n )类型的时候,id为null,这个时候,id的 ...

  3. C语言数据类型作业

    一.PTA实验作业 题目1:7-4 打印菱形图案 1. 本题PTA提交列表 2. 设计思路 1.定义m,n(用于计算空格数,输出"* "数),i,j,k(用于循环) 2.输入n,并 ...

  4. C语言程序设计第三次作业--选择结构(1)

    Deadline: 2017-10-29 22:00 一.学习要点 掌握关系运算符和关系表达式 掌握如何判断两个实数相等 掌握常用数学函数的使用 掌握逻辑运算符和逻辑表达式 理解逻辑运算的短路特性 掌 ...

  5. Linux下硬盘分区

    1  fdisk -l查看硬盘及分区信息 我的系统(Archlinux)下的命令效果如下: 由上面的图片可以得知该系统只挂载了1个硬盘,命名为sda,其有2个主分区,sda1和sda2,至于为什么这么 ...

  6. scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250

    scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250 前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大 ...

  7. 在深度linux下安装pip3与jupyter

    前言 以下安装说明基于已经正确安装python3 文件下载 https://pypi.python.org/pypi/pip 下载pip-9.0.1.tar.gz (md5, pgp)文件 安装准备工 ...

  8. Flask 扩展 Flask-RESTful

    Flask路由可以指定HTTP请求方法,并在请求函数中根据不同的请求方法,执行不同的逻辑.这样实现一个Restful的请求已经相当简单了 Flask还有更简便的方法,就是其Flask-RESTful扩 ...

  9. python利用twilio模块给自己发短信

    1.访问http://twilio.com/并填写注册表单.注册了新账户后,你需要验证一个手机号码,短信将发给该号码. 2.Twilio 提供的试用账户包括一个电话号码,它将作为短信的发送者.你将需要 ...

  10. day-6 机器学习概念及应用

    学习玩Python基础语法,今天开始进行机器学习,首先了解下机器学习和深度学习的一些基本概念和术语: 1.  机器学习概念及应用 2.  深度学习概念及应用 3.  机器学习基本术语及举例 4.  机 ...