This repository has been archived on 2026-03-28. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
eodev/edo/src/edoRepairerDispatcher.h

183 lines
6.4 KiB
C++

/*
The Evolving Distribution Objects framework (EDO) is a template-based,
ANSI-C++ evolutionary computation library which helps you to write your
own estimation of distribution algorithms.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2011 Thales group
*/
/*
Authors:
Johann Dréo <johann.dreo@thalesgroup.com>
Pierre Savéant <pierre.saveant@thalesgroup.com>
*/
#ifndef _edoRepairerDispatcher_h
#define _edoRepairerDispatcher_h
#include <vector>
#include <utility>
#include "edoRepairer.h"
/** Repair a candidate solution by sequentially applying several repairers on
* subparts of the solution (subparts being defined by the corresponding set
* of indexes).
*
* Only work on EOT that implements the "push_back( EOT::AtomType )" and
* "operator[](uint)" and "at(uint)" methods (i.e. random access containers).
*
* Expects _addresses_ of the repairer operators.
*
* Use the second template type if you want a different container to store
* indexes. You can use any iterable. For example, you may want to use a set if
* you need to be sure that indexes are use only once:
* edoRepairerDispatcher<EOT, std::set<unsigned int> > rpd;
* std::set<unsigned int> idx(1,1);
* idx.insert(2);
* rpd.add( idx, &repairer );
*
* A diagram trying to visually explain how it works:
\ditaa
|
/-\ | /------------\
| +---|---+ Dispatcher |
| | v | |
| |+-----+| --------------------------------+
| || x_0 || +-+-+-+ | +------------\ | /-\
| |+-----+| |2|3|5+*----*-* Repairer A +---|---+ |
| || x_1 || +-+-+-+ | | | | v | |
| |+-----+| | | | |+-----+| |
| || x_2 || | | | || x_2 || |
| |+-----+| | | | |+-----+| |
| || x_3 || | | | || x_3 || |
| |+-----+| | | | |+-----+| |
| || x_4 || | | | || x_5 || |
| |+-----+| | | | |+-----+| |
| || x_5 || | | | | | | |
| |+-----+| | | | +---|---+ |
| || x_6 || | | \------------/ | \-/
| |+-----+| <-------------------------------+
| || x_7 || | |
| |+-----+| +-+-+ | |
| || x_8 || |2|3+*------+
| |+-----+| +-+-+ |
| || x_9 || |
| |+-----+| +-+-+ | +------------\ /-\
| | | | |1|5+*--------* Repairer B +-------+ |
| | | | +-+-+ | | | | |
| | | | | | | | |
| | | | | | +-------+ |
| +---|---+ | \------------/ \-/
\-/ | \------------/
v
\endditaa
* @example t-dispatcher-round.cpp
*
* @ingroup Repairers
*/
template < typename EOT, typename ICT = std::vector<unsigned int> >
class edoRepairerDispatcher
: public edoRepairer<EOT>,
std::vector<
std::pair< ICT, edoRepairer< EOT >* >
>
{
public:
//! Empty constructor
edoRepairerDispatcher() :
std::vector<
std::pair< std::vector< unsigned int >, edoRepairer< EOT >* >
>()
{}
//! Constructor with a single index set and repairer operator
edoRepairerDispatcher( ICT idx, edoRepairer<EOT>* op ) :
std::vector<
std::pair< std::vector< unsigned int >, edoRepairer< EOT >* >
>()
{
this->add( idx, op );
}
//! Add more indexes set and their corresponding repairer operator address to the list
void add( ICT idx, edoRepairer<EOT>* op )
{
//assert( idx.size() > 0 );
#ifndef NDEBUG
eo::log << eo::warnings << "A repairer is added to the dispatcher while having an empty index list, nothing will be repaired" << std::endl;
#endif
assert( op != NULL );
this->push_back( std::make_pair(idx, op) );
}
//! Repair a solution by calling several repair operator on subset of indexes
virtual void operator()( EOT& sol )
{
// std::cout << "in dispatcher, sol = " << sol << std::endl;
// iterate over { indexe, repairer }
// ipair is an iterator that points on a pair of <indexes,repairer>
for( typename edoRepairerDispatcher<EOT>::iterator ipair = this->begin(); ipair != this->end(); ++ipair ) {
assert( ipair->first.size() <= sol.size() ); // assert there is less indexes than items in the whole solution
// a partial copy of the sol
EOT partsol;
// std::cout << "\tusing indexes = ";
//
// iterate over indexes
// j is an iterator that points on an uint
for( std::vector< unsigned int >::iterator j = ipair->first.begin(); j != ipair->first.end(); ++j ) {
// std::cout << *j << " ";
// std::cout.flush();
partsol.push_back( sol.at(*j) );
} // for j
// std::cout << std::endl;
// std::cout << "\tpartial sol = " << partsol << std::endl;
if( partsol.size() == 0 ) {
continue;
}
assert( partsol.size() > 0 );
// apply the repairer on the partial copy
// the repairer is a functor, thus second is callable
(*(ipair->second))( partsol );
{ // copy back the repaired partial solution to sol
// browse partsol with uint k, and the idx set with an iterator (std::vector is an associative tab)
unsigned int k=0;
for( std::vector< unsigned int >::iterator j = ipair->first.begin(); j != ipair->first.end(); ++j ) {
sol[ *j ] = partsol[ k ];
k++;
} // for j
} // context for k
} // for ipair
sol.invalidate();
}
};
#endif // !_edoRepairerDispatcher_h