Skip to content

Commit

Permalink
Merge pull request #116 from DestinyMy/master
Browse files Browse the repository at this point in the history
Upload new version: v4.0
  • Loading branch information
DestinyMy authored Oct 13, 2022
2 parents 9444fc2 + 82c22b7 commit 3714c36
Show file tree
Hide file tree
Showing 950 changed files with 22,689 additions and 4,098 deletions.
16 changes: 16 additions & 0 deletions Doc/releasenote.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
# Release Highlights of PlatEMO 4.0

* Dynamic optimization, multitasking optimization, bilevel optimization, and robust optimization are now supported in PlatEMO.

* Hybrid encoding is now supported in PlatEMO, where a problem can include real variables, integral variables, label variables, binary variables, and permutation variables simultaneously.

* Maximum runtime is provided as a new termination criterion, which can be set instead of maximum number of function evaluations.

* More algorithms and problems for single-objective optimization, multi-objective optimization, constrained optimization, sparse optimization, expensive optimization, multimodal optimization, dynamic optimization, multitasking optimization, bilevel optimization, and robust optimization. There are currently 216 algorithms and 432 problems in the platform.

* More efficient and powerful GUI, where the execution of algorithms in the test module and application module is highly accelerated.

* More performance metrics for different types of optimization problems, and the metrics are also tagged with labels. Different metrics will be shown in the dropdown lists when selecting different labels in the GUI.

* Gradient based search is now supported in PlatEMO, where users can define gradient functions to accelerate the convergence via mathematical programming algorithms and gradient assisted evolutionary algorithms.

# Release Highlights of PlatEMO 3.5

* Enhance the application module, where users can define problems and save results more easily.
Expand Down
167 changes: 80 additions & 87 deletions PlatEMO/Algorithms/ALGORITHM.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
%ALGORITHM - The superclass of algorithms.
%
% This is the superclass of algorithms. An object of ALGORITHM stores the
% settings of the algorithm and the information of the current execution.
% settings of the algorithm and the data generated in current execution.
%
% ALGORITHM properties:
% parameter <read-only> parameters of the algorithm
% save <read-only> number of populations saved in an execution
% outputFcn <read-only> function called after each generation
% pro <read-only> problem solved in current execution
% result <read-only> populations saved in current execution
% metric <read-only> metric values of current populations
% parameter <any> parameters of the algorithm
% save <scalar> number of populations saved in an execution
% outputFcn <function> function called after each generation
% pro <class> problem solved in current execution
% result <cell> populations saved in current execution
% metric <struct> metric values of current populations
%
% ALGORITHM methods:
% ALGORITHM <protected> the constructor, which sets all the properties specified by user
% ALGORITHM <protected> the constructor setting all the properties specified by user
% Solve <public> use the algorithm to solve a problem
% main <public> the main function of the algorithm
% NotTerminated <protected> the function called after each generation of the execution
Expand All @@ -28,10 +28,10 @@
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

properties(SetAccess = private)
properties(SetAccess = protected)
parameter = {}; % Parameters of the algorithm
save = 0; % Number of populations saved in an execution
outputFcn = @ALGORITHM.Output; % Function called after each generation
save = -10; % Number of populations saved in an execution
outputFcn = @DefaultOutput; % Function called after each generation
pro; % Problem solved in current execution
result; % Populations saved in current execution
metric; % Metric values of current populations
Expand All @@ -58,8 +58,8 @@
function Solve(obj,Problem)
%Solve - Use the algorithm to solve a problem.
%
% obj.Solve(Pro) executes the algorithm to solve a problem, where
% Pro is a PROBLEM object.
% obj.Solve(Pro) uses the algorithm to solve a problem, where Pro
% is a PROBLEM object.
%
% In terms of the default obj.outputFcn, the result will be
% displayed when obj.save = 0 and saved when obj.save > 0.
Expand All @@ -68,13 +68,13 @@ function Solve(obj,Problem)
% Algorithm.Solve(Problem)

try
obj.pro = Problem;
obj.result = {};
obj.metric = struct('runtime',0);
obj.pro = Problem;
obj.pro.FE = 0;
addpath(fileparts(which(class(obj))));
addpath(fileparts(which(class(obj.pro))));
tic; obj.main(PROBLEM.Current(obj.pro));
tic; obj.main(obj.pro);
catch err
if ~strcmp(err.identifier,'PlatEMO:Termination')
rethrow(err);
Expand All @@ -87,7 +87,7 @@ function main(obj,Problem)
%main - The main function of the algorithm.
%
% This function is expected to be implemented in each subclass of
% ALGORITHM, which will be called automatically.
% ALGORITHM, which is usually called by ALGORITHM.Solve.
end
end
methods(Access = protected, Sealed)
Expand All @@ -96,22 +96,27 @@ function main(obj,Problem)
%execution.
%
% obj.NotTerminated(P) stores the population P as the result of
% the current execution, and returns true if the number of
% function evaluations has not exceeded.
% the current execution, and returns true if the algorithm should
% be terminated, i.e., the number of function evaluations or
% runtime exceeds.
%
% obj.outputFcn is called here, whose runtime will not be counted
% in obj.runtime.
% in the runtime of current execution.
%
% Example:
% while obj.NotTerminated(Population)
% while Algorithm.NotTerminated(Population)
% ... ...
% end

obj.metric.runtime = obj.metric.runtime + toc;
if obj.save <= 0; num = 10; else; num = obj.save; end
if obj.pro.maxRuntime < inf
obj.pro.maxFE = obj.pro.FE*obj.pro.maxRuntime/obj.metric.runtime;
end
num = max(1,abs(obj.save));
index = max(1,min(min(num,size(obj.result,1)+1),ceil(num*obj.pro.FE/obj.pro.maxFE)));
obj.result(index,:) = {obj.pro.FE,Population};
drawnow limitrate; obj.outputFcn(obj,obj.pro);
drawnow('limitrate');
obj.outputFcn(obj,obj.pro);
nofinish = obj.pro.FE < obj.pro.maxFE;
assert(nofinish,'PlatEMO:Termination',''); tic;
end
Expand All @@ -124,85 +129,73 @@ function main(obj,Problem)
% set to the value given in v1, v2, ... otherwise.
%
% Example:
% [p1,p2,p3] = obj.ParameterSet(1,2,3)
% [p1,p2,p3] = Algorithm.ParameterSet(1,2,3)

varargout = varargin;
specified = ~cellfun(@isempty,obj.parameter);
varargout(specified) = obj.parameter(specified);
end
end
methods(Static, Sealed)
function Output(Algorithm,Problem)
% The default output function of ALGORITHM.
clc; fprintf('%s on %d-objective %d-variable %s (%6.2f%%), %.2fs passed...\n',class(Algorithm),Problem.M,Problem.D,class(Problem),Problem.FE/Problem.maxFE*100,Algorithm.metric.runtime);
if Problem.FE >= Problem.maxFE
if Algorithm.save == 0
if Problem.M > 1
Population = Algorithm.result{end};
if length(Population) >= size(Problem.optimum,1); name = 'HV'; else; name = 'IGD'; end
value = Algorithm.Metric(name);
figure('NumberTitle','off','Name',sprintf('%s : %.4e Runtime : %.2fs',name,value(end),Algorithm.Metric('runtime')));
title(sprintf('%s on %s',class(Algorithm),class(Problem)),'Interpreter','none');
top = uimenu(gcf,'Label','Data source');
g = uimenu(top,'Label','Population (obj.)','CallBack',{@(h,~,Pro,P)eval('Draw(gca);Pro.DrawObj(P);ALGORITHM.cb_menu(h);'),Problem,Population});
uimenu(top,'Label','Population (dec.)','CallBack',{@(h,~,Pro,P)eval('Draw(gca);Pro.DrawDec(P);ALGORITHM.cb_menu(h);'),Problem,Population});
uimenu(top,'Label','True Pareto front','CallBack',{@(h,~,P)eval('Draw(gca);Draw(P,{''\it f\rm_1'',''\it f\rm_2'',''\it f\rm_3''});ALGORITHM.cb_menu(h);'),Problem.optimum});
cellfun(@(s)uimenu(top,'Label',s,'CallBack',{@(h,~,A)eval('Draw(gca);Draw(A.Metric(h.Label),''-k.'',''LineWidth'',1.5,''MarkerSize'',10,{''Number of function evaluations'',h.Label,[]});ALGORITHM.cb_menu(h);'),Algorithm}),{'IGD','HV','GD','Feasible rate'});
set(top.Children(4),'Separator','on');
g.Callback{1}(g,[],Problem,Population);
else
best = Algorithm.Metric('Minimum value');
if isempty(best); best = nan; end
figure('NumberTitle','off','Name',sprintf('Minimum value : %.4e Runtime : %.2fs',best(end),Algorithm.Metric('runtime')));
title(sprintf('%s on %s',class(Algorithm),class(Problem)),'Interpreter','none');
top = uimenu(gcf,'Label','Data source');
uimenu(top,'Label','Population (dec.)','CallBack',{@(h,~,Pro,P)eval('Draw(gca);Pro.DrawDec(P);ALGORITHM.cb_menu(h);'),Problem,Algorithm.result{end}});
cellfun(@(s)uimenu(top,'Label',s,'CallBack',{@(h,~,A)eval('Draw(gca);Draw(A.Metric(h.Label),''-k.'',''LineWidth'',1.5,''MarkerSize'',10,{''Number of function evaluations'',h.Label,[]});ALGORITHM.cb_menu(h);'),Algorithm}),{'Minimum value','Feasible rate'});
set(top.Children(2),'Separator','on');
top.Children(2).Callback{1}(top.Children(2),[],Algorithm);
end
elseif Algorithm.save > 0
folder = fullfile('Data',class(Algorithm));
[~,~] = mkdir(folder);
file = fullfile(folder,sprintf('%s_%s_M%d_D%d_',class(Algorithm),class(Problem),Problem.M,Problem.D));
runNo = 1;
while exist([file,num2str(runNo),'.mat'],'file') == 2
runNo = runNo + 1;
end
result = Algorithm.result;
metric = Algorithm.metric;
save([file,num2str(runNo),'.mat'],'result','metric');
end
methods(Sealed)
function Scores = CalMetric(obj,metName)
% Calculate metric values

if ~isfield(obj.metric,metName)
obj.metric.(metName) = [cell2mat(obj.result(:,1)),cellfun(@(S)obj.pro.CalMetric(metName,S),obj.result(:,2))];
end
end
function cb_menu(h)
% Switch the selected menu.
set(get(get(h,'Parent'),'Children'),'Checked','off');
set(h,'Checked','on');
Scores = obj.metric.(metName);
end
end
methods(Sealed)
function value = Metric(obj,name,nPoints)
% Calculate metric values.
if nargin < 3
index = 1 : size(obj.result,1);
end

function DefaultOutput(Algorithm,Problem)
% The default output function of ALGORITHM

