document everything and remove dead code
This commit is contained in:
parent
11f49e58d7
commit
2accb17599
3 changed files with 150 additions and 10 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 Atom’s type. */
|
||||
using AtomType = typename EOT::AtomType;
|
||||
|
||||
/** Shortcut for container’s 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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 Atom’s 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;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue