// GeneralizedSpread.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 generalized spread metric for two or more dimensions.
* It can be used also as command line program just by typing.
* $ java jmetal.qualityIndicator.GeneralizedSpread <solutionFrontFile> <trueFrontFile> <getNumberOfObjectives>
* Reference: A. Zhou, Y. Jin, Q. Zhang, B. Sendhoff, and E. Tsang
* Combining model-based and genetics-based offspring generation for
* multi-objective optimization using a convergence criterion,
* 2006 IEEE Congress on Evolutionary Computation, 2006, pp. 3234-3241.
*/
public class GeneralizedSpread {
public static jmetal.qualityIndicator.util.MetricsUtil utils_; // MetricsUtil provides some
// utilities for implementing
// the metric
/**
* Constructor
* Creates a new instance of GeneralizedSpread
*/
public GeneralizedSpread() {
utils_ = new jmetal.qualityIndicator.util.MetricsUtil();
} // GeneralizedSpread
/**
* Calculates the generalized spread metric. Given the
* pareto front, the true pareto front as <code>double []</code>
* and the number of objectives, the method return the value for the
* metric.
* @param paretoFront The pareto front.
* @param paretoTrueFront The true pareto front.
* @param numberOfObjectives The number of objectives.
* @return the value of the generalized spread metric
**/
public double generalizedSpread(double [][] paretoFront,
double [][] paretoTrueFront,
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(paretoTrueFront,numberOfObjectives);
minimumValue = utils_.getMinimumValues(paretoTrueFront,numberOfObjectives);
normalizedFront = utils_.getNormalizedFront(paretoFront,
maximumValue,
minimumValue);
// STEP 2. Get the normalized front and true Pareto fronts
normalizedParetoFront = utils_.getNormalizedFront(paretoTrueFront,
maximumValue,
minimumValue);
// STEP 3. Find extremal values
double [][] extremValues = new double[numberOfObjectives][numberOfObjectives];
for (int i = 0; i < numberOfObjectives; i++) {
Arrays.sort(normalizedParetoFront,new jmetal.qualityIndicator.util.ValueComparator(i));
System.arraycopy(normalizedParetoFront[normalizedParetoFront.length - 1], 0, extremValues[i], 0, numberOfObjectives);
}
int numberOfPoints = normalizedFront.length;
int numberOfTruePoints = normalizedParetoFront.length;
// STEP 4. Sorts the normalized front
Arrays.sort(normalizedFront,new jmetal.qualityIndicator.util.LexicoGraphicalComparator());
// STEP 5. Calculate the metric value. The value is 1.0 by default
if (utils_.distance(normalizedFront[0],normalizedFront[normalizedFront.length-1])==0.0) {
return 1.0;
} else {
double dmean = 0.0;
// STEP 6. Calculate the mean distance between each point and its nearest neighbor
for (double[] aNormalizedFront : normalizedFront) {
dmean += utils_.distanceToNearestPoint(aNormalizedFront, normalizedFront);
}
dmean = dmean / (numberOfPoints);
// STEP 7. Calculate the distance to extremal values
double dExtrems = 0.0;
for (double[] extremValue : extremValues) {
dExtrems += utils_.distanceToClosedPoint(extremValue, normalizedFront);
}
// STEP 8. Computing the value of the metric
double mean = 0.0;
for (double[] aNormalizedFront : normalizedFront) {
mean += Math.abs(utils_.distanceToNearestPoint(aNormalizedFront, normalizedFront) -
dmean);
}
double value = (dExtrems + mean) / (dExtrems + (numberOfPoints*dmean));
return value;
}
} // generalizedSpread
/**
* This class can be invoked 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 < 3) {
System.err.println("Error using GeneralizedSpread. " +
"Usage: \n java GeneralizedSpread" +
" <SolutionFrontFile> " +
" <TrueFrontFile> + <getNumberOfObjectives>");
System.exit(1);
}
//Create a new instance of the metric
GeneralizedSpread qualityIndicator = new GeneralizedSpread();
//Read the front from the files
double [][] solutionFront = utils_.readFront(args[0]);
double [][] trueFront = utils_.readFront(args[1]);
//Obtain delta value
double value = qualityIndicator.generalizedSpread(solutionFront,
trueFront,
new Integer(args[2]));
System.out.println(value);
} // main
} // GeneralizedSpread