Compare commits

..

15 commits

Author SHA1 Message Date
Johann Dreo
3259d1b452 doc: bump version + clean authors list 2025-04-16 13:42:29 +02:00
Alessandro Sidero
c660489eaf
Optimize eoRanking: Add caching and index vector (#80)
* Adds eoRankingCached with better documentation
* Optimize eoRanking with caching and index vector
* Adds t-eoRankingCached.cpp
2025-04-15 18:04:35 +02:00
Johann Dreo
400c69c49a doc: mention Apptainer in INSTALL 2025-04-08 19:45:59 +02:00
Johann Dreo
bee47592af doc: adds howto_build_paradiseo script for apptainer 2025-04-07 23:06:52 +02:00
Johann Dreo
e14220ff69 fix(checkpoint): initialize a pointer 2025-04-07 22:57:21 +02:00
Johann Dreo
c218a19de6 fix(doc): disable doc-mpi 2025-04-07 22:56:58 +02:00
Johann Dreo
4b4344664b update(README): link to cmake-gui, citation ref 2025-04-07 14:50:03 +02:00
Johann Dreo
b8efdda6a2 Merge branch 'setup-ccache' of github.com:Jxtopher/nojhan_paradiseo 2025-04-07 14:18:58 +02:00
Johann Dreo
22275e434b fix several warnings
Probably fixes a bug in es/CMA, which has been deprecated for a long time in favor of the EDO module anyway.
2025-04-07 14:16:37 +02:00
Jxtopher
cfcd6e22bb Ccache setup
The goal is to speed up recompilation using ccache.

Ccache is a tool that speeds up recompilation of C/C++ code. It does this by caching the results of previous compilations.
When you recompile code, ccache checks if it has already compiled the same code with the same compiler flags. If so, it uses the cached result instead of recompiling.
2025-04-04 21:59:27 +02:00
48ca0fa5b8 Merge branch 'master' of github.jdreo:jdreo/paradiseo 2025-04-04 21:46:33 +02:00
172798a637 revert 399b22266 (virtual fitness interface temptative)
Incompatible with MOEO's change of interface.
2025-04-04 21:46:04 +02:00
7c88ec4fa7 feat(EO): allow overriding fitness accessors
May be useful for debugging, by tracing when fitness assignement occurs.
2025-04-04 21:45:56 +02:00
3dc2058400
Merge pull request #78 from Alessandro624/fix-mpi-ale
fix(MPI): resolved cyclic inclusion and MPI issue
2025-03-21 09:05:54 +01:00
Alessandro Sidero
77148b5a97 fix(MPI): resolved cyclic inclusion and MPI issue 2025-02-24 19:07:10 +01:00
29 changed files with 848 additions and 360 deletions

View file

@ -16,7 +16,14 @@ jobs:
compiler: [g++-10, g++-9, g++-8, g++-7, clang-6, clang-7, clang-8, clang-9, clang-10, clang-11, clang-12] compiler: [g++-10, g++-9, g++-8, g++-7, clang-6, clang-7, clang-8, clang-9, clang-10, clang-11, clang-12]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Caching objects
id: cache-objects
uses: actions/cache@v4
with:
path: ~/.cache/ccache
key: ${{ runner.os }}-${{env.BUILD_TYPE}}-${{ matrix.compiler }}-objects
- name: Install Dependencies - name: Install Dependencies
shell: bash shell: bash

35
AUTHORS
View file

@ -1,41 +1,52 @@
Current maintainers Current maintainers
=================== ===================
Arnaud Liefooghe <arnaud.liefooghe@univ-lille1.fr>
Clive Canape <clive.canape@inria.fr>
Johann Dreo <johann@dreo.fr>
Sébastien Verel <sebastien.verel@inria.fr>
Active developpers Johann Dreo <johann@dreo.fr>
==================
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@dsj.nl> Joost
Juan Julian Merelo Guervos Juan Julian Merelo Guervos
Jérémie Humeau Jérémie Humeau
Jxtopher
Karima Boufaras Karima Boufaras
legillon legillono
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,13 +13,24 @@ cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
## Name ## Name
project("ParadisEO" project("ParadisEO"
VERSION 3.0.0 VERSION 3.1.3
DESCRIPTION "Evolutionary optimization framework" DESCRIPTION "Evolutionary optimization framework"
LANGUAGES C CXX) LANGUAGES C CXX)
## Language ## Language
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
## ccache
find_program(CCACHE_PROGRAM ccache)
if (CCACHE_PROGRAM)
message(NOTICE "-- ccache is enabled (found here: ${CCACHE_PROGRAM})")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "\"${CCACHE_PROGRAM}\"")
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "\"${CCACHE_PROGRAM}\"")
else ()
message(NOTICE "-- ccache has not been found")
endif ()
###################################################################################### ######################################################################################
### 2) Check dependencies ### 2) Check dependencies

View file

@ -2,7 +2,8 @@
Summary Summary
======= =======
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. 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.
Build Build
@ -18,6 +19,11 @@ 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

