前言
后台有很多人催更我关于platEMO的操作实例,实在是由于科研期间琐事太多了,因此文章更新就停滞了(其实说白了就是自己太懒了),根据大家问我最多的几个问题,这次博客主要分为两部分:增加问题和增加算法。一些架构和官方的介绍可以参考我之前的两篇博客。这篇博客直接说怎么添加。除了matlab以外,还有一个python有关进化算法的库叫做geatpy,也非常不错,他的网址:http://geatpy.com,里面有详细的教程,感兴趣的朋友可以去学习一下。
增加问题
每一个多目标优化问题在platEMO中由一个.m文件表示,该文件应该放在文件夹Problems中。即我们首先需要在Problems这个文件夹新建一个我们问题的文件夹。我们定义一个多目标优化问题一般需要考虑他的问题个数Global.M,变量的个数Global.D,变量的上界Global.upper,变量的下界Global.lower,以及变量的编码方式Global.encoding,最后就是目标函数的形式(包括约束条件)了。以下我们以带约束的DTLZ1()函数为例说明问题是如何增加的。
classdef C1_DTLZ1 < PROBLEM
% <problem> <DTLZ variant>%如果你想在GUI界面去调用你的问题,这里<>必须起一个你问题自己的名字
% Constrained DTLZ1%如果你想在GUI界面去调用你的问题,这里<>必须起一个你问题自己的名字
methods
%% Initialization
function obj = C1_DTLZ1()
if isempty(obj.Global.M)
obj.Global.M = 3;%定义你优化问题的目标个数
end
if isempty(obj.Global.D)
obj.Global.D = obj.Global.M + 4;%定义你优化问题的变量个数,在DTLZ1中为目标个数加4
end
obj.Global.lower = zeros(1,obj.Global.D);定义你的优化问题的下界
obj.Global.upper = ones(1,obj.Global.D);定义你优化问题的上界
obj.Global.encoding = 'real';%定义你优化问题的编码方式,例如实数编码码'real',platEMO提供三种编码方式:'binary'二进制编码;'permutation'排列编码以及其他实数编码,根据你的优化问题的实际搜索空间可以自行选择
end
%% Calculate objective values计算目标函数值
function PopObj = CalObj(obj,PopDec)
[N,D] = size(PopDec);%首先我们需要得到种群大小N和自变量个数D
M = obj.Global.M;%得到目标个数
g = 100*(D-M+1+sum((PopDec(:,M:end)-0.5).^2-cos(20.*pi.*(PopDec(:,M:end)-0.5)),2));
PopObj = 0.5*repmat(1+g,1,M).*fliplr(cumprod([ones(N,1),PopDec(:,1:M-1)],2)).*[ones(N,1),1-PopDec(:,M-1:-1:1)];%给出自己问题的表达式,如果是黑盒优化问题,这里需要将黑盒问题抽象成包含输入和输出的接口形式,注意输入的矩阵PopDec每一行代表种群中的一条染色体,黑盒问题需要可以接受这样的输入形式,如果黑盒优化的函数只能一个个染色体计算,那么需要用for循环算出每一个染色体在不同目标上对应的目标函数值,再合成矩阵PopObj。
end
%% Calculate constraint violations计算目标函数的约束值,没有约束的话,可以不写这个接口函数
function PopCon = CalCon(obj,PopDec)
PopObj = obj.CalObj(PopDec);
PopCon = PopObj(:,end)/0.6 + sum(PopObj(:,1:end-1)/0.5,2) - 1;%值得注意的是,约束必须要写成g(x)>=0的形式哦,这里计算的g(x)的值
end
%% Sample reference points on Pareto front%这里是优化问题的最优PF,在实际问题中我们是得不到最优的PF的,因此实际问题时直接省略就可以的,这里C1_DTLZ1函数是学者们构造出来用来测试算法性能的,因此我们可以得到PF的理论解。
function P = PF(obj,N)
P = UniformPoint(N,obj.Global.M)/2;
end
end
end
首先由于C1_DTLZ1是PROBLEM的一个子类,每个操作都是一个重载方法。以上每条代码都给出来详细的注释,参考这些就可以加入自己的方法啦。一下有两点值得注意的事项:
- 决策变量在三种情况下可能是不可行的。首先,对于连续MOPs,它可能大于全局上界(GLOBAL.upper)或小于下界(GLOBAL.lower)。在这种情况下,它将被INDIVIDUAL的类设置为边界值,而MOP类不需要处理这种情况。其次,它可能没有满足约束(一个正的约束违背表明这个约束没有被满足),在这种情况下,