https://github.com/jMetal/jMetalDocumentation/blob/master/problem.md
Je viens d'en faire du japonais. Le texte ci-dessous.
The Problem
interface
La classe qui exprime le problème implémente l'interface Problem
.
package org.uma.jmetal.problem;
/**
* Interface representing a multi-objective optimization problem
*
* @author Antonio J. Nebro <[email protected]>
*
* @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() ;
Les problèmes sont caractérisés par le nombre de déterminants, le nombre de fonctions objectives et le nombre de contraintes.
Par conséquent, une méthode getter est définie pour obtenir chaque valeur.
Le paramètre virtuel «S» détermine le codage de la solution.
ʻEvaluate () est une méthode qui évalue la solution de la classe
S, et
createSolution () ʻest une méthode qui crée une nouvelle solution.
Comme l'interface Solution
est de type générique,
jMetal5 a de nombreuses interfaces qui étendent Solution
pour représenter des problèmes de valeur continue et des problèmes binaires.
Par exemple, l'interface «DoubleProblem» est définie comme suit.
package org.uma.jmetal.problem;
/**
* Interface representing continuous problems
*
* @author Antonio J. Nebro <[email protected]>
*/
public interface DoubleProblem extends Problem<DoubleSolution> {
Double getLowerBound(int index) ;
Double getUpperBound(int index) ;
}
Une classe qui implémente «DoubleProblem» n'accepte que «DoubleSolution».
Ensuite, il est nécessaire d'implémenter une méthode getter qui acquiert les limites inférieure et supérieure de chaque variable.
Dans jMetal5, ʻAbstractDoubleProblem est préparé comme la classe abstraite par défaut qui implémente
DoubleProblem`.
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) ;
}
}
Comme exemple du problème de la valeur continue, [Kursawa
](https://github.com/jMetal/jMetal/blob/jmetal-5.0/jmetal-problem/src/main/java/org/uma/jmetal /problem/multiobjective/Kursawe.java) Le problème est implémenté.
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]);
}
}
Comme l'interface DoubleProblem
et le AbstractDoubleProblem
,
BinaryProblem
et ʻAbstractBinaryProblem, ʻInteger Problem
et ʻAbstract Integer Problem` sont définis.
(module
jmetal-core`)) []: Définition de l'interface.(module
jmetal-core`) :) []: Implémentation par défaut.(module
jmetal-problem`) :) []: Problème implémenté.Il existe deux façons de gérer les problèmes contraints avec jMetal5.
ConstrainedProblem
avec une méthode pour évaluer les contraintes.package org.uma.jmetal.problem;
/**
* Interface representing problems having constraints
*
* @author Antonio J. Nebro <[email protected]>
*/
public interface ConstrainedProblem<S extends Solution<?>> extends Problem<S> {
/* Getters */
public int getNumberOfConstraints() ;
/* Methods */
public void evaluateConstraints(S solution) ;
}
jMetal5 adopte généralement cette dernière approche.
A titre d'exemple, voici un problème Tanaka
avec deux contraintes.
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
Incorporer l'interface ConstrainedProblem
Motivé par le fait que dans les versions précédentes, tous les problèmes avaient ʻevaluate () et ʻevaluateConstraints ()
.
Pour les problèmes sans contrainte, ʻevaluateConstraints () `a été implémenté comme une méthode de.
Afin d'éviter les violations du principe de séparation des interfaces, jMetal5 évalue les contraintes uniquement pour les problèmes qui nécessitent des contraintes.
Dans le jMetal original, il était nécessaire d'évaluer la solution deux fois comme suit.
Problem problem ;
Solution solution ;
...
problem.evaluate(solution) ;
problem.evaluateContraints(solution) ;
La version actuelle doit inclure une vérification des restrictions.
Problem problem ;
Solution solution ;
...
problem.evaluate(solution) ;
problem.evaluateContraints(solution) ;