经典遗传算法及MATLAB实例

经典遗传算法及MATLAB实例经典遗传算法及简单实例 MATLAB 1 遗传算法简单介绍 1 1 理论基础 1 2 算法要点 1 1 编码 1 2 适应度函数 1 3 基本流程 2 雪兔实例 1 遗传算法简单介绍 1 1 理论基础整个算法的基础就是达尔文的生物进化论 物竞天择 适者生存 这句话已经是常识了 雪兔的故事 东北那旮瘩 有群原始雪兔 刚从未知物种进化而来 五颜六色 表现型 漂亮极了 称之为 I 0 注意 种群初始化 入夏了 雪兔们出来觅食 浅色兔在草地中无所遁形 被雪狐收割了一波 大批浅色 小批深色 入冬了 雪

1. 遗传算法简单介绍

1.1 理论基础

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

用雪兔做一个引子吧:

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

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

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

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

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

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

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

1.2 算法要点

1.1 编码

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

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

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

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

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

1.2 适应度函数

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

这里,我们假设灰色兔子的适应能力最强,即兔色为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:numOfChromosome individual=lastPopulation(i,:); fitnessAll(i)=fitnessFunc(individual); end %% 如果达到最大迭代次数,跳出(不能再进行选择遗传和变异了) if iteration==iterationNum break; end %% 使用轮盘赌法选择numOfChromosome条染色体,种群中个体总数不变 fitnessSum=sum(fitnessAll); fitnessProportion=fitnessAll/fitnessSum; % 使用随机数进行numOfChromosome次选择,保持种群中个体数量不变 for i=1:numOfChromosome probability=rand(1); proportionSum=0; chromosomeIndex=1; for j=1:numOfChromosome proportionSum=proportionSum+fitnessProportion(j); if proportionSum>=probability chromosomeIndex=j; break; end end newPopulation(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) 
  

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

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

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

2.3 迭代终止判断

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

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

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

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

2.4 自然选择(轮盘赌法)

 %% 使用轮盘赌法选择numOfChromosome条染色体,种群中个体总数不变 fitnessSum=sum(fitnessAll); fitnessProportion=fitnessAll/fitnessSum; % 使用随机数进行numOfChromosome次选择,保持种群中个体数量不变 for i=1:numOfChromosome probability=rand(1); proportionSum=0; chromosomeIndex=1; for j=1:numOfChromosome proportionSum=proportionSum+fitnessProportion(j); if proportionSum>=probability chromosomeIndex=j; break; end end newPopulation(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) 
  

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

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

在这里插入图片描述

2.6 变异(基本位变异)

 %% 对每条染色体执行基本位变异操作 lastPopulation=newPopulation; for i=1:numOfChromosome % 定义染色体变异的概率,自己选择 probability=0.2; % 如果生成的随机数在变异概率内,执行变异操作 if rand(1) 
  

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

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

2.7 获得最优解

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

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

2.8 雪兔遗传结果

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

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

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




2.9 改善遗传算法的方法

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

这里有几个方案:

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

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

3. 多多交流!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/204416.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午8:20
下一篇 2026年3月19日 下午8:20


相关推荐

  • Django(19)QuerySet API[通俗易懂]

    Django(19)QuerySet API[通俗易懂]前言我们通常做查询操作的时候,都是通过模型名字.objects的方式进行操作。其实模型名字.objects是一个django.db.models.manager.Manager对象,而Manager

    2022年8月7日
    7
  • 以下为Seedance2.0(即梦AI)A股核心标的清单一、直接合作(最确定)

    以下为Seedance2.0(即梦AI)A股核心标的清单一、直接合作(最确定)

    2026年3月12日
    4
  • 从零开始学_JavaScript_系列(27)——dojo的文档相关模块

    从零开始学_JavaScript_系列(27)——dojo的文档相关模块先上图:dojo/dom模块:dojo/dom参数:dom方法:①dom.byId(id,doc);用于通过id来选择某个dom结点;②dom.isDescendant(node,ancestor);确认某个node是否是另外一个结点的子节点;③dom.setSelectable(node,se

    2025年8月30日
    7
  • 工程师的基本功是什么?如何练习?—学习心得分享「建议收藏」

    开头聊几句1、周末休息,今天下雨了,气温还行,不冷不热2、刚看完《这!就是街舞》,很燃很炸,一些作品表达的东西也很让人感动3、发现真正热爱的事情,并为之付出所有的能量,很让人羡慕开头周四上线到比较晚,好在中间有空,去公司楼下湖边散了散步,上线回到家,已经是凌晨了。周五中午在去公司的路上看到了美团技术团队的一篇文章,觉得很不错,值得学习,也分享到朋友圈了,希望保留下方便自己查阅,也分享给更多的技术伙伴,一起看好的文章。在技术之路上,不断的持续学习,持续进步,一起精进。那天朋友圈分享美团的这

    2022年3月1日
    45
  • 星愿浏览器有什么优点_星愿浏览器插件

    星愿浏览器有什么优点_星愿浏览器插件目的:想基于浏览器进程抓包,但是想获得噪声相对小的数据,则找相对ChromeGoogle等主流browser更简单的浏览器;想使用Google的某个扩展程序,所以找基于Chrome内核的浏览器所以,我要找基于Chrome内核的简单浏览器最后找到了这几个符合条件的浏览器:星愿、百分cent、Vival、Brave星愿优点:星愿的主页面具有相当的自主性,可以自由拖动添加图标和更换背景、搜索框等。其主页有个搜索漫画的功能,好像在看漫画这一块做了一些页面优化。缺点:只能在它提供的星愿商店里下扩.

    2025年6月11日
    4
  • not found for libcrypto「建议收藏」

    not found for libcrypto「建议收藏」解决方法sudocp/usr/lib/libcrypto.35.dyliblibcrypto.35.dylib参考:Unabletoconfigureopenssl,libcryptonotfounderrorwithopenssllibraryinstalled

    2022年6月29日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号