https://github.com/jMetal/jMetalDocumentation/blob/master/problem.md
I just made this into Japanese. The text below.
The Problem
interface
The class that expresses the problem implements the Problem
interface.
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() ;
Problem is characterized by the number of decision variables, the number of objective functions, and the number of constraints.
Therefore, getter methods are defined to get each value.
The virtual parameter S
determines the encoding of the solution.
ʻEvaluate ()is a method that evaluates the solution of class
S, and
createSolution () `is a method that creates a new solution.
Since the Solution
interface is a generic type,
jMetal5 has many interfaces that extend Solution
to represent continuous value problems and binary problems.
For example, the DoubleProblem
interface is defined as follows.
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) ;
}
The class that implements DoubleProblem
accepts only DoubleSolution
.
Then, it is necessary to implement a getter method to get the lower and upper limits of each variable.
In jMetal5, ʻAbstractDoubleProblem is prepared as the default abstract class that implements
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) ;
}
}
As an example of a continuous value problem, [Kursawa
](https://github.com/jMetal/jMetal/blob/jmetal-5.0/jmetal-problem/src/main/java/org/uma/jmetal /problem/multiobjective/Kursawe.java) The problem is implemented.
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]);
}
}
Similar to the DoubleProblem
interface and ʻAbstractDoubleProblem
BinaryProblem and ʻAbstractBinaryProblem
,
ʻInteger Problem and ʻAbstract Integer Problem
are defined.
(module
jmetal-core`)) []: Interface definition.(module
jmetal-core`) :) []: Default implementation.(module
jmetal-problem`) :) []: Implemented problem.There are two ways to handle constrained problems with jMetal5.
ConstrainedProblem
interface with methods to evaluate constraints.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 usually takes the latter approach.
As an example, the following is a Tanaka
problem with two constraints.
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
Incorporating the ConstrainedProblem
interface
Motivated by the fact that in previous versions all problems had ʻevaluate () and ʻevaluateConstraints ()
.
For unconstrained problems, ʻevaluateConstraints ()` was implemented as a method from.
In order to avoid interface segregation principle violations, jMetal5 evaluates constraints only for problems that require constraints.
The original jMetal required the solution to be evaluated twice as follows.
Problem problem ;
Solution solution ;
...
problem.evaluate(solution) ;
problem.evaluateContraints(solution) ;
The current version must include a check for restrictions.
Problem problem ;
Solution solution ;
...
problem.evaluate(solution) ;
problem.evaluateContraints(solution) ;