This commit is contained in:
Eremey Valetov 2026-03-01 00:55:46 +00:00 committed by GitHub
commit deaef83c99
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 668 additions and 2 deletions

View file

@ -0,0 +1,100 @@
/*
<moRealVectorNeighbor.h>
Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010
(C) OPAC Team, LIFL, 2002-2007
Eremey Valetov
This software is governed by the CeCILL license under French law and
abiding by the rules of distribution of free software. You can use,
modify and/ or redistribute the software under the terms of the CeCILL
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info".
As a counterpart to the access to the source code and rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty and the software's author, the holder of the
economic rights, and the successive licensors have only limited liability.
In this respect, the user's attention is drawn to the risks associated
with loading, using, modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean that it is complicated to manipulate, and that also
therefore means that it is reserved for developers and experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or
data to be ensured and, more generally, to use and operate it in the
same conditions as regards security.
The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.
ParadisEO WebSite : http://paradiseo.gforge.inria.fr
Contact: paradiseo-help@lists.gforge.inria.fr
*/
#ifndef _moRealVectorNeighbor_h
#define _moRealVectorNeighbor_h
#include <EO.h>
#include <neighborhood/moBackableNeighbor.h>
#include <vector>
#include <iterator>
#include <ostream>
/**
* Neighbor for real-valued vector solutions.
* Stores a delta vector; move() adds it to the solution, moveBack() subtracts it.
*/
template<class EOT, class Fitness = typename EOT::Fitness>
class moRealVectorNeighbor : public moBackableNeighbor<EOT, Fitness>, public std::vector<double> {
public:
typedef std::vector<double> EOVT;
using EOVT::operator[];
using EOVT::size;
moRealVectorNeighbor(unsigned _size = 0, double _value = 0.0)
: moBackableNeighbor<EOT, Fitness>(), EOVT(_size, _value) {}
moRealVectorNeighbor(const moRealVectorNeighbor& _n)
: moBackableNeighbor<EOT, Fitness>(_n), EOVT(_n) {}
moRealVectorNeighbor& operator=(const moRealVectorNeighbor& _source) {
moBackableNeighbor<EOT, Fitness>::operator=(_source);
EOVT::operator=(_source);
return *this;
}
bool equals(moRealVectorNeighbor& _neighbor) const {
if (size() != _neighbor.size())
return false;
for (size_t i = 0; i < size(); i++)
if ((*this)[i] != _neighbor[i])
return false;
return true;
}
void move(EOT& _solution) override {
for (size_t i = 0; i < _solution.size(); i++)
_solution[i] += (*this)[i];
_solution.invalidate();
}
void moveBack(EOT& _solution) override {
for (size_t i = 0; i < _solution.size(); i++)
_solution[i] -= (*this)[i];
_solution.invalidate();
}
void printOn(std::ostream& _os) const override {
EO<Fitness>::printOn(_os);
_os << ' ' << size() << ' ';
std::copy(this->begin(), this->end(), std::ostream_iterator<double>(_os, " "));
}
std::string className() const override {
return "moRealVectorNeighbor";
}
};
#endif

View file

@ -42,6 +42,12 @@
* Abstract class for multi-objective algorithms.
*/
class moeoAlgo
{};
{
public:
virtual ~moeoAlgo() = default;
/** Whether this algorithm supports finalize() for post-integration updates. */
virtual bool hasFinalize() const { return false; }
};
#endif /*MOEOALGO_H_*/

View file

@ -148,6 +148,17 @@ public:
while (continuator (_pop));
}
/**
* Recompute fitness and diversity assignments on the population.
* Useful after integrating immigrants from an island model.
* @param _pop the population to finalize
*/
void finalize(eoPop<MOEOT>& _pop) override {
fitnessAssignment(_pop);
diversityAssignment(_pop);
}
bool hasFinalize() const override { return true; }
protected:

View file

@ -47,6 +47,14 @@
*/
template < class MOEOT >
class moeoPopAlgo : public moeoAlgo, public eoAlgo < MOEOT >
{};
{
public:
/**
* Recompute fitness/diversity after external population changes (e.g. immigrant integration).
* Default implementation is a no-op. Override in subclasses that need it.
* @param _pop the population to finalize
*/
virtual void finalize(eoPop<MOEOT>&) {}
};
#endif /*MOEOPOPALGO_H_*/

View file

@ -0,0 +1,149 @@
/*
* <moeoUnifiedDominanceBasedLS_Real.h>
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2008
* (C) OPAC Team, LIFL, 2002-2008
*
* Eremey Valetov
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
* Contact: paradiseo-help@lists.gforge.inria.fr
*
*/
//-----------------------------------------------------------------------------
#ifndef _MOEOUNIFIEDDOMINANCEBASEDLSREAL_H
#define _MOEOUNIFIEDDOMINANCEBASEDLSREAL_H
#include <eoPop.h>
#include <eoContinue.h>
#include <eoEvalFunc.h>
#include <utils/eoLogger.h>
#include <archive/moeoArchive.h>
#include <algo/moeoPopLS.h>
#include <explorer/moeoPopNeighborhoodExplorer.h>
#include <selection/moeoUnvisitedSelect.h>
#ifdef _OPENMP
#include <omp.h>
#endif
/**
* Real-valued dominance-based local search for multi-objective optimization.
* Uses an archive, flexible selection strategy, and neighborhood exploration
* with optional OpenMP parallelism for initial population evaluation.
*/
template < class Neighbor >
class moeoUnifiedDominanceBasedLSReal : public moeoPopLS < Neighbor >
{
public:
typedef typename Neighbor::EOT MOEOT;
moeoUnifiedDominanceBasedLSReal(
eoContinue < MOEOT > & _continuator,
eoEvalFunc < MOEOT > & _eval,
moeoArchive < MOEOT > & _archive,
moeoPopNeighborhoodExplorer < Neighbor > & _explorer,
moeoUnvisitedSelect < MOEOT > & _select)
: continuator(_continuator), eval(_eval),
archive(_archive), explorer(_explorer), select(_select) {}
virtual void operator()(eoPop<MOEOT>& _pop) override
{
size_t initialPopSize = _pop.size();
int generation = 0;
std::vector<unsigned int> selectionVector;
std::vector<int> initialFlags;
eoPop<MOEOT> tmp_pop;
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (size_t i = 0; i < _pop.size(); i++)
eval(_pop[i]);
archive(_pop);
do {
tmp_pop.resize(0);
selectionVector = select(archive);
initialFlags.clear();
initialFlags.reserve(selectionVector.size());
for (auto idx : selectionVector)
initialFlags.push_back(archive[idx].flag());
eo::log << eo::progress << "LS generation " << ++generation
<< ", archive size = " << archive.size() << std::endl;
eo::log << eo::debug << "continuator = " << continuator << std::endl;
explorer(archive, selectionVector, tmp_pop);
// Verify explorer incremented visit counts correctly
bool allIncremented = true;
bool noneIncremented = true;
for (size_t i = 0; i < selectionVector.size(); i++) {
int newFlag = archive[selectionVector[i]].flag();
if (newFlag == initialFlags[i] + 1)
noneIncremented = false;
else
allIncremented = false;
}
if (!allIncremented && noneIncremented) {
eo::log << eo::warnings << "Explorer did not increment exploration counts" << std::endl;
for (auto idx : selectionVector)
archive[idx].flag(archive[idx].flag() + 1);
} else if (!allIncremented) {
eo::log << eo::warnings << "Exploration counts incremented inconsistently" << std::endl;
for (size_t i = 0; i < selectionVector.size(); i++)
archive[selectionVector[i]].flag(initialFlags[i] + 1);
}
archive(tmp_pop);
archive(_pop);
if (archive.size() <= initialPopSize) {
_pop = archive;
} else {
tmp_pop.resize(0);
for (size_t i = 0; i < initialPopSize; i++)
tmp_pop.push_back(archive[i]);
_pop = tmp_pop;
}
} while (continuator(archive));
}
protected:
eoContinue < MOEOT > & continuator;
eoEvalFunc<MOEOT>& eval;
moeoArchive < MOEOT > & archive;
moeoPopNeighborhoodExplorer < Neighbor > & explorer;
moeoUnvisitedSelect < MOEOT > & select;
};
#endif /* _MOEOUNIFIEDDOMINANCEBASEDLSREAL_H */

View file