@ -195,7 +195,7 @@ The build chain uses the classical workflow of CMake. The recommended method is
Under Linux, the default is make, and a build command is straitghtforward: `mkdir build ; cd build ; cmake .. && make -j`. Under Linux, the default is make, and a build command is straitghtforward: `mkdir build ; cd build ; cmake .. && make -j`.
There is, however, several build options which you may want to switch. To see them, we recommend the use of a CMake gui, like ccmake or cmake-gui . On the command line, you can see the available options with: `cmake -LH ..` . Those options can be set with the `-D<option>=<value>` argument to cmake. There is, however, several build options which you may want to switch. To see them, we recommend the use of a CMake gui, like ccmake or cmake-gui. On the command line, you can see the available options with: `cmake -LH ..` . Those options can be set with the `-D<option>=<value>` argument to cmake.
**The first option to consider is `CMAKE_BUILD_TYPE`, which you most probably want to set to `Debug` (during development/tests) or `Release` (for production/validation).** **The first option to consider is `CMAKE_BUILD_TYPE`, which you most probably want to set to `Debug` (during development/tests) or `Release` (for production/validation).**
@ -211,6 +211,9 @@ If you `ENABLE_CMAKE_EXAMPLE`, it will also build the examples.
If may want to make build scripts more verbose (especially when building the If may want to make build scripts more verbose (especially when building the
doc) by enabling `CMAKE_VERBOSE_MAKEFILE`. doc) by enabling `CMAKE_VERBOSE_MAKEFILE`.
If `ccache` installed in your environment, it will try its best to re-use other compilations,
which may speed-up your builds if you manage several compatible builds at the same time.
To clear all cached objects, execute `ccache -C`.
## Licenses ## Licenses
@ -236,11 +239,35 @@ For academic articles, books, more tutorials, presentations slides,
real life example of solvers and contact information, real life example of solvers and contact information,
please see the web site (available in `paradiseo/website/index.html`). please see the web site (available in `paradiseo/website/index.html`).
There is also an [online wiki](https://gitlab.inria.fr/paradiseo/paradiseo/-/wikis/home)
# Citing Paradiseo
If you use Paradiseo, please cite the following publication:
Johann Dreo, Arnaud Liefooghe, Sébastien Verel, Marc Schoenauer, Juan J. Merelo, Alexandre Quemy, Benjamin Bouvier, and Jan Gmys, [Paradiseo: from a modular framework for evolutionary computation to the automated design of metaheuristics —22 years of Paradiseo—](https://doi.org/10.1145/3449726.3463276), GECCO'21: Proceedings of the Genetic and Evolutionary Computation Conference Companion, 15221530 (2021).
BiBTeX entry:
```
@inproceedings{Dreo-al_2021_Paradiseo,
author = {Dreo, Johann and Liefooghe, Arnaud and Verel, S\'{e}bastien and Schoenauer, Marc and Merelo, Juan J. and Quemy, Alexandre and Bouvier, Benjamin and Gmys, Jan},
title = {Paradiseo: From a Modular Framework for Evolutionary Computation to the Automated Design of Metaheuristics: 22 Years of Paradiseo},
year = {2021},
isbn = {9781450383516},
publisher = {Association for Computing Machinery},
address = {Online conference},
url = {https://doi.org/10.1145/3449726.3463276},
booktitle = {Proceedings of the Genetic and Evolutionary Computation Conference Companion},
pages = {15221530},
numpages = {9}
}
```
# Contact # Contact
For further information about ParadisEO, help or to report any For further information about ParadisEO, help or to report any
problem, you can send an e-mail to: `paradiseo-help@lists.gforge.inria.fr` problem, you can either:
- Chat with us on our Matrix chatroom: https://app.element.io/#/room/#paradiseo:matrix.org
- Post an issue: https://github.com/nojhan/paradiseo/issues

View file

@ -27,7 +27,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
# set(DOC_SMP "") # set(DOC_SMP "")
# endif() # endif()
# if(MPI) # if(MPI)
# set(DOC_MPI "make doc-mpi") # set(DOC_MPI "make doc-mpi")
# else() # else()
# set(DOC_MPI "") # set(DOC_MPI "")
# endif() # endif()
@ -78,7 +78,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
COMMAND make doc-eo COMMAND make doc-eo
COMMAND make doc-mo COMMAND make doc-mo
COMMAND make doc-moeo COMMAND make doc-moeo
COMMAND make doc-mpi # COMMAND make doc-mpi
) )
endif() endif()
@ -89,7 +89,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
COMMAND make doc-mo COMMAND make doc-mo
COMMAND make doc-moeo COMMAND make doc-moeo
COMMAND make doc-smp COMMAND make doc-smp
COMMAND make doc-mpi # COMMAND make doc-mpi
) )
endif() endif()
if(EDO AND NOT SMP AND MPI) if(EDO AND NOT SMP AND MPI)
@ -98,7 +98,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
COMMAND make doc-mo COMMAND make doc-mo
COMMAND make doc-moeo COMMAND make doc-moeo
COMMAND make doc-edo COMMAND make doc-edo
COMMAND make doc-mpi # COMMAND make doc-mpi
) )
endif() endif()
if(EDO AND SMP AND NOT MPI) if(EDO AND SMP AND NOT MPI)
@ -119,7 +119,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
COMMAND make doc-moeo COMMAND make doc-moeo
COMMAND make doc-edo COMMAND make doc-edo
COMMAND make doc-smp COMMAND make doc-smp
COMMAND make doc-mpi # COMMAND make doc-mpi
) )
endif() endif()

View file

