上一节介绍了jMetal的大致框架结构,本节贴一个完整的例子。
优化问题
假定我们需要对这样的问题进行优化:
也就是多目标优化测试集ZDT1函数。
这个优化问题有30个决策变量,2个优化目标函数(最小化)。决策变量的定义域相同,都是[0,1]的实数。目标函数也是实数类型。
我们决定采用NSGA-II算法对这个优化问题进行建模求解,选择算子采用二元锦标赛选择法,交叉算子用SBXcrossover,变异算子用SimpleRandomMutation(随机变异)。
配置算法
定义Problem
既然定义域和目标函数都是实数域的,那我们只要对AbstractDoubleProblem类进行实现就行了。
-
public
class ZDT1 extends AbstractDoubleProblem {
-
-
/** Constructor. Creates default instance of problem ZDT1 (30 decision variables) */
-
public ZDT1() {
-
this(
30);
-
}
-
-
/**
-
* Creates a new instance of problem ZDT1.
-
*
-
* @param numberOfVariables Number of variables.
-
*/
-
public ZDT1(Integer numberOfVariables) {
-
setNumberOfVariables(numberOfVariables);
//设定决策变量个数,30
-
setNumberOfObjectives(
2);
//设定优化目标函数个数,2
-
setName(
"ZDT1");
//给这个问题起名,ZDT1.
-
-
List<Double> lowerLimit =
new ArrayList<>(getNumberOfVariables()) ;
-
List<Double> upperLimit =
new ArrayList<>(getNumberOfVariables()) ;
-
-
//设置定义域
-
for (
int i =
0; i < getNumberOfVariables(); i++) {
-
lowerLimit.add(
0.0);
-
upperLimit.add(
1.0);
-
}
-
-
setLowerLimit(lowerLimit);
-
setUpperLimit(upperLimit);
-
}
-
-
//这里就是优化目标函数的实现过程,Algorithm.evlataionPopulation()会调用这个方法
-
/** Evaluate() method */
-
public void evaluate(DoubleSolution solution) {
-
double[] f =
new
double[getNumberOfObjectives()];
-
-
f[
0] = solution.getVariableValue(
0);
-
double g =
this.evalG(solution);
-
double h =
this.evalH(f[
0], g);
-
f[
1] = h * g;
-
-
solution.setObjective(
0, f[
0]);
-
solution.setObjective(
1, f[
1]);
-
}
-
-
/**
-
* Returns the value of the ZDT1 function G.
-
*
-
* @param solution Solution
-
*/
-
private double evalG(DoubleSolution solution) {
-
double g =
0.0;
-
for (
int i =
1; i < solution.getNumberOfVariables(); i++) {
-
g += solution.getVariableValue(i);
-
}
-
double constant =
9.0 / (solution.getNumberOfVariables() -
1);
-
g = constant * g;
-
g = g +
1.0;
-
return g;
-
}
-
-
/**
-
* Returns the value of the ZDT1 function H.
-
*
-
* @param f First argument of the function H.
-
* @param g Second argument of the function H.
-
*/
-
public double evalH(double f, double g) {
-
double h ;
-
h =
1.0 - Math.sqrt(f / g);
-
return h;
-
}
-
}
上面是包里面的ZDT1源码。
定义Solution
决策变量不复杂,完全可以使用开源包提供的DefaultBinarySolution。
-
public
class DefaultDoubleSolution
-
extends
AbstractGenericSolution<
Double,
DoubleProblem>
-
implements
DoubleSolution {
-
-
/** Constructor */
-
public DefaultDoubleSolution(DoubleProblem problem) {
-
super(problem) ;
//会在父类AbstractGenericSolution里设置决策变量和优化目标函数空间,这里便是30和2.
-
-
initializeDoubleVariables();
//随机初始化决策变量
-
initializeObjectiveValues();
//优化目标函数设为0,0
-
}
-
-
/** Copy constructor */
-
public DefaultDoubleSolution(DefaultDoubleSolution solution) {
-
super(solution.problem) ;
-
-
for (
int i =
0; i < problem.getNumberOfVariables(); i++) {
-
setVariableValue(i, solution.getVariableValue(i));
-
}
-
-
for (
int i =
0; i < problem.getNumberOfObjectives(); i++) {
-
setObjective(i, solution.getObjective(i)) ;
-
}
-
-
attributes =
new HashMap<Object, Object>(solution.attributes) ;
-
}
-
-
@Override
-
public Double getUpperBound(int index) {
-
return problem.getUpperBound(index);
-
}
-
-
@Override
-
public Double getLowerBound(int index) {
-
return problem.getLowerBound(index) ;
-
}
-
-
@Override
-
public DefaultDoubleSolution copy() {
-
return
new DefaultDoubleSolution(
this);
-
}
-
-
@Override
-
public String getVariableValueString(int index) {
-
return getVariableValue(index).toString() ;
-
}
-
-
private void initializeDoubleVariables() {
-
for (
int i =
0 ; i < problem.getNumberOfVariables(); i++) {
-
Double value = randomGenerator.nextDouble(getLowerBound(i), getUpperBound(i)) ;
-
setVariableValue(i, value) ;
-
}
-
}
-
}
定义Operator
开源包的常用的操作算子都有,我们只要把需要的提供给Algorithm就可以了。
配置Algorithm
-
import org.uma.jmetal.algorithm.Algorithm;
-
import org.uma.jmetal.algorithm.multiobjective.nsgaii.NSGAIIBuilder;
-
import org.uma.jmetal.operator.CrossoverOperator;
-
import org.uma.jmetal.operator.MutationOperator;
-
import org.uma.jmetal.operator.SelectionOperator;
-
import org.uma.jmetal.operator.impl.crossover.SBXCrossover;
-
import org.uma.jmetal.operator.impl.mutation.SimpleRandomMutation;
-
import org.uma.jmetal.operator.impl.selection.BinaryTournamentSelection;
-
import org.uma.jmetal.problem.Problem;
-
import org.uma.jmetal.problem.multiobjective.zdt.ZDT1;
-
import org.uma.jmetal.solution.DoubleSolution;
-
import org.uma.jmetal.util.AlgorithmRunner;
-
import org.uma.jmetal.util.JMetalLogger;
-
import org.uma.jmetal.util.comparator.RankingAndCrowdingDistanceComparator;
-
-
import java.io.FileNotFoundException;
-
import java.util.List;
-
-
import
static org.uma.jmetal.runner.AbstractAlgorithmRunner.printFinalSolutionSet;
-
import
static org.uma.jmetal.runner.AbstractAlgorithmRunner.printQualityIndicators;
-
-
-
/**
-
* Solve ZDT1 with NSGA-II on jMetal
-
*/
-
public
class ZDT1_jMetal {
-
public static void main(String[] args) throws FileNotFoundException {
-
Problem<DoubleSolution> problem;
-
Algorithm<List<DoubleSolution>> algorithm;
-
CrossoverOperator<DoubleSolution> crossover;
-
MutationOperator<DoubleSolution> mutation;
-
SelectionOperator<List<DoubleSolution>, DoubleSolution> selection;
-
String referenceParetoFront =
"";
-
//定义优化问题
-
problem =
new ZDT1();
-
//配置SBX交叉算子
-
double crossoverProbability =
0.9;
-
double crossoverDistributionIndex =
20.0;
-
crossover =
new SBXCrossover(crossoverProbability, crossoverDistributionIndex);
-
//配置变异算子
-
double mutationProbability =
1.0 / problem.getNumberOfVariables();
-
// double mutationDistributionIndex = 20.0 ;
-
mutation =
new SimpleRandomMutation(mutationProbability);
-
//配置选择算子
-
selection =
new BinaryTournamentSelection<DoubleSolution>(
-
new RankingAndCrowdingDistanceComparator<DoubleSolution>());
-
//将组件注册到algorithm
-
algorithm =
new NSGAIIBuilder<DoubleSolution>(problem, crossover, mutation)
-
.setSelectionOperator(selection)
-
.setMaxEvaluations(
25000)
-
.setPopulationSize(
100)
-
.build();
-
/* 或者用这样的方法注册一个算法
-
evaluator = new SequentialSolutionListEvaluator<DoubleSolution>();
-
algorithm = new NSGAII<DoubleSolution>(problem, 25000, 100, crossover,
-
mutation, selection, evaluator);
-
*/
-
//用AlgorithmRunner运行算法
-
AlgorithmRunner algorithmRunner =
new AlgorithmRunner.Executor(algorithm).execute();
-
//获取结果集
-
List<DoubleSolution> population = algorithm.getResult();
-
long computingTime = algorithmRunner.getComputingTime();
-
-
JMetalLogger.logger.info(
"Total execution time: " + computingTime +
"ms");
-
//将全部种群打印到文件中
-
printFinalSolutionSet(population);
-
if (!referenceParetoFront.equals(
"")) printQualityIndicators(population, referenceParetoFront);
-
}
-
}
可能有人会问DefaultDoubleSolution是在哪里注册进算法的,答案是在类AbstractDoubleProblem里,因为ZDT1 extends AbstractDoubleProblem,而AbstractDoubleProblem override了createSolution()方法。
-
@Override
-
public DoubleSolution createSolution() {
-
return
new DefaultDoubleSolution(
this) ;
-
}
这样便把DefaultDoubleSolution注册进行了算法。
整个算法的全部组件也就注册完毕,可以用AlgorithmRunner跑算法了。
运行结束后,文件夹下有两个文件:FUN.tsv以及VAR.tsv,分别是种群中每个个体的目标函数值以及变量取值。
FUN.tsv:
-
0.9991565401450556 0.033138122686883334
-
2
.1067790428441063E-8 1
.0595872968618374
-
0
.9991565401450556 0
.033138122686883334
-
0
.0030874146922019036 1
.0077962135879674
-
0
.37208796983749715 0
.4376249588422198
-
0
.012235830807169515 0
.9449966538390078
-
0
.904673999160248 0
.08738808177979915
-
0
.8782179346960335 0
.09748359378144718
-
0
.5431994204942634 0
.30592147506205464
-
0
.9169218831064787 0
.07802500987158069
-
9
.468202994405428E-4 1
.0379086786786225
-
-
...
VAR.tsv:
-
0.9991565401450556 0.00794252537669871 0.005488981392981174 0.005967005140972121 0.01162606289274464 0.002201447846900849 9.94537425543528E-5 0.029018625966103245 6.246349761912435E-4 0.012411458377153944 6.13041394387238E-4 0.006672893568571068 0.004683245361043199 0.0060270800004386255 0.02092406367804804 0.006027912828149411 0.008141486757360285 0.005252329949473475 0.013588708050315333 4.75250834980327E-4 0.004877702130228007 0.00865616423126847 0.007134221657092997 5.82125403093642E-4 0.00218258306150891 0.002637239173984704 0.00470701459937204 0.003447998437515465 0.025117498398781753 3.858761644549365E-4
-
2
.1067790428441063E-8 0
.0013449663939222802 0
.005567610317640469 0
.005954896771763153 0
.011208137141151507 0
.0022871789133387587 2
.5533956835596477E-4 0
.0289730300686882 0
.0011161183476621267 0
.012088625407047743 4
.853248844326898E-4 0
.005576530486173516 0
.0044146222306917 0
.005591849962373359 0
.023510812594118094 0
.00559698303998508 0
.008526548202102548 0
.004978541310143319 0
.013456059721873422 2
.1599275436113581E-4 6
.464262956128893E-4 0
.008659442671210112 0
.007455323262755572 5
.330734255766625E-4 0
.0022947851159189434 0
.0030778464130739574 0
.004314818022123099 0
.001781848589289457 0
.021977664906484087 5
.945794636948833E-4
-
0
.9991565401450556 0
.00794252537669871 0
.005488981392981174 0
.005967005140972121 0
.01162606289274464 0
.002201447846900849 9
.94537425543528E-5 0
.029018625966103245 6
.246349761912435E-4 0
.012411458377153944 6
.13041394387238E-4 0
.006672893568571068 0
.004683245361043199 0
.0060270800004386255 0
.02092406367804804 0
.006027912828149411 0
.008141486757360285 0
.005252329949473475 0
.013588708050315333 4
.75250834980327E-4 0
.004877702130228007 0
.00865616423126847 0
.007134221657092997 5
.82125403093642E-4 0
.00218258306150891 0
.002637239173984704 0
.00470701459937204 0
.003447998437515465 0
.025117498398781753 3
.858761644549365E-4
-
0
.0030874146922019036 0
.0013365539852478229 0
.005182909391226278 0
.005924058411554409 0
.01118229152772865 0
.0023366965932723107 6
.324521846327583E-4 0
.02902028721867136 0
.0011174873826591525 0
.01607317788065011 6
.077775832455531E-4 0
.006609063533908074 0
.00472212763605761 0
.005586115559330742 0
.022093069920163133 0
.006032975289233088 0
.014177472883379724 0
.0052542905516060915 0
.013637172738984167 2
.734608072910316E-4 0
.0029789664575808625 0
.008723311209515585 0
.006044781487938784 0
.0013550275939853108 0
.002301784894338042 0
.003094401868258896 0
.00424763759778414 0
.006162891640480703 0
.02260147162700153 5
.921644622272565E-4
-
0
.37208796983749715 0
.007932549826772503 0
.005733838000832022 0
.0061354083927397255 0
.011604533262840262 0
.002057314894585316 0
.0010022101119812942 0
.02989733667311966 6
.08282024185579E-4 0
.012397126776630542 5
.998275335958403E-4 0
.01506087655460484 0
.00464291351178865 0
.0062300516654778156 0
.022091445462216315 0
.006034719138346714 0
.008774192194392884 0
.005141814397898589 0
.013523660901499517 2
.4368083649250132E-4 0
.005086534568764959 0
.00876978780529207 0
.0061817493730077135 3
.773946149720617E-4 0
.0022826316241897696 0
.0026309829327736903 0
.0043080146273272845 0
.004863767090151326 0
.022041285378979106 0
.002919760394030697
-
0
.012235830807169515 8
.125951402240999E-4 0
.0050749586887912515 0
.005970026173914942 0
.011124075536426553 0
.002255533872477719 2
.3804311416268848E-4 0
.02896806187268283 0
.001178737141893214 0
.012889284788012045 0
.001146718928935113 0
.006684571308397864 0
.004701577104002668 0
.006145095155351619 0
.009724710443257225 0
.005958323414437711 0
.008857307647993846 0
.005005266186932944 0
.013775188791515004 4
.986577741944896E-4 0
.0012484367533888785 0
.008655578390633521 0
.006356590677832672 0
.002476110520203009 0
.0037830608116732195 0
.0013633927705415851 0
.004291824785684132 0
.004911922026652875 0
.025117218984693157 3
.150747401875623E-4
-
0
.904673999160248 0
.00795295101934479 0
.004668491628057082 0
.005965422404070663 0
.010626120447424963 0
.0018483651646261116 1
.0211366264457851E-4 0
.029031421890728742 0
.001213671378936406 0
.012512256675432692 6
.128517111181102E-4 0
.015087440116505575 0
.004740608112462564 0
.0055412868961014165 0
.02094905360517965 0
.006027669409611225 0
.008384542334256154 0
.005253642628464492 0
.013586813701144918 0
.004404204800487962 0
.004886217079598717 0
.011257629400441088 0
.007164707950615741 4
.574943191636639E-4 0
.0021761859274254847 0
.014838541276046113 0
.004684293032704989 0
.0036265152774918536 0
.025032963402199793 4
.252820662178495E-4
-
0
.8782179346960335 0
.0016041708744499602 0
.006899999702285518 0
.00596999474056966 0
.011088167521215015 0
.002414424964104206 0
.0013525153329467644 0
.03008160193028079 0
.001191286365730821 0
.013034967872517633 0
.0011680907731348967 0
.00663808869634212 0
.004778598593081433 0
.006288306113962981 0
.02093409398141728 0
.006034864244001367 0
.008904099721092313 0
.005508775770161228 0
.01364664361798086 0
.0014072719221244947 0
.0018549389516085008 0
.00866606529745734 0
.00632902496958632 4
.3252550983526896E-4 0
.003591273575747169 0
.0038914114011958235 0
.00467832727817725 0
.0035085180247624317 0
.02227928299366481 0
.0028692334726116804
-
0
.5431994204942634 0
.00812864056228683 0
.0054381362608871 0
.00498397304793199 0
.01163767694734597 0
.002406401968957903 9
.361500782183961E-4 0
.028992472660711033 4
.280811187147705E-4 0
.012521274567758417 4
.8304214654408366E-4 0
.007111109599035777 0
.0044435470772817365 0
.006034656565301625 0
.02210510168861987 0
.0060382383279277965 0
.014059265672495021 0
.005262244892028347 0
.0145231048082589 2
.3815913505616292E-4 0
.004018610517012443 0
.008982714988567425 0
.007162729211694236 4
.6775328230258333E-4 0
.0038205971791198216 0
.0028941264828776193 0
.004715670709902365 0
.004113310760342626 0
.022015405766954235 0
.003089015596881602
-
0
.9169218831064787 0
.006873197457623489 0
.00447774875980394 0
.005954202128148086 0
.011576360276168318 0
.006896467448871528 9
.206732369738643E-4 0
.02897264139541762 5
.598003243183494E-4 0
.01237036281596434 4
.6634548218446635E-4 0
.015021961148446691 0
.004757679638463736 0
.005585230975314136 0
.020916036471700053 0
.005834251076688314 0
.009084933278510208 0
.005272191124850147 0
.0134324998468881 6
.047881665027912E-4 0
.002957451465274495 0
.008499051927838732 0
.007123894173680034 0
.002112191438272757 0
.002769627956314701 0
.002471389201318404 0
.0042890598339392245 0
.003901969367837922 0
.022247904479982455 8
.015950795629669E-4
-
9
.468202994405428E-4 0
.008108147862655369 0
.005583740318491689 0
.005946454839843732 0
.011164232647664014 0
.002286774670967257 1
.1149365314788023E-4 0
.028973009754609456 0
.0011721179276656145 0
.012385508343827754 3
.9589275921711405E-4 0
.014830479357325774 0
.004406450685528179 0
.0049941145573371105 0
.02177121944593872 0
.005609038391525347 0
.00844751082128077 0
.0049769935425854304 0
.013462266883788203 2
.3996073800178056E-4 6
.415175339798465E-4 0
.008758940923228804 0
.006348655136129133 0
.0014859936779251556 0
.002253622341351854 0
.019780768066960823 0
.004260788287923102 0
.001446761508704708 0
.021921147218730886 0
.0029345747646658715
-
0
.01881114602498743 0
.007950642093694135 0
.005488981392981174 0
.005966960159766708 0
.011167300795306003 0
.002181038745644766 7
.410690428433743E-5 0
.029012592469730494 0
.003946689261948498 0
.012325150399621565 3
.71494052081239E-4 0
.014776692391525034 0
.00475905650450145 0
.005997136771136709 0
.022168669550171185 0
.005664564121655441 0
.00936513900739629 0
.004982238230485714 0
.013584475258313973 1
.6149304723474316E-4 8
.903025893192045E-4 0
.00865639451948499 0
.0071707157124095595 6
.292935575611989E-4 0
.0022541207125643956 0
.002637239173984704 0
.004714748023095962 0
.003468929720545867 0
.02505763572340817 0
.0029598391320594573
-
0
.23298499893079222 0
.0016257135964861228 0
.005152513731803023 0
.005971223451951964 0
.013022620080819674 0
.0022741786008502523 2
.54873713356231E-4 0
.029021059392691468 6
.457452430218996E-4 0
.01198914807877857 4
.714804591001599E-4 0
.005437365608112113 0
.004408468955113647 0
.00558455308391179 0
.022058037793348712 0
.006037399830304305 0
.0085623704760998 0
.005273431769422143 0
.013741960971672398 0
.004770808818953412 6
.23699456592703E-4 0
.008743518199645634 0
.007113945292034585 0
.002483368688865986 0
.002730915065464896 0
.002197458924763655 0
.0042855016145770305 0
.0034872616532188806 0
.022200447971782188 0
.0029203348635731853
-
0
.33795832387903835 0
.0013878670101924624 0
.0055012503483938355 0
.005958291972440601 0
.012914031689822733 0
.007138961596017977 3
.84525222857473E-4 0
.029840209969010784 0
.0011032732823058758 0
.01283281375895352 4
.8202285623741715E-4 0
.014957296596785033 0
.004408204202206455 0
.005001675240016523 0
.02206280627496202 0
.006022449348261073 0
.01870705955357888 0
.005124585663793871 0
.01357482811478876 0
.004016850242940491 0
.0028816735759766903 0
.008982900408717218 0
.006108748845230449 4
.8987491496662E-4 0
.0023523795052291237 0
.0027156586238228945 0
.004296059457185933 0
.0033134144697818816 0
.022108790733905877 0
.002949604185074081
-
0
.4945505347724345 0
.008110055817903682 0
.00542073529197596 0
.004921465130614271 0
.005196867991197382 0
.0023591958295319845 9
.297511701872295E-4 0
.029021046828295295 4
.580314575888718E-4 0
.012336993098472863 3
.3578423302317443E-4 0
.006431969059674306 0
.004726765961830731 0
.0055315518363454885 0
.022076739525782676 0
.005591527738462926 0
.013957200637348632 0
.005506438608579756 0
.013181024528799675 2
.673496983465554E-4 0
.004012632628060874 0
.008799703034390628 0
.0071225117567952 0
.002247042705390879 0
.003755134298478031 0
.0026688968989695035 0
.004324543168471341 0
.004157400247394643 0
.022152291218177262 5
.158377860154952E-4
-
0
.5616446249215836 0
.001332180905821624 0
.005655272194585227 0
.005968019488366946 0
.011571283469224354 0
.006891705356197903 2
.245200277602782E-4 0
.028974273057526836 0
.0011294908731750352 0
.011696370199975221 0
.0010875099129613733 0
.006583585298019992 0
.004412862909391745 0
.006027765055281159 0
.021038488585787704 0
.00626320650333361 0
.013641898210769634 0
.004829241691886474 0
.013574885614491496 4
.908691193604029E-4 0
.0021466268588485483 0
.008986294882455328 0
.005986254921579244 0
.002148578218728449 0
.003633975416714848 0
.015335827444375675 0
.004276883749172991 0
.0036772290963547824 0
.022124858462572203 0
.0027092539305345028
-
0
.1357838304237608 0
.0012656456037606007 0
.0069005060777872235 0
.005954655120669166 0
.011208558910543785 0
.0024160739252773065 2
.0281725708336566E-4 0
.02898747166913942 0
.001132392022993191 0
.012517098440548102 0
.0010141382926396824 0
.013765693996134802 0
.004713277852764419 0
.006383591227011038 0
.022099275370331437 0
.005597872579773948 0
.014521025136041603 0
.004832002896453246 0
.01357872488190142 4
.899588499504312E-4 2
.3574371555969763E-4 0
.00897270251174062 0
.007089457465681361 5
.174000474507623E-4 0
.0037066112913601047 0
.02031417090275161 0
.004682521407157776 0
.006244701161205608 0
.025124929406302836 5
.501911428790443E-4
-
0
.5171866527435598 0
.008122573167751591 0
.004739832497325629 0
.004992906296453595 0
.005196867991197382 0
.002029563171327076 9
.361500782183961E-4 0
.029013023447398513 0
.0011380230514080284 0
.012522076761556481 5
.047260047591473E-4 0
.015955113743244508 0
.004406182320121727 0
.006262781650402496 0
.02207726263853931 0
.005991273194813399 0
.014043927290112078 0
.005508376666150078 0
.013467184258915264 0
.0011955836862612317 0
.004018610517012443 0
.008797223324041705 0
.007468262050684957 4
.726486298474967E-4 0
.0037840241667415685 0
.00237267724633475 0
.004690632068954894 0
.004113310760342626 0
.02502983137624691 0
.003175813306373884
-
0
.8433026103226733 0
.001436199490324531 0
.005571606478511475 0
.005964071398626945 0
.013009166284874042 0
.006941818510928281 2
.531838762130586E-4 0
.029021059392691468 0
.0012803651372021595 0
.01198914807877857 4
.714804591001599E-4 0
.005437365608112113 0
.004718759788322982 0
.005589514736340762 0
.022058801154936965 0
.0058469700250945895 0
.0085623704760998 0
.005273431769422143 0
.013745024981148685 0
.004710171224650045 6
.493293807968061E-4 0
.008743518199645634 0
.007113945292034585 0
.002483368688865986 0
.002730915065464896 0
.002197458924763655 0
.004289260849618118 0
.002152574294882734 0
.021996927062598665 0
.0029203348635731853
-
-
...
-
本节贴出了用NSGA-II解决ZDT1的完整例子,相信对整个框架的运行已经大致清楚了。下节将会介绍jMetal.util中的几个工具类,这些工具能配置大规模的实验,比如你需要采用多个算法进行多个优化问题的比较,那么使用这些工具会让实验非常得心应手。