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

hypervolume with nb objectives > 2 integration

parent f1dbdd67
Branches
No related tags found
No related merge requests found
...@@ -47,5 +47,7 @@ if(Python_FOUND) ...@@ -47,5 +47,7 @@ if(Python_FOUND)
target_link_libraries(bitstringNSGA2BiObjective ${Python_LIBRARIES}) target_link_libraries(bitstringNSGA2BiObjective ${Python_LIBRARIES})
target_link_libraries(tspNSGA2BiObjective ${Python_LIBRARIES}) target_link_libraries(tspNSGA2BiObjective ${Python_LIBRARIES})
# the following executables require the hypervolume library
target_link_libraries(tspNSGA2BiObjective hypervolume) target_link_libraries(tspNSGA2BiObjective hypervolume)
target_link_libraries(bitstringNSGA2BiObjective hypervolume)
endif () endif ()
...@@ -37,7 +37,9 @@ ...@@ -37,7 +37,9 @@
#include "opt/singleSolution/neighborhood/neighbor/IndexNeighbor.h" #include "opt/singleSolution/neighborhood/neighbor/IndexNeighbor.h"
#include "representation/bitstring/neighborhood/neighbor/FlipNeighbor.h" #include "representation/bitstring/neighborhood/neighbor/FlipNeighbor.h"
#include "opt/manySolutions/metrics/MultiObjectiveHypervolumeMetric.h"
#include "opt/manySolutions/metrics/BiObjectiveHypervolumeMetric.h"
#include "opt/manySolutions/metrics/BiObjectiveSpreadMetric.h"
#include "opt/manySolutions/geneticAlgorithm/NSGA2_Solution.h" #include "opt/manySolutions/geneticAlgorithm/NSGA2_Solution.h"
#include "opt/manySolutions/geneticAlgorithm/NSGA2_Algorithm.h" #include "opt/manySolutions/geneticAlgorithm/NSGA2_Algorithm.h"
...@@ -49,8 +51,7 @@ ...@@ -49,8 +51,7 @@
using namespace opt::manySolutions::geneticAlgorithm ; using namespace opt::manySolutions::geneticAlgorithm ;
#include "opt/manySolutions/metrics/BiObjectiveHypervolumeMetric.h"
#include "opt/manySolutions/metrics/BiObjectiveSpreadMetric.h"
int main() { int main() {
...@@ -130,6 +131,33 @@ int main() { ...@@ -130,6 +131,33 @@ int main() {
std::cout << "Result: SUCCESS, " << 1; std::cout << "Result: SUCCESS, " << 1;
std::cout << ", [" << hypervolume << ", " << spread << "], " << seed << std::endl; std::cout << ", [" << hypervolume << ", " << spread << "], " << seed << std::endl;
/** begin section in order to see the evolution of the hypervolume for all checkpoints. **/
std::vector<std::pair<double, double>> bounds ;
// step 1 : fixed bounds
bounds.push_back({archiveCheckpoint.getCheckpoints()[0][0].fitness()[0],
archiveCheckpoint.getCheckpoints()[0][0].fitness()[0]}) ;
bounds.push_back({bounds[0].first,bounds[0].second}) ; // init bounds with values of the first sol of first archive
for (auto archive : archiveCheckpoint.getCheckpoints()) {
for (auto nObj=0 ; nObj < 2 ; nObj++)
for (auto sol: archive) {
bounds[nObj].first = std::min(bounds[nObj].first, sol.fitness()[nObj]);
bounds[nObj].second = std::max(bounds[nObj].second, sol.fitness()[nObj]);
}
}
// step 2 : compute hypervolume
std::vector<double> hypervolumes ;
opt::manySolutions::metrics::MultiObjectiveHypervolumeMetric<POP> multiObjectiveHypervolumeMetric ;
for (auto archive : archiveCheckpoint.getCheckpoints()) {
hypervolumes.push_back (multiObjectiveHypervolumeMetric(archive,bounds));
}
matplotlibcpp::named_plot("Hypervolume (t)", archiveCheckpoint.getTimeValues(), hypervolumes);
matplotlibcpp::title("Genetic Algorithm");
matplotlibcpp::xlabel("Time (milliseconds)");
matplotlibcpp::ylabel("hypervolume");
matplotlibcpp::legend();
matplotlibcpp::show();
matplotlibcpp::named_plot("Best Obj 1 (t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getValues(0)); matplotlibcpp::named_plot("Best Obj 1 (t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getValues(0));
matplotlibcpp::named_plot("Best Obj 2 (t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getValues(1)); matplotlibcpp::named_plot("Best Obj 2 (t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getValues(1));
matplotlibcpp::named_plot("Best Obj 1 (0->t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getBestValues(0)); matplotlibcpp::named_plot("Best Obj 1 (0->t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getBestValues(0));
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
using namespace representation::permutation::problems::tsp; using namespace representation::permutation::problems::tsp;
#include "opt/manySolutions/metrics/BiObjectiveHypervolumeMetric.h" #include "opt/manySolutions/metrics/BiObjectiveHypervolumeMetric.h"
#include "opt/manySolutions/metrics/MultiObjectiveHypervolumeMetric.h"
#include "opt/manySolutions/metrics/BiObjectiveSpreadMetric.h" #include "opt/manySolutions/metrics/BiObjectiveSpreadMetric.h"
...@@ -99,7 +100,7 @@ int main() { ...@@ -99,7 +100,7 @@ int main() {
opt::factory::singleSolution::NeighborFactory<NSGA2_SOL, opt::singleSolution::neighborhood::neighbor::IndexNeighbor<NSGA2_SOL>> neighborFactory; opt::factory::singleSolution::NeighborFactory<NSGA2_SOL, opt::singleSolution::neighborhood::neighbor::IndexNeighbor<NSGA2_SOL>> neighborFactory;
opt::singleSolution::neighborhood::neighbor::IndexNeighbor<NSGA2_SOL> *neighbor = neighborFactory.create("2opt"); opt::singleSolution::neighborhood::neighbor::IndexNeighbor<NSGA2_SOL> *neighbor = neighborFactory.create("2opt");
MUTATION mutation(0.15, nsga2_eval, *neighbor); MUTATION mutation(0.15, nsga2_eval, *neighbor);
opt::checkpoint::ArchiveCheckpoint<POP> archiveCheckpoint; opt::checkpoint::ArchiveCheckpoint<POP> archiveCheckpoint(500); // checkpoints every 500 milliseconds
GA ga( GA ga(
&crossover, &crossover,
...@@ -114,26 +115,43 @@ int main() { ...@@ -114,26 +115,43 @@ int main() {
std::cout << "FINAL ARCHIVE :" << std::endl; std::cout << "FINAL ARCHIVE :" << std::endl;
population.sort(); population.sort();
std::cout << population << std::endl; std::cout << population << std::endl;
opt::manySolutions::metrics::BiObjectiveHypervolumeMetric<POP> biObjectiveHypervolumeMetric;
opt::manySolutions::metrics::BiObjectiveSpreadMetric<POP> biObjectiveSpreadMetric;
double hypervolume = biObjectiveHypervolumeMetric(population);
double spread = biObjectiveSpreadMetric(population);
std::cout << "Result: SUCCESS, " << 1;
std::cout << ", [" << hypervolume << ", " << spread << "], " << seed << std::endl;
/** begin section in order to see the evolution of the hypervolume for all checkpoints. **/ /** begin section in order to see the evolution of the hypervolume for all checkpoints. **/
std::vector<std::pair<double, double>> bounds ; std::vector<std::pair<double, double>> bounds ;
// step 1 : fixed bounds // step 1 : fixed bounds
bounds.push_back({0,0}) ; bounds.push_back({0,0}) ; bounds.push_back({archiveCheckpoint.getCheckpoints()[0][0].fitness()[0],
for (auto checkpoint : archiveCheckpoint.getCheckpoints()) { archiveCheckpoint.getCheckpoints()[0][0].fitness()[0]}) ;
bounds.push_back({bounds[0].first,bounds[0].second}) ; // init bounds with values of the first sol of first archive
for (auto archive : archiveCheckpoint.getCheckpoints()) {
for (auto nObj=0 ; nObj < 2 ; nObj++) for (auto nObj=0 ; nObj < 2 ; nObj++)
for (auto value : checkpoint[nObj]) { for (auto sol: archive) {
bounds[nObj].first = std::min(bounds[nObj].first, value); bounds[nObj].first = std::min(bounds[nObj].first, sol.fitness()[nObj]);
bounds[nObj].second = std::min(bounds[nObj].second, value); bounds[nObj].second = std::max(bounds[nObj].second, sol.fitness()[nObj]);
} }
} }
// step 2 : prepare data
opt::manySolutions::metrics::BiObjectiveHypervolumeMetric<POP> biObjectiveHypervolumeMetric;
opt::manySolutions::metrics::BiObjectiveSpreadMetric<POP> biObjectiveSpreadMetric;
double hypervolume = biObjectiveHypervolumeMetric(population);
double spread = biObjectiveSpreadMetric(population); // step 2 : compute hypervolume
std::cout << "Result: SUCCESS, " << 1; std::vector<double> hypervolumes ;
std::cout << ", [" << hypervolume << ", " << spread << "], " << seed << std::endl; opt::manySolutions::metrics::MultiObjectiveHypervolumeMetric<POP> multiObjectiveHypervolumeMetric ;
for (auto archive : archiveCheckpoint.getCheckpoints()) {
hypervolumes.push_back (multiObjectiveHypervolumeMetric(archive,bounds));
}
matplotlibcpp::named_plot("Hypervolume (t)", archiveCheckpoint.getTimeValues(), hypervolumes);
matplotlibcpp::title("Genetic Algorithm");
matplotlibcpp::xlabel("Time (milliseconds)");
matplotlibcpp::ylabel("hypervolume");
matplotlibcpp::legend();
matplotlibcpp::show();
matplotlibcpp::named_plot("Best Obj 1 (t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getValues(0)); matplotlibcpp::named_plot("Best Obj 1 (t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getValues(0));
matplotlibcpp::named_plot("Best Obj 2 (t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getValues(1)); matplotlibcpp::named_plot("Best Obj 2 (t)", archiveCheckpoint.getTimeValues(), archiveCheckpoint.getValues(1));
......
...@@ -6,3 +6,5 @@ ...@@ -6,3 +6,5 @@
# To create bundles of sources: # To create bundles of sources:
# set(<NAME> source1 [source2 ...]) # set(<NAME> source1 [source2 ...])
# Then use ${NAME} # Then use ${NAME}
file(GLOB_RECURSE SRC_LIST ${PROJECT_SOURCE_DIR} *.h)
...@@ -44,10 +44,7 @@ namespace opt::checkpoint { ...@@ -44,10 +44,7 @@ namespace opt::checkpoint {
typedef typename SOL::FITNESS FIT; typedef typename SOL::FITNESS FIT;
typedef typename FIT::VALUE_TYPE VALUE; typedef typename FIT::VALUE_TYPE VALUE;
protected: protected:
std::vector<std::vector<std::vector<VALUE>>> archive_checkpoint ; std::vector<ARCHIVE> archive_checkpoint ;
// archive is a vector of checkpoints, archive[i] corresponds to one checkpoint
// archive[i][j] corresponds to a vector of objective values for objective j
// archive[i][j][k] corresponds to an objective value
TimeCheckpoint<double> time_checkpoint; // elapsed time values TimeCheckpoint<double> time_checkpoint; // elapsed time values
unsigned long long int numberOfObjectives ; unsigned long long int numberOfObjectives ;
bool isMaximisationFitness ; bool isMaximisationFitness ;
...@@ -102,7 +99,7 @@ namespace opt::checkpoint { ...@@ -102,7 +99,7 @@ namespace opt::checkpoint {
* provide all checkpoints * provide all checkpoints
* @return * @return
**/ **/
virtual std::vector<std::vector<std::vector<VALUE>>> &getCheckpoints(); virtual std::vector<ARCHIVE> &getCheckpoints();
private: private:
/** /**
......
...@@ -45,13 +45,8 @@ template<typename ARCHIVE> ...@@ -45,13 +45,8 @@ template<typename ARCHIVE>
void ArchiveCheckpoint<ARCHIVE>::operator()(const ARCHIVE &_arch) { void ArchiveCheckpoint<ARCHIVE>::operator()(const ARCHIVE &_arch) {
if ((this->archive_checkpoint.size() == 0 // first checkpoint or delay between last checkpoint >= frequency if ((this->archive_checkpoint.size() == 0 // first checkpoint or delay between last checkpoint >= frequency
|| (this->time_checkpoint.getElapsedTime() - this->time_checkpoint.getValues().back()) >= this->frequency)) { || (this->time_checkpoint.getElapsedTime() - this->time_checkpoint.getValues().back()) >= this->frequency)) {
this->archive_checkpoint.resize(this->archive_checkpoint.size() + 1); // adding one element this->archive_checkpoint.push_back(_arch);
this->archive_checkpoint.back().resize(this->numberOfObjectives); this->time_checkpoint(0.0);
for (SOL sol: _arch) {
for (unsigned long long int obj = 0; obj < this->numberOfObjectives; obj++)
this->archive_checkpoint.back()[obj].push_back(sol.fitness().objectives()[obj]);
}
this->time_checkpoint(0.0); // a unique time_checkpoint for all objectives
} }
} }
...@@ -66,10 +61,12 @@ template<typename ARCHIVE> ...@@ -66,10 +61,12 @@ template<typename ARCHIVE>
std::vector<typename ArchiveCheckpoint<ARCHIVE>::VALUE> std::vector<typename ArchiveCheckpoint<ARCHIVE>::VALUE>
ArchiveCheckpoint<ARCHIVE>::getValues(unsigned long long int objNum) { ArchiveCheckpoint<ARCHIVE>::getValues(unsigned long long int objNum) {
std::vector<typename ArchiveCheckpoint<ARCHIVE>::VALUE> result; std::vector<typename ArchiveCheckpoint<ARCHIVE>::VALUE> result;
for (auto checkpoint: this->archive_checkpoint) { for (auto oneArchive: this->archive_checkpoint) {
typename ArchiveCheckpoint<ARCHIVE>::VALUE best = checkpoint[objNum][0]; typename ArchiveCheckpoint<ARCHIVE>::VALUE best = oneArchive[0].fitness()[objNum];
for (auto objValue: checkpoint[objNum]) for (auto sol : oneArchive) {
auto objValue = sol.fitness()[objNum] ;
if (this->isBetter(objValue, best)) best = objValue; if (this->isBetter(objValue, best)) best = objValue;
}
result.push_back(best); result.push_back(best);
} }
return result; return result;
...@@ -108,6 +105,6 @@ std::vector<double> &ArchiveCheckpoint<ARCHIVE>::getTimeValues() { ...@@ -108,6 +105,6 @@ std::vector<double> &ArchiveCheckpoint<ARCHIVE>::getTimeValues() {
* @return * @return
**/ **/
template<typename ARCHIVE> template<typename ARCHIVE>
std::vector<std::vector<std::vector<typename ArchiveCheckpoint<ARCHIVE>::VALUE>>> &ArchiveCheckpoint<ARCHIVE>::getCheckpoints() { std::vector<ARCHIVE> &ArchiveCheckpoint<ARCHIVE>::getCheckpoints() {
return this->archive_checkpoint; return this->archive_checkpoint;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment