// R2.java // // Author: // Juan J. Durillo <juanjo.durillo@gmail.com> // // Copyright (c) 2013 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 jmetal.core.SolutionSet; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.LinkedList; import java.util.StringTokenizer; public class R2 { public jmetal.qualityIndicator.util.MetricsUtil utils_; double [][] matrix_ = null; double [][] lambda_ = null; int nObj_ = 0; /** * Constructor * Creates a new instance of the R2 indicator for a problem with two objectives * and 100 lambda vectors */ public R2() { utils_ = new jmetal.qualityIndicator.util.MetricsUtil(); // by default it creates an R2 indicator for a two dimensions probllem and // uses only 100 weight vectors for the R2 computation nObj_ = 2; // generating the weights lambda_ = new double[100][2]; for (int n = 0; n < 100; n++) { double a = 1.0 * n / (100 - 1); lambda_[n][0] = a; lambda_[n][1] = 1 - a; } // for } // R2 /** * Constructor * Creates a new instance of the R2 indicator for a problem with two objectives * and N lambda vectors */ public R2(int nVectors) { utils_ = new jmetal.qualityIndicator.util.MetricsUtil(); // by default it creates an R2 indicator for a two dimensions probllem and // uses only <code>nVectors</code> weight vectors for the R2 computation nObj_ = 2; // generating the weights lambda_ = new double[nVectors][2]; for (int n = 0; n < nVectors; n++) { double a = 1.0 * n / (nVectors - 1); lambda_[n][0] = a; lambda_[n][1] = 1 - a; } // for } // R2 /** * Constructor * Creates a new instance of the R2 indicator for nDimensiosn * It loads the weight vectors from the file fileName */ public R2(int nObj, String file) { utils_ = new jmetal.qualityIndicator.util.MetricsUtil(); // A file is indicated, the weights are taken from there // by default it creates an R2 indicator for a two dimensions probllem and // uses only <code>nVectors</code> weight vectors for the R2 computation nObj_ = nObj; // generating the weights // reading weights try { // Open the file FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); int numberOfObjectives = 0; int i = 0; int j = 0; String aux = br.readLine(); LinkedList<double[]> list = new LinkedList<double[]>(); while (aux != null) { StringTokenizer st = new StringTokenizer(aux); j = 0; numberOfObjectives = st.countTokens(); double [] vector = new double[nObj]; while (st.hasMoreTokens()) { double value = new Double(st.nextToken()); vector[j++] = value; } list.add(vector); aux = br.readLine(); } br.close(); // convert the LinkedList into a vector lambda_ = new double[list.size()][]; int index = 0; for (double[] aList : list) lambda_[index++] = aList; } catch (Exception e) { System.out.println("initUniformWeight: failed when reading for file: " + file); e.printStackTrace(); } } // R2 /** * Returns the R2 indicator value of a given front * @param front The front * @param trueParetoFront The true Pareto front * @param numberOfObjectives The number of objectives * @param lambda A vector containing the lambda vectors for R2 */ private double R2Withouth(double [][] approximation,double [][] paretoFront, int index) { /** * 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 [][] normalizedApproximation ; /** * Stores the normalized true Pareto front. */ double [][] normalizedParetoFront ; // STEP 1. Obtain the maximum and minimum values of the Pareto front maximumValue = utils_.getMaximumValues(paretoFront, nObj_); minimumValue = utils_.getMinimumValues(paretoFront, nObj_); // STEP 2. Get the normalized front and true Pareto fronts normalizedApproximation = utils_.getNormalizedFront(approximation, maximumValue, minimumValue); normalizedParetoFront = utils_.getNormalizedFront(paretoFront, maximumValue, minimumValue); // STEP 3. compute all the matrix of tchebicheff values if it is null //if (matrix_ == null) { matrix_ = new double[approximation.length][lambda_.length]; for (int i = 0; i < approximation.length; i++) { for (int j = 0; j < lambda_.length; j++) { matrix_[i][j] = lambda_[j][0] * Math.abs(normalizedApproximation[i][0]); for (int n = 1; n < nObj_; n++) { matrix_[i][j] = Math.max(matrix_[i][j], lambda_[j][n] * Math.abs(normalizedApproximation[i][n])); } } } //} // STEP45. Compute the R2 value withouth the point double sumWithout = 0.0; for (int i = 0; i < lambda_.length; i++) { double tmp; if (index != 0) { tmp = matrix_[0][i]; } else { tmp = matrix_[1][i]; } for (int j = 0; j < approximation.length; j++) { if ( j != index) { tmp = Math.min(tmp, matrix_[j][i]); } } sumWithout += tmp; } // STEP 5. Return the R2 value return sumWithout / (double) lambda_.length; } // R2 /** * Returns the element contributing the most to the R2 indicator * @param front The front * @param trueParetoFront The true Pareto front * @param numberOfObjectives The number of objectives * @param lambda A vector containing the lambda vectors for R2 */ public int getBest(double [][] approximation,double [][] paretoFront) { int index_best = -1; double value = Double.NEGATIVE_INFINITY; for (int i = 0; i < approximation.length; i++) { double aux = this.R2Withouth(approximation, paretoFront, i); if (aux > value) { index_best = i; value = aux; } } return index_best; } // getBest /** * Returns the element contributing the less to the R2 * @param front The front * @param trueParetoFront The true Pareto front * @param numberOfObjectives The number of objectives * @param lambda A vector containing the lambda vectors for R2 */ public int getWorst(double [][] approximation,double [][] paretoFront) { int index_worst = -1; double value = Double.POSITIVE_INFINITY; for (int i = 0; i < approximation.length; i++) { double aux = this.R2Withouth(approximation, paretoFront, i); if (aux < value) { index_worst = i; value = aux; } } return index_worst; } // getWorst /** * Returns the element contributing the most to the R2 * @param front A solution set */ public int getBest(SolutionSet set) { double [][] approximationFront = set.writeObjectivesToMatrix(); double [][] trueFront = set.writeObjectivesToMatrix(); return this.getBest(approximationFront, trueFront); } // getWorst /** * Returns the element contributing the less to the R2 * @param front The front * @param trueParetoFront The true Pareto front */ public int getWorst(SolutionSet set) { double [][] approximationFront = set.writeObjectivesToMatrix(); double [][] trueFront = set.writeObjectivesToMatrix(); return this.getWorst(approximationFront, trueFront); } // getWorst /** * Returns the element contributing the most to the R2 indicator * @param front The front * @param trueParetoFront The true Pareto front * @param numberOfObjectives The number of objectives * @param lambda A vector containing the lambda vectors for R2 */ public int [] getNBest(double [][] approximation,double [][] paretoFront, int N) { int [] index_bests = new int[approximation.length]; double [] values = new double[approximation.length]; for (int i = 0; i < approximation.length; i++) { values[i] = this.R2Withouth(approximation, paretoFront, i); index_bests[i] = i; } // for // sorting the values and index_bests for (int i = 0; i < approximation.length; i++) { for (int j = i; j < approximation.length; j++) { if (values[j] < values[i]) { double aux = values[j]; values[j] = values[i]; values[i] = aux; int aux_index = index_bests[j]; index_bests[j] = index_bests[i]; index_bests[i] = aux_index; } } } int [] res = new int[N]; for (int i = 0; i< N; i++) { res[i] = index_bests[i]; } return res; } // getBest /** * Returns the indexes of the N best solutions according to this indicator * @param SolutionSet the solution set for which the best solutions are computed */ public int [] getNBest(SolutionSet set, int N) { double [][] approximationFront = set.writeObjectivesToMatrix(); double [][] trueFront = set.writeObjectivesToMatrix(); return this.getNBest(approximationFront,trueFront,N); } // getNBest /** * Returns the R2 indicator value of a given front * @param front The front * @param trueParetoFront The true Pareto front * @param numberOfObjectives The number of objectives * @param lambda A vector containing the lambda vectors for R2 */ public double R2(double [][] approximation,double [][] paretoFront) { /** * 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 [][] normalizedApproximation ; /** * Stores the normalized true Pareto front. */ double [][] normalizedParetoFront ; // STEP 1. Obtain the maximum and minimum values of the Pareto front maximumValue = utils_.getMaximumValues(paretoFront, nObj_); minimumValue = utils_.getMinimumValues(paretoFront, nObj_); // STEP 2. Get the normalized front and true Pareto fronts normalizedApproximation = utils_.getNormalizedFront(approximation, maximumValue, minimumValue); normalizedParetoFront = utils_.getNormalizedFront(paretoFront, maximumValue, minimumValue); // STEP 3. compute all the matrix of tchebicheff values if it is null //if (matrix_ == null) { matrix_ = new double[approximation.length][lambda_.length]; for (int i = 0; i < approximation.length; i++) { for (int j = 0; j < lambda_.length; j++) { matrix_[i][j] = lambda_[j][0] * Math.abs(normalizedApproximation[i][0]); for (int n = 1; n < nObj_; n++) { matrix_[i][j] = Math.max(matrix_[i][j], lambda_[j][n] * Math.abs(normalizedApproximation[i][n])); } } } //} // STEP 4. The matrix is not null. Compute the R2 value double sum = 0.0; for (int i = 0; i < lambda_.length; i++) { double tmp = matrix_[0][i]; for (int j = 1; j < approximation.length; j++) { tmp = Math.min(tmp, matrix_[j][i]); } sum += tmp; } // STEP 5. Return the R2 value return sum / (double) lambda_.length; } // R2 /** * Returns the R2 indicator of a given population, using as a reference * point 0, 0. Normalization is using taking into account the population itself * @param set * @return */ public double R2(SolutionSet set) { double [][] approximationFront = set.writeObjectivesToMatrix(); double [][] trueFront = set.writeObjectivesToMatrix(); return this.R2(approximationFront, trueFront); } // R2 /** * Returns the R2 indicator value of a given front * @param front The front * @param trueParetoFront The true Pareto front * @param numberOfObjectives The number of objectives * @param lambda A vector containing the lambda vectors for R2 */ public double R2Without(SolutionSet set, int index) { double [][] approximationFront = set.writeObjectivesToMatrix(); double [][] trueFront = set.writeObjectivesToMatrix(); return this.R2(approximationFront, trueFront); } // R2ContributionWithout /** * This class can be call from the command line. At least three parameters * are required: * 1) the name of the file containing the front, * 2) the number of objectives * 2) a file containing the reference point / the Optimal Pareto front for normalizing * 3) the file containing the weight vector */ public static void main(String args[]) { if (args.length < 3) { System.err.println("Error using R2. Usage: \n java jmetal.qualityIndicator.Hypervolume " + "<SolutionFrontFile> " + "<TrueFrontFile> " + "<getNumberOfObjectives>"); System.exit(1); } //Create a new instance of the metric R2 qualityIndicator; //Read the front from the files int nObj = new Integer(args[2]); if (nObj==2 && args.length==3) { qualityIndicator = new R2(); } else { qualityIndicator = new R2(nObj,args[3]); } double [][] approximationFront = qualityIndicator.utils_.readFront(args[0]); double [][] paretoFront = qualityIndicator.utils_.readFront(args[1]); //Obtain delta value double value = qualityIndicator.R2(approximationFront,paretoFront); System.out.println(value); System.out.println(qualityIndicator.R2Withouth(approximationFront,paretoFront,1)); System.out.println(qualityIndicator.R2Withouth(approximationFront,paretoFront,15)); System.out.println(qualityIndicator.R2Withouth(approximationFront,paretoFront,25)); System.out.println(qualityIndicator.R2Withouth(approximationFront,paretoFront,75)); } // main } // R2