@ -828,7 +828,7 @@
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>year</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;{2021},<br> &nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>year</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;{2021},<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>isbn</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;{9781450383516},<br> &nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>isbn</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;{9781450383516},<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>publisher</b></font>&nbsp;=&nbsp;{Association for Computing Machinery},<br> &nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>publisher</b></font>&nbsp;=&nbsp;{Association for Computing Machinery},<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>address</b></font>&nbsp;&nbsp; =&nbsp;{New York, NY, USA},<br> &nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>address</b></font>&nbsp;&nbsp; =&nbsp;{Online conference},<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>url</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&nbsp;{<a href="https://doi.org/10.1145/3449726.3463276},">https://doi.org/10.1145/3449726.3463276},</a><br> &nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>url</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&nbsp;{<a href="https://doi.org/10.1145/3449726.3463276},">https://doi.org/10.1145/3449726.3463276},</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>booktitle</b></font>&nbsp;=&nbsp;{Proceedings of the Genetic and Evolutionary Computation Conference Companion},<br> &nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>booktitle</b></font>&nbsp;=&nbsp;{Proceedings of the Genetic and Evolutionary Computation Conference Companion},<br>
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>pages</b></font>&nbsp;&nbsp;&nbsp;&nbsp; =&nbsp;{15221530},<br> &nbsp;&nbsp;&nbsp;&nbsp;<font color="#da4939"><b>pages</b></font>&nbsp;&nbsp;&nbsp;&nbsp; =&nbsp;{15221530},<br>
@ -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.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>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> 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>.
@ -1221,7 +1221,7 @@ undiscovered knowledge.
</p> </p>
<p>There is, however, several build options which you may want to switch. <p>There is, however, several build options which you may want to switch.
To see them, we recommend the use of a CMake gui, like <code>ccmake</code> or <code>cmake-gui</code>. To see them, we recommend the use of a CMake gui, like <code>ccmake</code> (available through the <code>cmake-curses-gui</code> package in Debian/Ubuntu) or <a href="https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#cmake-gui-tool">cmake-gui</a>.
On the command line, you can see the available options with: <code class="command">cmake -LH ..</code>. On the command line, you can see the available options with: <code class="command">cmake -LH ..</code>.
Those options can be set with the <code>-D&lt;option&gt;=&lt;value&gt;</code> argument to cmake. Those options can be set with the <code>-D&lt;option&gt;=&lt;value&gt;</code> argument to cmake.
</p> </p>

View file

@ -65,7 +65,7 @@ eoCheckPoint<EOT>& do_make_checkpoint(eoParser& _parser, eoState& _state, eoValu
#ifndef _MSC_VER #ifndef _MSC_VER
// the CtrlC monitoring interception // the CtrlC monitoring interception
eoSignal<EOT> *mon_ctrlCCont; eoSignal<EOT> *mon_ctrlCCont = nullptr;
eoValueParam<bool>& mon_ctrlCParam = _parser.createParam(false, "monitor-with-CtrlC", "Monitor current generation upon Ctrl C",0, "Stopping criterion"); eoValueParam<bool>& mon_ctrlCParam = _parser.createParam(false, "monitor-with-CtrlC", "Monitor current generation upon Ctrl C",0, "Stopping criterion");
if (mon_ctrlCParam.value()) if (mon_ctrlCParam.value())
{ {

View file

@ -174,18 +174,18 @@ protected:
// if the flight does not need to be used, use the dummy flight instance // if the flight does not need to be used, use the dummy flight instance
class eoDummyFlight:public eoFlight < POT > class eoDummyFlight:public eoFlight < POT >
{ {
public: public:
eoDummyFlight () {} eoDummyFlight () {}
void operator () (POT &) {} void operator() (POT &) override {}
}dummyFlight; } dummyFlight;
// if the initializer does not need to be used, use the dummy one instead // if the initializer does not need to be used, use the dummy one instead
class eoDummyInitializer:public eoInitializerBase < POT > class eoDummyInitializer:public eoInitializerBase < POT >
{ {
public: public:
eoDummyInitializer () {} eoDummyInitializer () {}
void operator () (POT &) {} void operator() () override {}
}dummyInit; } dummyInit;
}; };
/** /**

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): eoRanking(double _p = 2.0, double _e = 1.0) : pressure(_p), exponent(_e)
pressure(_p), exponent(_e) {}
/* helper function: finds index in _pop of _eo, an EOT * */
int lookfor(const EOT *_eo, const eoPop<EOT>& _pop)
{ {
typename eoPop<EOT>::const_iterator it; assert(1 < pressure and pressure <= 2);
for (it=_pop.begin(); it<_pop.end(); it++)
{
if (_eo == &(*it))
return it-_pop.begin();
}
throw eoException("Not found in eoLinearRanking");
} }
/* COmputes the ranked fitness: fitnesses range in [m,M] /* helper function: finds index in _pop of _eo, an EOT * */
with m=2-pressure/popSize and M=pressure/popSize. int lookfor(const EOT *_eo, const eoPop<EOT> &_pop)
in between, the progression depstd::ends on exponent (linear if 1).
*/
virtual void operator()(const eoPop<EOT>& _pop)
{ {
std::vector<const EOT *> rank; typename eoPop<EOT>::const_iterator it;
_pop.sort(rank); for (it = _pop.begin(); it < _pop.end(); it++)
unsigned pSize =_pop.size();
unsigned int pSizeMinusOne = pSize-1;
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);
double beta = (2-pressure)/pSize;
if (exponent == 1.0) // no need for exponetial then
{ {
double alpha = (2*pressure-2)/(pSize*pSizeMinusOne); if (_eo == &(*it))
for (unsigned i=0; i<pSize; i++) return it - _pop.begin();
}
throw eoException("Not found in eoLinearRanking");
}
/* COmputes the ranked fitness: fitnesses range in [m,M]
with m=2-pressure/popSize and M=pressure/popSize.
in between, the progression depstd::ends on exponent (linear if 1).
*/
virtual void operator()(const eoPop<EOT> &_pop)
{
std::vector<const EOT *> rank;
_pop.sort(rank);
unsigned pSize = _pop.size();
unsigned int pSizeMinusOne = pSize - 1;
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);
double beta = (2 - pressure) / pSize;
if (exponent == 1.0) // no need for exponential then
{
double alpha = (2 * pressure - 2) / (pSize * pSizeMinusOne);
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 in in [0,1] // value is 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:
double pressure; // selective pressure private:
double exponent; double pressure; // selective pressure
double exponent;
}; };
#endif #endif

139
eo/src/eoRankingCached.h Normal file
View file

@ -0,0 +1,139 @@
/** -*- 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

@ -230,27 +230,25 @@ protected:
// if the eval does not need to be used, use the dummy eval instance // if the eval does not need to be used, use the dummy eval instance
class eoDummyEval : public eoEvalFunc<POT> class eoDummyEval : public eoEvalFunc<POT>
{
public:
void operator()(POT &)
{}
}
dummyEval;
class eoDummyFlight:public eoFlight < POT >
{ {
public: public:
eoDummyFlight () {} void operator()(POT &) override {}
void operator () (POT &) {} } dummyEval;
}dummyFlight;
class eoDummyFlight:public eoFlight < POT >
{
public:
eoDummyFlight () {}
void operator() (POT &) override {}
} dummyFlight;
// if the initializer does not need to be used, use the dummy one instead // if the initializer does not need to be used, use the dummy one instead
class eoDummyInitializer:public eoInitializerBase < POT > class eoDummyInitializer:public eoInitializerBase < POT >
{ {
public: public:
eoDummyInitializer () {} eoDummyInitializer () {}
void operator () (POT &) {} void operator() () override {}
}dummyInit; } dummyInit;
}; };
/** @example t-eoSyncEasyPSO.cpp /** @example t-eoSyncEasyPSO.cpp

View file

@ -113,16 +113,19 @@ CMAParams::CMAParams(eoParser& parser, unsigned dimensionality) {
for (unsigned i = 0; i < weights.size(); ++i) { for (unsigned i = 0; i < weights.size(); ++i) {
weights[i] = mu - i; weights[i] = mu - i;
} }
break;
} }
case 2: case 2:
{ {
weights = 1.; weights = 1.;
break;
} }
default : default :
{ {
for (unsigned i = 0; i < weights.size(); ++i) { for (unsigned i = 0; i < weights.size(); ++i) {
weights[i] = log(mu+1.)-log(i+1.); weights[i] = log(mu+1.)-log(i+1.);
} }
break;
} }
} }

View file

@ -468,8 +468,11 @@ private :
switch(new_arity) switch(new_arity)
{ {
case 3 : args[2].copy(s.args[2]); args[2].parent = this; // no break! case 3 : args[2].copy(s.args[2]); args[2].parent = this; // no break!
[[fallthrough]];
case 2 : args[1].copy(s.args[1]); args[1].parent = this; case 2 : args[1].copy(s.args[1]); args[1].parent = this;
[[fallthrough]];
case 1 : args[0].copy(s.args[0]); args[0].parent = this; case 1 : args[0].copy(s.args[0]); args[0].parent = this;
[[fallthrough]];
case 0 : break; case 0 : break;
default : default :
{ {
@ -523,7 +526,9 @@ private :
switch(arity()) switch(arity())
{ {
case 3 : args[2].parent = 0; // no break! case 3 : args[2].parent = 0; // no break!
[[fallthrough]];
case 2 : args[1].parent = 0; case 2 : args[1].parent = 0;
[[fallthrough]];
case 1 : args[0].parent = 0; break; case 1 : args[0].parent = 0; break;
case 0 : break; case 0 : break;
default : default :
@ -542,7 +547,9 @@ private :
switch(arity()) switch(arity())
{ {
case 3 : args[2].parent = this; // no break! case 3 : args[2].parent = this; // no break!
[[fallthrough]];
case 2 : args[1].parent = this; case 2 : args[1].parent = this;
[[fallthrough]];
case 1 : args[0].parent = this; break; case 1 : args[0].parent = this; break;
case 0 : break; case 0 : break;
default : default :

View file

@ -161,7 +161,7 @@ namespace mpi
MPI_Barrier( MPI_COMM_WORLD ); MPI_Barrier( MPI_COMM_WORLD );
} }
void broadcast( communicator & comm, int value, int root ) void broadcast( communicator & /*comm*/, int value, int root )
{ {
MPI_Bcast( &value, 1, MPI_INT, root, MPI_COMM_WORLD ); MPI_Bcast( &value, 1, MPI_INT, root, MPI_COMM_WORLD );
} }

View file

@ -22,7 +22,7 @@ Authors:
#ifndef __EO_IMPL_MPI_HPP__ #ifndef __EO_IMPL_MPI_HPP__
#define __EO_IMPL_MPI_HPP__ #define __EO_IMPL_MPI_HPP__
#include "eoMpi.h" #include <mpi.h>
#include "../serial/eoSerial.h" #include "../serial/eoSerial.h"
/** /**
@ -43,290 +43,288 @@ Authors:
*/ */
namespace eo namespace eo
{ {
namespace mpi namespace mpi
{
/**
* @ingroup Parallel
* @{
*/
/**
* @brief Constant indicating that a message can come from any process.
*/
extern const int any_source;
/**
* @brief Constant indicating that a message can come from any tag (channel).
*/
extern const int any_tag;
/**
* @brief Wrapper class to have a MPI environment.
*
* Instead of calling MPI_Init and MPI_Finalize, it is only necessary to instantiate
* this class once, in the global context.
*/
class environment
{ {
public: /**
* @ingroup Parallel
* @{
*/
/** /**
* @brief Inits MPI context. * @brief Constant indicating that a message can come from any process.
*/
extern const int any_source;
/**
* @brief Constant indicating that a message can come from any tag (channel).
*/
extern const int any_tag;
/**
* @brief Wrapper class to have a MPI environment.
* *
* @param argc Number of params in command line (same as one in main) * Instead of calling MPI_Init and MPI_Finalize, it is only necessary to instantiate
* @param argv Strings containing params (same as one in main) * this class once, in the global context.
*/ */
environment(int argc, char**argv); class environment
{
/**
* @brief Closes MPI context.
*/
~environment();
};
struct MPI_Status {
int count;
int cancelled;
int MPI_SOURCE;
int MPI_TAG;
int MPI_ERROR;
};
/**
* @brief Wrapper class for MPI_Status
*
* Consists only in a C++ wrapper class, giving getters on status attributes.
*/
class status
{
public: public:
/**
* @brief Inits MPI context.
*
* @param argc Number of params in command line (same as one in main)
* @param argv Strings containing params (same as one in main)
*/
environment(int argc, char **argv);
/**
* @brief Closes MPI context.
*/
~environment();
};
/* struct MPI_Status
{
int count;
int cancelled;
int MPI_SOURCE;
int MPI_TAG;
int MPI_ERROR;
}; */
/** /**
* @brief Converts a MPI_Status into a status. * @brief Wrapper class for MPI_Status
*
* Consists only in a C++ wrapper class, giving getters on status attributes.
*/ */
status( const MPI_Status & s ); class status
{
public:
/**
* @brief Converts a MPI_Status into a status.
*/
status(const MPI_Status &s);
/** /**
* @brief Returns the tag of the associated communication. * @brief Returns the tag of the associated communication.
*/ */
int tag() { return _tag; } int tag() { return _tag; }
/** /**
* @brief Indicates which error number we obtained in the associated communication. * @brief Indicates which error number we obtained in the associated communication.
*/ */
int error() { return _error; } int error() { return _error; }
/** /**
* @brief Returns the MPI rank of the source of the associated communication. * @brief Returns the MPI rank of the source of the associated communication.
*/ */
int source() { return _source; } int source() { return _source; }
private: private:
int _source; int _source;
int _tag; int _tag;
int _error; int _error;
}; };
/** /**
* @brief Main object, used to send / receive messages, get informations about the rank and the size of the world, * @brief Main object, used to send / receive messages, get informations about the rank and the size of the world,
* etc. * etc.
*/ */
class communicator class communicator
{ {
public: public:
/**
* Creates the communicator, using the whole world as a MPI_Comm.
*
* @todo Allow the user to precise which MPI_Comm to use
*/
communicator();
/** ~communicator();
* Creates the communicator, using the whole world as a MPI_Comm.
*
* @todo Allow the user to precise which MPI_Comm to use
*/
communicator( );
~communicator(); /**
* @brief Returns the MPI rank of the current process.
*/
int rank();
/** /**
* @brief Returns the MPI rank of the current process. * @brief Returns the size of the MPI cluster.
*/ */
int rank(); int size();
/** /*
* @brief Returns the size of the MPI cluster. * SEND / RECV INT
*/ */
int size();
/* /**
* SEND / RECV INT * @brief Sends an integer to dest on channel "tag".
*/ *
* @param dest MPI rank of the receiver
* @param tag MPI tag of message
* @param n The integer to send
*/
void send(int dest, int tag, int n);
/** /*
* @brief Sends an integer to dest on channel "tag". * @brief Receives an integer from src on channel "tag".
* *
* @param dest MPI rank of the receiver * @param src MPI rank of the sender
* @param tag MPI tag of message * @param tag MPI tag of message
* @param n The integer to send * @param n Where to save the received integer
*/ */
void send( int dest, int tag, int n ); void recv(int src, int tag, int &n);
/* /*
* @brief Receives an integer from src on channel "tag". * SEND / RECV STRING
* */
* @param src MPI rank of the sender
* @param tag MPI tag of message
* @param n Where to save the received integer
*/
void recv( int src, int tag, int& n );
/* /**
* SEND / RECV STRING * @brief Sends a string to dest on channel "tag".
*/ *
* @param dest MPI rank of the receiver
* @param tag MPI tag of message
* @param str The std::string to send
*/
void send(int dest, int tag, const std::string &str);
/** /*
* @brief Sends a string to dest on channel "tag". * @brief Receives a string from src on channel "tag".
* *
* @param dest MPI rank of the receiver * @param src MPI rank of the sender
* @param tag MPI tag of message * @param tag MPI tag of message
* @param str The std::string to send * @param std::string Where to save the received string
*/ */
void send( int dest, int tag, const std::string& str ); void recv(int src, int tag, std::string &str);
/* /*
* @brief Receives a string from src on channel "tag". * SEND / RECV Objects
* */
* @param src MPI rank of the sender
* @param tag MPI tag of message
* @param std::string Where to save the received string
*/
void recv( int src, int tag, std::string& str );
/* /**
* SEND / RECV Objects * @brief Sends an eoserial::Persistent to dest on channel "tag".
*/ *
* @param dest MPI rank of the receiver
* @param tag MPI tag of message
* @param persistent The object to send (it must absolutely implement eoserial::Persistent)
*/
void send(int dest, int tag, const eoserial::Persistent &persistent);
/** /**
* @brief Sends an eoserial::Persistent to dest on channel "tag". * @brief Sends an array of eoserial::Persistent to dest on channel "tag".
* *
* @param dest MPI rank of the receiver * @param dest MPI rank of the receiver
* @param tag MPI tag of message * @param tag MPI tag of message
* @param persistent The object to send (it must absolutely implement eoserial::Persistent) * @param table The array of eoserial::Persistent objects
*/ * @param size The number of elements to send (no check is done, the user has to be sure that the size won't
void send( int dest, int tag, const eoserial::Persistent & persistent ); * overflow!)
*/
/** template <class T>
* @brief Sends an array of eoserial::Persistent to dest on channel "tag". void send(int dest, int tag, T *table, int size)
*
* @param dest MPI rank of the receiver
* @param tag MPI tag of message
* @param table The array of eoserial::Persistent objects
* @param size The number of elements to send (no check is done, the user has to be sure that the size won't
* overflow!)
*/
template< class T >
void send( int dest, int tag, T* table, int size )
{
// Puts all the values into an array
eoserial::Array* array = new eoserial::Array;
for( int i = 0; i < size; ++i )
{ {
array->push_back( table[i].pack() ); // Puts all the values into an array
eoserial::Array *array = new eoserial::Array;
for (int i = 0; i < size; ++i)
{
array->push_back(table[i].pack());
}
// Encapsulates the array into an object
eoserial::Object *obj = new eoserial::Object;
obj->add("array", array);
std::stringstream ss;
obj->print(ss);
delete obj;
// Sends the object as a string
send(dest, tag, ss.str());
} }
// Encapsulates the array into an object /*
eoserial::Object* obj = new eoserial::Object; * @brief Receives an eoserial::Persistent object from src on channel "tag".
obj->add( "array", array ); *
std::stringstream ss; * @param src MPI rank of the sender
obj->print( ss ); * @param tag MPI tag of message
delete obj; * @param persistent Where to unpack the serialized object?
*/
void recv(int src, int tag, eoserial::Persistent &persistent);
// Sends the object as a string /*
send( dest, tag, ss.str() ); * @brief Receives an array of eoserial::Persistent from src on channel "tag".
} *
* @param src MPI rank of the sender
/* * @param tag MPI tag of message
* @brief Receives an eoserial::Persistent object from src on channel "tag". * @param table The table in which we're saving the received objects. It must have been allocated by the user,
* * as no allocation is performed here.
* @param src MPI rank of the sender * @param size The number of elements to receive (no check is done, the user has to be sure that the size won't
* @param tag MPI tag of message * overflow!)
* @param persistent Where to unpack the serialized object? */
*/ template <class T>
void recv( int src, int tag, eoserial::Persistent & persistent ); void recv(int src, int tag, T *table, int size)
/*
* @brief Receives an array of eoserial::Persistent from src on channel "tag".
*
* @param src MPI rank of the sender
* @param tag MPI tag of message
* @param table The table in which we're saving the received objects. It must have been allocated by the user,
* as no allocation is performed here.
* @param size The number of elements to receive (no check is done, the user has to be sure that the size won't
* overflow!)
*/
template< class T >
void recv( int src, int tag, T* table, int size )
{
// Receives the string which contains the object
std::string asText;
recv( src, tag, asText );
// Parses the object and retrieves the table
eoserial::Object* obj = eoserial::Parser::parse( asText );
eoserial::Array* array = static_cast<eoserial::Array*>( (*obj)["array"] );
// Retrieves all the values from the array
for( int i = 0; i < size; ++i )
{ {
eoserial::unpackObject( *array, i, table[i] ); // Receives the string which contains the object
std::string asText;
recv(src, tag, asText);
// Parses the object and retrieves the table
eoserial::Object *obj = eoserial::Parser::parse(asText);
eoserial::Array *array = static_cast<eoserial::Array *>((*obj)["array"]);
// Retrieves all the values from the array
for (int i = 0; i < size; ++i)
{
eoserial::unpackObject(*array, i, table[i]);
}
delete obj;
} }
delete obj;
}
/* /*
* Other methods * Other methods
*/ */
/** /**
* @brief Wrapper for MPI_Probe * @brief Wrapper for MPI_Probe
* *
* Waits for a message to come from process having rank src, on the channel * Waits for a message to come from process having rank src, on the channel
* tag. * tag.
* *
* @param src MPI rank of the sender (any_source if it can be any sender) * @param src MPI rank of the sender (any_source if it can be any sender)
* @param tag MPI tag of the expected message (any_tag if it can be any tag) * @param tag MPI tag of the expected message (any_tag if it can be any tag)
*/ */
status probe( int src = any_source, int tag = any_tag ); status probe(int src = any_source, int tag = any_tag);
/** /**
* @brief Wrapper for MPI_Barrier * @brief Wrapper for MPI_Barrier
* *
* *
*/ */
void barrier(); void barrier();
private: private:
int _rank; int _rank;
int _size; int _size;
char* _buf; // temporary buffer for sending and receiving strings. Avoids reallocations char *_buf; // temporary buffer for sending and receiving strings. Avoids reallocations
int _bufsize; // size of the above temporary buffer int _bufsize; // size of the above temporary buffer
}; };
/** /**
* @brief Wrapper for MPI_Bcast * @brief Wrapper for MPI_Bcast
* *
* Broadcasts an integer value on the communicator comm, from the process having the MPI rank root. * Broadcasts an integer value on the communicator comm, from the process having the MPI rank root.
* *
* @param comm The communicator on which to broadcast * @param comm The communicator on which to broadcast
* @param value The integer value to send * @param value The integer value to send
* @param root The MPI rank of the broadcaster * @param root The MPI rank of the broadcaster
* *
* @todo Actually comm isn't used and broadcast is performed on the whole MPI_COMM_WORLD. TODO: Use comm instead * @todo Actually comm isn't used and broadcast is performed on the whole MPI_COMM_WORLD. TODO: Use comm instead
*/ */
void broadcast( communicator & comm, int value, int root ); void broadcast(communicator &comm, int value, int root);
/** /**
* @} * @}
*/ */
} // namespace mpi } // namespace mpi
} // namespace eo } // namespace eo
# endif //__EO_IMPL_MPI_HPP__ #endif //__EO_IMPL_MPI_HPP__

View file

@ -42,16 +42,16 @@ int Check( PCom *com )
} }
PCom * PipeComOpen( char *prog ) PCom * PipeComOpen( const char *prog )
{ {
char *args[2]; char *args[2];
args[0] = prog; args[0] = strdup( prog );
args[1] = NULL; args[1] = NULL;
return PipeComOpenArgv( prog, args ); return PipeComOpenArgv( prog, args );
} }
PCom * PipeComOpenArgv( char *prog, char *argv[] ) PCom * PipeComOpenArgv( const char *prog, char *argv[] )
{ {
int toFils[2]; int toFils[2];
int toPere[2]; int toPere[2];

View file

@ -23,8 +23,8 @@ typedef struct PipeCommunication {
} PCom; } PCom;
extern PCom *PipeComOpen( char *prog ); extern PCom *PipeComOpen( const char *prog );
extern PCom *PipeComOpenArgv( char *prog, char *argv[] ); extern PCom *PipeComOpenArgv( const char *prog, char *argv[] );
extern int PipeComSend( PCom *to, const char *line ); extern int PipeComSend( PCom *to, const char *line );
extern int PipeComSendn( PCom *to, const char *data, int n ); extern int PipeComSendn( PCom *to, const char *data, int n );

View file

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

View file

@ -0,0 +1,219 @@
#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;
}
}

View file

@ -0,0 +1,54 @@
Bootstrap: docker
From: ubuntu:24.04
%post
# Update the available packages list.
apt -y update
# And add the "universe" repository (allow to install many more software).
apt -y install software-properties-common
add-apt-repository universe
apt -y update
# Update the operating systems (install last versions with bugfixes).
apt -y dist-upgrade
# Install dependencies for your project.
apt -y install git g++ cmake ccache make libeigen3-dev libopenmpi-dev doxygen graphviz libgnuplot-iostream-dev
# Download sources.
git clone --branch master --single-branch --recurse-submodules https://github.com/nojhan/paradiseo
cd paradiseo
# Build directory that holds built binaries and cache.
mkdir -p build
cd build
# Example of minimum build:
# Use that if you want the minimal set of libraries needed to build a simple solver.
# cmake -DCMAKE_BUILD_TYPE=Release -DEDO=ON .. && make
# Example of trying to build everything:
# Use that to test if everything can be built with your setup,
# or if you modified something in Paradiseo and want to test it.
cmake -DCMAKE_BUILD_TYPE=Release -DEDO=ON -DENABLE_CMAKE_EXAMPLE=ON -DENABLE_CMAKE_TESTING=ON -DENABLE_GNUPLOT=ON -DENABLE_OPENMP=ON -DMPI=ON -DSMP=ON .. && make
# You may run the tests, to check if everything works:
ctest
# Make the documentation:
make doc
# Clean-up of the APT cache (will lighten the container).
apt -y purge software-properties-common git g++ cmake ccache make libeigen3-dev libopenmpi-dev doxygen graphviz libgnuplot-iostream-dev
apt -y --purge autoremove
apt -y autoclean
apt clean
%environment
%runscript
# When executing the container, this will be called,
# and pass all the command line arguments.
./paradiseo/build/edo/application/cmaes/cmaes $*
%labels
Author Johann Dreo

