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

nsga-ii in progress

parent bfc1118b
No related branches found
No related tags found
No related merge requests found
......@@ -35,8 +35,9 @@
#include "opt/criterion/TimeCriterion.h"
#include "opt/checkpoint/ArchiveCheckpoint.h"
#include "opt/manySolutions/geneticAlgorithm/GeneticAlgorithm.h"
#include "opt/manySolutions/geneticAlgorithm/NS_GA2.h"
#include "opt/manySolutions/geneticAlgorithm/NS_GA2_Population.h"
//#include "opt/manySolutions/geneticAlgorithm/NS_GA2.h"
//#include "opt/manySolutions/geneticAlgorithm/NS_GA2_Population.h"
#include "opt/manySolutions/geneticAlgorithm/replacement/NS_GA2_Replacement.h"
#include "opt/factory/singleSolution/NeighborFactory.h"
#include "opt/singleSolution/neighborhood/neighbor/IndexNeighbor.h"
......@@ -54,7 +55,8 @@ int main(void) {
typedef Population<SOL> POPULATION;
typedef selection::TournamentSelection<POPULATION> SELECTION ;
typedef crossover::OXCrossover<POPULATION> CROSSOVER ;
typedef replacement::ElitismReplacement<POPULATION> REPLACEMENT ;
//typedef replacement::ElitismReplacement<POPULATION> REPLACEMENT ;
typedef replacement::NS_GA2_Replacement<POPULATION> REPLACEMENT ;
typedef mutation::Mutation<POPULATION> MUTATION ;
typedef opt::criterion::TimeCriterion<POPULATION> STOP ;
typedef GeneticAlgorithm<POPULATION> GA ;
......
......@@ -65,97 +65,7 @@ class NS_GA2 : public GeneticAlgorithm<POPULATION> {
*/
virtual ~NS_GA2() = default;
/**
* The operator that runs the ns-ga2 algorithm
* @param NS_GA2_Population<INDIVIDUAL> sol the population
*/
void operator()(NS_GA2_Population<INDIVIDUAL> &sol) override {
this->init(sol);
unsigned long long int N =sol.size() ;
//code for first generation
POPULATION R = sol ; // do a copy of initial population (parent)
this->selection->operator()(sol);
this->crossover->operator()(this->selection->getSelectedPopulation());
this->mutation->operator()(this->crossover->getOffspring());
R(this->mutation->getOffspring()) ; // merge parent and offspring
vector<vector<unsigned long long int>> F = this->fastNonDominatedSort(R);
sol.clear() ; unsigned long long int i = 0;
while ((sol.size() + F[i].size() ) < N )
this->crowdingDistanceAssignment(F[i],R) ;
sol()
while (newSol)
while (this->criterion->operator()()) { // <1>
this->numberOfGenerations++;
this->selection->operator()(sol); // <2>
this->crossover->operator()(this->selection->getSelectedPopulation()); // <3>
this->mutation->operator()(this->crossover->getOffspring()); // <4>
this->replacement->operator()(sol,this->mutation->getOffspring()) ; // <5>
this->criterion->update(); // <6>
this->checkpoint->operator()(sol); // <7>
}
}
private:
vector<vector<unsigned long long int>> fastNonDominatedSort(NS_GA2_Population<INDIVIDUAL> &pop) {
auto popSize = pop.size();
pop.initRanks();
vector<vector<unsigned long long int>> S(popSize) ;
vector<unsigned long long int> n(popSize) ;
vector<vector<unsigned long long int>> F ; F.clear();
for (auto ind_p = 0 ; ind_p < popSize ; ind_p++) {
S[ind_p].clear() ;
n[ind_p] = 0 ;
for (auto ind_q = 0 ; ind_q < pop.size(); ind_q++)
if (pop[ind_p].fitness() > pop[ind_q].fitness()) // if (p dominates q)
S[ind_p].push_back(ind_q) ; // add q to the set of solutions dominated by p
else if (pop[ind_p].fitness() < pop[ind_q].fitness())
n[ind_p]++ ; // increment the domination counter of p
if (n[ind_p] == 0) { // p belongs to the first front
pop.setRank(ind_p,0);
F[0].push_back(ind_p);
}
}
unsigned long long int i = 0 ; // initialize the front counter
while (F[i].size() != 0) {
vector<unsigned long long int> Q ; // Used to store the members of the next front
Q.clear() ;
for(unsigned long long int ind_p : F[i])
for (unsigned long long int ind_q : S[ind_p]) {
n[ind_q]-- ;
if (n[ind_q]==0) { // q belongs to the next front
pop.setRank(ind_q,i+1);
Q.push_back(ind_q);
}
}
i++ ;
F[i]=Q ;
}
return F ;
}
void crowdingDistanceAssignment(vector<unsigned long long int> & Front, NS_GA2_Population<INDIVIDUAL> & pop ) {
auto F_size=Front.size() ; // number of solutions in front
for(unsigned long long int ind : Front) pop.setCrowdingDistance(ind,0) ; // initialize distance
for (unsigned long long int ind_m = 0 ; ind_m < pop[0].fitness().objectives().size(); ind_m ++) {
// sort using each objective value
std::sort(Front.begin(), Front.end(),
[&ind_m, &pop](const unsigned long long int &i1, const auto unsigned long long int &i2) {
return pop[i1].fitness()[ind_m] > pop[i2].fitness()[ind_m];
});
pop.setCrowdingDistance(Front[0], std::numeric_limits<double>::infinity());
pop.setCrowdingDistance(Front[F_size - 1], std::numeric_limits<double>::infinity());
for (unsigned long long int i = 1; i < (F_size - 1); i++)
pop.setCrowdingDistance(Front[i], pop.setCrowdingDistance(Front[i]) +
(pop[Front[i + 1]].fitness()[ind_m] -
pop[Front[i - 1]].fitness()[ind_m]) /
(pop[Front[0]].fitness()[ind_m] -
pop[Front[F_size - 1]].fitness()[ind_m])
);
}
}
};
}
......
......@@ -37,8 +37,7 @@ namespace opt::manySolutions::geneticAlgorithm {
template < typename SOLUTION >
class NS_GA2_Population : public Population<SOLUTION> {
protected:
std::vector<unsigned long long int > ranks ; // the calculated rank for each solution of the archive
std::vector<unsigned long long int> crowdingDistance ;
public:
/**
......@@ -54,43 +53,7 @@ namespace opt::manySolutions::geneticAlgorithm {
this->ranks.resize(this->archive.size());
std::fill(this->ranks.begin(), this->ranks.end(), -1);
}
/**
* update the rank for a solution specified by its position (index)
* @param index the index of the solution in the archive
* @param value the new rank value
*/
void setRank(const unsigned long long int index, const unsigned long long int value) {
assert(index > 0 and index < this->archive.size());
this->ranks[index] = value ;
}
/**
* provides the rank of a solution specified by its position (index)
* @param index
* @return the rank value
*/
unsigned long long int getRankAt(const unsigned long long int index) const {
assert(index > 0 and index < this->archive.size());
return this->ranks[index] ;
}
/**
* set the crowding distance of the ith individual
* @param index the nth individual
* @param value the new value of the crowding distance
*/
void setCrowdingDistance(const unsigned long long int index, const unsigned long long int value) {
assert(index > 0 and index < this->archive.size());
this->crowdingDistance[index]=value;
}
/**
* provides the crowding distance of the ith individual
* @param index the nth individual
* @return
*/
unsigned long long int getCrowdingDistance(unsigned long long int index) const {
assert(index > 0 and index < this->archive.size());
return this->crowdingDistance[index];
}
};
}
......
......@@ -21,12 +21,90 @@ Authors: Olivier Caron and additional contributors (see Authors)
#ifndef MH_BUILDER_NS_GA2_SOLUTION_H
#define MH_BUILDER_NS_GA2_SOLUTION_H
template <typename T>
concept NS_GA2_Solution =
requires(T sol) {
sol.setRank(const unsigned long long int );
unsigned long long int sol.getRank() const ;
sol.setCrowdingDistance();
#include <vector>
template <typename INDIVIDUAL>
/**
* this class encapsulates an Individual and provides the management of rank and
* crowding distance for NS_GA2 algorithm
* @tparam INDIVIDUAL
*/
class NS_GA2_Solution {
public:
/**
* default constructor
*/
NS_GA2_Solution(INDIVIDUAL &_ind) : ind(&_ind), rank(-1), crowdingDistance(0.0) {
}
/**
* default destructor
*/
virtual ~NS_GA2_Solution() = default;
/**
* update the rank for an individual
* @param value the new rank value
*/
void setRank(const unsigned long long int value) {
this->rank = value ;
}
/**
* provides the rank of an individual
* @return the rank value
*/
unsigned long long int getRank() const {
return this->rank ;
}
/**
* set the crowding distance
* @param value the new value of the crowding distance
*/
void setCrowdingDistance(const double value) {
this->crowdingDistance=value;
}
/**
* provides the crowding distance
* @return the distance
*/
double getCrowdingDistance() const {
return this->crowdingDistance;
}
/**
* provides the inner individual
* @return the individual
*/
INDIVIDUAL &getIndividual() { return *this->ind ;}
/**
* provides the domination counter
* @return
*/
unsigned long long int getN() const { return this->n ;}
/*
* provides the set of individuals that the current individual dominates
*/
std::vector<NS_GA2_Solution<INDIVIDUAL>> &getS() {
return this->S;
}
/**
* updates the domination counter
* @param _n
*/
void setN(unsigned long long int _n) { this->n = _n ; }
protected:
INDIVIDUAL *ind ;
unsigned long long int rank; // the calculated rank
double crowdingDistance;
// the following properties are set during the fast-non-dominated-sort procedure
std::vector<NS_GA2_Solution<INDIVIDUAL>> S ; // the set of individuals that the current individual dominates
unsigned long long int n ; // the domination counter of the current individual
} ;
#endif //MH_BUILDER_NS_GA2_SOLUTION_H
......@@ -28,8 +28,8 @@ Authors: Olivier Caron and additional contributors (see Authors)
namespace opt::manySolutions::geneticAlgorithm::replacement {
/**
* Class representing the All Replacement operator
* all individuals of offspring are inserted in the resulting population
* Class representing the Elitism Replacement operator
* best individuals of offspring are inserted in the resulting population
* @tparam POPULATION
*/
template<typename POPULATION>
......
/***************************************************************************************
* MH-Builder, a framework for designing adaptive metaheuristics *
* for single and multi-objective optimization. *
* (c) 2019 University of Lille, CNRS *
* *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU 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 General Public License *
* for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************
Authors: Olivier Caron and additional contributors (see Authors)
****************************************************************************************/
#ifndef MH_BUILDER_GA_NS_GA2_REPLACEMENT_H
#define MH_BUILDER_GA_NS_GA2_REPLACEMENT_H
#include "opt/manySolutions/geneticAlgorithm/replacement/Replacement.h"
#include "opt/manySolutions/geneticAlgorithm/NS_GA2_Solution.h"
#include<vector>
#include <limits>
namespace opt::manySolutions::geneticAlgorithm::replacement {
/**
* Class representing the NS_GA2 Replacement operator
* @tparam POPULATION
*/
template<typename POPULATION>
class NS_GA2_Replacement : public Replacement<POPULATION> {
public:
typedef typename POPULATION::SOLUTION_TYPE INDIVIDUAL;
/**
* default constructor
*/
explicit NS_GA2_Replacement() = default ;
/**
* the operator that updates the initial population with the offspring
* the replacement follows instructions of the NS_GA2 Algorithm
*/
void operator()(POPULATION &_parent_pop, const POPULATION offspring) {
// NSGA2 algorithm : _parent_pop : Pt, offspring : Qt
unsigned long long int N = _parent_pop.size();
std::vector<NS_GA2_Solution<INDIVIDUAL>> R; // build Rt=P union Q
for (auto ind: _parent_pop) { R.emplace_back(ind); }
for (auto ind: offspring) { R.emplace_back(ind); }
std::vector<std::vector<NS_GA2_Solution<INDIVIDUAL>>> F = this->fastNonDominatedSort(R);
_parent_pop.clear();// Pt = {}
unsigned long long int i = 0;
while ((_parent_pop.size() + F[i].size()) < N) { // until the parent population is filled
this->crowdingDistanceAssignment(F[i]); // calculate the crowding-distance in F_i
for (auto f : F[i])
_parent_pop.push_back(f.getIndividual()); // include the ith nondominated front in the parent pop
i++; // check the next front for inclusion
}
std::sort(F[i].begin(), F[i].end(), // sort in descending order using <_n
[&](const NS_GA2_Solution<INDIVIDUAL> &i, const NS_GA2_Solution<INDIVIDUAL> &j) {
return (i.getRank() < j.getRank() or
( (i.getRank()==j.getRank()) and (i.getCrowdingDistance() > j.getCrowdingDistance())));
});
for (unsigned long long int ind=0; ind < (N - _parent_pop.size()); ind++)
_parent_pop.push_back(F[i][ind].getIndividual()) ;
}
private:
std::vector<std::vector<NS_GA2_Solution<INDIVIDUAL>>> fastNonDominatedSort(std::vector<NS_GA2_Solution<INDIVIDUAL>> &P) {
std::vector<std::vector<NS_GA2_Solution<INDIVIDUAL>>> F ;
std::vector<NS_GA2_Solution<INDIVIDUAL>> Q ; // used to store the members of the new front
Q.clear();
for (NS_GA2_Solution<INDIVIDUAL> p : P) {
p.getS().clear(); // S_p = {}
p.setN(0); // n_p = 0
F[0].clear();
for (NS_GA2_Solution<INDIVIDUAL> q: P) {
if (p.getIndividual().fitness() > q.getIndividual().fitness()) // if (p dominates q)
p.getS().push_back(q); // add q to the set of solutions dominated by p
else if (p.getIndividual().fitness() < q.getIndividual().fitness())
p.setN(p.getN() + 1); // increment the domination counter of p
if (p.getN() == 0) { // p belongs to the first front
p.setRank(0);
Q.push_back(p);
}
}
}
F.push_back(Q) ; // F[0] is set
unsigned long long int i = 0 ;
while (F[i].size()!= 0) {
Q.clear();
for (auto p: F[i]) {
for (auto q: p.getS()) {
q.setN(q.getN() - 1);
if (q.getN() == 0) {
q.setRank(i + 1);
Q.push_back(q);
}
}
}
i = i + 1;
F.push_back(Q);
}
return F ;
}
/**
* set the crowding distance for all individuals stored in Front
* @param Front
*/
void crowdingDistanceAssignment(std::vector<NS_GA2_Solution<INDIVIDUAL>> & Front) {
auto F_size=Front.size() ; // number of solutions in front
if (F_size==0) return ;
for(auto f : Front) f.setCrowdingDistance(0) ; // initialize distance
for (unsigned long long int ind_obj = 0 ; ind_obj < Front[0].getIndividual().fitness().objectives().size(); ind_obj ++) {
// for each objecive value m
// sort using each objective value
std::sort(Front.begin(), Front.end(),
[&ind_obj](NS_GA2_Solution<INDIVIDUAL> &i1, NS_GA2_Solution<INDIVIDUAL> &i2) {
return i1.getIndividual().fitness()[ind_obj] > i2.getIndividual().fitness()[ind_obj];
});
// so that boundary points are always selected
Front[0].setCrowdingDistance(std::numeric_limits<double>::infinity());
Front[F_size - 1].setCrowdingDistance(std::numeric_limits<double>::infinity());
for (unsigned long long int i = 1; i < (F_size - 1); i++) // for all other points
Front[i].setCrowdingDistance(Front[i].getCrowdingDistance() +
(Front[i + 1].getIndividual().fitness()[ind_obj] -
Front[i - 1].getIndividual().fitness()[ind_obj]) /
(Front[0].getIndividual().fitness()[ind_obj] -
Front[F_size-1].getIndividual().fitness()[ind_obj])
);
}
}
};
}
#endif //MH_BUILDER_GA_NS_GA2_REPLACEMENT_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment