该篇文章仅涉及 GitHub 中相关的 jMetal 官方代码(MIT License)以及其扩展使用,GitHub网址:jMetal
版本信息
jMetal 版本:5.11-SNAPSHOT
Eclipse 版本:Eclipse Modeling Tools 2020-12 (4.18.0)
需注意,Eclipse必须使用 Modeling Tools 版本,而非普通的Java版本,Eclipse不同版本软件下载官方网址:Eclipse Packages
Eclipse环境配置
该部分可解决Java与Modeling Tools两类Eclipse版本共存的特殊情况,同时也是Eclipse Modeling Tools Java环境配置的简单教程
1、从Eclipse官网下载Modeling Tools版本,下载网址:Eclipse Packages,该网站中有Eclipse多种版本可供下载,找到jMetal所需的版本,如下图所示,选择合适的操作系统版本
2、下载好的zip压缩文件可解压到合适的位置,解压后的文件如下图所示,其中 plugins 文件中包含Eclipse支持的全部依赖,若有其他依赖需要,可手动添加
3、解压后的Eclipse直接双击 eclipse.exe 运行,若无jdk相关的错误提示,可跳过步骤4和步骤5,直接查看步骤6,若提示jdk不存在或是版本不适配的问题,此时需要从jdk官网下载合适的版本,具体的版本号在 eclipse.exe 弹出的窗口中提及,可根据此版本号下载对应的jdk,jdk官方下载网址:Java SE Downloads
4、将下载的jdk保存到合适的位置,记录该文件位置,用于之后的环境变量设置,若下载的jdk文件中不包含jre文件,可参考该网址解决:如何解决安装JDK12版本后没有JRE的问题
5、鼠标右键单击 我的电脑 或是 此电脑 图标,选中 属性
在弹出窗口的左侧导航栏中选择 高级系统设置
而后选择 环境变量
在 系统变量 中添加以下内容:
变量名:CLASSPATH
变量值:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
变量名:JAVA_HOME
变量值:D:\Eclipse\eclipse-modeling_tools\jdk-15.0.1
变量名:Path
变量值:%JAVA_HOME%\bin
变量名:Path
变量值:%JAVA_HOME%\jre\bin
其中 JAVA_HOME 的变量值为具体的jdk文件位置
若原有Java版本的Eclipse存在,jdk的环境配置已设置完好,可直接更新相关变量值,不需要重新添加新的变量,配置完成后对原有的Eclipse Java的使用不会造成影响
变量添加完成后,在打开的两类窗口中均选中 确定 按钮,保存环境变量配置
6、jdk配置完成后,再次打开 eclipse.exe ,可能弹出以下错误
用 记事本 打开Eclipse文件夹中的 eclipse.ini 文件,在图中所示的位置添加同样的内容
-vm
jdk-15.0.1/bin/javaw.exe
其中 jdk-15.0.1/bin/javaw.exe 需要根据jdk具体的文件位置进行修改
文件保存后,双击 eclipse.exe ,便可正常使用 Eclipse Modeling Tools
使用教程
1、新建Java项目
与Java版本的Eclipse新建项目方法相同,在菜单栏中选中 File >> New >> Other…
在弹出的向导窗口中找到 Java ,并选中其中的 Java Project ,而后选择 Next >
在新建项目的窗口找到 Project name ,输入自定义的项目名称;Location 部分为该项目存储文件位置,可自行修改;查看 JRE 版本确保其环境存在,一般而言默认的JRE均存在,因此该步骤可跳过;其余选项可默认不变,而后直接点击窗口右下角的 Finish 创建项目
Finish 创建项目可能会弹出以下图片中的内容,可直接选择右下角的 Don’t Create
而后可能会弹出询问Eclipse操作透视图(Java Perspective)是否打开的窗口,可选择 No
至此,新项目创建完毕,可在Eclipse左侧导航栏中查看到项目的存储结构
2、导入jMetal
导入jMetal的方法有两种:
(1)将GitHub中jMetal的源码下载,在新建的项目中以package包的形式导入所需的jMetal代码
(2)将封装好的jMetal jar包导入新建项目,import相关package使用jMetal
两种方法各有优缺:
(1)以源码形式导入jMetal,适用于需要对jMetal的基本功能进行按需修改的操作,但jMetal不同部分的package可能相互依赖,因此导入的源码复杂而多样
(2)导入jar包,可以避免第一种方法产生的缺点,但在需要修改jMetal代码的情况下,需要重写相关函数调用
博主更为推荐第二种方法,主要因为在大多数情况下jMetal源码提供的功能已经足够齐全,重写部分代码的工作量相比第一种方法会小很多,以下教程的介绍也是基于第二种方法实现的
jMetal相关jar包可以在 Maven 中下载,或是直接使用maven仓库获取
jmetal5.jar 包并未在maven仓库中直接提供,可从以下链接中获取(包含本教程所使用的全部jar包)
链接:https://pan.baidu.com/s/19aAVIutKENiDRmC43sVABw
提取码:9khw
鼠标右键单击项目名称,选择 Build Path >> Configure Build Path…
在弹出的窗口中选择 Java Build Path >> Libraries ,单击 Libraries 中的 Classpath ,点击右侧导航中的 Add External JARs… ,在弹出的文件窗口中选中需要添加的jMetal jar包,而后点击 Apply and Close
其中每一个jMetal jar包拥有的函数功能可在GitHub的源码中查看,或是使用Eclipse的插件直接查看,推荐插件 JD-Eclipse,下载官网:Java Decompiler
3、执行jMetal算法
jmetal-example中包含原作者所编写的一些算法实例,图中展示的是5.10版本的example
以其中的 NSGAIIIntegerRunner 为例,若添加了JD-Eclipse插件,可直接双击打开
import部分,导入相关package,可用于之后程序类与函数的溯源查找
import java.io.FileNotFoundException;
import java.util.List;
import org.uma.jmetal.algorithm.multiobjective.nsgaii.NSGAII;
import org.uma.jmetal.algorithm.multiobjective.nsgaii.NSGAIIBuilder;
import org.uma.jmetal.example.AlgorithmRunner;
import org.uma.jmetal.operator.crossover.impl.IntegerSBXCrossover;
import org.uma.jmetal.operator.mutation.impl.IntegerPolynomialMutation;
import org.uma.jmetal.operator.selection.impl.BinaryTournamentSelection;
import org.uma.jmetal.problem.Problem;
import org.uma.jmetal.solution.integersolution.IntegerSolution;
import org.uma.jmetal.util.AbstractAlgorithmRunner;
import org.uma.jmetal.util.JMetalLogger;
import org.uma.jmetal.util.ProblemUtils;
NSGAIIIntegerRunner类中,以下代码为NSGAII算法相关的参数配置,具体参数含义可由其变量名确定
Problem<IntegerSolution> problem = ProblemUtils.loadProblem(problemName);
double crossoverProbability = 0.9D;
double crossoverDistributionIndex = 20.0D;
IntegerSBXCrossover integerSBXCrossover = new IntegerSBXCrossover(crossoverProbability, crossoverDistributionIndex);
double mutationProbability = 1.0D / problem.getNumberOfVariables();
double mutationDistributionIndex = 20.0D;
IntegerPolynomialMutation integerPolynomialMutation = new IntegerPolynomialMutation(mutationProbability, mutationDistributionIndex);
BinaryTournamentSelection binaryTournamentSelection = new BinaryTournamentSelection();
int populationSize = 100;
创建NSGAII算法类,该算法类可通过import的包名找到相关代码
NSGAII nSGAII = (new NSGAIIBuilder(problem, integerSBXCrossover, integerPolynomialMutation, populationSize)).setSelectionOperator(binaryTournamentSelection).setMaxEvaluations(25000).build();
算法执行
AlgorithmRunner algorithmRunner = (new AlgorithmRunner.Executor(nSGAII)).execute();
获得执行结果
List<IntegerSolution> population = (List)nSGAII.getResult();
输出结果
printFinalSolutionSet(population);
printQualityIndicators(population, referenceParetoFront);
以上均为jMetal提供的默认操作实现,创建一个可执行的class,将原本内容复制到该class,可实现运行,如果某一部分需要自定义,可追溯到其原本的类与函数,根据源码重写新的类或函数
4、计算 Quality Indicator
jmetal-exec中提供有原作者编写的一些Quality Indicator计算实例,以 NSGAIIStudy 为例
该部分定义相关的problem列表,包含了ZDT1、ZDT2、ZDT3、ZDT4、ZDT6
List<ExperimentProblem<DoubleSolution>> problemList = new ArrayList<ExperimentProblem<DoubleSolution>>();
problemList.add(new ExperimentProblem(new ZDT1()));
problemList.add(new ExperimentProblem(new ZDT2()));
problemList.add(new ExperimentProblem(new ZDT3()));
problemList.add(new ExperimentProblem(new ZDT4()));
problemList.add(new ExperimentProblem(new ZDT6()));
定义problem对应的算法列表,其中 configureAlgorithmList 函数同样定义在NSGAIIStudy类中,用于创建jMetal算法对象,形成算法列表,创建方法与第三步骤类似
List<ExperimentAlgorithm<DoubleSolution, List<DoubleSolution>>> algorithmList = configureAlgorithmList(problemList);
声明理想Pareto Front文件名列表
List<String> referenceFrontFileNames = Arrays.asList(new String[] { "ZDT1.pf", "ZDT2.pf", "ZDT3.pf", "ZDT4.pf", "ZDT6.pf" });
设置剩余参数变量,其中结果文件存放位置为 experimentBaseDirectory/NSGAIIStudy
Experiment<DoubleSolution, List<DoubleSolution>> experiment = (
new ExperimentBuilder("NSGAIIStudy")) //结果文件存放位置
.setAlgorithmList(algorithmList) //算法列表
.setProblemList(problemList) //问题列表
.setExperimentBaseDirectory(experimentBaseDirectory) //结果文件存放位置
.setOutputParetoFrontFileName("FUN") //fitness文件名,默认不可更改
.setOutputParetoSetFileName("VAR") //solution文件名,默认不可更改
.setReferenceFrontDirectory("/pareto_fronts") //理想Pareto Front文件位置
.setReferenceFrontFileNames(referenceFrontFileNames) //理想Pareto Front文件名列表
.setIndicatorList(Arrays.asList(new GenericIndicator[] { //Quality Indicators
new Epsilon(),
new Spread(),
new GenerationalDistance(),
new PISAHypervolume(),
new InvertedGenerationalDistance(),
new InvertedGenerationalDistancePlus()
})).setIndependentRuns(25) //运行次数
.setNumberOfCores(8) //运行线程数量
.build(); //创建
其中,Quality Indicator源码位于jmetal-core中,详情如下图
计算执行,该部分源码同样位于jmetal-core中,如图所示
(new ExecuteAlgorithms(experiment)).run();
(new ComputeQualityIndicators(experiment)).run();
(new GenerateLatexTablesWithStatistics(experiment)).run();
(new GenerateWilcoxonTestTablesWithR(experiment)).run();
(new GenerateFriedmanTestTables(experiment)).run();
(new GenerateBoxplotsWithR(experiment)).setRows(3).setColumns(3).run();
与使用jMetal算法类似,以上内容为jMetal默认定义,同样可复制到可执行class中运行,同样,如需自定义类与函数,可参考jMetal提供的相关源码,按其相同格式进行编写,益于模仿与使用