Skip to content
Snippets Groups Projects
Commit 83074aa6 authored by Caron Olivier's avatar Caron Olivier
Browse files

archive metrics refactoring

parent 1ad07dcf
No related branches found
No related tags found
No related merge requests found
......@@ -25,16 +25,16 @@
#include <vector>
#include "util/ArchiveMetricHelper.h"
#include <stdexcept>
#include "opt/manySolutions/metrics/Metric.h"
namespace opt {
namespace manySolutions {
namespace metrics {
namespace opt::manySolutions::metrics {
/**
* Class representing the Normalized Hypervolume metric
* @tparam ARCHIVE
*/
template<typename ARCHIVE>
class BiObjectiveHypervolumeMetric {
class BiObjectiveHypervolumeMetric : public Metric<ARCHIVE> {
public:
/**
......@@ -42,7 +42,7 @@ namespace opt {
* @param _archive
* @return the normalized hypervolume
*/
double operator()(const ARCHIVE &_archive) {
double operator()(const ARCHIVE &_archive) override {
if (_archive.size() < 1)
throw std::runtime_error(
"BiObjectiveHypervolumeMetric : Archive size need to be greater than 0");
......@@ -54,6 +54,12 @@ namespace opt {
return computeHypervolume(_archive[0].fitness().isMaximisationFitness());
}
/**
* Compute the normalized hypervolume metric according to an archive
* @param _archive
* @param bounds
* @return
*/
double operator()(const ARCHIVE &_archive, const std::vector<std::pair<double, double>> bounds) {
if (_archive.size() < 1)
throw std::runtime_error(
......@@ -69,6 +75,11 @@ namespace opt {
protected:
util::ArchiveMetricHelper<ARCHIVE> archiveMetricHelper;
/**
*
* @param isMaximisationFitness
* @return
*/
double computeHypervolume(bool isMaximisationFitness) {
archiveMetricHelper.sortNormalizedFrontAccordingToAnObjective(isMaximisationFitness);
......@@ -86,6 +97,6 @@ namespace opt {
}
};
}
}
}
#endif //MH_BUILDER_BIOBJECTIVEHYPERVOLUMEMETRIC_H
......@@ -26,16 +26,16 @@
#include "util/ArchiveMetricHelper.h"
#include "util/MathHelper.h"
#include <stdexcept>
#include "opt/manySolutions/metrics/Metric.h"
namespace opt {
namespace manySolutions {
namespace metrics {
namespace opt::manySolutions::metrics {
/**
* Class representing the Normalized Spread metric
* @tparam ARCHIVE
*/
template<typename ARCHIVE>
class BiObjectiveSpreadMetric {
class BiObjectiveSpreadMetric : public Metric<ARCHIVE> {
public:
/**
......@@ -43,7 +43,7 @@ namespace opt {
* @param _archive
* @return the normalized spread
*/
double operator()(const ARCHIVE &_archive) {
double operator()(const ARCHIVE &_archive) override {
if (_archive.size() < 2)
throw std::runtime_error("BiObjectiveSpreadMetric : Archive size need to be greater than 1");
......@@ -53,7 +53,11 @@ namespace opt {
archiveMetricHelper.computeNormalizedFront(_archive);
return computeSpread();
}
/**
* Compute the normalized spread metric according to an archive and fixed min/max bounds of each objective
* @param _archive
* @return the normalized spread
*/
double operator()(const ARCHIVE &_archive, const std::vector<std::pair<double, double>> bounds) {
if (_archive.size() < 1)
throw std::runtime_error("BiObjectiveSpreadMetric : Archive size need to be greater than 0");
......@@ -67,7 +71,10 @@ namespace opt {
protected:
util::ArchiveMetricHelper<ARCHIVE> archiveMetricHelper;
/**
* Compute the spread metric of the normalized front located in the archiveMetricHelper instance variable
* @return the spread metric
*/
double computeSpread() {
archiveMetricHelper.sortNormalizedFrontAccordingToAnObjective(0);
......@@ -90,6 +97,6 @@ namespace opt {
}
};
}
}
}
#endif //MH_BUILDER_BIOBJECTIVESPREADMETRIC_H
......@@ -22,15 +22,22 @@
#ifndef MH_BUILDER_METRICS_H
#define MH_BUILDER_METRICS_H
namespace opt {
namespace manySolutions {
namespace metrics {
namespace opt::manySolutions::metrics {
/**
* abstract class for all metric concrete class. useful for evaluate the quality of an archive
* @tparam ARCHIVE
*/
template<typename ARCHIVE>
class Metric {
public:
double operator()(const ARCHIVE &_archive) = 0;
/**
* abstract method
* methods that override this method have to perform an evaluation of the quality of a given archive
* @param _archive
* @return a calculated metric value
*/
virtual double operator()(const ARCHIVE &_archive) = 0;
};
}
}
}
#endif //MH_BUILDER_METRICS_H
......@@ -23,49 +23,87 @@
#define MH_BUILDER_ARCHIVEMETRICHELPER_H
namespace util {
/**
* helper class for archive of solutions
* allows to compute a normalized archive (where each value are in [0,1])
* @tparam ARCHIVE
**/
template <typename ARCHIVE>
class ArchiveMetricHelper {
public:
/**
* provide for all objectives of an archive the min and max bounds
* the computeBounds method must be invoked before this method
* @return
**/
std::vector<std::pair<double, double>>& getBounds() {
return bounds;
return this->bounds;
}
/**
* provide the normalized Front, this vector is the result of the execution of the
* "computeNormalizedFront" method
**/
std::vector<std::vector<double>>& getNormalizedFront() {
return normalizedFront;
return this->normalizedFront;
}
/**
* computes the min and max bounds for all objectives of the given archive
* stores the result in the "bounds" instance variable such as :
* bounds[i].first : the min value for the objective no i,
* bounds[i].second : the max value for the objective no i,
* @param _archive
**/
void computeBounds(const ARCHIVE &_archive) {
if ( _archive.size() < 1)
throw std::runtime_error("Archive size must be greater than 1");
else {
unsigned long long int nbObj = _archive[0].fitness().objectives().size();
bounds.resize(nbObj);
this->bounds.resize(nbObj);
for(unsigned long long int i = 0; i < nbObj; i++) {
bounds[i] = {_archive[0].fitness().objectives()[i], _archive[0].fitness().objectives()[i]};
this->bounds[i] = {_archive[0].fitness().objectives()[i], _archive[0].fitness().objectives()[i]};
for (unsigned long long int j = 1; j < _archive.size(); j++) {
bounds[i].first = std::min(bounds[i].first, _archive[j].fitness().objectives()[i]);
bounds[i].second = std::max(bounds[i].second, _archive[j].fitness().objectives()[i]);
this->bounds[i].first = std::min(this->bounds[i].first, _archive[j].fitness().objectives()[i]);
this->bounds[i].second = std::max(this->bounds[i].second, _archive[j].fitness().objectives()[i]);
}
}
}
}
/**
* computes the normalized front for the given archive
* the result is stored in the "normalizedFront" instance variable
**/
void computeNormalizedFront(const ARCHIVE &_archive) {
computeBounds(_archive);
computeNormalizedFront(_archive, bounds);
this->computeBounds(_archive);
this->computeNormalizedFront(_archive, bounds);
}
/**
* computes the normalized front for the given archive
* min and max bounds of each objective required for the normalisation are given
* the result is stored in the "normalizedFront" instance variable
* @param _archive
* @param _bounds
**/
void computeNormalizedFront(const ARCHIVE &_archive, const std::vector<std::pair<double, double>> &_bounds) {
if ( _archive.size() < 1)
throw std::runtime_error("Archive size must be greater than 1");
normalizedFront.resize(_archive.size());
unsigned long long int numberOfObjectives=_archive[0].fitness().objectives().size();
for (unsigned long long int i = 0; i < _archive.size(); i++) {
normalizedFront[i].resize(_archive[i].fitness().objectives().size());
normalizedFront[i].resize(numberOfObjectives);
for (unsigned long long int j = 0; j < normalizedFront[i].size() ; j++) {
normalizedFront[i][j] = (_archive[i].fitness().objectives()[j] - _bounds[j].first) / (_bounds[j].second - _bounds[j].first);
}
}
}
/**
* update the normalized front by a sort according to an objective
* @param k the objective number
**/
void sortNormalizedFrontAccordingToAnObjective(unsigned long long int k) {
std::sort(normalizedFront.begin(), normalizedFront.end(), [&](std::vector<double> i, std::vector<double> j) {
return i[k] < j[k];
......
......@@ -21,6 +21,10 @@
#ifndef MH_BUILDER_BIMAXIMISATIONOBJECTIVEHYPERVOLUMEMETRICTEST_H
#define MH_BUILDER_BIMAXIMISATIONOBJECTIVEHYPERVOLUMEMETRICTEST_H
#include "gtest/gtest.h"
#include "core/Solution.h"
#include "core/fitness/FitnessMax.h"
#include "core/archive/NonDominatedArchive.h"
#include "opt/manySolutions/metrics/BiObjectiveHypervolumeMetric.h"
......
......@@ -21,6 +21,10 @@
#ifndef MH_BUILDER_BIMINIMISATIONOBJECTIVEHYPERVOLUMEMETRICTEST_H
#define MH_BUILDER_BIMINIMISATIONOBJECTIVEHYPERVOLUMEMETRICTEST_H
#include "gtest/gtest.h"
#include "core/Solution.h"
#include "core/fitness/FitnessMin.h"
#include "core/archive/NonDominatedArchive.h"
#include "opt/manySolutions/metrics/BiObjectiveHypervolumeMetric.h"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment