##元のページ
https://github.com/jMetal/jMetalDocumentation/blob/master/problem.md
これを雑に日本語にしただけ.
以下本文.
##The Problem
interface
問題を表現するクラスは,Problem
インターフェースをimplementする.
package org.uma.jmetal.problem;
/**
* Interface representing a multi-objective optimization problem
*
* @author Antonio J. Nebro <antonio@lcc.uma.es>
*
* @param <S> Encoding
*/
public interface Problem<S extends Solution<?>> extends Serializable {
/* Getters */
public int getNumberOfVariables() ;
public int getNumberOfObjectives() ;
public int getNumberOfConstraints() ;
public String getName() ;
/* Methods */
public void evaluate(S solution) ;
public S createSolution() ;
Problemは決定変数の数,目的関数の数,制約の数で特徴付けられる.
そのため,それぞれの値を取得するためのgetterメソッドが定義されている.
仮想パラメータS
は解のエンコーディングを決定する.
evaluate()
はクラスS
の解を評価するメソッド,createSolution()
は新しい解を生成するメソッドである.
Solution
インターフェースはジェネリック型なので,
jMetal5には連続値問題や,2値問題を表すためのSolution
を拡張したインターフェースが多数存在する.
例えば,DoubleProblem
インターフェースは以下のように定義されている.
package org.uma.jmetal.problem;
/**
* Interface representing continuous problems
*
* @author Antonio J. Nebro <antonio@lcc.uma.es>
*/
public interface DoubleProblem extends Problem<DoubleSolution> {
Double getLowerBound(int index) ;
Double getUpperBound(int index) ;
}
DoubleProblem
を実装したクラスは,DoubleSolution
のみを受け付ける.
そして,各変数の下限値と上限値を取得するgetterメソッドを実装する必要がある.
jMetal5では,DoubleProblem
を実装したデフォルトのabstract classとしてAbstractDoubleProblem
が用意されている.
package org.uma.jmetal.problem.impl;
public abstract class AbstractDoubleProblem extends AbstractGenericProblem<DoubleSolution>
implements DoubleProblem {
private List<Double> lowerLimit ;
private List<Double> upperLimit ;
/* Getters */
@Override
public Double getUpperBound(int index) {
return upperLimit.get(index);
}
@Override
public Double getLowerBound(int index) {
return lowerLimit.get(index);
}
/* Setters */
protected void setLowerLimit(List<Double> lowerLimit) {
this.lowerLimit = lowerLimit;
}
protected void setUpperLimit(List<Double> upperLimit) {
this.upperLimit = upperLimit;
}
@Override
public DoubleSolution createSolution() {
return new DefaultDoubleSolution(this) ;
}
}
連続値問題の例として,次のようにKursawa
問題が実装されている.
package org.uma.jmetal.problem.multiobjective;
/**
* Class representing problem Kursawe
*/
public class Kursawe extends AbstractDoubleProblem {
/**
* Constructor.
* Creates a default instance of the Kursawe problem.
*/
public Kursawe() {
// 3 variables by default
this(3);
}
/**
* Constructor.
* Creates a new instance of the Kursawe problem.
*
* @param numberOfVariables Number of variables of the problem
*/
public Kursawe(Integer numberOfVariables) {
setNumberOfVariables(numberOfVariables);
setNumberOfObjectives(2);
setName("Kursawe");
List<Double> lowerLimit = new ArrayList<>(getNumberOfVariables()) ;
List<Double> upperLimit = new ArrayList<>(getNumberOfVariables()) ;
for (int i = 0; i < getNumberOfVariables(); i++) {
lowerLimit.add(-5.0);
upperLimit.add(5.0);
}
setLowerLimit(lowerLimit);
setUpperLimit(upperLimit);
}
/** Evaluate() method */
public void evaluate(DoubleSolution solution){
double aux, xi, xj;
double[] fx = new double[getNumberOfObjectives()];
double[] x = new double[getNumberOfVariables()];
for (int i = 0; i < solution.getNumberOfVariables(); i++) {
x[i] = solution.getVariableValue(i) ;
}
fx[0] = 0.0;
for (int var = 0; var < solution.getNumberOfVariables() - 1; var++) {
xi = x[var] * x[var];
xj = x[var + 1] * x[var + 1];
aux = (-0.2) * Math.sqrt(xi + xj);
fx[0] += (-10.0) * Math.exp(aux);
}
fx[1] = 0.0;
for (int var = 0; var < solution.getNumberOfVariables(); var++) {
fx[1] += Math.pow(Math.abs(x[var]), 0.8) +
5.0 * Math.sin(Math.pow(x[var], 3.0));
}
solution.setObjective(0, fx[0]);
solution.setObjective(1, fx[1]);
}
}
DoubleProblem
インターフェースとAbstractDoubleProblem
と同様に,
BinaryProblem
とAbstractBinaryProblem
,
IntegerProblem
とAbstractIntegerProblem
が定義されている.
- (
org.uma.jmetal.problem
(modulejmetal-core
))[]: インターフェースの定義. - (
org.uma.jmetal.problem.impl
(modulejmetal-core
):)[]: デフォルトの実装. - (
org.uma.jmetal.problem
(modulejmetal-problem
):)[]: 実装された問題.
制約付き問題
jMetal5で制約付き問題を扱う方法は2種類ある.
-
evaluate()
メソッド内で制約違反を処理する. - 制約を評価するメソッドを持つ
ConstrainedProblem
インターフェースを実装する.
package org.uma.jmetal.problem;
/**
* Interface representing problems having constraints
*
* @author Antonio J. Nebro <antonio@lcc.uma.es>
*/
public interface ConstrainedProblem<S extends Solution<?>> extends Problem<S> {
/* Getters */
public int getNumberOfConstraints() ;
/* Methods */
public void evaluateConstraints(S solution) ;
}
jMetal5では普通,後者のアプローチをとる.
例として,以下は2つの制約を持つTanaka
問題である.
package org.uma.jmetal.problem.multiobjective;
/**
* Class representing problem Tanaka
*/
public class Tanaka extends AbstractDoubleProblem implements ConstrainedProblem<DoubleSolution> {
public OverallConstraintViolation<DoubleSolution> overallConstraintViolationDegree ;
public NumberOfViolatedConstraints<DoubleSolution> numberOfViolatedConstraints ;
/**
* Constructor.
* Creates a default instance of the problem Tanaka
*/
public Tanaka() {
setNumberOfVariables(2);
setNumberOfObjectives(2);
setNumberOfConstraints(2);
setName("Tanaka") ;
List<Double> lowerLimit = new ArrayList<>(getNumberOfVariables()) ;
List<Double> upperLimit = new ArrayList<>(getNumberOfVariables()) ;
for (int i = 0; i < getNumberOfVariables(); i++) {
lowerLimit.add(10e-5);
upperLimit.add(Math.PI);
}
setLowerLimit(lowerLimit);
setUpperLimit(upperLimit);
overallConstraintViolationDegree = new OverallConstraintViolation<DoubleSolution>() ;
numberOfViolatedConstraints = new NumberOfViolatedConstraints<DoubleSolution>() ;
}
@Override
public void evaluate(DoubleSolution solution) {
solution.setObjective(0, solution.getVariableValue(0));
solution.setObjective(1, solution.getVariableValue(1));
}
/** EvaluateConstraints() method */
@Override
public void evaluateConstraints(DoubleSolution solution) {
double[] constraint = new double[this.getNumberOfConstraints()];
double x1 = solution.getVariableValue(0) ;
double x2 = solution.getVariableValue(1) ;
constraint[0] = (x1 * x1 + x2 * x2 - 1.0 - 0.1 * Math.cos(16.0 * Math.atan(x1 / x2)));
constraint[1] = -2.0 * ((x1 - 0.5) * (x1 - 0.5) + (x2 - 0.5) * (x2 - 0.5) - 0.5);
double overallConstraintViolation = 0.0;
int violatedConstraints = 0;
for (int i = 0; i < getNumberOfConstraints(); i++) {
if (constraint[i]<0.0){
overallConstraintViolation+=constraint[i];
violatedConstraints++;
}
}
overallConstraintViolationDegree.setAttribute(solution, overallConstraintViolation);
numberOfViolatedConstraints.setAttribute(solution, violatedConstraints);
}
}
###Discusion
ConstrainedProblem
インターフェースを組み込むことは,
以前のバージョンですべての問題がevaluate()
とevaluateConstraints()
を持っていたことに動機付けられている.
制約のない問題ではevaluateConstraints()
はからのメソッドとして実装されていた.
Interface Segregation Principle違反を回避するために,jMetal5では制約が必要な問題だけ,制約を評価する.
元のjMetalでは以下のように解の評価が2回必要だった.
Problem problem ;
Solution solution ;
...
problem.evaluate(solution) ;
problem.evaluateContraints(solution) ;
現在のバージョンでは,制約があるかどうかのチェックが含まれていなければならない.
Problem problem ;
Solution solution ;
...
problem.evaluate(solution) ;
problem.evaluateContraints(solution) ;