LoginSignup
1
1

More than 5 years have passed since last update.

jMetal解説 - Problem interface

Last updated at Posted at 2018-02-19

元のページ

これを雑に日本語にしただけ.
以下本文.

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と同様に,
BinaryProblemAbstractBinaryProblem
IntegerProblemAbstractIntegerProblemが定義されている.

  • (org.uma.jmetal.problem (module jmetal-core))[]: インターフェースの定義.
  • (org.uma.jmetal.problem.impl (module jmetal-core):)[]: デフォルトの実装.
  • (org.uma.jmetal.problem (module jmetal-problem):)[]: 実装された問題.

制約付き問題

jMetal5で制約付き問題を扱う方法は2種類ある.
1. evaluate()メソッド内で制約違反を処理する.
2. 制約を評価するメソッドを持つ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) ;

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1