From 19ec4c4ff760b5470163f0e940d1148449b6f3ad Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 26 Sep 2024 13:24:10 +0200 Subject: [PATCH] feat(eo): wrap ops on float vecs into ops on int vecs Adds wrapper classes to make any MonOp or QuadOp that operates on eoReal embbedable in any operator needing an eoInt. --- eo/src/eo | 4 ++ eo/src/eoInt.h | 5 +- eo/src/eoRealToIntMonOp.h | 73 +++++++++++++++++++++++++ eo/src/eoRealToIntQuadOp.h | 94 +++++++++++++++++++++++++++++++++ eo/src/es/eoReal.h | 1 + eo/test/CMakeLists.txt | 2 + eo/test/t-eoRealToIntMonOp.cpp | 28 ++++++++++ eo/test/t-eoRealToIntQuadOp.cpp | 35 ++++++++++++ 8 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 eo/src/eoRealToIntMonOp.h create mode 100644 eo/src/eoRealToIntQuadOp.h create mode 100644 eo/test/t-eoRealToIntMonOp.cpp create mode 100644 eo/test/t-eoRealToIntQuadOp.cpp diff --git a/eo/src/eo b/eo/src/eo index 55c070857..77a65e249 100644 --- a/eo/src/eo +++ b/eo/src/eo @@ -224,6 +224,10 @@ #include "utils/eoLogger.h" #include "utils/eoParallel.h" +#include "eoInt.h" +#include "eoRealToIntMonOp.h" +#include "eoRealToIntQuadOp.h" + #endif // Local Variables: diff --git a/eo/src/eoInt.h b/eo/src/eoInt.h index 0f0feb3e1..efeba4a62 100644 --- a/eo/src/eoInt.h +++ b/eo/src/eoInt.h @@ -36,9 +36,12 @@ * * @ingroup Representations */ -template class eoInt: public eoVector +template +class eoInt: public eoVector { public: + using AtomType = size_t; + using FitnessType = FitT; /** * (Default) Constructor. diff --git a/eo/src/eoRealToIntMonOp.h b/eo/src/eoRealToIntMonOp.h new file mode 100644 index 000000000..47207a185 --- /dev/null +++ b/eo/src/eoRealToIntMonOp.h @@ -0,0 +1,73 @@ +#ifndef eoRealToIntMonOp_h_INCLUDED +#define eoRealToIntMonOp_h_INCLUDED + +#include "es/eoReal.h" +#include "utils/eoIntBounds.h" + +template> +class eoRealToIntMonOp : public eoMonOp +{ +public: + + using EOTreal = EOTREAL; + + enum Repair { + folds, + truncate + }; + + eoRealToIntMonOp( eoMonOp& monop ) : + _whenout(Repair::truncate), + _nobounds(), + _bounds(_nobounds), + _monop(monop) + { } + + eoRealToIntMonOp( eoMonOp& monop, eoIntBounds& bounds, Repair whenout = Repair::truncate ) : + _whenout(whenout), + _nobounds(), + _bounds(bounds), + _monop(monop) + { } + + bool operator()(EOTINT& intsol) + { + #ifndef NDEBUG + for(size_t i=0; i < intsol.size(); ++i) { + assert(_bounds.isInBounds(intsol[i])); + } + #endif + + EOTreal floatsol; + std::copy( std::begin(intsol), std::end(intsol), std::back_inserter(floatsol) ); + + bool changed = _monop(floatsol); + + if(changed) { + for(size_t i=0; i < floatsol.size(); ++i) { + typename EOTreal::AtomType rounded = std::round(floatsol[i]); + if( not _bounds.isInBounds(rounded) ) { + switch(_whenout) { + case Repair::truncate: + _bounds.truncate(rounded); + break; + case Repair::folds: + _bounds.foldsInBounds(rounded); + break; + } + } + intsol[i] = static_cast(rounded); + } + } + return changed; + } + +protected: + Repair _whenout; + eoIntNoBounds _nobounds; + + eoIntBounds& _bounds; + eoMonOp& _monop; +}; + +#endif // eoRealToIntMonOp_h_INCLUDED diff --git a/eo/src/eoRealToIntQuadOp.h b/eo/src/eoRealToIntQuadOp.h new file mode 100644 index 000000000..7a5e02044 --- /dev/null +++ b/eo/src/eoRealToIntQuadOp.h @@ -0,0 +1,94 @@ +#ifndef eoRealToIntQuadOp_h_INCLUDED +#define eoRealToIntQuadOp_h_INCLUDED + +#include "es/eoReal.h" +#include "utils/eoIntBounds.h" + +template> +class eoRealToIntQuadOp : public eoQuadOp +{ +public: + + using EOTreal = EOTREAL; + + enum Repair { + folds, + truncate + }; + + eoRealToIntQuadOp( eoQuadOp& quadop ) : + _whenout(Repair::truncate), + _nobounds(), + _bounds(_nobounds), + _quadop(quadop) + { } + + eoRealToIntQuadOp( eoQuadOp& quadop, eoIntBounds& bounds, Repair whenout = Repair::truncate ) : + _whenout(whenout), + _nobounds(), + _bounds(bounds), + _quadop(quadop) + { } + + bool operator()(EOTINT& intsol1, EOTINT& intsol2) + { + #ifndef NDEBUG + for(size_t i=0; i < intsol1.size(); ++i) { + assert(_bounds.isInBounds(intsol1[i])); + } + for(size_t i=0; i < intsol2.size(); ++i) { + assert(_bounds.isInBounds(intsol2[i])); + } + #endif + + EOTreal floatsol1; + std::copy( std::begin(intsol1), std::end(intsol1), std::back_inserter(floatsol1) ); + + EOTreal floatsol2; + std::copy( std::begin(intsol2), std::end(intsol2), std::back_inserter(floatsol2) ); + + bool changed = _quadop(floatsol1, floatsol2); + + if(changed) { + for(size_t i=0; i < floatsol1.size(); ++i) { + typename EOTreal::AtomType rounded = std::round(floatsol1[i]); + if( not _bounds.isInBounds(rounded) ) { + switch(_whenout) { + case Repair::truncate: + _bounds.truncate(rounded); + break; + case Repair::folds: + _bounds.foldsInBounds(rounded); + break; + } + } + intsol1[i] = static_cast(rounded); + } + for(size_t i=0; i < floatsol2.size(); ++i) { + typename EOTreal::AtomType rounded = std::round(floatsol2[i]); + if( not _bounds.isInBounds(rounded) ) { + switch(_whenout) { + case Repair::truncate: + _bounds.truncate(rounded); + break; + case Repair::folds: + _bounds.foldsInBounds(rounded); + break; + } + } + intsol2[i] = static_cast(rounded); + } + } + return changed; + } + +protected: + Repair _whenout; + eoIntNoBounds _nobounds; + + eoIntBounds& _bounds; + eoQuadOp& _quadop; +}; + + +#endif // eoRealToIntQuadOp_h_INCLUDED diff --git a/eo/src/es/eoReal.h b/eo/src/es/eoReal.h index 440234f60..a611df3b6 100644 --- a/eo/src/es/eoReal.h +++ b/eo/src/es/eoReal.h @@ -39,6 +39,7 @@ template class eoReal: public eoVector { public: + using AtomType = double; using FitnessType = FitT; /** diff --git a/eo/test/CMakeLists.txt b/eo/test/CMakeLists.txt index b6b9afee6..8f8000890 100644 --- a/eo/test/CMakeLists.txt +++ b/eo/test/CMakeLists.txt @@ -80,6 +80,8 @@ set (TEST_LIST t-forge-FastGA t-eoFoundryFastGA t-eoAlgoFoundryFastGA + t-eoRealToIntMonOp + t-eoRealToIntQuadOp ) diff --git a/eo/test/t-eoRealToIntMonOp.cpp b/eo/test/t-eoRealToIntMonOp.cpp new file mode 100644 index 000000000..0aee0481a --- /dev/null +++ b/eo/test/t-eoRealToIntMonOp.cpp @@ -0,0 +1,28 @@ +#include + +#include +#include + +using namespace std; + +int main(int, char**) +{ + eoIntInterval bounds(1,5); + + using Chrom = eoInt; + using MutWrapper = eoRealToIntMonOp; + + eoDetUniformMutation< typename MutWrapper::EOTreal > mutreal(/*range*/6, /*nb*/5); + + MutWrapper mutint(mutreal, bounds); + + Chrom sol({1,2,3,4,5}); + + bool changed = mutint(sol); + assert(changed); + + for(auto& x : sol) { + assert(bounds.isInBounds(x)); + } +} + diff --git a/eo/test/t-eoRealToIntQuadOp.cpp b/eo/test/t-eoRealToIntQuadOp.cpp new file mode 100644 index 000000000..0ddfe7846 --- /dev/null +++ b/eo/test/t-eoRealToIntQuadOp.cpp @@ -0,0 +1,35 @@ +#include + +#include +#include + +using namespace std; + +int main(int, char**) +{ + eoIntInterval intbounds(1,5); + eoRealInterval rb(1,5); + eoRealVectorBounds realbounds(5, rb); + + using Chrom = eoInt; + using CrossWrapper = eoRealToIntQuadOp; + + eoSegmentCrossover< typename CrossWrapper::EOTreal > crossreal(realbounds, /*alpha*/0); + + CrossWrapper crossint(crossreal, intbounds); + + Chrom sol1({1,2,3,4,5}); + Chrom sol2({1,2,3,4,5}); + + bool changed = crossint(sol1, sol2); + assert(changed); + + for(auto& x : sol1) { + assert(intbounds.isInBounds(x)); + } + for(auto& x : sol2) { + assert(intbounds.isInBounds(x)); + } +} + +