From eb763661c6d6ab7f9392ca214943af14e9ab52e1 Mon Sep 17 00:00:00 2001 From: jhumeau Date: Thu, 17 Dec 2009 15:40:53 +0000 Subject: [PATCH] new fast archive added git-svn-id: svn://scm.gforge.inria.fr/svnroot/paradiseo@1631 331e1502-861f-0410-8da2-ba01fb791d7f --- .../src/archive/moeoArchiveIndex.h | 83 +++++++ .../src/archive/moeoIndexedArchive.h | 111 +++++++++ .../src/{utils => archive}/moeoQuadTree.h | 135 ++++++++-- .../archive/moeoQuickUnboundedArchiveIndex.h | 235 ++++++++++++++++++ trunk/paradiseo-moeo/src/moeo | 7 +- 5 files changed, 544 insertions(+), 27 deletions(-) create mode 100755 trunk/paradiseo-moeo/src/archive/moeoArchiveIndex.h create mode 100755 trunk/paradiseo-moeo/src/archive/moeoIndexedArchive.h rename trunk/paradiseo-moeo/src/{utils => archive}/moeoQuadTree.h (78%) mode change 100644 => 100755 create mode 100755 trunk/paradiseo-moeo/src/archive/moeoQuickUnboundedArchiveIndex.h diff --git a/trunk/paradiseo-moeo/src/archive/moeoArchiveIndex.h b/trunk/paradiseo-moeo/src/archive/moeoArchiveIndex.h new file mode 100755 index 000000000..809530d6e --- /dev/null +++ b/trunk/paradiseo-moeo/src/archive/moeoArchiveIndex.h @@ -0,0 +1,83 @@ +#ifndef MOEOARCHIVEINDEX_H_ +#define MOEOARCHIVEINDEX_H_ + +#include +#include + +/** + * Inteface for Archive Indexes + */ +template < class MOEOT > +class moeoArchiveIndex +{ + + public: + //type of MOEOT Objective vector + typedef typename MOEOT::ObjectiveVector ObjectiveVector; + + /**type for a modification that will have to be applied to the archive + * each item concern one ObjectiveVector, designated by itemObjective + **/ + struct modif{ + public: + //Objective vector of the concerned item + ObjectiveVector itemObjective; + //oldIdx is the index of the item in the vector before the modification (in the archive itself, not in the index) + int oldIdx; + //newIdx is the new index of the item in the vector after the modification (in the archive itself, not in the index) + //-1 if deletion has to occur + int newIdx; + /** + * ctor for a deletion + * @param _obj the objectiveVector of the concerned entry + * @param _oldIdx the current index of the concerned entry in the vector (before deletion) + */ + modif(ObjectiveVector& _obj, int _oldIdx):itemObjective(_obj),oldIdx(_oldIdx),newIdx(-1){} + /** + * ctor for a move + * @param _obj the objectiveVector of the concerned entry + * @param _oldIdx the current index of the concerned entry in the vector (before moving) + * @param _newIdx the index of the concerned entry in the vector after moving + **/ + modif(ObjectiveVector& _obj, int _oldIdx,int _newIdx):itemObjective(_obj),oldIdx(_oldIdx),newIdx(_newIdx){} + }; + + /** + * principal method for the index, add a moeot to the index + * @param _moeot the MOEOT we try to insert + * @param _insert should we really insert the moeot, or just check if we have to + * @return a pair, the first is a boolean indicating if the insertion can occur, the second a vector of modification + **/ + virtual std::pair > operator()(const MOEOT& _moeot, bool _insert=true)=0; + + /* + * method for adding a population of moeot to the the index + * @param _pop the population of MOEOT we try to insert + * @param _insert should we really insert the moeot, or just check if we have to + * @return a pair, the first is how many moeot can be inserted, the second a vector of modification that would have to occur to insert + */ +// virtual std::pair > operator()(const eoPop& _pop, bool _insert=true)=0; + + /** + * when updates will be necessary to keep indexes of archive and index synced, the archive will launch this method + * @param _update the update to do, see modif documentation + * @return false if no problem occured + */ + virtual bool update( modif& _update)=0; + + /** + * creates a modif that move the item ObjectiveVector placed at idx oldIdx in the archive to newIdx, or delete it if newIdx=-1 + * @param _obj the objectiveVector we want to move + * @param _oldIdx the index of the item we want to move in the vector + * @param _newIdx the new index for the item, -1 if we want it deleted + **/ + static modif make_modif(ObjectiveVector &_obj,int _oldIdx,int _newIdx=-1){ + modif res(_obj,_oldIdx,_newIdx); + return res; + } + + + +}; + +#endif /*MOEOARCHIVEINDEX_H_*/ diff --git a/trunk/paradiseo-moeo/src/archive/moeoIndexedArchive.h b/trunk/paradiseo-moeo/src/archive/moeoIndexedArchive.h new file mode 100755 index 000000000..44ea7a4e0 --- /dev/null +++ b/trunk/paradiseo-moeo/src/archive/moeoIndexedArchive.h @@ -0,0 +1,111 @@ +#ifndef MOEOINDEXEDARCHIVE_H_ +#define MOEOINDEXEDARCHIVE_H_ + +#include +#include +#include + +/** + * Archive used for 2 dimension vectors which remove pareto dominated values + * Use an moeoArchiveIndex + */ +template < class MOEOT > +class moeoIndexedArchive : public moeoArchive < MOEOT > +{ + + public: + + + using eoPop < MOEOT > :: size; + using eoPop < MOEOT > :: operator[]; + using eoPop < MOEOT > :: pop_back; + + /** + * The type of an objective vector for a solution + */ + typedef typename MOEOT::ObjectiveVector ObjectiveVector; + + /** + * Default ctor. + * The moeoObjectiveVectorComparator used to compare solutions is based on Pareto dominance + */ + moeoIndexedArchive(moeoArchiveIndex& _index) : index(_index) {} + + + /** + * Updates the archive with a given individual _moeo + * @param _moeo the given individual + */ + bool operator()(const MOEOT & _moeo){ + bool added=false; + std::pair::modif> > res=index(_moeo); + if (!(res.first)){ + return false; + } + else{ + for (unsigned int i=0;i & _pop) + { + bool res=false; + for (unsigned int i=0;i<_pop.size();i++){ + res=operator()(_pop[i])||res; + } + return res; + } + + + + protected: + /** + * apply a modification + * @param _modif the modification to apply + **/ + void apply_modif(typename moeoArchiveIndex::modif &_modif){ + if (_modif.newIdx==-1){ + int oldIdx=size()-1; + (*this)[_modif.oldIdx]=(*this)[size()-1]; + ObjectiveVector obj=(*this)[_modif.oldIdx].objectiveVector(); + typename moeoArchiveIndex::modif upd(obj,oldIdx,_modif.oldIdx); + index.update(upd); + pop_back(); + } + } + + //not used yet... + void apply_modif(std::vector::modif> &_modifs){ + unsigned int num_to_delete=0; + for (unsigned int i=0;i<_modifs.size();i++){ + if (_modifs[i].newIdx==-1){ + num_to_delete++; + int oldIdx=size()-1; + (*this)[_modifs[i].oldIdx]=(*this)[size()-1]; + ObjectiveVector obj=(*this)[_modifs[i].oldIdx].objectiveVector(); + typename moeoArchiveIndex::modif upd(obj,oldIdx,_modifs[i].oldIdx); + index.update(upd); + } + } + for (unsigned int i=0;i &index; + + + +}; + +#endif /*MOEOINDEXEDARCHIVE_H_*/ diff --git a/trunk/paradiseo-moeo/src/utils/moeoQuadTree.h b/trunk/paradiseo-moeo/src/archive/moeoQuadTree.h old mode 100644 new mode 100755 similarity index 78% rename from trunk/paradiseo-moeo/src/utils/moeoQuadTree.h rename to trunk/paradiseo-moeo/src/archive/moeoQuadTree.h index a9f5de39a..358df79fd --- a/trunk/paradiseo-moeo/src/utils/moeoQuadTree.h +++ b/trunk/paradiseo-moeo/src/archive/moeoQuadTree.h @@ -40,10 +40,12 @@ #define MOEOQUADTREE_H_ #include - +#include template < class ObjectiveVector > class QuadTreeNode{ public: + + QuadTreeNode(ObjectiveVector& _objVec):objVec(_objVec),subTree(){} QuadTreeNode(const QuadTreeNode& _source):objVec(_source.objVec),subTree(_source.subTree){} @@ -51,6 +53,8 @@ public: QuadTreeNode& operator=(const QuadTreeNode& _src){ (*this).objVec=_src.objVec; (*this).subTree=subTree; + (*this).inserted=_src.is_inserted(); + if(inserted) (*this).index=_src.get_index(); return *this; } @@ -72,25 +76,42 @@ public: return res; } + + + std::map*>& getSubTree(){ return (*this).subTree; } + void set_index(int idx){ + inserted=true; + index=idx; + } + unsigned int get_index(){ + if (!inserted) std::cerr<<"moeoQuadTree getting index of a non-inserted node"<*> subTree; - - //TODO Ajouter l'index du vecteur + unsigned int index; + bool inserted; }; -template < class ObjectiveVector > -class moeoQuadTree{ +template < class MOEOT > +class moeoQuadTree : public moeoArchiveIndex { + typedef typename MOEOT::ObjectiveVector ObjectiveVector; typedef typename std::map*>::iterator QuadTreeIterator; + typedef typename moeoArchiveIndex::modif modif; public: - moeoQuadTree():root(NULL){ + moeoQuadTree():root(NULL),current_size(0){ bound=pow(2,ObjectiveVector::nObjectives())-1; comparator=new moeoParetoObjectiveVectorComparator(); } @@ -99,24 +120,50 @@ public: delete(comparator); } + /** + * insert a _moeot in the index if it can be inserted + * @param @_moeot the individual ton insert + * @param _insert not used, should be changed... + */ + std::pair > operator()(const MOEOT& _moeot, bool _insert=true){ + std::pair > res; + insert(_moeot.objectiveVector(),res); + if (res.first){ + current_size=current_size+1-res.second.size(); + } + return res; + }; + + /** + * apply the modif + * @param _update the modif to apply (move only) + * @return false if no problem occured + **/ + bool update( modif& _update){ + QuadTreeNode* node=find_node(_update.itemObjective,getRoot()); + if (node==NULL) return true; + node->set_index(_update.newIdx); + return false; + } + /** * @paramm _obj the Objective Vector to insert into the tree. * @return true if it is inserted */ - bool insert(ObjectiveVector& _obj){ - bool res=false; + void insert(ObjectiveVector _obj, std::pair > &res){ //create a new node QuadTreeNode* tmp = new QuadTreeNode(_obj); //if the tree is empty, we have a new root! if(isEmpty()){ root=tmp; - res=true; + tmp->set_index(0); + res.first=true; } //else try to insert the new node in the tree else{ - res = insert_aux(tmp, root, NULL, 0); + res.first = insert_aux(tmp, root, NULL, 0, res.second); + if(res.first) tmp->set_index(size()-1); } - return res; } /** @@ -126,7 +173,7 @@ public: * @param _succ the index of _parent where the _tmproot is linked * @return true if the _newnode is inserted */ - bool insert_aux(QuadTreeNode* _newnode, QuadTreeNode* _tmproot, QuadTreeNode* _parent, unsigned int _succ){ + bool insert_aux(QuadTreeNode* _newnode, QuadTreeNode* _tmproot, QuadTreeNode* _parent, unsigned int _succ, std::vector &modifs){ bool res=false; bool dominated=false; @@ -137,7 +184,7 @@ public: } else if(succ==0){ //_newnode dominates _tmproot - replace(_newnode, _tmproot, _parent, _succ); + replace(_newnode, _tmproot, _parent, _succ, modifs); res=true; } else{ @@ -163,7 +210,7 @@ public: while(it != _tmproot->getSubTree().end()){ if((*it).second != NULL){ if( (succ < (*it).first) && ((succ & (*it).first) == succ)){ - test2(_newnode, (*it).second, _tmproot, (*it).first); + test2(_newnode, (*it).second, _tmproot, (*it).first, modifs); } } it++; @@ -176,7 +223,7 @@ public: } else{ //else if the child is not inserted, insert it in the subtree - res=insert_aux(_newnode, _tmproot->getSubTree()[succ], _tmproot, succ); + res=insert_aux(_newnode, _tmproot->getSubTree()[succ], _tmproot, succ , modifs); } } } @@ -208,13 +255,13 @@ public: * @param _parent the parent of _tmproot * @param _succ the index of _parent where the _tmproot is linked */ - void replace(QuadTreeNode* _newnode, QuadTreeNode* _tmproot, QuadTreeNode* _parent, unsigned int _succ){ + void replace(QuadTreeNode* _newnode, QuadTreeNode* _tmproot, QuadTreeNode* _parent, unsigned int _succ, std::vector & res){ if(!(_tmproot->getSubTree().empty())){ //reconsider each son of the old root QuadTreeIterator it; for(it=(_tmproot->getSubTree()).begin(); it != (_tmproot->getSubTree()).end(); it++){ if((*it).second!=NULL){ - reconsider(_newnode, (*it).second); + reconsider(_newnode, (*it).second, res); } } } @@ -226,6 +273,8 @@ public: _parent->getSubTree()[_succ]=_newnode; } //kill the old root + modif new_modif(_tmproot->getVec(),_tmproot->get_index()); + res.push_back(new_modif); delete(_tmproot); } @@ -233,7 +282,7 @@ public: * @param _newroot the new root * @param _child a node to reconsider regarding tthe _newroot */ - void reconsider(QuadTreeNode* _newroot, QuadTreeNode* _child){ + void reconsider(QuadTreeNode* _newroot, QuadTreeNode* _child, std::vector & res){ unsigned int succ; //reconsider all child of _child if(!(_child->getSubTree().empty())){ @@ -242,14 +291,17 @@ public: if((*it).second != NULL){ QuadTreeNode* tmp=(*it).second; _child->getSubTree()[(*it).first]=NULL; - reconsider(_newroot, tmp); + reconsider(_newroot, tmp, res ); } } } succ=k_succ(_child->getVec(),_newroot->getVec()); //if _child is dominated by the newroot, delete it - if(succ==bound) + if(succ==bound){ + modif new_modif(_child->getVec(),_child->get_index()); + res.push_back(new_modif); delete(_child); + } //else reinsert it in the tree rooted at _newroot else if(_newroot->getSubTree()[succ] != NULL){ reinsert(_newroot->getSubTree()[succ],_child); @@ -295,7 +347,7 @@ public: * @param _parent its parent * @param _succ the index of _parent where the _node is linked */ - void remove(QuadTreeNode* _node, QuadTreeNode* _parent, unsigned int _succ){ + void remove(QuadTreeNode* _node, QuadTreeNode* _parent, unsigned int _succ, std::vector & res){ unsigned int k=1; QuadTreeNode* tmp=NULL; _parent->getSubTree()[_succ]=NULL; @@ -313,6 +365,8 @@ public: } k++; } + modif new_modif(_node->getVec(),_node->get_index()); + res.push_back(new_modif); delete(_node); } @@ -347,21 +401,21 @@ public: * @param _node1 first node * @param _node2 second node */ - void test2(QuadTreeNode* _node1, QuadTreeNode* _node2, QuadTreeNode* _parent, unsigned int _succ){ + void test2(QuadTreeNode* _node1, QuadTreeNode* _node2, QuadTreeNode* _parent, unsigned int _succ, std::vector & res){ unsigned int succ; succ=k_succ(_node1->getVec(), _node2->getVec()); if(succ==0){ - remove(_node2, _parent, _succ); + remove(_node2, _parent, _succ, res); if(_parent->getSubTree()[_succ]!=NULL) - test2(_node1, _parent->getSubTree()[_succ], _parent, _succ); + test2(_node1, _parent->getSubTree()[_succ], _parent, _succ, res); } else{ QuadTreeIterator it=_node2->getSubTree().begin(); while(it != _node2->getSubTree().end()){ if((*it).second!=NULL){ if( (succ & (*it).first) == succ){ - test2(_node1, (*it).second, _node2, (*it).first); + test2(_node1, (*it).second, _node2, (*it).first, res); } } it++; @@ -423,9 +477,37 @@ public: return root; } + /** + * the number of individual currently indexed + * @return the tree size + */ + unsigned int size(){ + return current_size; + } + private: + /** + * to find a node from his objectiveVector + * @param _obj the objective to find + * @param current the node in which we are looking (to be able to recurse) + * @return the node with obj as objectiveVector, or null if it's not found + */ + QuadTreeNode* find_node(ObjectiveVector &_obj, QuadTreeNode* current){ + if (current->getVec()==_obj) return current; + else{ + int succ=k_succ(current->getVec(),_obj); + if(current->getSubTree()[succ]!=NULL) + return find_node(_obj,current->getSubTree()[succ]); + else{ + return NULL; + } + + } + + } + //pointer on the root of the tree QuadTreeNode* root; @@ -435,6 +517,9 @@ private: //Pareto comparator moeoParetoObjectiveVectorComparator* comparator; + //current tree size + int current_size; + }; diff --git a/trunk/paradiseo-moeo/src/archive/moeoQuickUnboundedArchiveIndex.h b/trunk/paradiseo-moeo/src/archive/moeoQuickUnboundedArchiveIndex.h new file mode 100755 index 000000000..a40add6ae --- /dev/null +++ b/trunk/paradiseo-moeo/src/archive/moeoQuickUnboundedArchiveIndex.h @@ -0,0 +1,235 @@ +#ifndef MOEOQUICKUNBOUNDEDARCHIVEINDEX_H_ +#define MOEOQUICKUNBOUNDEDARCHIVEINDEX_H_ + +#include +#include +#include +#include +#include +#include + +/** + * Archive used for 2 dimension vectors which remove pareto dominated values + * the index is ordered following the first objective + */ +template < class MOEOT > +class moeoQuickUnboundedArchiveIndex : public moeoArchiveIndex < MOEOT > +{ + + public: + + + + /** + * The type of an objective vector for a solution + */ + typedef typename MOEOT::ObjectiveVector ObjectiveVector; + typedef typename moeoArchiveIndex::modif modif; +// typedef typename moeoArchiveIndex < MOEOT> :: s_update s_update; + + /** + * Default ctor. Pareto !!!! + * The moeoObjectiveVectorComparator used to compare solutions is based on Pareto dominance + */ + moeoQuickUnboundedArchiveIndex() : index() {} + + /** + * Ctor + * @param _comparator the moeoObjectiveVectorComparator used to compare solutions + */ + //moeoQuickUnboundedArchive(moeoObjectiveVectorComparator < ObjectiveVector > & _comparator) : moeoArchive < MOEOT >(_comparator),index() {} + + /**struct for an entry of the index + * obj is the objective vector of the vector[indice] + */ + struct entree{ + entree(ObjectiveVector _obj, int _indice):obj(_obj),indice(_indice){} + bool operator == (const entree a){ + return obj==a.obj; + } + ObjectiveVector obj; + int indice; + }; + /** + * equivalent to "number one element should be on top of number two element" in the list by looking to the first obj + */ + struct CompareByFirst + : std::binary_function< bool, entree, entree > { + bool operator ()( + const entree& elem1, + const entree& elem2 + ) const { + if (ObjectiveVector::minimizing(0)){ + return elem1.obj[0] > elem2.obj[0]; + } + else{ + return elem1.obj[0] < elem2.obj[0]; + } + } + }cbf; + /** + * equivalent to "number one element should be on top of number two element" in the list by looking to the 2nd obj + */ + struct CompareByLast + : std::binary_function< bool, entree, entree > { + bool operator ()( + const entree& elem1, + const entree& elem2 + ) const { + if (ObjectiveVector::minimizing(1)){ + return elem1.obj[1] < elem2.obj[1]; + } + else{ + return elem1.obj[1] > elem2.obj[1]; + } + } + }cbl; + + + struct CompareByLast2 + : std::binary_function< bool, MOEOT, MOEOT > { + bool operator ()( + const MOEOT& elem1, + const MOEOT& elem2 + ) const { + if (ObjectiveVector::minimizing(1)){ + return elem1.objectiveVector()[1] < elem2.objectiveVector()[1]; + } + else{ + return elem1.objectiveVector()[1] > elem2.objectiveVector()[1]; + } + } + }cbl2; + /** + * type for the index + */ + typedef typename std::set MOEOTIndex; + /** + * iterator from the index + */ + typedef typename std::set::iterator MOEOTIndexIte; + /** + * iterator for gcc stop being annoying + */ + typedef typename std::set::iterator set_ite; + + + + /** + updates the index following a modif + @param _update the modification to apply + @return false + */ + bool update(modif& _update){ + entree oldEnt(_update.itemObjective,_update.oldIdx); + entree newEnt(_update.itemObjective,_update.newIdx); + index.erase(oldEnt); + index.insert(newEnt); + return false; + } + +/* + std::pair > operator()(const eoPop& _pop, bool _insert=true){ + std::cout<<"OH, HI, je fais quelque chose"< > res; + res.first=false; + std::vector tmp; + for (unsigned int i=0;i<_pop.size();i++){ + std::cout<<"once va être créé"< > once=operator()(_pop[i],_insert); + if (once.first){ + std::cout<<"once vrai taille "< > operator()(const MOEOT& _moeo, bool _insert=true){ + return insert(_moeo,_insert); + } + /** + * inserts a _moeo in the index + * @param _moeo the MOEOT to insert + * @param _insert if _insert is false we only ask the index, and dont modify it + * @return a pair composed by a boolean indicating if the moeot can be inserted, and a list of modif to do so + */ + virtual std::pair > insert(const MOEOT& _moeo, bool _insert=true){ +// std::cout<<"entree dans l'algo avec "<<_moeo.objectiveVector()< > res; + std::vector to_er; + res.first=false; + if (index.empty()){ + std::cout<<"empty donc ok"< comparator; + + + +}; + +#endif /*MOEOQUICKUNBOUNDEDARCHIVE_H_*/ diff --git a/trunk/paradiseo-moeo/src/moeo b/trunk/paradiseo-moeo/src/moeo index 7d0683bae..67e087d44 100644 --- a/trunk/paradiseo-moeo/src/moeo +++ b/trunk/paradiseo-moeo/src/moeo @@ -61,14 +61,17 @@ #include +#include #include #include +#include #include #include #include #include //#include -#include +#include +#include #include @@ -84,6 +87,7 @@ #include #include #include +#include #include #include @@ -174,7 +178,6 @@ #include #include #include -#include #include #include #include