/* Copyright 2009-2016 David Hadka * * This file is part of the MOEA Framework. * * The MOEA Framework is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * The MOEA Framework is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>. */ package org.moeaframework.algorithm.jmetal; import jmetal.core.SolutionType; import jmetal.encodings.solutionType.BinarySolutionType; import jmetal.encodings.solutionType.PermutationSolutionType; import jmetal.encodings.solutionType.RealSolutionType; import org.moeaframework.core.Problem; import org.moeaframework.core.Solution; import org.moeaframework.core.Variable; import org.moeaframework.core.variable.BinaryVariable; import org.moeaframework.core.variable.Permutation; import org.moeaframework.core.variable.RealVariable; import org.moeaframework.problem.ProblemException; /** * Adapter for JMetal problems. This allows MOEA Framework {@link Problem}s to * be used within the JMetal library. */ public class JMetalProblemAdapter extends jmetal.core.Problem { private static final long serialVersionUID = 668044250314229409L; /** * The problem. */ private final Problem problem; /** * Constructs a JMetal problem adapter. * * @param problem the problem */ public JMetalProblemAdapter(Problem problem) { super(); this.problem = problem; if (problem.getNumberOfConstraints() > 1) { System.err.println("multiple constraints not supported, aggregating into first constraint"); } numberOfVariables_ = problem.getNumberOfVariables(); numberOfObjectives_ = problem.getNumberOfObjectives(); numberOfConstraints_ = problem.getNumberOfConstraints(); problemName_ = problem.getName(); lowerLimit_ = new double[numberOfVariables_]; upperLimit_ = new double[numberOfVariables_]; length_ = new int[numberOfVariables_]; Solution solution = problem.newSolution(); SolutionType solutionType = null; try { for (int i = 0; i < numberOfVariables_; i++) { Variable variable = solution.getVariable(i); if (variable instanceof RealVariable) { RealVariable real = (RealVariable)variable; lowerLimit_[i] = real.getLowerBound(); upperLimit_[i] = real.getUpperBound(); if (solutionType == null) { solutionType = new RealSolutionType(this); } else if (!(solutionType instanceof RealSolutionType)) { throw new ProblemException(problem, "mixed types not supported"); } } else if (variable instanceof BinaryVariable) { BinaryVariable binary = (BinaryVariable)variable; length_[i] = binary.getNumberOfBits(); if (solutionType == null) { solutionType = new BinarySolutionType(this); } else if (!(solutionType instanceof BinarySolutionType)) { throw new ProblemException(problem, "mixed types not supported"); } } else if (variable instanceof Permutation) { Permutation permutation = (Permutation)variable; length_[i] = permutation.size(); if (solutionType == null) { solutionType = new PermutationSolutionType(this); } else if (!(solutionType instanceof PermutationSolutionType)) { throw new ProblemException(problem, "mixed types not supported"); } } else { throw new ProblemException(problem, "type not supported"); } } } catch (ClassNotFoundException e) { throw new ProblemException(problem, e); } solutionType_ = solutionType; } @Override public void evaluate(jmetal.core.Solution solution) throws jmetal.util.JMException { Solution result = translate(solution); problem.evaluate(result); for (int i = 0; i < result.getNumberOfObjectives(); i++) { solution.setObjective(i, result.getObjective(i)); } // calculate constraint violation double overallConstraintViolation = 0.0; int numberOfViolations = 0; for (int i = 0; i < result.getNumberOfConstraints(); i++) { if (result.getConstraint(i) != 0.0) { numberOfViolations++; overallConstraintViolation -= Math.abs(result.getConstraint(i)); } } solution.setOverallConstraintViolation(overallConstraintViolation); solution.setNumberOfViolatedConstraint(numberOfViolations); } /** * Translates the specified JMetal solution into a {@link Solution}. Only * works with {@link RealVariable}, {@link BinaryVariable} and * {@link Permutation} decision variables. Since JMetal uses aggregate * constraints, constraint values are only copied if there is a single * constraint. * * @param solution the JMetal solution to be translated * @return the translated solution */ public Solution translate(jmetal.core.Solution solution) { Solution result = problem.newSolution(); for (int i = 0; i < solution.numberOfVariables(); i++) { jmetal.core.Variable variable = solution.getDecisionVariables()[i]; if (variable instanceof jmetal.encodings.variable.Real) { jmetal.encodings.variable.Real real = (jmetal.encodings.variable.Real)variable; result.setVariable(i, new RealVariable(real.getValue(), real .getLowerBound(), real.getUpperBound())); } else if (variable instanceof jmetal.encodings.variable.Binary) { jmetal.encodings.variable.Binary binary = (jmetal.encodings.variable.Binary)variable; BinaryVariable bv = new BinaryVariable( binary.getNumberOfBits()); for (int j = 0; j < binary.getNumberOfBits(); j++) { bv.set(j, binary.getIth(j)); } result.setVariable(i, bv); } else if (variable instanceof jmetal.encodings.variable.Permutation) { jmetal.encodings.variable.Permutation permutation = (jmetal.encodings.variable.Permutation)variable; Permutation p = new Permutation(permutation.vector_); result.setVariable(i, p); } else { throw new IllegalStateException(); } } for (int i = 0; i < solution.numberOfObjectives(); i++) { result.setObjective(i, solution.getObjective(i)); } if (problem.getNumberOfConstraints() == 1) { result.setConstraint(0, solution.getOverallConstraintViolation()); } return result; } /** * Returns the problem underlying by this adapter. * * @return the problem underlying by this adapter */ public Problem getProblem() { return problem; } }