遗传算法求解函数极大值问题(附测试代码)

2023-10-07 21:59

本文主要是介绍遗传算法求解函数极大值问题(附测试代码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

遗传算法(Genetic Algorithm, GA)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。
简而言之,遗传算法就是通过每次选择比较好的个体进入下一次循环来保证每一轮解的最优特性,其核心思想有以下几个方面。
(1)初始化值(染色体),转化成二进制的形式(为了方便交叉和变异)
(2)使用轮盘赌算法设计策略来选择下一轮进入循环的染色体(只要是为了防止当前适应度值不太好的染色体直接被淘汰)
(3)复制染色体(保证每一轮染色体的条数和初始染色体条数一样,比如初始染色体有4条,通过轮盘赌算法后只选择了3条,那么剩下的一条一般是复制当前轮中比较好的染色体,当然,这个时候4条染色体中有2条是一样的,所以要进行交叉和变异)
(4)交叉,交叉的策略很多,可以选择任意两条染色体相交叉(其实就是交换染色体对应的二进制的某些值,比如选择第一条染色体对应的二进制前3个值和第二条染色体对应的二进制前3个值对换,交叉的目的在于检验这些比较好的染色体相互组合后是否能达到求解要求,也可以说是保留最优染色体基因,其实交叉后也有可能会变差)
(5)变异,当染色体相互交叉后并不能找到最优值,就需要变异,变异就是改变某条染色体中对应的基因值,把染色体对应的二进制中某个1变成0,或者0变成1,变异策略也有很多,需要几个基因变异因问题不同而不同。
交叉和变异都是为了防止进入局部最优。
为了方便说明,根据遗传算法原理,求解二次函数极大值问题,定义域为(1,10)
在这里插入图片描述
步骤为:
(1)根据定义域,初始化染色体数目和值
(2)计算每条染色体对应的y值
(3)根据轮盘赌算法选择下一次要遗传的染色体,染色体数目不够就复制
(4)二进制编码染色体
(5)交叉
(6)变异,更新下一轮循环染色体
(7)没有达到最大循环次数,返回(2),否则,输入目标值。
另外,交叉和变异后最好都检验下新的染色体是否还在定义域范围,如果超出范围,要调整。
代码如下:

clc;
clear all;
%遗传算法求y=x1^2在区间[1 10]的最大值,求y的值和x的值
%初始种群规模M=4
%终止迭代次数
%交叉概率
%变异概率
% 复制 、交叉、变异
beginNum=1+(10-1)*rand(1,4)%随机生成4个初始值,染色体
%计算初始使用度值
T=100;%最大循环次数
tt=1;
maxsyd=[];
while tt<=TbeginNumzydz=[];for j=1:length(beginNum)zydz(j)=beginNum(j)^2;end%      if max(zydz)==100
%          beginNum;
%          break;
%      end%根据轮盘赌算法决定下次遗传的%计算适应度的选择概率p=[];for z=1:length(zydz)p(z)=zydz(z)/sum(zydz);endp;%计算累加概率qq=[];q(1)=p(1);for y=2:length(p)q(y)=p(y)+ q(y-1);endq;gxnum=[];r=rand(1,length(beginNum));%在[0 1]之间产生随机数字r产生length(beginNum)个for k=1:length(r)if r(k)<=q(1)gxnum=[gxnum beginNum(1)];endfor kk=2:length(q) %每个随机数字r在q中的范围if q(kk-1)<r(k)&&r(k)<=q(kk)gxnum=[gxnum beginNum(kk)];endendendgxnum=unique(gxnum,'stable');%判断是否需要复制if length(gxnum)<length(beginNum)% 选择复制优势染色体while length(gxnum)~=length(beginNum)gxnum=[gxnum max(beginNum)];endendm=8;newbeginenum={};%转换成二进制后的初始数,方便变异和交叉操作for i=1:length(gxnum)n=beginNum(i);a=dec2bin(n*2^m);%     b=[a(1:end-m),'.',a(end-m+1:end)];% str2double(a)newbeginenum{i}=a;endt=char(newbeginenum(1));%转成字符串类型%所有二进制的位数必须一样,不足的在前面补0yycount=0;for yy=1:length(newbeginenum)% 找最长位数的二进制yyt1=length(char(newbeginenum(yy)));if yyt1>yycountyycount=yyt1;endendfor pj=1:length(newbeginenum)yy2=length(char(newbeginenum(pj)));if yy2<yycounttempj(1:yycount-yy2)='0';newbeginenum{pj}=strcat(tempj,char(newbeginenum(pj)));%更新newbeginenumendendnm=2;%交换前2位jcnewbeginenum={};%交叉产生新的染色体jcnewbeginenumfor nk=1:2:length(newbeginenum)-1t1=char(newbeginenum(nk));t2=char(newbeginenum(nk+1));tz1=t1(1:nm);tz2=t2(1:nm);% 交换tztemp=tz1;t1(1:nm)=tz2;t2(1:nm)=tztemp;jcnewbeginenum{nk}=t1;jcnewbeginenum{nk+1}=t2;end%判断变异是否超出定义域范围jcnewbeginenum(3);%% 变异,根据要求,设置变异概率10%,%变异基因个数jycountbyhbegine={}; %变异后的值,等下记得判断是否超出定义域的范围for jyk=1:length(jcnewbeginenum)jycount=ceil(length(char(jcnewbeginenum(jyk)))*0.1);% rk=randperm(length(char(jcnewbeginenumjyk))),jycount));%产生变异基因的位置rk=randperm(length(char(jcnewbeginenum(jyk))),jycount);% 替换变异位置bywz=char(jcnewbeginenum(jyk));for byw=1:length(rk)if strcmp(bywz(rk(byw)),'0')bywz(rk(byw))='1';elsebywz(rk(byw))='1';end%     bywz(rk(byw))=~bywz(rk(byw));endbyhbegine{jyk}=bywz;end%把变异后的值转换成十进制替换初始值zzbyhbegine=[];for ncs=1:length(byhbegine)tempaa=char(byhbegine(ncs));%二进制转换成十进制zzbyhbegine(ncs)=bin2dec(tempaa(1:end-m))+bin2dec(tempaa(end-m+1:end))/2^m;endbeginNum=zzbyhbegine;for bj=1:length(beginNum)if beginNum(bj)<1beginNum(bj)=1;endif beginNum(bj)>10beginNum(bj)=10;endendtt=tt+1;maxsyd=[maxsyd max(zydz)];
end
xsyd=1:100;
plot(xsyd,maxsyd,'r-')

