// Spread.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.qualityIndicator; import java.util.Arrays; /** * This class implements the spread quality indicator. * It can be used also as command line program just by typing: * "java jmetal.qualityIndicator.Spread <solutionFrontFile> <trueFrontFile>". * This metric is only applicable to two bi-objective problems. * Reference: Deb, K., Pratap, A., Agarwal, S., Meyarivan, T.: A fast and * elitist multiobjective genetic algorithm: NSGA-II. IEEE Trans. * on Evol. Computation 6 (2002) 182-197 */ public class Spread { public static jmetal.qualityIndicator.util.MetricsUtil utils_;//utils_ is used to access to //the MetricsUtil funcionalities /** * Constructor. * Creates a new instance of a Spread object */ public Spread() { utils_ = new jmetal.qualityIndicator.util.MetricsUtil(); } // Delta /** Calculates the Spread metric. Given the front, the true pareto front as * <code>double []</code>, and the number of objectives, * the method returns the value of the metric. * @param front The front. * @param trueParetoFront The true pareto front. * @param numberOfObjectives The number of objectives. */ public double spread(double [][] front, double [][] trueParetoFront, int numberOfObjectives) { /** * Stores the maximum values of true pareto front. */ double [] maximumValue ; /** * Stores the minimum values of the true pareto front. */ double [] minimumValue ; /** * Stores the normalized front. */ double [][] normalizedFront ; /** * Stores the normalized true Pareto front. */ double [][] normalizedParetoFront ; // STEP 1. Obtain the maximum and minimum values of the Pareto front maximumValue = utils_.getMaximumValues(trueParetoFront, numberOfObjectives); minimumValue = utils_.getMinimumValues(trueParetoFront, numberOfObjectives); // STEP 2. Get the normalized front and true Pareto fronts normalizedFront = utils_.getNormalizedFront(front, maximumValue, minimumValue); normalizedParetoFront = utils_.getNormalizedFront(trueParetoFront, maximumValue, minimumValue); // STEP 3. Sort normalizedFront and normalizedParetoFront; Arrays.sort(normalizedFront, new jmetal.qualityIndicator.util.LexicoGraphicalComparator()); Arrays.sort(normalizedParetoFront, new jmetal.qualityIndicator.util.LexicoGraphicalComparator()); int numberOfPoints = normalizedFront.length; // int numberOfTruePoints = normalizedParetoFront.length; // STEP 4. Compute df and dl (See specifications in Deb's description of // the metric) double df = utils_.distance(normalizedFront[0],normalizedParetoFront[0]); double dl = utils_.distance(normalizedFront[normalizedFront.length-1], normalizedParetoFront[normalizedParetoFront.length-1]); double mean = 0.0; double diversitySum = df + dl; // STEP 5. Calculate the mean of distances between points i and (i - 1). // (the poins are in lexicografical order) for (int i = 0; i < (normalizedFront.length-1); i++) { mean += utils_.distance(normalizedFront[i],normalizedFront[i+1]); } // for mean = mean / (double)(numberOfPoints - 1); // STEP 6. If there are more than a single point, continue computing the // metric. In other case, return the worse value (1.0, see metric's // description). if (numberOfPoints > 1) { for (int i = 0; i < (numberOfPoints -1); i++) { diversitySum += Math.abs(utils_.distance(normalizedFront[i], normalizedFront[i+1]) - mean); } // for return diversitySum / (df + dl + (numberOfPoints-1)*mean); } else return 1.0; } // spread /** * This class can be invoqued from the command line. Three params are required: * 1) the name of the file containing the front, * 2) the name of the file containig the true Pareto front * 3) the number of objectives */ public static void main(String args[]) { if (args.length < 2) { System.err.println("Spread::Main: Error using Spread. Usage: \n java " + "Spread <FrontFile> <TrueFrontFile> " + "<getNumberOfObjectives>"); System.exit(1); } // if // STEP 1. Create a new instance of the metric Spread qualityIndicator = new Spread(); // STEP 2. Read the fronts from the files double [][] solutionFront = utils_.readFront(args[0]); double [][] trueFront = utils_.readFront(args[1]); // STEP 3. Obtain the metric value double value = qualityIndicator.spread(solutionFront,trueFront,2); System.out.println(value); } // Main } // Spread