// Distance.java // // Author: // Antonio J. Nebro <antonio@lcc.uma.es> // Juan J. Durillo <durillo@lcc.uma.es> // // Copyright (c) 2011 Antonio J. Nebro, Juan J. Durillo // // This program 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. // // This program 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 this program. If not, see <http://www.gnu.org/licenses/>. package jmetal.util; import jmetal.core.Solution; import jmetal.core.SolutionSet; import jmetal.util.comparators.ObjectiveComparator; import jmetal.util.wrapper.XReal; /** * This class implements some utilities for calculating distances */ public class Distance { /** * Constructor. */ public Distance() { //do nothing. } // Distance /** * Returns a matrix with distances between solutions in a * <code>SolutionSet</code>. * @param solutionSet The <code>SolutionSet</code>. * @return a matrix with distances. */ public double [][] distanceMatrix(SolutionSet solutionSet) { Solution solutionI, solutionJ; //The matrix of distances double [][] distance = new double [solutionSet.size()][solutionSet.size()]; //-> Calculate the distances for (int i = 0; i < solutionSet.size(); i++){ distance[i][i] = 0.0; solutionI = solutionSet.get(i); for (int j = i + 1; j < solutionSet.size(); j++){ solutionJ = solutionSet.get(j); distance[i][j] = this.distanceBetweenObjectives(solutionI,solutionJ); distance[j][i] = distance[i][j]; } // for } // for //->Return the matrix of distances return distance; } // distanceMatrix /** Returns the minimum distance from a <code>Solution</code> to a * <code>SolutionSet according to the objective values</code>. * @param solution The <code>Solution</code>. * @param solutionSet The <code>SolutionSet</code>. * @return The minimum distance between solution and the set. * @throws JMException */ public double distanceToSolutionSetInObjectiveSpace(Solution solution, SolutionSet solutionSet) throws JMException{ //At start point the distance is the max double distance = Double.MAX_VALUE; // found the min distance respect to population for (int i = 0; i < solutionSet.size();i++){ double aux = this.distanceBetweenObjectives(solution,solutionSet.get(i)); if (aux < distance) distance = aux; } // for //->Return the best distance return distance; } // distanceToSolutionSetinObjectiveSpace /** Returns the minimum distance from a <code>Solution</code> to a * <code>SolutionSet according to the encodings.variable values</code>. * @param solution The <code>Solution</code>. * @param solutionSet The <code>SolutionSet</code>. * @return The minimum distance between solution and the set. * @throws JMException */ public double distanceToSolutionSetInSolutionSpace(Solution solution, SolutionSet solutionSet) throws JMException{ //At start point the distance is the max double distance = Double.MAX_VALUE; // found the min distance respect to population for (int i = 0; i < solutionSet.size();i++){ double aux = this.distanceBetweenSolutions(solution,solutionSet.get(i)); if (aux < distance) distance = aux; } // for //->Return the best distance return distance; } // distanceToSolutionSetInSolutionSpace /** Returns the distance between two solutions in the search space. * @param solutionI The first <code>Solution</code>. * @param solutionJ The second <code>Solution</code>. * @return the distance between solutions. * @throws JMException */ public double distanceBetweenSolutions(Solution solutionI, Solution solutionJ) throws JMException{ /* double distance = 0.0; if ((solutionI.getDecisionVariables() != null) && (solutionJ.getDecisionVariables() != null)) { Variable[] decisionVariableI = solutionI.getDecisionVariables(); Variable[] decisionVariableJ = solutionJ.getDecisionVariables(); double diff; //Auxiliar var //-> Calculate the Euclidean distance for (int i = 0; i < decisionVariableI.length; i++){ diff = decisionVariableI[i].getValue() - decisionVariableJ[i].getValue(); distance += Math.pow(diff,2.0); } // for } //-> Return the euclidean distance return Math.sqrt(distance); */ double distance = 0.0; XReal solI = new XReal(solutionI) ; XReal solJ = new XReal(solutionJ) ; double diff; //Auxiliar var //-> Calculate the Euclidean distance for (int i = 0; i < solI.getNumberOfDecisionVariables(); i++){ diff = solI.getValue(i) - solJ.getValue(i); distance += Math.pow(diff,2.0); } // for //-> Return the euclidean distance return Math.sqrt(distance); } // distanceBetweenSolutions /** Returns the distance between two solutions in objective space. * @param solutionI The first <code>Solution</code>. * @param solutionJ The second <code>Solution</code>. * @return the distance between solutions in objective space. */ public double distanceBetweenObjectives(Solution solutionI, Solution solutionJ){ double diff; //Auxiliar var double distance = 0.0; //-> Calculate the euclidean distance for (int nObj = 0; nObj < solutionI.getNumberOfObjectives();nObj++){ diff = solutionI.getObjective(nObj) - solutionJ.getObjective(nObj); distance += Math.pow(diff,2.0); } // for //Return the euclidean distance return Math.sqrt(distance); } // distanceBetweenObjectives. /** * Return the index of the nearest solution in the solution set to a given solution * @param solution * @param solutionSet * @return The index of the nearest solution; -1 if the solutionSet is empty */ public int indexToNearestSolutionInSolutionSpace(Solution solution, SolutionSet solutionSet) { int index = -1 ; double minimumDistance = Double.MAX_VALUE ; try { for (int i = 0 ; i < solutionSet.size(); i++) { double distance = 0; distance = distanceBetweenSolutions(solution, solutionSet.get(i)); if (distance < minimumDistance) { minimumDistance = distance ; index = i ; } } } catch (Exception e) { e.printStackTrace(); } return index ; } /** Assigns crowding distances to all solutions in a <code>SolutionSet</code>. * @param solutionSet The <code>SolutionSet</code>. * @param nObjs Number of objectives. */ public void crowdingDistanceAssignment(SolutionSet solutionSet, int nObjs) { int size = solutionSet.size(); if (size == 0) return; if (size == 1) { solutionSet.get(0).setCrowdingDistance(Double.POSITIVE_INFINITY); return; } // if if (size == 2) { solutionSet.get(0).setCrowdingDistance(Double.POSITIVE_INFINITY); solutionSet.get(1).setCrowdingDistance(Double.POSITIVE_INFINITY); return; } // if //Use a new SolutionSet to evite alter original solutionSet SolutionSet front = new SolutionSet(size); for (int i = 0; i < size; i++){ front.add(solutionSet.get(i)); } for (int i = 0; i < size; i++) front.get(i).setCrowdingDistance(0.0); double objetiveMaxn; double objetiveMinn; double distance; for (int i = 0; i<nObjs; i++) { // Sort the population by Obj n front.sort(new ObjectiveComparator(i)); objetiveMinn = front.get(0).getObjective(i); objetiveMaxn = front.get(front.size()-1).getObjective(i); //Set de crowding distance front.get(0).setCrowdingDistance(Double.POSITIVE_INFINITY); front.get(size-1).setCrowdingDistance(Double.POSITIVE_INFINITY); for (int j = 1; j < size-1; j++) { distance = front.get(j+1).getObjective(i) - front.get(j-1).getObjective(i); distance = distance / (objetiveMaxn - objetiveMinn); distance += front.get(j).getCrowdingDistance(); front.get(j).setCrowdingDistance(distance); } // for } // for } // crowdingDistanceAssing } // Distance