View file

@ -66,7 +66,7 @@ bool testDirRes(std::string _dirName, bool _erase);
* @param _archive the archive of non-dominated solutions * @param _archive the archive of non-dominated solutions
*/ */
template < class MOEOT > template < class MOEOT >
eoCheckPoint < MOEOT > & do_make_checkpoint_moeo (eoParser & _parser, eoState & _state, eoEvalFuncCounter < MOEOT > & _eval, eoContinue < MOEOT > & _continue, eoPop < MOEOT > & _pop, moeoArchive < MOEOT > & _archive) eoCheckPoint < MOEOT > & do_make_checkpoint_moeo (eoParser & _parser, eoState & _state, eoEvalFuncCounter < MOEOT > & /*_eval*/, eoContinue < MOEOT > & _continue, eoPop < MOEOT > & _pop, moeoArchive < MOEOT > & _archive)
{ {
eoCheckPoint < MOEOT > & checkpoint = _state.storeFunctor(new eoCheckPoint < MOEOT > (_continue)); eoCheckPoint < MOEOT > & checkpoint = _state.storeFunctor(new eoCheckPoint < MOEOT > (_continue));
/* the objective vector type */ /* the objective vector type */

View file

@ -85,7 +85,7 @@
* @param _archive the archive of non-dominated solutions * @param _archive the archive of non-dominated solutions
*/ */
template < class MOEOT > template < class MOEOT >
moeoEA < MOEOT > & do_make_ea_moeo(eoParser & _parser, eoState & _state, eoEvalFunc < MOEOT > & _eval, eoContinue < MOEOT > & _continue, eoGenOp < MOEOT > & _op, moeoArchive < MOEOT > & _archive) moeoEA < MOEOT > & do_make_ea_moeo(eoParser & _parser, eoState & _state, eoEvalFunc < MOEOT > & _eval, eoContinue < MOEOT > & _continue, eoGenOp < MOEOT > & _op, moeoArchive < MOEOT > & /*_archive*/)
{ {
/* the objective vector type */ /* the objective vector type */

View file

@ -55,7 +55,7 @@ class moeoHyperVolumeMetric : public moeoVectorUnaryMetric < ObjectiveVector , d
* @param _normalize allow to normalize data (default true) * @param _normalize allow to normalize data (default true)
* @param _rho coefficient to determine the reference point. * @param _rho coefficient to determine the reference point.
*/ */
moeoHyperVolumeMetric(bool _normalize=true, double _rho=1.1): normalize(_normalize), rho(_rho), ref_point(NULL){ moeoHyperVolumeMetric(bool _normalize=true, double _rho=1.1): normalize(_normalize), rho(_rho) {
bounds.resize(ObjectiveVector::Traits::nObjectives()); bounds.resize(ObjectiveVector::Traits::nObjectives());
// initialize bounds in case someone does not want to use them // initialize bounds in case someone does not want to use them
for (unsigned int i=0; i<ObjectiveVector::Traits::nObjectives(); i++) for (unsigned int i=0; i<ObjectiveVector::Traits::nObjectives(); i++)
@ -69,7 +69,7 @@ class moeoHyperVolumeMetric : public moeoVectorUnaryMetric < ObjectiveVector , d
* @param _normalize allow to normalize data (default true) * @param _normalize allow to normalize data (default true)
* @param _ref_point the reference point * @param _ref_point the reference point
*/ */
moeoHyperVolumeMetric(bool _normalize=true, ObjectiveVector& _ref_point=NULL): normalize(_normalize), rho(0.0), ref_point(_ref_point){ moeoHyperVolumeMetric(bool _normalize, ObjectiveVector& _ref_point): normalize(_normalize), rho(0.0), ref_point(_ref_point){
bounds.resize(ObjectiveVector::Traits::nObjectives()); bounds.resize(ObjectiveVector::Traits::nObjectives());
// initialize bounds in case someone does not want to use them // initialize bounds in case someone does not want to use them
for (unsigned int i=0; i<ObjectiveVector::Traits::nObjectives(); i++) for (unsigned int i=0; i<ObjectiveVector::Traits::nObjectives(); i++)

View file

@ -47,11 +47,11 @@ using namespace std;
class Sch1ObjectiveVectorTraits : public moeoObjectiveVectorTraits class Sch1ObjectiveVectorTraits : public moeoObjectiveVectorTraits
{ {
public: public:
static bool minimizing (int i) static bool minimizing (int /*i*/)
{ {
return true; return true;
} }
static bool maximizing (int i) static bool maximizing (int /*i*/)
{ {
return false; return false;
} }

View file

@ -52,7 +52,7 @@ class Loop<T,Arg...>
} }
template<class U> template<class U>
U& findValueImpl(T& t, Arg&... arg, std::true_type) U& findValueImpl(T& t, Arg&... /*arg*/, std::true_type)
{ {
return t; return t;
} }

View file

@ -59,6 +59,10 @@ paradiseo::smp::Island<EOAlgo,EOT,bEOT>::Island(eoPop<EOT>& _pop, IntPolicy<EOT>
_pop, _intPolicy, _migPolicy, args...) _pop, _intPolicy, _migPolicy, args...)
{ } { }
template<template <class> class EOAlgo, class EOT, class bEOT>
paradiseo::smp::Island<EOAlgo,EOT,bEOT>::~Island()
{ }
template<template <class> class EOAlgo, class EOT, class bEOT> template<template <class> class EOAlgo, class EOT, class bEOT>
void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::operator()() void paradiseo::smp::Island<EOAlgo,EOT,bEOT>::operator()()
{ {

View file

@ -134,6 +134,7 @@ public:
//AIsland<bEOT> clone() const; //AIsland<bEOT> clone() const;
virtual ~Island();
protected: protected:
/** /**

View file

@ -30,6 +30,8 @@ Contact: paradiseo-help@lists.gforge.inria.fr
#ifndef _QAPGA_h #ifndef _QAPGA_h
#define _QAPGA_h #define _QAPGA_h
extern int n; // size
class ProblemInit : public eoInit<Problem> class ProblemInit : public eoInit<Problem>
{ {
public: public: