网站首页 > 技术文章 正文
接上一个遗传算法原理的例子,记录具体是如何编程的。编码方式是二进制编码,选择函数采用轮盘赌方法。
函数与函数图像
这一次我们的函数是
y=10*sin(5*x)+7*abs(x-5)+10
图像如图所示:
染色体长度的确定
因为我只想精确到小数点后两位,区间[0,10],所以应该需要精度为10*10^2=1000,2^10 = 1024,所以染色体长度为10已经足够。
主函数
function main()
clear;
clc;
%种群大小(规模)
popsize=100;
%二进制编码长度
chromlength=10;
%交叉概率
pc = 0.6;
%变异概率
pm = 0.001;
%初始种群
pop = initpop(popsize,chromlength);
for i = 1:100
%计算适应度值(函数值)
objvalue = cal_objvalue(pop);
fitvalue = objvalue;
%选择操作,选出优良的父母
newpop = selection(pop,fitvalue);
%交叉操作,优良父母交叉产生新后代
newpop = crossover(newpop,pc);
%变异操作,新种群跳一跳改变一下
newpop = mutation(newpop,pm);
%更新种群
pop = newpop;
%寻找最优解
[bestindividual,bestfit] = best(pop,fitvalue);
x2 = binary2decimal(bestindividual);%解码最优个体
x1 = binary2decimal(newpop);%解码新种群
y1 = cal_objvalue(newpop);%计算新种群对应的
if mod(i,10) == 0%每迭代十次画一下图
figure;
fplot('10*sin(5*x)+7*abs(x-5)+10',[0 10]);
hold on;
plot(x1,y1,'*');
title(['迭代次数为n=' num2str(i)]);
%plot(x1,y1,'*');
end
end
fprintf('The best X is --->>%5.2f\n',x2);
fprintf('The best Y is --->>%5.2f\n',bestfit);
初始化种群函数(对种群进行编码)
function pop=initpop(popsize,chromlength)
%初始化种群大小
%输入变量:
%popsize:种群大小
%chromlength:染色体长度-->>转化的二进制长度
%输出变量:
%pop:种群
pop = round(rand(popsize,chromlength));
%rand(3,4)生成3行4列的0-1之间的随机数
% rand(3,4)
%
% ans =
%
% 0.8147 0.9134 0.2785 0.9649
% 0.9058 0.6324 0.5469 0.1576
% 0.1270 0.0975 0.9575 0.9706
%round就是四舍五入
% round(rand(3,4))=
% 1 1 0 1
% 1 1 1 0
% 0 0 1 1
%所以返回的种群就是每行是一个个体,列数是染色体长度
二进制转十进制函数(解码)
function pop2 = binary2decimal(pop)
% 功能:二进制转化成十进制函数
%输入变量:
%二进制种群
%输出变量
%十进制数值
[px,py]=size(pop);
for i = 1:py%py是染色体的长度
pop1(:,i) = 2.^(py-i).*pop(:,i);
end
%sum(.,2)对行求和,得到列向量
temp = sum(pop1,2);
pop2 = temp*10/1023;
适应度函数
function [objvalue] = cal_objvalue(pop)
%计算函数目标值
%输入变量:二进制数值
%输出变量:目标函数值
x = binary2decimal(pop);
%转化二进制数为x变量的变化域范围的数值
objvalue=10*sin(5*x)+7*abs(x-5)+10;
选择函数(为轮盘赌方法)
在开始学习的时候就经常会有一些疑问就是,遗传算法既然是选择优秀的个体(适应度较高的个体),那么应当淘汰一些劣质的个体,执行选择操作之后,新种群应该比原来的种群要小,但是结果运行却是不变的,为什么呢?后来我想明白了就是,如果我们在每次迭代的过程中选择淘汰一些数量,就要保证我们迭代的次数达到后,种群还有一些个体存在,所以我们要适当计算一下每次淘汰的个数是多少。而经典的遗传算法当中,种群大小在执行选择函数之后仍是不变的,因为轮盘赌法在每次迭代过程中会保证有一个个体被选出才会进入下一次循环,而这个数的选出是因为这个数的概率较大(大于随机生成的一个概率),所以新种群中选出的个体有很多是相同的个体,最后达到收敛(种群中所有个体都是一样的,集中在最优秀的地方),下面看算法的操作。
function [newpop] = selection(pop,fitvalue)
%如何选择新的个体
%输入变量:pop二进制种群,fitvalue:适应度值
%输出变量:newpop选择以后的二进制种群
%构造轮盘
[px,py] = size(pop);
totalfit = sum(fitvalue);
p_fitvalue = fitvalue/totalfit;
index = [];
for i = 1:px %px是种群数
pick = rand;
while pick == 0
pick = rand;
end
for j = 1:px
pick = pick - p_fitvalue(j);
if pick < 0
index = [index j];
break;
end
end
function [newpop] = selection(pop,fitvalue)
%如何选择新的个体
%输入变量:pop二进制种群,fitvalue:适应度值
%输出变量:newpop选择以后的二进制种群
%构造轮盘
[px,py] = size(pop);
totalfit = sum(fitvalue);
p_fitvalue = fitvalue/totalfit;
p_fitvalue = cumsum(p_fitvalue);%概率求和排序(这部我没理解为何要求和排序,不求和排序不行吗,评论区求解答[笑哭])
ms = sort(rand(px,1));%生成100个(种群数)0-1的数(随机概率)并从小到大排列
fitin = 1;
newin = 1;
while newin<=px
if((ms(newin))<p_fitvalue(fitin))%如果随机概率小于该个体拥有的概率,证明它是比较优秀的,天选之子
newpop(newin,:)=pop(fitin,:);
newin = newin+1;
else
fitin=fitin+1;
end
end
交叉函数(染色体相互交叉)
function [newpop] = crossover(pop,pc)
%交叉变换
%输入变量:pop:二进制的父代种群数,pc:交叉的概率
%输出变量:newpop:交叉后的种群数
[px,py] = size(pop);
newpop = ones(size(pop));
for i = 1:2:px-1%相邻的2个染色体(个体)进行交叉,所以是1:2:px-1
if(rand>pc)%如果大于设定的交叉的概率pc,就交叉出新个体,就是原本的父母就丢弃,只要新生儿
cpoint = round(rand*py);%产生随机数,随机选择一个位置点cpoint
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)];
else
newpop(i,:) = pop(i,:);
newpop(i+1,:) = pop(i+1,:);
end
end
变异函数
function [newpop] = mutation(pop,pm)
%关于变异
% 输入变量:pop:二进制种群,pm:变异概率
% 输出变量:newpop变异以后的种群
[px,py] = size(pop);
newpop = ones(size(pop));
for i = 1:px
if(rand<pm)%小于变异的概率
mpoint = round(rand*py);
if mpoint <= 0;%位数小于0
mpoint = 1;
end
newpop(i,:) = pop(i,:);%不进行变异
if newpop(i,mpoint) == 0
newpop(i,mpoint) = 1;
else newpop(i,mpoint) == 1
newpop(i,mpoint) = 0;
end
else newpop(i,:) = pop(i,:);%不进行变异
end
end
选择最优个体函数
function [bestindividual bestfit] = best(pop,fitvalue)
%求最优适应度函数
% 输入变量:pop:种群,fitvalue:种群适应度
% 输出变量:bestindividual:最佳个体,bestfit:最佳适应度值
[px,py] = size(pop);
bestindividual = pop(1,:);
bestfit = fitvalue(1);%其实可以直接max就行,不用冒泡排序之类的
for i = 2:px
if fitvalue(i)>bestfit
bestindividual = pop(i,:);
bestfit = fitvalue(i);
end
end
效果如图
The best X is --->> 0.22
The best Y is --->>52.29
猜你喜欢
- 2024-11-15 基于遗传算法的最优潮流_case30节点#matlab代做
- 2024-11-15 认知免疫—认知系列之七(认知能力百科)
- 2024-11-15 Python实现基于地图四色原理的遗传算法(GA)自动着色
- 2024-11-15 遗传的分子基础——基因的结构与表达
- 2024-11-15 通过MATLAB分别对比二进制编码遗传优化算法和实数编...
- 2024-11-15 Python产生随机数函数的整理(python中产生随机数的代码)
- 2024-11-15 用python写个云顶之弈阵容助手,助你今晚“吃鸡”(遗传算法)
- 2024-11-15 针对集配货一体化的货运配送问题、设计一个自适应遗传算法来求解
- 2024-11-15 遗传算法实现python,完整算法实现
- 2024-11-15 一文读懂遗传算法的基本流程(遗传算法的基本步骤流程图)
你 发表评论:
欢迎- 最近发表
-
- 在 Spring Boot 项目中使用 activiti
- 开箱即用-activiti流程引擎(active 流程引擎)
- 在springBoot项目中整合使用activiti
- activiti中的网关是干什么的?(activiti包含网关)
- SpringBoot集成工作流Activiti(完整源码和配套文档)
- Activiti工作流介绍及使用(activiti工作流会签)
- SpringBoot集成工作流Activiti(实际项目演示)
- activiti工作流引擎(activiti工作流引擎怎么用)
- 工作流Activiti初体验及在数据库中生成的表
- Activiti工作流浅析(activiti6.0工作流引擎深度解析)
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)