@ -0,0 +1,262 @@
/*
* <moeoRealVectorNeighborhoodExplorer.h>
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2008
* (C) OPAC Team, LIFL, 2002-2008
*
* Eremey Valetov
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
* Contact: paradiseo-help@lists.gforge.inria.fr
*
*/
//-----------------------------------------------------------------------------
#ifndef MOEOREALVECTORNEIGHBORHOODEXPLORER_H
#define MOEOREALVECTORNEIGHBORHOODEXPLORER_H
#include <eoPop.h>
#include <utils/eoRealVectorBounds.h>
#include <explorer/moeoPopNeighborhoodExplorer.h>
#include <comparator/moeoParetoObjectiveVectorComparator.h>
#include <random>
#include <cmath>
/**
* Neighborhood explorer for real-valued vector solutions.
* Generates random directions in the search space, evaluates neighbors,
* and performs geometric scaling along improving directions.
*
* @tparam Neighbor neighbor type (must provide EOT typedef)
*/
template <class Neighbor>
class RealVectorNeighborhoodExplorer : public moeoPopNeighborhoodExplorer<Neighbor> {
public:
typedef typename Neighbor::EOT MOEOT;
/**
* @param _eval evaluation function
* @param _bounds bounds for each dimension
* @param _epsilon step size relative to range (scalar, applied to all dimensions)
* @param _ntrydirections number of random directions to try
* @param _breakdirectionlooponfirstsuccess stop direction loop on first improving direction
* @param _minntryscaling minimum scaling iterations before stopping
* @param _maxntryscaling maximum scaling iterations
* @param _scalingfactor multiplicative factor for scaling steps
*/
RealVectorNeighborhoodExplorer(eoEvalFunc<MOEOT>& _eval, const eoRealVectorBounds& _bounds,
double _epsilon = 1e-5, unsigned int _ntrydirections = 10,
bool _breakdirectionlooponfirstsuccess = false,
unsigned int _minntryscaling = 2, unsigned int _maxntryscaling = 5,
unsigned int _scalingfactor = 4)
: bounds(_bounds), epsilons(std::vector<double>(_bounds.size(), _epsilon)),
ntrydirections(_ntrydirections), breakdirectionlooponfirstsuccess(_breakdirectionlooponfirstsuccess),
minntryscaling(_minntryscaling), maxntryscaling(_maxntryscaling), scalingfactor(_scalingfactor),
evalFunc(_eval), minntryscaling_vectype(false) {}
/**
* @param _eval evaluation function
* @param _bounds bounds for each dimension
* @param _epsilon step size relative to range (scalar)
* @param _ntrydirections number of random directions
* @param _breakdirectionlooponfirstsuccess stop on first success
* @param _mintryscaling_explored per-visit-count minimum scaling vector
* @param _maxntryscaling maximum scaling iterations
* @param _scalingfactor multiplicative factor
*/
RealVectorNeighborhoodExplorer(eoEvalFunc<MOEOT>& _eval, const eoRealVectorBounds& _bounds,
double _epsilon, unsigned int _ntrydirections,
bool _breakdirectionlooponfirstsuccess,
std::vector<unsigned int> _mintryscaling_explored,
unsigned int _maxntryscaling = 5, unsigned int _scalingfactor = 4)
: bounds(_bounds), epsilons(std::vector<double>(_bounds.size(), _epsilon)),
ntrydirections(_ntrydirections), breakdirectionlooponfirstsuccess(_breakdirectionlooponfirstsuccess),
minntryscaling_explored(_mintryscaling_explored), maxntryscaling(_maxntryscaling),
scalingfactor(_scalingfactor), evalFunc(_eval), minntryscaling_vectype(true) {}
/**
* @param _eval evaluation function
* @param _bounds bounds for each dimension
* @param _epsilons per-dimension step sizes
* @param _ntrydirections number of random directions
* @param _breakdirectionlooponfirstsuccess stop on first success
* @param _minntryscaling minimum scaling iterations
* @param _maxntryscaling maximum scaling iterations
* @param _scalingfactor multiplicative factor
*/
RealVectorNeighborhoodExplorer(eoEvalFunc<MOEOT>& _eval, const eoRealVectorBounds& _bounds,
std::vector<double> _epsilons, unsigned int _ntrydirections = 10,
bool _breakdirectionlooponfirstsuccess = false,
unsigned int _minntryscaling = 2, unsigned int _maxntryscaling = 5,
unsigned int _scalingfactor = 4)
: bounds(_bounds), epsilons(_epsilons), ntrydirections(_ntrydirections),
breakdirectionlooponfirstsuccess(_breakdirectionlooponfirstsuccess),
minntryscaling(_minntryscaling), maxntryscaling(_maxntryscaling), scalingfactor(_scalingfactor),
evalFunc(_eval), minntryscaling_vectype(false) {
if (epsilons.size() != bounds.size())
throw std::invalid_argument("The number of epsilons must match the number of bounds.");
}
/**
* @param _eval evaluation function
* @param _bounds bounds for each dimension
* @param _epsilons per-dimension step sizes
* @param _ntrydirections number of random directions
* @param _breakdirectionlooponfirstsuccess stop on first success
* @param _mintryscaling_explored per-visit-count minimum scaling vector
* @param _maxntryscaling maximum scaling iterations
* @param _scalingfactor multiplicative factor
*/
RealVectorNeighborhoodExplorer(eoEvalFunc<MOEOT>& _eval, const eoRealVectorBounds& _bounds,
std::vector<double> _epsilons, unsigned int _ntrydirections,
bool _breakdirectionlooponfirstsuccess,
std::vector<unsigned int> _mintryscaling_explored,
unsigned int _maxntryscaling = 5, unsigned int _scalingfactor = 4)
: bounds(_bounds), epsilons(_epsilons), ntrydirections(_ntrydirections),
breakdirectionlooponfirstsuccess(_breakdirectionlooponfirstsuccess),
minntryscaling_explored(_mintryscaling_explored), maxntryscaling(_maxntryscaling),
scalingfactor(_scalingfactor), evalFunc(_eval), minntryscaling_vectype(true) {
if (epsilons.size() != bounds.size())
throw std::invalid_argument("The number of epsilons must match the number of bounds.");
}
void operator()(eoPop<MOEOT>& _src, std::vector<unsigned int> _select, eoPop<MOEOT>& _dest) override {
for (unsigned int i = 0; i < _select.size(); i++) {
explore(_src[_select[i]], _dest);
_src[_select[i]].flag(_src[_select[i]].flag() + 1);
}
for (MOEOT& individual : _dest)
individual.flag(0);
}
protected:
eoRealVectorBounds bounds;
std::vector<double> epsilons;
unsigned int ntrydirections;
bool breakdirectionlooponfirstsuccess;
bool minntryscaling_vectype;
unsigned int minntryscaling;
std::vector<unsigned int> minntryscaling_explored;
unsigned int maxntryscaling;
unsigned int scalingfactor;
eoEvalFunc<MOEOT>& evalFunc;
virtual void explore(MOEOT& _src, eoPop<MOEOT>& _dest) {
std::random_device rd;
std::mt19937 generator(rd());
std::uniform_real_distribution<double> distribution(-1, 1);
unsigned int minntryscaling_eff;
if (minntryscaling_vectype) {
if (!minntryscaling_explored.empty()) {
minntryscaling_eff = minntryscaling_explored[
std::min(static_cast<size_t>(_src.flag()),
minntryscaling_explored.size() - 1)];
} else {
minntryscaling_eff = 1;
}
} else {
minntryscaling_eff = minntryscaling;
}
for (unsigned int i = 0; i < ntrydirections; ++i) {
MOEOT modified_individual = _src;
std::vector<double> random_direction(modified_individual.size());
double magnitude;
do {
magnitude = 0.0;
for (unsigned int j = 0; j < _src.size(); ++j) {
random_direction[j] = distribution(generator);
magnitude += random_direction[j] * random_direction[j];
}
} while (magnitude > 1.0 || magnitude == 0);
magnitude = std::sqrt(magnitude);
for (unsigned int j = 0; j < modified_individual.size(); ++j) {
double range = bounds.maximum(j) - bounds.minimum(j);
random_direction[j] *= range * epsilons[j] / magnitude;
}
for (unsigned int j = 0; j < modified_individual.size(); ++j)
modified_individual[j] += random_direction[j];
modified_individual.invalidate();
if (!bounds.isInBounds(modified_individual))
continue;
moeoParetoObjectiveVectorComparator<typename MOEOT::ObjectiveVector> comparator;
evalFunc(modified_individual);
if (comparator(_src.objectiveVector(), modified_individual.objectiveVector())) {
_dest.push_back(modified_individual);
MOEOT previous_explored_individual = modified_individual;
bool continued_to_scale = false;
for (unsigned int k = 0; k < maxntryscaling; ++k) {
for (unsigned int j = 0; j < modified_individual.size(); ++j)
random_direction[j] *= scalingfactor;
MOEOT scaled_individual = _src;
for (unsigned int j = 0; j < scaled_individual.size(); ++j)
scaled_individual[j] += random_direction[j];
scaled_individual.invalidate();
if (!bounds.isInBounds(scaled_individual))
break;
evalFunc(scaled_individual);
if (k == maxntryscaling - 1)
break;
if (comparator(_src.objectiveVector(), scaled_individual.objectiveVector())) {
_dest.push_back(scaled_individual);
} else if (k < minntryscaling_eff - 1) {
continued_to_scale = true;
} else {
break;
}
if (!comparator(scaled_individual.objectiveVector(), previous_explored_individual.objectiveVector())) {
if (k < minntryscaling_eff - 1)
continued_to_scale = true;
else
break;
}
previous_explored_individual = scaled_individual;
}
if (breakdirectionlooponfirstsuccess) break;
}
}
}
};
#endif //MOEOREALVECTORNEIGHBORHOODEXPLORER_H

