Compare commits

..

No commits in common. "master" and "v3.1.2" have entirely different histories.

8 changed files with 62 additions and 438 deletions

33
AUTHORS
View file

@ -1,52 +1,41 @@
Current maintainers Current maintainers
=================== ===================
Arnaud Liefooghe <arnaud.liefooghe@univ-lille1.fr>
Clive Canape <clive.canape@inria.fr>
Johann Dreo <johann@dreo.fr> Johann Dreo <johann@dreo.fr>
Sébastien Verel <sebastien.verel@inria.fr>
Active developpers
==================
Alexandre Quemy <alexandre.quemy@inria.fr>
Benjamin Bouvier <bnjbouv@gmail.com>
Caner Candan <caner@candan.fr>
Pierre Savéant <pierre.saveant@thalesgroup.com>
Past contributors Past contributors
================= =================
atantar atantar
Alesandro Sidero
Alexandre Quemy
Alix Zheng
Amine Aziz-Alaoui
Arnaud Liefooghe
Benjamin Bouvier
Bahri
Caner Candan
Clive Canape
fatene fatene
Gustavo Romero Lopez Gustavo Romero Lopez
jboisson jboisson
Jeroen Eggermont Jeroen Eggermont
Jochen Küpper Jochen Küpper
Joost Joost <joost@dsj.nl>
Juan Julian Merelo Guervos Juan Julian Merelo Guervos
Jérémie Humeau Jérémie Humeau
Jxtopher
Karima Boufaras Karima Boufaras
legillono legillon
Leo Bertheas
Louis Da Costa Louis Da Costa
Loïc Jean David Arjanen Loïc Jean David Arjanen
Maarten Keijzer Maarten Keijzer
Mammar Amara
Manu
Marc Schoenauer Marc Schoenauer
Marie-Éleonore Marie-Éleonore
Mostepha Khouadjia Mostepha Khouadjia
Olivier König Olivier König
Pierre Savéant
Pedro Angel Castillo Valdivieso Pedro Angel Castillo Valdivieso
Potalas
Ronald Pinho
Steve Madere Steve Madere
Sébastien Cahon Sébastien Cahon
Sébastien Verel
Thomas Legrand Thomas Legrand
Thibault Lasnier
Victor Manuel Rivas Santos Victor Manuel Rivas Santos
wcancino wcancino
xohm xohm

View file

@ -13,7 +13,7 @@ cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
## Name ## Name
project("ParadisEO" project("ParadisEO"
VERSION 3.1.3 VERSION 3.0.0
DESCRIPTION "Evolutionary optimization framework" DESCRIPTION "Evolutionary optimization framework"
LANGUAGES C CXX) LANGUAGES C CXX)

View file

