// FastHypervolume.java
//
// Authors:
// Antonio J. Nebro <antonio@lcc.uma.es>
// Juan J. Durillo <durillo@lcc.uma.es>
//
// Copyright (c) 2013 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.fastHypervolume;
import jmetal.core.Solution;
import jmetal.core.SolutionSet;
import jmetal.qualityIndicator.fastHypervolume.wfg.Front;
import jmetal.qualityIndicator.fastHypervolume.wfg.WFGHV;
import jmetal.util.comparators.ObjectiveComparator;
/**
* Created with IntelliJ IDEA.
* User: Antonio J. Nebro
* Date: 26/08/13
* Time: 10:20
*/
public class FastHypervolume {
Solution referencePoint_ ;
int numberOfObjectives_ ;
double offset_ = 20.0 ;
public FastHypervolume() {
referencePoint_ = null ;
numberOfObjectives_ = 0 ;
}
public FastHypervolume(double offset) {
referencePoint_ = null ;
numberOfObjectives_ = 0 ;
offset_ = offset ;
}
public double computeHypervolume(SolutionSet solutionSet) {
double hv ;
if (solutionSet.size() == 0)
hv = 0.0 ;
else {
numberOfObjectives_ = solutionSet.get(0).getNumberOfObjectives() ;
referencePoint_ = new Solution(numberOfObjectives_) ;
updateReferencePoint(solutionSet);
if (numberOfObjectives_ == 2) {
solutionSet.sort(new ObjectiveComparator(numberOfObjectives_-1, true));
hv = get2DHV(solutionSet) ;
}
else {
updateReferencePoint(solutionSet);
Front front = new Front(solutionSet.size(), numberOfObjectives_, solutionSet) ;
hv = new WFGHV(numberOfObjectives_, solutionSet.size(), referencePoint_).getHV(front) ;
}
}
return hv ;
}
public double computeHypervolume(SolutionSet solutionSet, Solution referencePoint) {
double hv = 0.0;
if (solutionSet.size() == 0)
hv = 0.0;
else {
numberOfObjectives_ = solutionSet.get(0).getNumberOfObjectives();
referencePoint_ = referencePoint;
if (numberOfObjectives_ == 2) {
solutionSet.sort(new ObjectiveComparator(numberOfObjectives_ - 1, true));
hv = get2DHV(solutionSet);
} else {
WFGHV wfg = new WFGHV(numberOfObjectives_, solutionSet.size());
Front front = new Front(solutionSet.size(), numberOfObjectives_, solutionSet);
hv = wfg.getHV(front, referencePoint);
}
}
return hv;
}
/**
* Updates the reference point
*/
private void updateReferencePoint(SolutionSet solutionSet) {
double [] maxObjectives = new double[numberOfObjectives_] ;
for (int i = 0; i < numberOfObjectives_; i++)
maxObjectives[i] = 0 ;
for (int i = 0; i < solutionSet.size(); i++)
for (int j = 0 ; j < numberOfObjectives_; j++)
if (maxObjectives[j] < solutionSet.get(i).getObjective(j))
maxObjectives[j] = solutionSet.get(i).getObjective(j) ;
for (int i = 0; i < referencePoint_.getNumberOfObjectives(); i++) {
referencePoint_.setObjective(i, maxObjectives[i]+ offset_) ;
}
}
/**
* Computes the HV of a solution set.
* REQUIRES: The problem is bi-objective
* REQUIRES: The archive is ordered in descending order by the second objective
* @return
*/
public double get2DHV(SolutionSet solutionSet) {
double hv = 0.0;
if (solutionSet.size() > 0) {
hv = Math.abs((solutionSet.get(0).getObjective(0) - referencePoint_.getObjective(0)) *
(solutionSet.get(0).getObjective(1) - referencePoint_.getObjective(1)));
for (int i = 1; i < solutionSet.size(); i++) {
double tmp = Math.abs((solutionSet.get(i).getObjective(0) - referencePoint_.getObjective(0)) *
(solutionSet.get(i).getObjective(1) - solutionSet.get(i - 1).getObjective(1)));
hv += tmp;
}
}
return hv;
}
/**
* Computes the HV contribution of the solutions
* @return
*/
public void computeHVContributions(SolutionSet solutionSet) {
double[] contributions = new double[solutionSet.size()] ;
double solutionSetHV = 0 ;
solutionSetHV = computeHypervolume(solutionSet) ;
for (int i = 0; i < solutionSet.size(); i++) {
Solution currentPoint = solutionSet.get(i);
solutionSet.remove(i) ;
if (numberOfObjectives_ == 2) {
//updateReferencePoint(solutionSet);
//solutionSet.sort(new ObjectiveComparator(numberOfObjectives_-1, true));
contributions[i] = solutionSetHV - get2DHV(solutionSet) ;
}
else {
Front front = new Front(solutionSet.size(), numberOfObjectives_, solutionSet) ;
double hv = new WFGHV(numberOfObjectives_, solutionSet.size(), referencePoint_).getHV(front) ;
contributions[i] = solutionSetHV - hv ;
}
solutionSet.add(i, currentPoint) ;
}
for (int i = 0; i < solutionSet.size(); i++) {
solutionSet.get(i).setCrowdingDistance(contributions[i]) ;
}
}
}