feat: prepare the use of binary partitions for signatures

This commit is contained in:
Johann Dreo 2022-09-12 15:20:05 +02:00 committed by nojhan
commit 11f49e58d7
3 changed files with 304 additions and 0 deletions

View file

@ -0,0 +1,107 @@
#pragma once
#include <set>
#include <eo>
template<class FitT>
class moBinaryPartition : public EO<FitT>
{
public:
using AtomType = size_t;
using ContainerType = std::set<AtomType>;
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<FitT>::printOn(out); // Fitness.
// Trailing space already inserted.
out << selected.size() << " "; // Size.
std::copy(std::begin(selected), std::end(selected),
std::ostream_iterator<AtomType>(out, " ")); // Values.
out << " ";
out << rejected.size() << " "; // Size.
std::copy(std::begin(rejected), std::end(rejected),
std::ostream_iterator<AtomType>(out, " ")); // Values.
}
/** Deserialization of the `selected` atoms. */
virtual void readFrom(std::istream& in)
{
EO<FitT>::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";
}
};

View file

@ -0,0 +1,89 @@
#pragma once
#include <utility>
#include <mo>
#include "moBinaryPartition.h"
template<class EOT, class Fitness=typename EOT::Fitness>
class moBinaryPartitionSwapNeighbor :
public moBackableNeighbor<EOT,double>//,
// public moIndexNeighbor<EOT,double>
{
public:
using AtomType = typename EOT::AtomType;
using ContainerType = typename EOT::ContainerType;
using moBackableNeighbor<EOT, Fitness>::fitness;
// using moIndexNeighbor<EOT, Fitness>::key;
// using moIndexNeighbor<EOT, Fitness>::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<AtomType,AtomType> get() {
assert(is_set);
return std::make_pair(select, reject);
}
virtual bool equals(moBinaryPartitionSwapNeighbor<EOT,Fitness>& 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
};

View file

@ -0,0 +1,108 @@
#pragma once
#include <utility>
#include <mo>
#include "moBinaryPartition.h"
template <class EOT, class Fitness=typename EOT::Fitness>
class moBinaryPartitionSwapNeighborhood : public moNeighborhood<moBinaryPartitionSwapNeighbor<EOT, Fitness> >
{
public:
using Neighbor = moBinaryPartitionSwapNeighbor<EOT, Fitness>;
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;
};