document everything and remove dead code

This commit is contained in:
Johann Dreo 2022-09-13 15:25:33 +02:00 committed by nojhan
commit 2accb17599
3 changed files with 150 additions and 10 deletions

View file

@ -4,30 +4,76 @@
#include <eo>
/** A partition of a binary space.
*
* This data structure defines a grouping of the elements of a multi-dimensional
* set in a space of boolean numbers.
* \f[
* \mathrm{1}^n = \bigcup_{i=1}^n \{0,1\}_i
* \f]
* Elements of the set may be either "selected" (in the set S) or "rejected" (in the set R).
* \f[
* (S \in \mathrm{1}^m) \cup (R \in \mathrm{1}^k) \in \mathrm{1}^n,\; n=m+k
* \f]
* Elements are referred to by their index in the set (hereby named "atoms").
*
* This representation is useful if your problem can be defined has selecting
* a subset of elements that optimize some objective function.
*
* The core data structures are two ordered sets of unique atoms,
* the union of which is guaranteed to have the correct dimension.
*/
template<class FitT>
class moBinaryPartition : public EO<FitT>
{
public:
/** The type for indices. */
using AtomType = size_t;
/** The data structures holding the indices. */
using ContainerType = std::set<AtomType>;
/** The set of selected atoms. */
ContainerType selected;
/** The set of not-selected atoms. */
ContainerType rejected;
/** Constructor
/** Consistent constructor
*
* @param total_nb_genes Total number of possible genes from whith to select.
* Put all `total_nb_atoms` indices in the @ref rejected set.
* Indices starts at zero and fill the set in increasing order.
*
* @param total_nb_atoms Total number of possible atoms from whith to select.
*/
moBinaryPartition( const size_t total_nb_genes )
moBinaryPartition( const size_t total_nb_atoms )
{
// Fill the rejected list with all possible gene indices,
// starting from zero.
for(size_t i = 0; i < total_nb_genes; ++i) {
for(size_t i = 0; i < total_nb_atoms; ++i) {
rejected.insert(i);
}
// No selected.
// None selected.
}
/** Empty constructor
*
* Do not fill the @ref rejected set.
* You are responsible for making it consistent after instantiation.
*
* @warning If you do not fill at least the @ref rejected set,
* errors will be raised whe trying to @ref select or @ref reject.
*/
moBinaryPartition()
{ }
/** Move one atom in the @ref selected set.
*
* That is: erase the atom from @ref rejected,
* insert it in @ref selected.
*
* @note In debug mode, double check that elements were actually moved.
*/
void select(const size_t atom) {
assert(not selected.contains(atom));
@ -44,6 +90,13 @@ class moBinaryPartition : public EO<FitT>
assert(has_inserted);
}
/** Move one atom in the @ref rejected set.
*
* That is: insert the atom in @ref rejected,
* erase it from @ref selected.
*
* @note In debug mode, double check that elements were actually moved.
*/
void reject(const size_t atom) {
assert(not rejected.contains(atom));
@ -95,6 +148,7 @@ class moBinaryPartition : public EO<FitT>
assert(rejected.size() == size);
}
/** Returns true if all sets are equals. */
bool operator==(const moBinaryPartition& other) {
return this->selected == other.selected
and this->rejected == other.rejected;

View file

@ -6,25 +6,53 @@
#include "moBinaryPartition.h"
/** Stable neighbor for a binary partition.
*
* Models how to move from a solution to a neighbor,
* by swaping one selected atom for one rejected atom.
* The number of selected atoms is thus guaranteed to be stable.
*
* The core data structure is two atoms:
* - the selected one,
* - the rejected one.
*/
template<class EOT, class Fitness=typename EOT::Fitness>
class moBinaryPartitionSwapNeighbor :
public moBackableNeighbor<EOT,double>//,
// public moIndexNeighbor<EOT,double>
// public moIndexNeighbor<EOT,double> // FIXME see if we can model that.
{
public:
/** Shortcut for Atoms type. */
using AtomType = typename EOT::AtomType;
/** Shortcut for containers type. */
using ContainerType = typename EOT::ContainerType;
/** Shortcut for fitness. */
using moBackableNeighbor<EOT, Fitness>::fitness;
// using moIndexNeighbor<EOT, Fitness>::key;
// using moIndexNeighbor<EOT, Fitness>::index;
/** Consistent constructor.
*
* Will ensure that the dimension of the partition does not change.
*
* @param _selected_nb Number of selected atoms to maintain.
*/
moBinaryPartitionSwapNeighbor( const size_t _selected_nb ) :
selected_nb(_selected_nb),
is_set(false)
selected_nb(_selected_nb)
#ifndef NDEBUG
, is_set(false)
#endif
{
assert(selected_nb > 0);
}
/** Apply the currently stored move.
*
* That is: reject one atom and select one other.
*/
virtual void move(EOT& solution) override {
assert(is_set);
// Swap the two atoms.
@ -35,6 +63,10 @@ class moBinaryPartitionSwapNeighbor :
solution.invalidate();
}
/** Apply the opposite of the currently stored move.
*
* That is: reject the selected atom, and select the rejected one.
*/
virtual void moveBack(EOT& solution) override {
assert(is_set);
solution.reject(this->select);
@ -44,6 +76,11 @@ class moBinaryPartitionSwapNeighbor :
solution.invalidate();
}
/** Set the considered atoms.
*
* @param in The selected atom.
* @param out The rejected atom.
*/
void set(AtomType in, AtomType out) {
this->select = in;
this->reject = out;
@ -52,11 +89,16 @@ class moBinaryPartitionSwapNeighbor :
#endif
}
/** Get the considered atom.
*
* @returns A pair of atoms, the first being the selected atom, the second being the rejected one.
*/
std::pair<AtomType,AtomType> get() {
assert(is_set);
return std::make_pair(select, reject);
}
/** Returns true if this neighbor has the same selected & rejected atoms than the given neighbor. */
virtual bool equals(moBinaryPartitionSwapNeighbor<EOT,Fitness>& neighbor) {
auto [in, out] = neighbor.get();
return this->select == in and this->reject == out;
@ -66,6 +108,7 @@ class moBinaryPartitionSwapNeighbor :
return "moBinaryPartitionSwapNeighbor";
}
/** Fancy print. */
virtual void printOn(std::ostream& out) const override {
assert(is_set);
out << selected_nb
@ -78,10 +121,21 @@ class moBinaryPartitionSwapNeighbor :
#else
protected:
#endif
/** Fixed dimension of the handled solutions. */
const size_t selected_nb;
/** Selected atom. */
AtomType select;
/** Rejected atom. */
AtomType reject;
#ifndef NDEBUG
/** Sanity flag.
*
* Used in debug builds to ensure that the neighbor
* have been set before being used.
*/
bool is_set;
#endif
};

View file

@ -5,13 +5,32 @@
#include <mo>
#include "moBinaryPartition.h"
/** Stable neighborhood for binary partitions.
*
* This generates all neighbors of a binary partition
* that have the same dimension than the considered solution.
* I.e. it enumerates all the swaps of two atoms
* between the selected and rejected sets.
*
* The core data structure is two indices:
* - one for the position within the selected set of a binary partition,
* - the other for the position within the rejected set.
*
* The neighborhood is defined as enumerating the neighbors,
* first by going over the rejected atoms (outer loop),
* then by iterating over the selected atoms (inner loop).
*/
template <class EOT, class Fitness=typename EOT::Fitness>
class moBinaryPartitionSwapNeighborhood : public moNeighborhood<moBinaryPartitionSwapNeighbor<EOT, Fitness> >
{
public:
/** Shortcut for neighbor's type. */
using Neighbor = moBinaryPartitionSwapNeighbor<EOT, Fitness>;
/** Shortcut for Atoms type. */
using AtomType = typename EOT::AtomType;
/** Get the currently pointed selected atom. */
AtomType selected(EOT& from, const size_t i_select) {
typename EOT::ContainerType::iterator
it = std::begin(from.rejected);
@ -19,6 +38,7 @@ class moBinaryPartitionSwapNeighborhood : public moNeighborhood<moBinaryPartitio
return *it;
}
/** Get the currently pointed rejected atom. */
AtomType rejected(EOT& from, const size_t j_reject) {
typename EOT::ContainerType::iterator
it = std::begin(from.selected);
@ -26,6 +46,11 @@ class moBinaryPartitionSwapNeighborhood : public moNeighborhood<moBinaryPartitio
return *it;
}
/** Initialize the neighborhood.
*
* This actually make the neighborhood point to the first possible swap:
* between the first selected atom and the first rejected atom.
*/
virtual void init(EOT& from, Neighbor& to) override {
i_select = 0;
j_reject = 0;
@ -41,6 +66,7 @@ class moBinaryPartitionSwapNeighborhood : public moNeighborhood<moBinaryPartitio
to.set(in, out);
}
/** Point to the next neighbor. */
virtual void next(EOT& from, Neighbor& to) override {
// If last item of the inner loop.
if( i_select == from.rejected.size()-1 ) {
@ -66,9 +92,8 @@ class moBinaryPartitionSwapNeighborhood : public moNeighborhood<moBinaryPartitio
);
}
/** Returns true if there is more neighbors to be enumerated. */
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()
@ -90,6 +115,10 @@ class moBinaryPartitionSwapNeighborhood : public moNeighborhood<moBinaryPartitio
}
}
/** Returns true if there is actual neighbors in the neighborhood.
*
* Essentially just tells if the rejected set is not empty.
*/
virtual bool hasNeighbor(EOT& solution) override {
return solution.rejected.size() > 0;
}
@ -103,6 +132,9 @@ class moBinaryPartitionSwapNeighborhood : public moNeighborhood<moBinaryPartitio
#else
protected:
#endif
/** Index of the currently pointed selected atom. */
size_t i_select;
/** Index of the currently pointed rejected atom. */
size_t j_reject;
};