clc; fprintf('%s on %d-objective %d-variable %s (%6.2f%%), %.2fs passed...\n',class(Algorithm),Problem.M,Problem.D,class(Problem),Problem.FE/Problem.maxFE*100,Algorithm.metric.runtime);
if Problem.FE >= Problem.maxFE
if Algorithm.save < 0
if Problem.M > 1
Population = Algorithm.result{end};
if length(Population) >= size(Problem.optimum,1); name = 'HV'; else; name = 'IGD'; end
value = Algorithm.CalMetric(name);
figure('NumberTitle','off','Name',sprintf('%s : %.4e Runtime : %.2fs',name,value(end),Algorithm.CalMetric('runtime')));
title(sprintf('%s on %s',class(Algorithm),class(Problem)),'Interpreter','none');
top = uimenu(gcf,'Label','Data source');
g = uimenu(top,'Label','Population (obj.)','CallBack',{@(h,~,Pro,P)eval('Draw(gca);Pro.DrawObj(P);cb_menu(h);'),Problem,Population});
uimenu(top,'Label','Population (dec.)','CallBack',{@(h,~,Pro,P)eval('Draw(gca);Pro.DrawDec(P);cb_menu(h);'),Problem,Population});
uimenu(top,'Label','True Pareto front','CallBack',{@(h,~,P)eval('Draw(gca);Draw(P,{''\it f\rm_1'',''\it f\rm_2'',''\it f\rm_3''});cb_menu(h);'),Problem.optimum});
cellfun(@(s)uimenu(top,'Label',s,'CallBack',{@(h,~,A)eval('Draw(gca);Draw(A.CalMetric(h.Label),''-k.'',''LineWidth'',1.5,''MarkerSize'',10,{''Number of function evaluations'',strrep(h.Label,''_'','' ''),[]});cb_menu(h);'),Algorithm}),{'IGD','HV','GD','Feasible_rate'});
set(top.Children(4),'Separator','on');
g.Callback{1}(g,[],Problem,Population);
else
index = ceil(linspace(1,size(obj.result,1),nPoints));
best = Algorithm.CalMetric('Min_value');
if isempty(best); best = nan; end
figure('NumberTitle','off','Name',sprintf('Min value : %.4e Runtime : %.2fs',best(end),Algorithm.CalMetric('runtime')));
title(sprintf('%s on %s',class(Algorithm),class(Problem)),'Interpreter','none');
top = uimenu(gcf,'Label','Data source');
uimenu(top,'Label','Population (dec.)','CallBack',{@(h,~,Pro,P)eval('Draw(gca);Pro.DrawDec(P);cb_menu(h);'),Problem,Algorithm.result{end}});
cellfun(@(s)uimenu(top,'Label',s,'CallBack',{@(h,~,A)eval('Draw(gca);Draw(A.CalMetric(h.Label),''-k.'',''LineWidth'',1.5,''MarkerSize'',10,{''Number of function evaluations'',strrep(h.Label,''_'','' ''),[]});cb_menu(h);'),Algorithm}),{'Min_value','Feasible_rate'});
set(top.Children(2),'Separator','on');
top.Children(2).Callback{1}(top.Children(2),[],Algorithm);
end
name = strrep(name,' ','');
if ~isfield(obj.metric,name)
obj.metric.(name) = [cell2mat(obj.result(index,1)),cellfun(@(S)feval(name,S,obj.pro.optimum),obj.result(index,2))];
elseif Algorithm.save > 0
folder = fullfile('Data',class(Algorithm));
[~,~] = mkdir(folder);
file = fullfile(folder,sprintf('%s_%s_M%d_D%d_',class(Algorithm),class(Problem),Problem.M,Problem.D));
runNo = 1;
while exist([file,num2str(runNo),'.mat'],'file') == 2
runNo = runNo + 1;
end
value = obj.metric.(name);
result = Algorithm.result;
metric = Algorithm.metric;
save([file,num2str(runNo),'.mat'],'result','metric');
end
end
end

function score = Minimumvalue(Population,~)
score = Population.best.objs;
if isempty(score); score = nan; end
end
function cb_menu(h)
% Switch between the selected menu

function score = Feasiblerate(Population,~)
score = mean(all(Population.cons<=0,2));
end
set(get(get(h,'Parent'),'Children'),'Checked','off');
set(h,'Checked','on');
end
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
classdef ANSGAIII < ALGORITHM
% <multi/many> <real/binary/permutation> <constrained/none>
% <multi/many> <real/integer/label/binary/permutation> <constrained/none>
% Adaptive NSGA-III

%------------------------------- Reference --------------------------------
Expand Down Expand Up @@ -32,7 +32,7 @@ function main(Algorithm,Problem)
%% Optimization
while Algorithm.NotTerminated(Population)
MatingPool = TournamentSelection(2,Problem.N,sum(max(0,Population.cons),2));
Offspring = OperatorGA(Population(MatingPool));
Offspring = OperatorGA(Problem,Population(MatingPool));
Zmin = min([Zmin;Offspring(all(Offspring.cons<=0,2)).objs],[],1);
Population = EnvironmentalSelection([Population,Offspring],Problem.N,Z,Zmin);
Z = Adaptive(Population.objs,Z,Problem.N,interval);
Expand Down
Loading

0 comments on commit 3714c36

Please sign in to comment.