paradiseo/mo/src/problems/partition/moBinaryPartitionSwapNeighbor.h
2022-09-13 15:25:33 +02:00

143 lines
4.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <utility>
#include <mo>
#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> // 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)
#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.
solution.reject(this->reject);
solution.select(this->select);
assert(solution.selected.size() == this->selected_nb);
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);
solution.select(this->reject);
assert(solution.selected.size() == this->selected_nb);
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;
#ifndef NDEBUG
is_set = true;
#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;
}
virtual std::string className() const override {
return "moBinaryPartitionSwapNeighbor";
}
/** Fancy print. */
virtual void printOn(std::ostream& out) const override {
assert(is_set);
out << selected_nb
<< " -" << reject
<< " +" << select;
}
#ifndef NDEBUG
public:
#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
};