From 11f49e58d77afc3cd9cbf46fa57bc25d6872918a Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Mon, 12 Sep 2022 15:20:05 +0200 Subject: [PATCH] feat: prepare the use of binary partitions for signatures --- mo/src/problems/partition/moBinaryPartition.h | 107 +++++++++++++++++ .../partition/moBinaryPartitionSwapNeighbor.h | 89 +++++++++++++++ .../moBinaryPartitionSwapNeighborhood.h | 108 ++++++++++++++++++ 3 files changed, 304 insertions(+) create mode 100644 mo/src/problems/partition/moBinaryPartition.h create mode 100644 mo/src/problems/partition/moBinaryPartitionSwapNeighbor.h create mode 100644 mo/src/problems/partition/moBinaryPartitionSwapNeighborhood.h diff --git a/mo/src/problems/partition/moBinaryPartition.h b/mo/src/problems/partition/moBinaryPartition.h new file mode 100644 index 000000000..2fedb50ef --- /dev/null +++ b/mo/src/problems/partition/moBinaryPartition.h @@ -0,0 +1,107 @@ +#pragma once + +#include + +#include + +template +class moBinaryPartition : public EO +{ + public: + using AtomType = size_t; + using ContainerType = std::set; + + ContainerType selected; + ContainerType rejected; + + /** Constructor + * + * @param total_nb_genes Total number of possible genes from whith to select. + */ + moBinaryPartition( const size_t total_nb_genes ) + { + // Fill the rejected list with all possible gene indices, + // starting from zero. + for(size_t i = 0; i < total_nb_genes; ++i) { + rejected.insert(i); + } + // No selected. + } + + void select(const size_t atom) { + assert(not selected.contains(atom)); + + #ifndef NDEBUG + size_t has_erased = + #endif + this->rejected.erase(atom); + assert(has_erased == 1); + + #ifndef NDEBUG + auto [where, has_inserted] = + #endif + this->selected.insert(atom); + assert(has_inserted); + } + + void reject(const size_t atom) { + assert(not rejected.contains(atom)); + + #ifndef NDEBUG + size_t has_erased = + #endif + this->selected.erase(atom); + assert(has_erased == 1); + + #ifndef NDEBUG + auto [where, has_inserted] = + #endif + this->rejected.insert(atom); + assert(has_inserted); + } + + /** Serialization of the `selected` atoms. */ + virtual void printOn(std::ostream& out) const + { + EO::printOn(out); // Fitness. + // Trailing space already inserted. + out << selected.size() << " "; // Size. + std::copy(std::begin(selected), std::end(selected), + std::ostream_iterator(out, " ")); // Values. + out << " "; + out << rejected.size() << " "; // Size. + std::copy(std::begin(rejected), std::end(rejected), + std::ostream_iterator(out, " ")); // Values. + } + + /** Deserialization of the `selected` atoms. */ + virtual void readFrom(std::istream& in) + { + EO::readFrom(in); // Fitness. + unsigned size; + in >> size; // Size. + for(size_t i = 0; i < size; ++i) { + AtomType atom; + in >> atom; // Value. + selected.insert(atom); + } + assert(selected.size() == size); + in >> size; // Size. + for(size_t i = 0; i < size; ++i) { + AtomType atom; + in >> atom; // Value. + rejected.insert(atom); + } + assert(rejected.size() == size); + } + + bool operator==(const moBinaryPartition& other) { + return this->selected == other.selected + and this->rejected == other.rejected; + } + + virtual std::string className() const + { + return "moBinaryPartition"; + } +}; diff --git a/mo/src/problems/partition/moBinaryPartitionSwapNeighbor.h b/mo/src/problems/partition/moBinaryPartitionSwapNeighbor.h new file mode 100644 index 000000000..86e97a74d --- /dev/null +++ b/mo/src/problems/partition/moBinaryPartitionSwapNeighbor.h @@ -0,0 +1,89 @@ +#pragma once + +#include + +#include + +#include "moBinaryPartition.h" + +template +class moBinaryPartitionSwapNeighbor : + public moBackableNeighbor//, + // public moIndexNeighbor +{ + public: + using AtomType = typename EOT::AtomType; + using ContainerType = typename EOT::ContainerType; + using moBackableNeighbor::fitness; + // using moIndexNeighbor::key; + // using moIndexNeighbor::index; + + moBinaryPartitionSwapNeighbor( const size_t _selected_nb ) : + selected_nb(_selected_nb), + is_set(false) + { + assert(selected_nb > 0); + } + + virtual void move(EOT& solution) override { + assert(is_set); + // Swap the two atoms. + solution.reject(this->reject); + solution.select(this->select); + assert(solution.selected.size() == this->selected_nb); + + solution.invalidate(); + } + + virtual void moveBack(EOT& solution) override { + assert(is_set); + solution.reject(this->select); + solution.select(this->reject); + assert(solution.selected.size() == this->selected_nb); + + solution.invalidate(); + } + + void set(AtomType in, AtomType out) { + this->select = in; + this->reject = out; + #ifndef NDEBUG + is_set = true; + #endif + } + + std::pair get() { + assert(is_set); + return std::make_pair(select, reject); + } + + virtual bool equals(moBinaryPartitionSwapNeighbor& neighbor) { + auto [in, out] = neighbor.get(); + return this->select == in and this->reject == out; + } + + virtual std::string className() const override { + return "moBinaryPartitionSwapNeighbor"; + } + + virtual void printOn(std::ostream& out) const override { + assert(is_set); + out << selected_nb + << " -" << reject + << " +" << select; + } + +#ifndef NDEBUG + public: +#else + protected: +#endif + const size_t selected_nb; + AtomType select; + AtomType reject; + #ifndef NDEBUG + bool is_set; + #endif +}; + + diff --git a/mo/src/problems/partition/moBinaryPartitionSwapNeighborhood.h b/mo/src/problems/partition/moBinaryPartitionSwapNeighborhood.h new file mode 100644 index 000000000..e92382357 --- /dev/null +++ b/mo/src/problems/partition/moBinaryPartitionSwapNeighborhood.h @@ -0,0 +1,108 @@ +#pragma once + +#include + +#include +#include "moBinaryPartition.h" + +template +class moBinaryPartitionSwapNeighborhood : public moNeighborhood > +{ + public: + using Neighbor = moBinaryPartitionSwapNeighbor; + using AtomType = typename EOT::AtomType; + + AtomType selected(EOT& from, const size_t i_select) { + typename EOT::ContainerType::iterator + it = std::begin(from.rejected); + std::advance(it, i_select); + return *it; + } + + AtomType rejected(EOT& from, const size_t j_reject) { + typename EOT::ContainerType::iterator + it = std::begin(from.selected); + std::advance(it, j_reject); + return *it; + } + + virtual void init(EOT& from, Neighbor& to) override { + i_select = 0; + j_reject = 0; + + // std::clog << "Init neighborhood:" + // << " -" << rejected(from, j_reject) + // << " +" << selected(from, i_select) + // << std::endl; + + // First item in both lists. + AtomType in = selected(from, i_select); + AtomType out = rejected(from, j_reject); + to.set(in, out); + } + + virtual void next(EOT& from, Neighbor& to) override { + // If last item of the inner loop. + if( i_select == from.rejected.size()-1 ) { + i_select = 0; // Reset inner loop. + j_reject++; // Next outer loop. + } else { + i_select++; // Next inner loop. + } + + // std::clog << "Next in neighborhood:" + // << " -" << rejected(from, j_reject) + // << " +" << selected(from, i_select) + // << std::endl; + + assert( from.rejected.contains(selected(from,i_select)) ); + assert( from.selected.contains(rejected(from,j_reject)) ); + assert( selected(from,i_select) != rejected(from,j_reject) ); + + // Implant this move in the neighbor. + to.set( + selected(from, i_select), + rejected(from, j_reject) + ); + } + + virtual bool cont(EOT& from) override { + // Outer loop on selected, + // inner loop on rejected. + // std::clog << "cont neighborhood?" + // << " " << j_reject << "(-" << rejected(from, j_reject) << ")/" << from.selected.size() + // << " " << i_select << "(-" << selected(from, i_select) << ")/" << from.rejected.size() + // << std::endl; + + // If reached the last item of the outer loop. + if( i_select == from.rejected.size()-1 + and j_reject == from.selected.size()-1) { + // We should also have reached the end of the inner loop, + // and have set the inner loop to zero. + // std::clog << "\tnope" << std::endl; + return false; + + } else { // There is still some items in the outer loop. + // and thus also in the inner loop. + // std::clog << "\tyes" << std::endl; + assert( j_reject < from.selected.size() ); + return true; + } + } + + virtual bool hasNeighbor(EOT& solution) override { + return solution.rejected.size() > 0; + } + + virtual std::string className() const override { + return "moBinaryPartitionSwapNeighborhood"; + } + +#ifndef NDEBUG + public: +#else + protected: +#endif + size_t i_select; + size_t j_reject; +};