View file

@ -56,6 +56,7 @@
#include <algo/moeoSEEA.h>
#include <algo/moeoSPEA2.h>
#include <algo/moeoUnifiedDominanceBasedLS.h>
#include <algo/moeoUnifiedDominanceBasedLS_Real.h>
//#include <archive/moeo2DMinHypervolumeArchive.h>
#include <archive/moeoArchive.h>
@ -115,6 +116,7 @@
#include <explorer/moeoNoDesimprovingNeighborhoodExplorer.h>
#include <explorer/moeoPopNeighborhoodExplorer.h>
#include <explorer/moeoSimpleSubNeighborhoodExplorer.h>
#include <explorer/moeoRealVectorNeighborhoodExplorer.h>
#include <explorer/moeoSubNeighborhoodExplorer.h>
#include <fitness/moeoAggregationFitnessAssignment.h>
@ -206,6 +208,7 @@
#include <selection/moeoSelectors.h>
#include <selection/moeoStochTournamentSelect.h>
#include <selection/moeoUnvisitedSelect.h>
#include <selection/moeoBestUnvisitedSelect.h>
#include <utils/moeoArchiveObjectiveVectorSavingUpdater.h>
#include <utils/moeoArchiveUpdater.h>

View file

@ -0,0 +1,127 @@
/*
* <moeoBestUnvisitedSelect.h>
* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2008
* (C) OPAC Team, LIFL, 2002-2008
*
* Arnaud Liefooghe
* Jérémie Humeau
* Eremey Valetov
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*
* ParadisEO WebSite : http://paradiseo.gforge.inria.fr
* Contact: paradiseo-help@lists.gforge.inria.fr
*
*/
//-----------------------------------------------------------------------------
#ifndef _MOEOBESTUNVISITEDSELECT_H
#define _MOEOBESTUNVISITEDSELECT_H
#include <eoPop.h>
#include <selection/moeoUnvisitedSelect.h>
#include <comparator/moeoParetoObjectiveVectorComparator.h>
#include <algorithm>
#include <random>
/**
* Selects up to a given number of unvisited (or all) individuals from a population,
* optionally excluding those dominated by given objective vectors. The selected
* indices are returned in shuffled order.
*/
template < class MOEOT >
class moeoBestUnvisitedSelect : public moeoUnvisitedSelect < MOEOT >
{
public:
/**
* @param _number maximum number of individuals to select
* @param _selectVisited if true, also consider visited individuals
*/
moeoBestUnvisitedSelect(unsigned int _number, bool _selectVisited = true)
: number(_number), selectVisited(_selectVisited) {}
/**
* @param _number maximum number of individuals to select
* @param _excludeObjectives individuals dominated by any of these are excluded
* @param _selectVisited if true, also consider visited individuals
*/
moeoBestUnvisitedSelect(unsigned int _number,
const std::vector<typename MOEOT::ObjectiveVector>& _excludeObjectives,
bool _selectVisited = true)
: number(_number), excludeObjectives(_excludeObjectives), selectVisited(_selectVisited) {}
std::vector<unsigned int> operator()(eoPop<MOEOT>& _src) override
{
std::vector<unsigned int> res;
res.reserve(_src.size());
moeoParetoObjectiveVectorComparator<typename MOEOT::ObjectiveVector> comparator;
for (unsigned int i = 0; i < _src.size(); i++) {
if (!selectVisited && _src[i].flag() != 0)
continue;
bool isExcluded = false;
for (const auto& objVec : excludeObjectives) {
if (comparator(_src[i].objectiveVector(), objVec)) {
isExcluded = true;
eo::log << eo::debug << "Excluding individual " << i
<< " based on exclusion objective vector" << std::endl;
break;
}
}
if (!isExcluded)
res.push_back(i);
}
// Ensure at least one unvisited individual if possible
if (!selectVisited && res.empty()) {
for (unsigned int i = 0; i < _src.size(); i++) {
if (_src[i].flag() == 0) {
res.push_back(i);
break;
}
}
}
// Last resort: pick the first individual
if (res.empty() && !_src.empty())
res.push_back(0);
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(res.begin(), res.end(), g);
res.resize(std::min(number, static_cast<unsigned int>(res.size())));
return res;
}
private:
unsigned int number;
std::vector<typename MOEOT::ObjectiveVector> excludeObjectives;
bool selectVisited;
};
#endif /*_MOEOBESTUNVISITEDSELECT_H*/