运行结果
在这里插入图片描述
可以看到,在定义域为(1,10)中,遗传算法收敛速度还是非常快的(大约在第三轮就已经收敛了)。另外,在实验过程中,由于变异和交叉策略选择的原因,发现该算法还是会陷入局部最优,其陷入局部最优的概率为约为5%。

这篇关于遗传算法求解函数极大值问题(附测试代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/160691

相关文章

linux生产者,消费者问题

pthread_cond_wait() :用于阻塞当前线程,等待别的线程使用pthread_cond_signal()或pthread_cond_broadcast来唤醒它。 pthread_cond_wait() 必须与pthread_mutex 配套使用。pthread_cond_wait()函数一进入wait状态就会自动release mutex。当其他线程通过pthread

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

2024.6.24 IDEA中文乱码问题(服务器 控制台 TOMcat)实测已解决

1.问题产生原因: 1.文件编码不一致:如果文件的编码方式与IDEA设置的编码方式不一致,就会产生乱码。确保文件和IDEA使用相同的编码,通常是UTF-8。2.IDEA设置问题:检查IDEA的全局编码设置和项目编码设置是否正确。3.终端或控制台编码问题:如果你在终端或控制台看到乱码,可能是终端的编码设置问题。确保终端使用的是支持你的文件的编码方式。 2.解决方案: 1.File -> S

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但是本人给出一些暂时的解决办法: 问题1: 我在安装库命令行使用的是 .\vcpkg.exe install opencv 我的电脑是x64,vcpkg在这条命令后默认下载的也是opencv2:x6

【操作系统】信号Signal超详解|捕捉函数

🔥博客主页: 我要成为C++领域大神🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞👍收藏⭐评论✍️ 本博客致力于知识分享,与更多的人进行学习交流 ​ 如何触发信号 信号是Linux下的经典技术,一般操作系统利用信号杀死违规进程,典型进程干预手段,信号除了杀死进程外也可以挂起进程 kill -l 查看系统支持的信号

问题-windows-VPN不正确关闭导致网页打不开

为什么会发生这类事情呢? 主要原因是关机之前vpn没有关掉导致的。 至于为什么没关掉vpn会导致网页打不开,我猜测是因为vpn建立的链接没被更改。 正确关掉vpn的时候,会把ip链接断掉,如果你不正确关掉,ip链接没有断掉,此时你vpn又是没启动的,没有域名解析,所以就打不开网站。 你可以在打不开网页的时候,把vpn打开,你会发现网络又可以登录了。 方法一 注意:方法一虽然方便,但是可能会有

java中查看函数运行时间和cpu运行时间

android开发调查性能问题中有一个现象,函数的运行时间远低于cpu执行时间,因为函数运行期间线程可能包含等待操作。native层可以查看实际的cpu执行时间和函数执行时间。在java中如何实现? 借助AI得到了答案 import java.lang.management.ManagementFactory;import java.lang.management.Threa

vue同页面多路由懒加载-及可能存在问题的解决方式

先上图,再解释 图一是多路由页面,图二是路由文件。从图一可以看出每个router-view对应的name都不一样。从图二可以看出层路由对应的组件加载方式要跟图一中的name相对应,并且图二的路由层在跟图一对应的页面中要加上components层,多一个s结尾,里面的的方法名就是图一路由的name值,里面还可以照样用懒加载的方式。 页面上其他的路由在路由文件中也跟图二是一样的写法。 附送可能存在

vue+elementui--$message提示框被dialog遮罩层挡住问题解决

最近碰到一个先执行this.$message提示内容,然后接着弹出dialog带遮罩层弹框。那么问题来了,message提示框会默认被dialog遮罩层挡住,现在就是要解决这个问题。 由于都是弹框,问题肯定是出在z-index比重问题。由于用$message方式是写在js中而不是写在html中所以不是很好直接去改样式。 不过好在message组件中提供了customClass 属性,我们可以利用

SQL Server中,isnull()函数以及null的用法

SQL Serve中的isnull()函数:          isnull(value1,value2)         1、value1与value2的数据类型必须一致。         2、如果value1的值不为null,结果返回value1。         3、如果value1为null,结果返回vaule2的值。vaule2是你设定的值。        如