经典遗传算法及简单实例(MATLAB)

  • 1. 遗传算法简单介绍
    • 1.1 理论基础
    • 1.2 算法要点
      • 1.1 编码
      • 1.2 适应度函数
    • 1.3 基本流程
  • 2. 代码实例(MATLAB)
    • 2.1 代码汇总
    • 2.1 初始化种群
    • 2.2 计算适应度
    • 2.3 迭代终止判断
    • 2.4 自然选择(轮盘赌法)
    • 2.5 配对交叉(单点)
    • 2.6 变异(基本位变异)
    • 2.7 获得最优解
    • 2.8 雪兔遗传结果
    • 2.9 改善遗传算法的方法
  • 3. 多多交流!

1. 遗传算法简单介绍

1.1 理论基础

整个算法的基础就是达尔文的生物进化论,“物竞天择,适者生存” 这句话已经是常识了。

用雪兔做一个引子吧:

东北那旮瘩,有群原始雪兔,刚从未知物种进化而来,五颜六色(表现型)漂亮极了,称之为 I(0)。
(注意:种群初始化)

入夏了,雪兔们出来觅食,浅色兔在草地中无所遁形,被雪狐收割了一波(大批浅色+小批深色)。
入冬了,雪兔们出来觅食,深色兔在雪地中光彩夺目,被雪狐收割了一波(大批深色+小批浅色)。
(注意:自然选择过程)

春天到了,又到了兔兔们生孩的季节,雪兔们染色体内的基因进行 重组/不重组 ,产生一批受精卵。
(注意:交叉遗传过程)

受精卵内的生命活动非常强烈,造成了基因的 突变/不突变,产生了各种各样奇怪的小雪兔。
(注意:基因变异过程)

老雪兔们完成了自己繁衍的使命,全部不知所踪。留下新生代,继续在各种威胁下苟活,这一代叫 I(1)。

再次入冬入夏,雪兔们又出来觅食。。。。。。再次入冬,觅食。。。。。。入冬,觅食。。。。。。

就这样,50年后,基因突变和重组造就了种神奇的兔子:夏天褐色,冬天白色,可以轻易躲避雪狐的追捕

再次入冬入夏,雪兔们又出来觅食。。。。。。再次入冬,觅食。。。。。。入冬,觅食。。。。。。

这样,50年后,雪地里基本上见不到五颜六色的雪兔了,这时候雪兔们达到了兔生巅峰!

这就是遗传算法的理论基础,自然选择、交叉、变异、迭代,最终获得最优解。

注意:算法是根据表现型来进行选择,最终选出最优的表现型及其对应的基因。

1.2 算法要点

1.1 编码

编码是为了把我们的输入参数变成染色体(每个个体只有一条染色体),以便于进行交叉和遗传运算。

例如我们把雪兔的颜色进行划分, 0-255 (表现型)代表 黑->白 的不同程度,0就是纯黑的,255就是纯白的。

我们这里只谈一下简单的二进制编码,二进制编码中的每一个二进制位是一个基因,整个数字为染色体。

那么0-255共有256阶(表现型),我们可以用8位2进制数来表示(基因型)。

兔色为0的编码为 00000000,兔色为2的编码为 00000010,兔色为255的编码为 11111111。

1.2 适应度函数

适应度函数就是个体对环境的适应度,适应度越强的越能产生后代,保留自己的基因及表现型。

这里,我们假设灰色兔子的适应能力最强,即兔色为128的兔子不会被吃掉,设定函数为:

是一个最大值为128的分段函数,图像如下:

适应度函数的极值点一般是未知的,这里我们为了演示方便,就先展示出来。

1.3 基本流程

流程就和雪兔故事一样简单,如下所示:

注意:迭代的终止条件可以不是最大迭代次数,比如规定为种群适应度值的方差小于某个值(即种群表现型趋于一致)。

2. 代码实例(MATLAB)

2.1 代码汇总

遗传算法代码(通用代码):

function [bestChromosome,fitnessBest]=GA(numOfChromosome,numOfGene,iterationNum)
%% 函数功能:执行基于自适应遗传算法的卸载决策
%   输入:
%       numOfChromosome:染色体数量,即迭代的种群大小
%       numOfGene:基因的数量,即所用二进制编码的位数
%       iterationNum:迭代的总次数,达到迭代次数即终止迭代
%   输出:
%       bestChromosome:最优的染色体(即最优的输入)
%       fitnessBest:最优的适应度值(即最优的结果)%% 随机生成初始种群,种群大小为numOfChromosome,染色体中基因数为numOfGene
% lastPopulation:上一代的种群(染色体)
% newPopulation:新一代的种群(染色体)
% randi([0,1])会产生0或1的整数
lastPopulation=randi([0,1],numOfChromosome,numOfGene);
newPopulation=zeros(numOfChromosome,numOfGene);%% 进行遗传迭代,直至达到最大迭代次数iterationNum
for iteration=1:iterationNum%% 计算所有个体(染色体)的适应度,一共有numOfChromosome个适应度值fitnessAll=zeros(1,numOfChromosome);for i=1:numOfChromosomeindividual=lastPopulation(i,:);fitnessAll(i)=fitnessFunc(individual);end%% 如果达到最大迭代次数,跳出(不能再进行选择遗传和变异了)if iteration==iterationNumbreak;end%% 使用轮盘赌法选择numOfChromosome条染色体,种群中个体总数不变fitnessSum=sum(fitnessAll);fitnessProportion=fitnessAll/fitnessSum;% 使用随机数进行numOfChromosome次选择,保持种群中个体数量不变for i=1:numOfChromosomeprobability=rand(1);proportionSum=0;chromosomeIndex=1;for j=1:numOfChromosomeproportionSum=proportionSum+fitnessProportion(j);if proportionSum>=probabilitychromosomeIndex=j;break;endendnewPopulation(i,:)=lastPopulation(chromosomeIndex,:);end%% 将染色体进行配对,执行单点交叉lastPopulation=newPopulation;% 生成从1到numOfChromosome的无序排列,每两个相邻数字进行配对coupleAllIndex=randperm(numOfChromosome);for i=1:floor(numOfChromosome/2)coupleOneIndex=coupleAllIndex(2*i-1:2*i);% 定义两条染色体交叉的概率,自己选择probability=0.6;% 如果生成的随机数在交叉概率内,执行交叉操作if rand(i)<probability% 随机生成交叉的基因点,将两条基因进行交叉crossPosition=randi([1,numOfGene],1);newPopulation(coupleOneIndex(1),crossPosition:end)=lastPopulation(coupleOneIndex(2),crossPosition:end);newPopulation(coupleOneIndex(2),crossPosition:end)=lastPopulation(coupleOneIndex(1),crossPosition:end);endend%% 对每条染色体执行基本位变异操作lastPopulation=newPopulation;for i=1:numOfChromosome% 定义染色体变异的概率,自己选择probability=0.2;% 如果生成的随机数在变异概率内,执行变异操作if rand(1)<probability% 选择变异的位置mutatePosition=randi([1,numOfGene],1);% 将对应基因位置的二进制数反转if(lastPopulation(i,mutatePosition)==0)newPopulation(i,mutatePosition)=1;elsenewPopulation(i,mutatePosition)=0;endendend %% 完成了一次迭代,更新种群lastPopulation=newPopulation;
end%% 遗传迭代结束后,获得最优适应度值和对应的基因
fitnessBest=max(fitnessAll);
bestChromosome=newPopulation(find(fitnessAll==fitnessBest,1),:);

雪兔例子的适应度计算代码:

function fitness=fitnessFunc(chromosome)
%% 函数功能:计算染色体的表现型及其适应度
% 输入:
%       chromosome:染色体的基因序列
% 输出:
%       fitness:染色体(个体)的适应度值%% 计算雪兔染色体对应表现型
len=length(chromosome);
numList=2.^(len-1:-1:0);
x=sum(chromosome.*numList);%% 计算表现型对应的适应度
if x<128fitness=x;
elseif x>128fitness=256-x;elsefitness=128;end
end

2.1 初始化种群

%% 随机生成初始种群,种群大小为numOfChromosome,染色体中基因数为numOfGene
% lastPopulation:上一代的种群(染色体)
% newPopulation:新一代的种群(染色体)
% randi([0,1])会产生0或1的整数
lastPopulation=randi([0,1],numOfChromosome,numOfGene);
newPopulation=zeros(numOfChromosome,numOfGene);

这里使用随机数生成函数生成了numOfChromosome条染色体,每条染色体有numOfGene个基因。

将生成的种群放入lastPopulation中,每一行是一条染色体。

newPopulation相当于一个辅助数组,存储生成种群的中间结果。

2.2 计算适应度

    %% 计算所有个体(染色体)的适应度,一共有numOfChromosome个适应度值fitnessAll=zeros(1,numOfChromosome);for i=1:numOfChromosomeindividual=lastPopulation(i,:);fitnessAll(i)=fitnessFunc(individual);end

计算种群中所有个体的适应度,即把每一条染色体(个体)都放入适应度函数中,得到适应度结果。

2.3 迭代终止判断

    %% 如果达到最大迭代次数,跳出(不能再进行选择遗传和变异了)if iteration==iterationNumbreak;end

计算完适应度,如果达到终止条件,就不再进行选择、遗传和变异了。

否则你跳出循环时,种群适应度与计算的的适应度不匹配。

另一种方案:执行选择、遗传、变异,跳出循环后再次计算适应度即可。

2.4 自然选择(轮盘赌法)

    %% 使用轮盘赌法选择numOfChromosome条染色体,种群中个体总数不变fitnessSum=sum(fitnessAll);fitnessProportion=fitnessAll/fitnessSum;% 使用随机数进行numOfChromosome次选择,保持种群中个体数量不变for i=1:numOfChromosomeprobability=rand(1);proportionSum=0;chromosomeIndex=1;for j=1:numOfChromosomeproportionSum=proportionSum+fitnessProportion(j);if proportionSum>=probabilitychromosomeIndex=j;break;endendnewPopulation(i,:)=lastPopulation(chromosomeIndex,:);end

计算每个个体适应度占总适应度的比例,总适应度是一个饼图,每个个体占据一定的扇形区域。

然后生成numOfChromosome个0-1的随机数,随机数落在哪个区域,哪个个体便被生存,可重复选择。

显然,适应度高的个体容易被选择,将自己的基因和表现型遗传下去。

2.5 配对交叉(单点)

    %% 将染色体进行配对,执行单点交叉lastPopulation=newPopulation;% 生成从1到numOfChromosome的无序排列,每两个相邻数字进行配对coupleAllIndex=randperm(numOfChromosome);for i=1:floor(numOfChromosome/2)coupleOneIndex=coupleAllIndex(2*i-1:2*i);% 定义两条染色体交叉的概率,自己选择probability=0.6;% 如果生成的随机数在交叉概率内,执行交叉操作if rand(i)<probability% 随机生成交叉的基因点,将两条基因进行交叉crossPosition=randi([1,numOfGene],1);newPopulation(coupleOneIndex(1),crossPosition:end)=lastPopulation(coupleOneIndex(2),crossPosition:end);newPopulation(coupleOneIndex(2),crossPosition:end)=lastPopulation(coupleOneIndex(1),crossPosition:end);endend

进行遗传的前提是配对,每两条染色体组合成一对,将两者的部分染色体进行交换。

单点交叉,顾名思义,选择染色体上的一个基因点,从这个基因点开始的两条染色体片段互换:

2.6 变异(基本位变异)

    %% 对每条染色体执行基本位变异操作lastPopulation=newPopulation;for i=1:numOfChromosome% 定义染色体变异的概率,自己选择probability=0.2;% 如果生成的随机数在变异概率内,执行变异操作if rand(1)<probability% 选择变异的位置mutatePosition=randi([1,numOfGene],1);% 将对应基因位置的二进制数反转if(lastPopulation(i,mutatePosition)==0)newPopulation(i,mutatePosition)=1;elsenewPopulation(i,mutatePosition)=0;endendend

基本位变异就是选择一条染色体上的一个基因点,将其取反。

如染色体 11111111,选择其第四个基因进行基本位变异, 新染色体变为 11101111

2.7 获得最优解

%% 遗传迭代结束后,获得最优适应度值和对应的基因
fitnessBest=max(fitnessAll);
bestChromosome=newPopulation(find(fitnessAll==fitnessBest,1),:);

迭代结束之后,我们求出最大的适应度及其对应的染色体(个体),这就是我们需要的最优个体。

2.8 雪兔遗传结果

我们运行2.1给出的GA函数,在命令行输入以下代码运行:

[bestChromosome,fitnessBest]=GA(40,8,60)

40个染色体进行60次迭代。多次这行代码,发现结果可以不同,如下:



虽然结果不尽相同,但都接近最优解128,这是遗传算法本身的局限,不一定能获得最优解。

2.9 改善遗传算法的方法

通过2.8我们知道,遗传算法有时候只能逼近最优解,那么有什么方法能让他达到更好的逼近效果呢?

这里有几个方案:

  1. 使用自适应遗传和变异概率
  2. 增加种群中个体数量
  3. 增大迭代次数
  4. 使用双点交叉法
  5. 采用多样的变异方法
  6. 更改编码方式(某些情况)
  7. 更换适应度函数,将个体适应度的差距拉大
  8. 更换选择方法,轮盘赌法是最基本的方法,不科学

大家可以自行了解,以后可能会继续就这几个方面探讨。

3. 多多交流!

经典遗传算法及MATLAB实例相关推荐

  1. 智能优化算法及其MATLAB实例(第二版)——遗传算法2.1

    一.遗传算法运算流程: (1)初始化.设置进化代数计数器g=0,设置最大进化代数G,随机生成NP个个体作为初始群体P(0). (2)个体评价.计算群体P( t)中各个个体的适应度. (3)选择运算.将 ...

  2. 龙格库塔法解微分方程组的matlab程序,MATLAB实例源码教程:龙格库塔法求解微分方程组源代码实例.doc...

    MATLAB实例源码教程:龙格库塔法求解微分方程组源代码实例.doc MATLAB实例源码教程龙格库塔法求解微分方程组源代码实例题目用经典 Runge-Kutta方法求下列一阶微分方程组的近似解y1 ...

  3. Algorithm之PrA:PrA之IP整数规划(包括0-1整数规划)算法经典案例剖析+Matlab编程实现

    Algorithm之PrA:PrA之IP整数规划算法经典案例剖析+Matlab编程实现 目录 分枝定界法 整数规划例题 0-1整数规划实例 分枝定界法 对有约束条件的最优化问题(其可行解为有限数)的所 ...

  4. 小波图像去噪及matlab实例

    图像去噪        图像去噪是信号处理的一个经典问题,传统的去噪方法多采用平均或线性方法进行,常用的是维纳滤波,但是去噪效果不太好(维纳滤波在图像复原中的作用). 小波去噪             ...

  5. TSP问题遗传算法通用Matlab程序

    程序一:主程序 %TSP问题(又名:旅行商问题,货郎担问题)遗传算法通用matlab程序 %D是距离矩阵,n为种群个数 %参数a是中国31个城市的坐标 %C为停止代数,遗传到第 C代时程序停止,C的具 ...

  6. Algorithm之PrA:PrA之nLP非线性规划算法经典案例剖析+Matlab编程实现

    Algorithm之PrA:PrA之nLP整数规划算法经典案例剖析+Matlab编程实现 目录 有约束非线性规划案例分析 1.投资决策问题 2.利用Matlab实现求解下列非线性规划​ 无约束极值问题 ...

  7. c语言编程 输入螺旋数组,C语言 经典题目螺旋矩阵 实例详解

    C语言 经典题目螺旋矩阵 实例详解 C语言 经典题目螺旋矩阵 //N阶螺旋矩阵 #include #include int main() { int N,i,j,n,num=1; int a[10][ ...

  8. bp神经网络matlab实例蚊子,bp神经网络matlab实例

    bp神经网络matlab实例 采用 Matlab 工具箱函数建立神经网络,对一些基本的神经网络参数进行了说明,深入了解参考 Matlab 帮助文档.实例一% 例 1 采用动量梯度下降算法训练 BP 网 ...

  9. matlab指派问题求法,MATLAB实例:Munkres指派算法

    MATLAB实例:Munkres指派算法 1. 指派问题陈述 指派问题涉及将机器分配给任务,将工人分配给工作,将足球运动员分配给职位等.目标是确定最佳分配,例如,使总成本最小化或使团队效率最大化.指派 ...

  10. matlab中二维散点图,MATLAB实例:二维散点图

    MATLAB实例:二维散点图 用MATLAB实现简单的散点图的绘制,可以自行设置点的形状与颜色,可以去掉坐标轴边框. 数据来源:MATLAB高斯混合数据的生成 将二维数据保存为gauss.txt. 1 ...

最新文章

  1. linux-glibc内存管理小结2(内存相关系统调用的实现)
  2. coreutils-5.0中几个命令的执行过程
  3. python保存两位小数的几种方法,python2保留小数
  4. ubuntu安装pytorch镜像修改及下载
  5. 笑说设计模式-小白逃课被点名
  6. cocoapods安装速度慢,CDN: trunk Repo update failed等问题
  7. 经典神经网络 -- MobileNet : 设计原理与pytorch实现
  8. XP系统优化超简单实用版
  9. Kconfig 基本笔录
  10. 圣诞表白html,圣诞节表白,最浪漫的表白方式
  11. 浙江大学2020计算机考研复试线,浙江大学2020考研复试分数线已公布
  12. hdu 2665 Kth number(划分树模板)
  13. FME将用SHP数据对栅格影像数据进行裁剪
  14. linux大页卸载失败,Linux下CUDA卸载不完全与重装失败
  15. 极其简单的响应式的模块化布局、看板布局 js 工具
  16. 插值与拟合 (二) : 曲线拟合的线性最小二乘法
  17. SpringBoot整合thymeleaf及常用th:标签使用方法
  18. 网络I/O与磁盘I/O
  19. 小型企业网络设计与规划
  20. 据说这是北大教师孔庆东的韩国游记

热门文章

  1. 从HighGUI的一段代码中看OpenCV打开视频的方式
  2. 数电第二版 潘松 陈龙 第一章 答案
  3. SAP物料批次管理配置及操作手册
  4. MATLAB Simulink仿真应用
  5. Fiddler中文乱码解决方法
  6. 软考初级程序员知识点整理之 网络协议与标准
  7. php验证手机号码 函数,PHP 匹配电话,手机,400号码 函数 及正则。很管用。
  8. 2021年全国大学生电子设计大赛题目
  9. java中的递归算法_java递归算法详解
  10. matlab光伏最大功率,光伏系统最大功率点跟踪技术的比较