@ -2,8 +2,7 @@
Summary Summary
======= =======
As Paradiseo is a development framework, you do not really need to install it on all your systems. As Paradiseo is a development framework, you do not really need to install it on all your systems. Just put it somewhere on your development computer, compile it from here and indicate where to find it to your favorite build system.
Just put it somewhere on your development computer, compile it from here and indicate where to find it to your favorite build system.
Build Build
@ -19,11 +18,6 @@ Paradiseo use the CMake build system, so building it should be as simple as:
mkdir build ; cd build ; cmake -DEDO=ON .. && make -j mkdir build ; cd build ; cmake -DEDO=ON .. && make -j
``` ```
The file `howto_build_paradiseo.apptainer.def` shows you how to install and build from scratch.
It is a definition file for the [Apptainer](https://apptainer.org/) container system,
which is often used on HPC clusters.
Develop Develop
------- -------

View file

@ -1169,7 +1169,7 @@ undiscovered knowledge.
<div id="Downloads"> <div id="Downloads">
<h2><a name="Downloads"></a>Downloads</h2> <h2><a name="Downloads"></a>Downloads</h2>
<p>The current stable release is version: <a href="https://github.com/nojhan/paradiseo/releases">Paradiseo 3.1.3</a>. Some other releases (older or newer) can be found on <a href="https://github.com/nojhan/paradiseo/tags">GitHub/paradiseo/releases</a>.</p> <p>The current stable release is version: <a href="https://github.com/nojhan/paradiseo/releases">Paradiseo 3.0.0-beta</a>. Some other releases (older or newer) can be found on <a href="https://github.com/nojhan/paradiseo/tags">GitHub/paradiseo/releases</a>.</p>
<p> You can obtain the latest stable and beta version directly via the Git repository: <p> You can obtain the latest stable and beta version directly via the Git repository:
<code class="command">git clone https://github.com/jdreo/paradiseo.git</code>. <code class="command">git clone https://github.com/jdreo/paradiseo.git</code>.

View file

@ -40,73 +40,73 @@ template <class EOT>
class eoRanking : public eoPerf2Worth<EOT> // false: do not cache fitness class eoRanking : public eoPerf2Worth<EOT> // false: do not cache fitness
{ {
public: public:
using eoPerf2Worth<EOT>::value; using eoPerf2Worth<EOT>::value;
/* Ctor: /* Ctor:
@param _p selective pressure (in (1,2] @param _p selective pressure (in (1,2]
@param _e exponent (1 == linear) @param _e exponent (1 == linear)
*/ */
eoRanking(double _p = 2.0, double _e = 1.0) : pressure(_p), exponent(_e) eoRanking(double _p=2.0, double _e=1.0):
{ pressure(_p), exponent(_e) {}
assert(1 < pressure and pressure <= 2);
}
/* helper function: finds index in _pop of _eo, an EOT * */ /* helper function: finds index in _pop of _eo, an EOT * */
int lookfor(const EOT *_eo, const eoPop<EOT> &_pop) int lookfor(const EOT *_eo, const eoPop<EOT>& _pop)
{ {
typename eoPop<EOT>::const_iterator it; typename eoPop<EOT>::const_iterator it;
for (it = _pop.begin(); it < _pop.end(); it++) for (it=_pop.begin(); it<_pop.end(); it++)
{ {
if (_eo == &(*it)) if (_eo == &(*it))
return it - _pop.begin(); return it-_pop.begin();
} }
throw eoException("Not found in eoLinearRanking"); throw eoException("Not found in eoLinearRanking");
} }
/* COmputes the ranked fitness: fitnesses range in [m,M] /* COmputes the ranked fitness: fitnesses range in [m,M]
with m=2-pressure/popSize and M=pressure/popSize. with m=2-pressure/popSize and M=pressure/popSize.
in between, the progression depstd::ends on exponent (linear if 1). in between, the progression depstd::ends on exponent (linear if 1).
*/ */
virtual void operator()(const eoPop<EOT> &_pop) virtual void operator()(const eoPop<EOT>& _pop)
{ {
std::vector<const EOT *> rank; std::vector<const EOT *> rank;
_pop.sort(rank); _pop.sort(rank);
unsigned pSize = _pop.size(); unsigned pSize =_pop.size();
unsigned int pSizeMinusOne = pSize - 1; unsigned int pSizeMinusOne = pSize-1;
if (pSize <= 1) if (pSize <= 1)
throw eoPopSizeException(pSize, "cannot do ranking with population of size <= 1"); throw eoPopSizeException(pSize,"cannot do ranking with population of size <= 1");
// value() refers to the std::vector of worthes (we're in an eoParamvalue) // value() refers to the std::vector of worthes (we're in an eoParamvalue)
value().resize(pSize); value().resize(pSize);
double beta = (2 - pressure) / pSize; double beta = (2-pressure)/pSize;
if (exponent == 1.0) // no need for exponential then if (exponent == 1.0) // no need for exponetial then
{ {
double alpha = (2 * pressure - 2) / (pSize * pSizeMinusOne); double alpha = (2*pressure-2)/(pSize*pSizeMinusOne);
for (unsigned i = 0; i < pSize; i++) for (unsigned i=0; i<pSize; i++)
{ {
int which = lookfor(rank[i], _pop); int which = lookfor(rank[i], _pop);
value()[which] = alpha * (pSize - i) + beta; // worst -> 1/[P(P-1)/2] value()[which] = alpha*(pSize-i)+beta; // worst -> 1/[P(P-1)/2]
} }
} }
else // exponent != 1 else // exponent != 1
{ {
double gamma = (2 * pressure - 2) / pSize; double gamma = (2*pressure-2)/pSize;
for (unsigned i = 0; i < pSize; i++) for (unsigned i=0; i<pSize; i++)
{ {
int which = lookfor(rank[i], _pop); int which = lookfor(rank[i], _pop);
// value is in [0,1] // value in in [0,1]
double tmp = ((double)(pSize - i)) / pSize; double tmp = ((double)(pSize-i))/pSize;
// to the exponent, and back to [m,M] // to the exponent, and back to [m,M]
value()[which] = gamma * pow(tmp, exponent) + beta; value()[which] = gamma*pow(tmp, exponent)+beta;
} }
} }
} }
private:
private: double pressure; // selective pressure
double pressure; // selective pressure double exponent;
double exponent;
}; };
#endif #endif

View file

@ -1,139 +0,0 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoRankingCached.h
(c) Maarten Keijzer, Marc Schoenauer, 2001
This library 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 2 of the License, or (at your option) any later version.
This library 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 library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mkeijzer@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef eoRankingCached_h
#define eoRankingCached_h
#include "eoPerf2Worth.h"
/**
* @class eoRankingCached
* @brief Cached version of eoRanking that stores precomputed values for better performance
*
* This class implements the same ranking algorithm as eoRanking but adds a caching layer
* that stores frequently used values when the population size remains constant between
* calls. This optimization is particularly useful in steady-state evolution where the
* population size typically doesn't change between selection operations.
*
* The caching mechanism stores:
* - Population size related values (pSize, pSizeMinusOne)
* - Precomputed coefficients (alpha, beta, gamma)
*
* @warning This optimization should only be used when the population size remains constant
* between calls to the operator. For dynamic population sizes, use the standard eoRanking.
*
* @ingroup Selectors
*/
template <class EOT>
class eoRankingCached : public eoPerf2Worth<EOT>
{
public:
using eoPerf2Worth<EOT>::value;
/* Ctor:
@param _p selective pressure (in (1,2]
@param _e exponent (1 == linear)
*/
eoRankingCached(double _p = 2.0, double _e = 1.0) : pressure(_p), exponent(_e), cached_pSize(0)
{
assert(1 < pressure and pressure <= 2);
}
/*
Computes the ranked fitness with caching optimization
Fitnesses range in [m,M] where:
- m = 2-pressure/popSize
- M = pressure/popSize
The progression between m and M depends on the exponent (linear when exponent=1)
@param _pop The population to rank
*/
virtual void operator()(const eoPop<EOT> &_pop)
{
unsigned pSize = _pop.size();
if (pSize <= 1)
throw eoPopSizeException(pSize, "cannot do ranking with population of size <= 1");
// value() refers to the std::vector of worthes (we're in an eoParamvalue)
value().resize(pSize);
// Cache population-size dependent values only when population size changes
if (pSize != cached_pSize)
{
cached_pSize = pSize;
cached_pSizeMinusOne = pSize - 1;
cached_beta = (2 - pressure) / pSize;
cached_gamma = (2 * pressure - 2) / pSize;
cached_alpha = (2 * pressure - 2) / (pSize * cached_pSizeMinusOne);
}
std::vector<const EOT *> rank;
_pop.sort(rank);
// map of indices for the population
std::unordered_map<const EOT *, unsigned> indexMap;
for (unsigned i = 0; i < pSize; ++i)
{
indexMap[&_pop[i]] = i;
}
if (exponent == 1.0) // no need for exponential then (linear case)
{
for (unsigned i = 0; i < pSize; i++)
{
const EOT *indiv = rank[i];
int which = indexMap[indiv];
value()[which] = cached_alpha * (pSize - i) + cached_beta;
}
}
else // non-linear case (exponent != 1)
{
for (unsigned i = 0; i < pSize; i++)
{
const EOT *indiv = rank[i];
int which = indexMap[indiv];
// value is in [0,1]
double tmp = ((double)(pSize - i)) / pSize;
// to the exponent, and back to [m,M]
value()[which] = cached_gamma * pow(tmp, exponent) + cached_beta;
}
}
}
private:
double pressure; // selective pressure (1 < pressure <= 2)
double exponent; // exponent (1 = linear)
// Cached values (recomputed only when population size changes)
unsigned cached_pSize; // last seen population size
unsigned cached_pSizeMinusOne; // pSize - 1
double cached_alpha; // linear scaling coefficient
double cached_beta; // base value coefficient
double cached_gamma; // non-linear scaling coefficient
};
#endif

View file

@ -82,7 +82,6 @@ set (TEST_LIST
t-eoAlgoFoundryFastGA t-eoAlgoFoundryFastGA
t-eoRealToIntMonOp t-eoRealToIntMonOp
t-eoRealToIntQuadOp t-eoRealToIntQuadOp
t-eoRankingCached
) )

View file

@ -1,219 +0,0 @@
#include <apply.h>
#include <eo>
#include <eoRanking.h>
#include <eoRankingCached.h>
#include <es/eoReal.h>
#include <utils/eoRNG.h>
#include "real_value.h"
class RankingTest
{
public:
RankingTest(eoParser &parser, eoEvalFuncCounter<eoReal<double>> &_eval, unsigned size = 100)
: rng(0),
popSize(size),
seedParam(parser.createParam(uint32_t(time(0)), "seed", "Random seed", 'S')),
pressureParam(parser.createParam(1.5, "pressure", "Selective pressure", 'p')),
exponentParam(parser.createParam(1.0, "exponent", "Ranking exponent", 'e')),
eval(_eval)
{
rng.reseed(seedParam.value());
initPopulation();
}
void initPopulation()
{
pop.clear();
for (unsigned i = 0; i < popSize; ++i)
{
eoReal<double> ind;
ind.resize(1);
ind[0] = rng.uniform();
pop.push_back(ind);
}
apply<eoReal<double>>(eval, pop);
}
const unsigned popSize;
eoPop<eoReal<double>> pop;
eoRng rng;
double pressure() const { return pressureParam.value(); }
double exponent() const { return exponentParam.value(); }
private:
eoValueParam<uint32_t> &seedParam;
eoValueParam<double> &pressureParam;
eoValueParam<double> &exponentParam;
eoEvalFuncCounter<eoReal<double>> eval;
};
// Test case 1: Verify both implementations produce identical results
void test_Consistency(eoParser &parser)
{
eoEvalFuncPtr<eoReal<double>, double, const std::vector<double> &> mainEval(real_value);
eoEvalFuncCounter<eoReal<double>> eval(mainEval);
RankingTest fixture(parser, eval);
eoRanking<eoReal<double>> ranking(fixture.pressure(), fixture.exponent());
eoRankingCached<eoReal<double>> rankingCached(fixture.pressure(), fixture.exponent());
ranking(fixture.pop);
rankingCached(fixture.pop);
const std::vector<double> &values = ranking.value();
const std::vector<double> &cachedValues = rankingCached.value();
for (unsigned i = 0; i < fixture.pop.size(); ++i)
{
if (abs(values[i] - cachedValues[i]) > 1e-9)
{
throw std::runtime_error("Inconsistent ranking values between implementations");
}
}
std::clog << "Test 1 passed: Both implementations produce identical results" << std::endl;
}
// Test case 2: Test edge case with minimum population size
void test_MinPopulationSize(eoParser &parser)
{
eoPop<eoReal<double>> smallPop;
eoReal<double> ind1, ind2;
ind1.resize(1);
ind1[0] = 0.5;
ind2.resize(1);
ind2[0] = 1.0;
smallPop.push_back(ind1);
smallPop.push_back(ind2);
eoEvalFuncPtr<eoReal<double>, double, const std::vector<double> &> mainEval(real_value);
eoEvalFuncCounter<eoReal<double>> eval(mainEval);
RankingTest fixture(parser, eval, 2); // Use fixture to get parameters
eoRanking<eoReal<double>> ranking(fixture.pressure(), fixture.exponent());
eoRankingCached<eoReal<double>> rankingCached(fixture.pressure(), fixture.exponent());
apply<eoReal<double>>(eval, smallPop);
ranking(smallPop);
rankingCached(smallPop);
if (ranking.value()[0] >= ranking.value()[1] ||
rankingCached.value()[0] >= rankingCached.value()[1])
{
throw std::runtime_error("Invalid ranking for population size 2");
}
std::clog << "Test 2 passed: Minimum population size handled correctly" << std::endl;
}
// Test case 3: Verify caching actually works
void test_CachingEffectiveness(eoParser &parser)
{
eoEvalFuncPtr<eoReal<double>, double, const std::vector<double> &> mainEval(real_value);
eoEvalFuncCounter<eoReal<double>> eval(mainEval);
RankingTest fixture(parser, eval, 50); // Fixed size for cache test
eoRankingCached<eoReal<double>> rankingCached(fixture.pressure(), fixture.exponent());
// First run - should compute all values
rankingCached(fixture.pop);
const auto firstValues = rankingCached.value();
// Modify fitness values but keep same population size
for (auto &ind : fixture.pop)
{
ind[0] = fixture.rng.uniform();
}
apply<eoReal<double>>(eval, fixture.pop);
// Second run - should use cached coefficients
rankingCached(fixture.pop);
// Add one individual to invalidate cache
eoReal<double> newInd;
newInd.resize(1);
newInd[0] = fixture.rng.uniform();
fixture.pop.push_back(newInd);
apply<eoReal<double>>(eval, fixture.pop);
// Third run - should recompute coefficients
rankingCached(fixture.pop);
std::clog << "Test 3 passed: Caching mechanism properly invalidated" << std::endl;
}
// Helper function to test constructor assertions
bool testRankingConstructor(double pressure, double exponent)
{
try
{
eoRanking<eoReal<double>> ranking(pressure, exponent);
return true; // Constructor succeeded
}
catch (...)
{
return false; // Assertion failed
}
}
// Helper function to test constructor assertions
bool testRankingCachedConstructor(double pressure, double exponent)
{
try
{
eoRankingCached<eoReal<double>> ranking(pressure, exponent);
return true;
}
catch (...)
{
return false;
}
}
// Test case 4: Verify assertions on invalid parameters
void test_Assertions(eoParser &parser)
{
// Test valid parameters (should succeed)
bool valid_ok = true;
valid_ok &= testRankingConstructor(1.1, 1.0); // Valid pressure
valid_ok &= testRankingCachedConstructor(1.1, 1.0); // Valid pressure
// Test invalid parameters (should fail)
bool invalid_ok = true;
invalid_ok &= !testRankingConstructor(1.0, 1.0); // pressure = 1 (invalid)
invalid_ok &= !testRankingConstructor(0.5, 1.0); // pressure < 1 (invalid)
invalid_ok &= !testRankingConstructor(2.1, 1.0); // pressure > 2 (invalid)
invalid_ok &= !testRankingCachedConstructor(1.0, 1.0); // pressure = 1 (invalid)
invalid_ok &= !testRankingCachedConstructor(0.5, 1.0); // pressure < 1 (invalid)
invalid_ok &= !testRankingCachedConstructor(2.1, 1.0); // pressure > 2 (invalid)
if (!valid_ok)
{
throw std::runtime_error("Valid parameter tests failed");
}
if (!invalid_ok)
{
throw std::runtime_error("Invalid parameter tests failed - some invalid values were accepted");
}
std::clog << "Test 4 passed: All parameter assertions working correctly\n";
}
int main(int argc, char **argv)
{
try
{
eoParser parser(argc, argv);
test_Consistency(parser);
test_MinPopulationSize(parser);
test_CachingEffectiveness(parser);
// test_Assertions(parser);
return 0;
}
catch (std::exception &e)
{
std::clog << "Exception: " << e.what() << std::endl;
return 1;
}
}