From 77148b5a972fb76cfc66a4ed3cbbc72ce1440d9e Mon Sep 17 00:00:00 2001
From: Alessandro Sidero <75628365+Alessandro624@users.noreply.github.com>
Date: Mon, 24 Feb 2025 19:07:10 +0100
Subject: [PATCH 01/12] fix(MPI): resolved cyclic inclusion and MPI issue
---
eo/src/mpi/implMpi.h | 474 +++++++++++++++++++++----------------------
1 file changed, 236 insertions(+), 238 deletions(-)
diff --git a/eo/src/mpi/implMpi.h b/eo/src/mpi/implMpi.h
index d52b84b26..0efb89a75 100644
--- a/eo/src/mpi/implMpi.h
+++ b/eo/src/mpi/implMpi.h
@@ -22,7 +22,7 @@ Authors:
#ifndef __EO_IMPL_MPI_HPP__
#define __EO_IMPL_MPI_HPP__
-#include "eoMpi.h"
+#include
#include "../serial/eoSerial.h"
/**
@@ -43,290 +43,288 @@ Authors:
*/
namespace eo
{
-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
+ namespace mpi
{
- 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)
- * @param argv Strings containing params (same as one in main)
+ * Instead of calling MPI_Init and MPI_Finalize, it is only necessary to instantiate
+ * this class once, in the global context.
*/
- 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 Wrapper class for MPI_Status
- *
- * Consists only in a C++ wrapper class, giving getters on status attributes.
- */
- class status
- {
+ class environment
+ {
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.
- */
- int tag() { return _tag; }
+ /**
+ * @brief Returns the tag of the associated communication.
+ */
+ int tag() { return _tag; }
- /**
- * @brief Indicates which error number we obtained in the associated communication.
- */
- int error() { return _error; }
+ /**
+ * @brief Indicates which error number we obtained in the associated communication.
+ */
+ int error() { return _error; }
- /**
- * @brief Returns the MPI rank of the source of the associated communication.
- */
- int source() { return _source; }
+ /**
+ * @brief Returns the MPI rank of the source of the associated communication.
+ */
+ int source() { return _source; }
private:
int _source;
int _tag;
int _error;
- };
+ };
- /**
- * @brief Main object, used to send / receive messages, get informations about the rank and the size of the world,
- * etc.
- */
- class communicator
- {
+ /**
+ * @brief Main object, used to send / receive messages, get informations about the rank and the size of the world,
+ * etc.
+ */
+ class communicator
+ {
public:
+ /**
+ * Creates the communicator, using the whole world as a MPI_Comm.
+ *
+ * @todo Allow the user to precise which MPI_Comm to use
+ */
+ 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();
- ~communicator();
+ /**
+ * @brief Returns the MPI rank of the current process.
+ */
+ int rank();
- /**
- * @brief Returns the MPI rank of the current process.
- */
- int rank();
+ /**
+ * @brief Returns the size of the MPI cluster.
+ */
+ int size();
- /**
- * @brief Returns the size of the MPI cluster.
- */
- int size();
+ /*
+ * SEND / RECV INT
+ */
- /*
- * 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".
- *
- * @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 Receives an integer from src on channel "tag".
+ *
+ * @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);
- /*
- * @brief Receives an integer from src on channel "tag".
- *
- * @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
+ */
- /*
- * 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".
- *
- * @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 Receives a string from src on channel "tag".
+ *
+ * @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);
- /*
- * @brief Receives a string from src on channel "tag".
- *
- * @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
+ */
- /*
- * 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".
- *
- * @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 array of eoserial::Persistent to dest on channel "tag".
- *
- * @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 )
+ /**
+ * @brief Sends an array of eoserial::Persistent to dest on channel "tag".
+ *
+ * @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
+ void send(int dest, int tag, T *table, int size)
{
- 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;
- obj->add( "array", array );
- std::stringstream ss;
- obj->print( ss );
- delete obj;
+ /*
+ * @brief Receives an eoserial::Persistent object from src on channel "tag".
+ *
+ * @param src MPI rank of the sender
+ * @param tag MPI tag of message
+ * @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 eoserial::Persistent object from src on channel "tag".
- *
- * @param src MPI rank of the sender
- * @param tag MPI tag of message
- * @param persistent Where to unpack the serialized object?
- */
- void recv( int src, int tag, eoserial::Persistent & persistent );
-
- /*
- * @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( (*obj)["array"] );
-
- // Retrieves all the values from the array
- for( int i = 0; i < size; ++i )
+ /*
+ * @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
+ void recv(int src, int tag, T *table, int size)
{
- 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((*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
- *
- * Waits for a message to come from process having rank src, on the channel
- * tag.
- *
- * @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)
- */
- status probe( int src = any_source, int tag = any_tag );
+ /**
+ * @brief Wrapper for MPI_Probe
+ *
+ * Waits for a message to come from process having rank src, on the channel
+ * tag.
+ *
+ * @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)
+ */
+ status probe(int src = any_source, int tag = any_tag);
- /**
- * @brief Wrapper for MPI_Barrier
- *
- *
- */
- void barrier();
+ /**
+ * @brief Wrapper for MPI_Barrier
+ *
+ *
+ */
+ void barrier();
private:
int _rank;
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
- };
+ };
- /**
- * @brief Wrapper for MPI_Bcast
- *
- * 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 value The integer value to send
- * @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
- */
- void broadcast( communicator & comm, int value, int root );
+ /**
+ * @brief Wrapper for MPI_Bcast
+ *
+ * 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 value The integer value to send
+ * @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
+ */
+ void broadcast(communicator &comm, int value, int root);
- /**
- * @}
- */
-} // namespace mpi
+ /**
+ * @}
+ */
+ } // namespace mpi
} // namespace eo
-# endif //__EO_IMPL_MPI_HPP__
+#endif //__EO_IMPL_MPI_HPP__
From 7c88ec4fa7af22bd485c7e446c7d07ff2838475d Mon Sep 17 00:00:00 2001
From: nojhan
Date: Fri, 10 Feb 2023 09:47:58 +0100
Subject: [PATCH 02/12] feat(EO): allow overriding fitness accessors
May be useful for debugging, by tracing when fitness assignement occurs.
---
eo/src/EO.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eo/src/EO.h b/eo/src/EO.h
index 09bb2d20d..9c29dbbce 100644
--- a/eo/src/EO.h
+++ b/eo/src/EO.h
@@ -95,7 +95,7 @@ public:
/** Set fitness. At the same time, validates it.
* @param _fitness New fitness value.
*/
- void fitness(const Fitness& _fitness)
+ virtual void fitness(const Fitness& _fitness)
{
repFitness = _fitness;
invalidFitness = false;
From 172798a637ffa66878fb96f34cc2eefc1369fb57 Mon Sep 17 00:00:00 2001
From: nojhan
Date: Fri, 10 Feb 2023 11:54:45 +0100
Subject: [PATCH 03/12] revert 399b22266 (virtual fitness interface temptative)
Incompatible with MOEO's change of interface.
---
eo/src/EO.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eo/src/EO.h b/eo/src/EO.h
index 9c29dbbce..09bb2d20d 100644
--- a/eo/src/EO.h
+++ b/eo/src/EO.h
@@ -95,7 +95,7 @@ public:
/** Set fitness. At the same time, validates it.
* @param _fitness New fitness value.
*/
- virtual void fitness(const Fitness& _fitness)
+ void fitness(const Fitness& _fitness)
{
repFitness = _fitness;
invalidFitness = false;
From cfcd6e22bb2081fa9f730c4ee0e07d04b1c8fe55 Mon Sep 17 00:00:00 2001
From: Jxtopher <39927513+Jxtopher@users.noreply.github.com>
Date: Fri, 28 Mar 2025 22:30:30 +0100
Subject: [PATCH 04/12] 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.
---
.github/workflows/build_ubuntu_debug.yml | 9 ++++++++-
CMakeLists.txt | 11 +++++++++++
README.md | 1 +
3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/build_ubuntu_debug.yml b/.github/workflows/build_ubuntu_debug.yml
index b68744cb2..58aac6a42 100644
--- a/.github/workflows/build_ubuntu_debug.yml
+++ b/.github/workflows/build_ubuntu_debug.yml
@@ -16,8 +16,15 @@ jobs:
compiler: [g++-10, g++-9, g++-8, g++-7, clang-6, clang-7, clang-8, clang-9, clang-10, clang-11, clang-12]
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
shell: bash
run: |
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5bec9ae43..1b364f35f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,6 +20,17 @@ project("ParadisEO"
## Language
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
diff --git a/README.md b/README.md
index 686b08334..ff158606d 100644
--- a/README.md
+++ b/README.md
@@ -211,6 +211,7 @@ If you `ENABLE_CMAKE_EXAMPLE`, it will also build the examples.
If may want to make build scripts more verbose (especially when building the
doc) by enabling `CMAKE_VERBOSE_MAKEFILE`.
+If `ccache` installed in your environment, library recompilation times can be significantly reduced. To clear all cached objects, execute `ccache -C`.
## Licenses
From 22275e434b078bfb5bc480c77f74685aecb4395b Mon Sep 17 00:00:00 2001
From: Johann Dreo
Date: Mon, 7 Apr 2025 14:16:37 +0200
Subject: [PATCH 05/12] 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.
---
eo/src/eoEasyPSO.h | 16 ++++++-------
eo/src/eoSyncEasyPSO.h | 30 ++++++++++++-------------
eo/src/es/CMAParams.cpp | 3 +++
eo/src/gp/parse_tree.h | 7 ++++++
eo/src/mpi/implMpi.cpp | 2 +-
eo/src/utils/pipecom.cpp | 6 ++---
eo/src/utils/pipecom.h | 4 ++--
moeo/src/do/make_checkpoint_moeo.h | 2 +-
moeo/src/do/make_ea_moeo.h | 2 +-
moeo/src/metric/moeoHyperVolumeMetric.h | 4 ++--
moeo/tutorial/Lesson1/Sch1.cpp | 4 ++--
smp/src/PPExpander.h | 2 +-
smp/src/island.cpp | 4 ++++
smp/src/island.h | 3 ++-
smp/tutorial/Lesson1/QAPGA.h | 2 ++
15 files changed, 53 insertions(+), 38 deletions(-)
diff --git a/eo/src/eoEasyPSO.h b/eo/src/eoEasyPSO.h
index 87c27cad3..25f030595 100644
--- a/eo/src/eoEasyPSO.h
+++ b/eo/src/eoEasyPSO.h
@@ -174,18 +174,18 @@ protected:
// if the flight does not need to be used, use the dummy flight instance
class eoDummyFlight:public eoFlight < POT >
{
- public:
- eoDummyFlight () {}
- void operator () (POT &) {}
- }dummyFlight;
+ public:
+ eoDummyFlight () {}
+ void operator() (POT &) override {}
+ } dummyFlight;
// if the initializer does not need to be used, use the dummy one instead
class eoDummyInitializer:public eoInitializerBase < POT >
{
- public:
- eoDummyInitializer () {}
- void operator () (POT &) {}
- }dummyInit;
+ public:
+ eoDummyInitializer () {}
+ void operator() () override {}
+ } dummyInit;
};
/**
diff --git a/eo/src/eoSyncEasyPSO.h b/eo/src/eoSyncEasyPSO.h
index 11640af53..183148896 100644
--- a/eo/src/eoSyncEasyPSO.h
+++ b/eo/src/eoSyncEasyPSO.h
@@ -230,27 +230,25 @@ protected:
// if the eval does not need to be used, use the dummy eval instance
class eoDummyEval : public eoEvalFunc
- {
- public:
- void operator()(POT &)
- {}
- }
- dummyEval;
-
- class eoDummyFlight:public eoFlight < POT >
{
- public:
- eoDummyFlight () {}
- void operator () (POT &) {}
- }dummyFlight;
+ public:
+ void operator()(POT &) override {}
+ } dummyEval;
+
+ 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
class eoDummyInitializer:public eoInitializerBase < POT >
{
- public:
- eoDummyInitializer () {}
- void operator () (POT &) {}
- }dummyInit;
+ public:
+ eoDummyInitializer () {}
+ void operator() () override {}
+ } dummyInit;
};
/** @example t-eoSyncEasyPSO.cpp
diff --git a/eo/src/es/CMAParams.cpp b/eo/src/es/CMAParams.cpp
index 2862cdd1a..d27204f97 100644
--- a/eo/src/es/CMAParams.cpp
+++ b/eo/src/es/CMAParams.cpp
@@ -113,16 +113,19 @@ CMAParams::CMAParams(eoParser& parser, unsigned dimensionality) {
for (unsigned i = 0; i < weights.size(); ++i) {
weights[i] = mu - i;
}
+ break;
}
case 2:
{
weights = 1.;
+ break;
}
default :
{
for (unsigned i = 0; i < weights.size(); ++i) {
weights[i] = log(mu+1.)-log(i+1.);
}
+ break;
}
}
diff --git a/eo/src/gp/parse_tree.h b/eo/src/gp/parse_tree.h
index 84ec04d35..6b9ab80ae 100644
--- a/eo/src/gp/parse_tree.h
+++ b/eo/src/gp/parse_tree.h
@@ -468,8 +468,11 @@ private :
switch(new_arity)
{
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;
+ [[fallthrough]];
case 1 : args[0].copy(s.args[0]); args[0].parent = this;
+ [[fallthrough]];
case 0 : break;
default :
{
@@ -523,7 +526,9 @@ private :
switch(arity())
{
case 3 : args[2].parent = 0; // no break!
+ [[fallthrough]];
case 2 : args[1].parent = 0;
+ [[fallthrough]];
case 1 : args[0].parent = 0; break;
case 0 : break;
default :
@@ -542,7 +547,9 @@ private :
switch(arity())
{
case 3 : args[2].parent = this; // no break!
+ [[fallthrough]];
case 2 : args[1].parent = this;
+ [[fallthrough]];
case 1 : args[0].parent = this; break;
case 0 : break;
default :
diff --git a/eo/src/mpi/implMpi.cpp b/eo/src/mpi/implMpi.cpp
index 2dd1ca0d5..d045da3ac 100644
--- a/eo/src/mpi/implMpi.cpp
+++ b/eo/src/mpi/implMpi.cpp
@@ -161,7 +161,7 @@ namespace mpi
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 );
}
diff --git a/eo/src/utils/pipecom.cpp b/eo/src/utils/pipecom.cpp
index a175112f9..bef9ae2ce 100644
--- a/eo/src/utils/pipecom.cpp
+++ b/eo/src/utils/pipecom.cpp
@@ -42,16 +42,16 @@ int Check( PCom *com )
}
-PCom * PipeComOpen( char *prog )
+PCom * PipeComOpen( const char *prog )
{
char *args[2];
- args[0] = prog;
+ args[0] = strdup( prog );
args[1] = NULL;
return PipeComOpenArgv( prog, args );
}
-PCom * PipeComOpenArgv( char *prog, char *argv[] )
+PCom * PipeComOpenArgv( const char *prog, char *argv[] )
{
int toFils[2];
int toPere[2];
diff --git a/eo/src/utils/pipecom.h b/eo/src/utils/pipecom.h
index 56b031708..16685225c 100644
--- a/eo/src/utils/pipecom.h
+++ b/eo/src/utils/pipecom.h
@@ -23,8 +23,8 @@ typedef struct PipeCommunication {
} PCom;
-extern PCom *PipeComOpen( char *prog );
-extern PCom *PipeComOpenArgv( char *prog, char *argv[] );
+extern PCom *PipeComOpen( const char *prog );
+extern PCom *PipeComOpenArgv( const char *prog, char *argv[] );
extern int PipeComSend( PCom *to, const char *line );
extern int PipeComSendn( PCom *to, const char *data, int n );
diff --git a/moeo/src/do/make_checkpoint_moeo.h b/moeo/src/do/make_checkpoint_moeo.h
index 188c340ea..98bb1e2a1 100644
--- a/moeo/src/do/make_checkpoint_moeo.h
+++ b/moeo/src/do/make_checkpoint_moeo.h
@@ -66,7 +66,7 @@ bool testDirRes(std::string _dirName, bool _erase);
* @param _archive the archive of non-dominated solutions
*/
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));
/* the objective vector type */
diff --git a/moeo/src/do/make_ea_moeo.h b/moeo/src/do/make_ea_moeo.h
index aee4dcd0d..76559e198 100644
--- a/moeo/src/do/make_ea_moeo.h
+++ b/moeo/src/do/make_ea_moeo.h
@@ -85,7 +85,7 @@
* @param _archive the archive of non-dominated solutions
*/
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 */
diff --git a/moeo/src/metric/moeoHyperVolumeMetric.h b/moeo/src/metric/moeoHyperVolumeMetric.h
index dc65ac4c9..ce1ee0c1c 100644
--- a/moeo/src/metric/moeoHyperVolumeMetric.h
+++ b/moeo/src/metric/moeoHyperVolumeMetric.h
@@ -55,7 +55,7 @@ class moeoHyperVolumeMetric : public moeoVectorUnaryMetric < ObjectiveVector , d
* @param _normalize allow to normalize data (default true)
* @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());
// initialize bounds in case someone does not want to use them
for (unsigned int i=0; i
}
template
- U& findValueImpl(T& t, Arg&... arg, std::true_type)
+ U& findValueImpl(T& t, Arg&... /*arg*/, std::true_type)
{
return t;
}
diff --git a/smp/src/island.cpp b/smp/src/island.cpp
index 783d42d75..eb8fa85ca 100644
--- a/smp/src/island.cpp
+++ b/smp/src/island.cpp
@@ -59,6 +59,10 @@ paradiseo::smp::Island::Island(eoPop& _pop, IntPolicy
_pop, _intPolicy, _migPolicy, args...)
{ }
+template class EOAlgo, class EOT, class bEOT>
+paradiseo::smp::Island::~Island()
+{ }
+
template class EOAlgo, class EOT, class bEOT>
void paradiseo::smp::Island::operator()()
{
diff --git a/smp/src/island.h b/smp/src/island.h
index 752b671ef..8c5ccff6e 100644
--- a/smp/src/island.h
+++ b/smp/src/island.h
@@ -133,7 +133,8 @@ public:
virtual void receive(void);
//AIsland clone() const;
-
+
+ virtual ~Island();
protected:
/**
diff --git a/smp/tutorial/Lesson1/QAPGA.h b/smp/tutorial/Lesson1/QAPGA.h
index 6f3bf8031..8af54f17d 100644
--- a/smp/tutorial/Lesson1/QAPGA.h
+++ b/smp/tutorial/Lesson1/QAPGA.h
@@ -30,6 +30,8 @@ Contact: paradiseo-help@lists.gforge.inria.fr
#ifndef _QAPGA_h
#define _QAPGA_h
+extern int n; // size
+
class ProblemInit : public eoInit
{
public:
From 4b4344664b5e5a1b8977e319a580ee5afc14de20 Mon Sep 17 00:00:00 2001
From: Johann Dreo
Date: Mon, 7 Apr 2025 14:50:03 +0200
Subject: [PATCH 06/12] update(README): link to cmake-gui, citation ref
---
README.md | 36 +++++++++++++++++++++++++++++++-----
docs/index.html | 4 ++--
2 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index ff158606d..78f5c96fe 100644
--- a/README.md
+++ b/README.md
@@ -168,7 +168,7 @@ It is, for instance, easy to start with a simple local search, then add multi-ob
Paradiseo is mainly developed under Linux operating systems, where its dependencies and the C++ toolchain are easy to install. Recent versions have been tested with gcc and clang compilers.
-Stable versions should however work on Windows and any Unix-like operating system with a standard-conforming C++ development system.
+Stable versions should however work on Windows and any Unix-like operating system with a standard-conforming C++ development system.
# Code
@@ -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`.
-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
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.
+ To see them, we recommend the use of a CMake gui, like ccmake (available through the cmake-curses-gui package in Debian/Ubuntu) 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.
From c218a19de6aab83507a9d19e9b48190a2b4201d4 Mon Sep 17 00:00:00 2001
From: Johann Dreo
Date: Mon, 7 Apr 2025 22:56:58 +0200
Subject: [PATCH 07/12] fix(doc): disable doc-mpi
---
cmake/Target.cmake | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/cmake/Target.cmake b/cmake/Target.cmake
index 30d60f531..faacdf299 100644
--- a/cmake/Target.cmake
+++ b/cmake/Target.cmake
@@ -27,7 +27,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
# set(DOC_SMP "")
# endif()
# if(MPI)
- # set(DOC_MPI "make doc-mpi")
+ # set(DOC_MPI "make doc-mpi")
# else()
# set(DOC_MPI "")
# endif()
@@ -78,7 +78,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
COMMAND make doc-eo
COMMAND make doc-mo
COMMAND make doc-moeo
- COMMAND make doc-mpi
+ # COMMAND make doc-mpi
)
endif()
@@ -89,7 +89,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
COMMAND make doc-mo
COMMAND make doc-moeo
COMMAND make doc-smp
- COMMAND make doc-mpi
+ # COMMAND make doc-mpi
)
endif()
if(EDO AND NOT SMP AND MPI)
@@ -98,7 +98,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
COMMAND make doc-mo
COMMAND make doc-moeo
COMMAND make doc-edo
- COMMAND make doc-mpi
+ # COMMAND make doc-mpi
)
endif()
if(EDO AND SMP AND NOT MPI)
@@ -119,7 +119,7 @@ if(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
COMMAND make doc-moeo
COMMAND make doc-edo
COMMAND make doc-smp
- COMMAND make doc-mpi
+ # COMMAND make doc-mpi
)
endif()
@@ -131,7 +131,7 @@ endif(DOXYGEN_FOUND AND DOXYGEN_EXECUTABLE)
######################################################################################
if(PROFILING)
- find_program(LCOV
+ find_program(LCOV
NAMES lcov
PATHS
"/usr/local/bin /usr/bin [HKEY_LOCAL_MACHINE\\SOFTWARE\\Rational Software\\Purify\\Setup;InstallFolder] [HKEY_CURRENT_USER\\Software]"
From e14220ff69fb8c636f3e61edc21b194da7269f80 Mon Sep 17 00:00:00 2001
From: Johann Dreo
Date: Mon, 7 Apr 2025 22:57:21 +0200
Subject: [PATCH 08/12] fix(checkpoint): initialize a pointer
---
eo/src/do/make_checkpoint.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eo/src/do/make_checkpoint.h b/eo/src/do/make_checkpoint.h
index 84ef99961..2c2385524 100644
--- a/eo/src/do/make_checkpoint.h
+++ b/eo/src/do/make_checkpoint.h
@@ -65,7 +65,7 @@ eoCheckPoint& do_make_checkpoint(eoParser& _parser, eoState& _state, eoValu
#ifndef _MSC_VER
// the CtrlC monitoring interception
- eoSignal *mon_ctrlCCont;
+ eoSignal *mon_ctrlCCont = nullptr;
eoValueParam& mon_ctrlCParam = _parser.createParam(false, "monitor-with-CtrlC", "Monitor current generation upon Ctrl C",0, "Stopping criterion");
if (mon_ctrlCParam.value())
{
From bee47592af830566b00a77f84c5109621c82854d Mon Sep 17 00:00:00 2001
From: Johann Dreo
Date: Mon, 7 Apr 2025 23:01:43 +0200
Subject: [PATCH 09/12] doc: adds howto_build_paradiseo script for apptainer
---
howto_build_paradiseo.apptainer.def | 54 +++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
create mode 100644 howto_build_paradiseo.apptainer.def
diff --git a/howto_build_paradiseo.apptainer.def b/howto_build_paradiseo.apptainer.def
new file mode 100644
index 000000000..9297a7fbf
--- /dev/null
+++ b/howto_build_paradiseo.apptainer.def
@@ -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
From 400c69c49a6d1105d461bcacc7aef50c9f5b1337 Mon Sep 17 00:00:00 2001
From: Johann Dreo
Date: Tue, 8 Apr 2025 19:45:59 +0200
Subject: [PATCH 10/12] doc: mention Apptainer in INSTALL
---
INSTALL.md | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/INSTALL.md b/INSTALL.md
index b30e1c76f..a3fb4e1b7 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -2,7 +2,8 @@
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
@@ -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
```
+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
-------
@@ -187,13 +193,13 @@ Examples and lessons are generated when `ENABLE_CMAKE_EXAMPLE` is set.
If you want to build a specific lesson or example, you can check the list of available targets with `make help`.
All lessons are build on the same pattern: `Lesson`.
-For instance, make `moLesson4` will build the Lesson 4 from the MO module.
+For instance, make `moLesson4` will build the Lesson 4 from the MO module.
Easy, isn't it ?
Tests
-----
-By performing tests, you can check your installation.
+By performing tests, you can check your installation.
Testing is disable by default, except if you build with the full install type.
To enable testing, define `ENABLE_CMAKE_TESTING` when you run cmake.
From c660489eaf93a8b19617956f4ec25126bbbab55c Mon Sep 17 00:00:00 2001
From: Alessandro Sidero <75628365+Alessandro624@users.noreply.github.com>
Date: Tue, 15 Apr 2025 18:04:35 +0200
Subject: [PATCH 11/12] Optimize `eoRanking`: Add caching and index vector
(#80)
* Adds eoRankingCached with better documentation
* Optimize eoRanking with caching and index vector
* Adds t-eoRankingCached.cpp
---
eo/src/eoRanking.h | 104 ++++++++--------
eo/src/eoRankingCached.h | 139 +++++++++++++++++++++
eo/test/CMakeLists.txt | 1 +
eo/test/t-eoRankingCached.cpp | 219 ++++++++++++++++++++++++++++++++++
4 files changed, 411 insertions(+), 52 deletions(-)
create mode 100644 eo/src/eoRankingCached.h
create mode 100644 eo/test/t-eoRankingCached.cpp
diff --git a/eo/src/eoRanking.h b/eo/src/eoRanking.h
index 63a031071..f4c10951e 100644
--- a/eo/src/eoRanking.h
+++ b/eo/src/eoRanking.h
@@ -40,73 +40,73 @@ template
class eoRanking : public eoPerf2Worth // false: do not cache fitness
{
public:
-
using eoPerf2Worth::value;
- /* Ctor:
- @param _p selective pressure (in (1,2]
- @param _e exponent (1 == linear)
- */
- eoRanking(double _p=2.0, double _e=1.0):
- pressure(_p), exponent(_e) {}
-
- /* helper function: finds index in _pop of _eo, an EOT * */
- int lookfor(const EOT *_eo, const eoPop& _pop)
+ /* Ctor:
+ @param _p selective pressure (in (1,2]
+ @param _e exponent (1 == linear)
+ */
+ eoRanking(double _p = 2.0, double _e = 1.0) : pressure(_p), exponent(_e)
{
- typename eoPop::const_iterator it;
- for (it=_pop.begin(); it<_pop.end(); it++)
- {
- if (_eo == &(*it))
- return it-_pop.begin();
- }
- throw eoException("Not found in eoLinearRanking");
+ assert(1 < pressure and pressure <= 2);
}
- /* 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& _pop)
+ /* helper function: finds index in _pop of _eo, an EOT * */
+ int lookfor(const EOT *_eo, const eoPop &_pop)
{
- std::vector 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 exponetial then
+ typename eoPop::const_iterator it;
+ for (it = _pop.begin(); it < _pop.end(); it++)
{
- double alpha = (2*pressure-2)/(pSize*pSizeMinusOne);
- for (unsigned i=0; i &_pop)
+ {
+ std::vector 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);
- value()[which] = alpha*(pSize-i)+beta; // worst -> 1/[P(P-1)/2]
+ int which = lookfor(rank[i], _pop);
+ value()[which] = alpha * (pSize - i) + beta; // worst -> 1/[P(P-1)/2]
}
}
- else // exponent != 1
+ else // exponent != 1
{
- double gamma = (2*pressure-2)/pSize;
- for (unsigned i=0; i
+class eoRankingCached : public eoPerf2Worth
+{
+public:
+ using eoPerf2Worth::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 &_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 rank;
+ _pop.sort(rank);
+
+ // map of indices for the population
+ std::unordered_map 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
diff --git a/eo/test/CMakeLists.txt b/eo/test/CMakeLists.txt
index 8f8000890..edf8c4030 100644
--- a/eo/test/CMakeLists.txt
+++ b/eo/test/CMakeLists.txt
@@ -82,6 +82,7 @@ set (TEST_LIST
t-eoAlgoFoundryFastGA
t-eoRealToIntMonOp
t-eoRealToIntQuadOp
+ t-eoRankingCached
)
diff --git a/eo/test/t-eoRankingCached.cpp b/eo/test/t-eoRankingCached.cpp
new file mode 100644
index 000000000..33973e5ee
--- /dev/null
+++ b/eo/test/t-eoRankingCached.cpp
@@ -0,0 +1,219 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include "real_value.h"
+
+class RankingTest
+{
+public:
+ RankingTest(eoParser &parser, eoEvalFuncCounter> &_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 ind;
+ ind.resize(1);
+ ind[0] = rng.uniform();
+ pop.push_back(ind);
+ }
+ apply>(eval, pop);
+ }
+
+ const unsigned popSize;
+ eoPop> pop;
+ eoRng rng;
+ double pressure() const { return pressureParam.value(); }
+ double exponent() const { return exponentParam.value(); }
+
+private:
+ eoValueParam &seedParam;
+ eoValueParam &pressureParam;
+ eoValueParam &exponentParam;
+ eoEvalFuncCounter> eval;
+};
+
+// Test case 1: Verify both implementations produce identical results
+void test_Consistency(eoParser &parser)
+{
+ eoEvalFuncPtr, double, const std::vector &> mainEval(real_value);
+ eoEvalFuncCounter> eval(mainEval);
+ RankingTest fixture(parser, eval);
+
+ eoRanking> ranking(fixture.pressure(), fixture.exponent());
+ eoRankingCached> rankingCached(fixture.pressure(), fixture.exponent());
+
+ ranking(fixture.pop);
+ rankingCached(fixture.pop);
+
+ const std::vector &values = ranking.value();
+ const std::vector &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> smallPop;
+ eoReal 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, double, const std::vector &> mainEval(real_value);
+ eoEvalFuncCounter> eval(mainEval);
+
+ RankingTest fixture(parser, eval, 2); // Use fixture to get parameters
+ eoRanking> ranking(fixture.pressure(), fixture.exponent());
+ eoRankingCached> rankingCached(fixture.pressure(), fixture.exponent());
+
+ apply>(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, double, const std::vector &> mainEval(real_value);
+ eoEvalFuncCounter> eval(mainEval);
+ RankingTest fixture(parser, eval, 50); // Fixed size for cache test
+
+ eoRankingCached> 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>(eval, fixture.pop);
+
+ // Second run - should use cached coefficients
+ rankingCached(fixture.pop);
+
+ // Add one individual to invalidate cache
+ eoReal newInd;
+ newInd.resize(1);
+ newInd[0] = fixture.rng.uniform();
+ fixture.pop.push_back(newInd);
+
+ apply>(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> 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> 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;
+ }
+}
From 3259d1b452e4d6625300bea694e933cf12bfffd4 Mon Sep 17 00:00:00 2001
From: Johann Dreo
Date: Wed, 16 Apr 2025 13:42:29 +0200
Subject: [PATCH 12/12] doc: bump version + clean authors list
---
AUTHORS | 35 +++++++++++++++++++++++------------
CMakeLists.txt | 2 +-
docs/index.html | 2 +-
3 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/AUTHORS b/AUTHORS
index 604157f80..47e9ce4b9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,41 +1,52 @@
Current maintainers
===================
-Arnaud Liefooghe
-Clive Canape
-Johann Dreo
-Sébastien Verel
-Active developpers
-==================
-Alexandre Quemy
-Benjamin Bouvier
-Caner Candan
-Pierre Savéant
+Johann Dreo
+
Past contributors
=================
+
atantar
+Alesandro Sidero
+Alexandre Quemy
+Alix Zheng
+Amine Aziz-Alaoui
+Arnaud Liefooghe
+Benjamin Bouvier
+Bahri
+Caner Candan
+Clive Canape
fatene
Gustavo Romero Lopez
jboisson
Jeroen Eggermont
Jochen Küpper
-Joost
+Joost
Juan Julian Merelo Guervos
Jérémie Humeau
+Jxtopher
Karima Boufaras
-legillon
+legillono
+Leo Bertheas
Louis Da Costa
Loïc Jean David Arjanen
Maarten Keijzer
+Mammar Amara
+Manu
Marc Schoenauer
Marie-Éleonore
Mostepha Khouadjia
Olivier König
+Pierre Savéant
Pedro Angel Castillo Valdivieso
+Potalas
+Ronald Pinho
Steve Madere
Sébastien Cahon
+Sébastien Verel
Thomas Legrand
+Thibault Lasnier
Victor Manuel Rivas Santos
wcancino
xohm
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1b364f35f..52c1fa4a5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,7 +13,7 @@ cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
## Name
project("ParadisEO"
- VERSION 3.0.0
+ VERSION 3.1.3
DESCRIPTION "Evolutionary optimization framework"
LANGUAGES C CXX)
diff --git a/docs/index.html b/docs/index.html
index 5d7cea626..33c2eaae6 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1169,7 +1169,7 @@ undiscovered knowledge.