model.hh
Go to the documentation of this file.
00001 // METSlib source file - model.hh                                -*- C++ -*-
00002 //
00003 /*
00004  * Software License Agreement (BSD License)
00005  *
00006  *  Copyright (c) 2006-2012, Mirko Maischberger <mirko.maischberger@gmail.com>
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *
00020  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031  *  POSSIBILITY OF SUCH DAMAGE.
00032  *
00033  */
00034 
00035 #ifndef METS_MODEL_HH_
00036 #define METS_MODEL_HH_
00037 
00038 namespace mets {
00039 
00045   typedef double gol_type;
00046 
00049   class no_moves_error 
00050     : public std::runtime_error
00051   {
00052   public:
00053     no_moves_error() 
00054       : std::runtime_error("There are no more available moves.") {}
00055     no_moves_error(const std::string message) 
00056       : std::runtime_error(message) {}
00057   };
00058 
00063   class sequence
00064   {
00065   public:
00067     sequence(int start = 0) 
00068       : value_m(start) 
00069     { }
00072     int operator()() 
00073     { return value_m++; }
00074   protected:
00075     int value_m;
00076   };
00077 
00079   class clonable {
00080   public:
00081     virtual 
00082     ~clonable() {};
00083     virtual clonable* 
00084     clone() const = 0;
00085   };
00086 
00088   class hashable {
00089   public:
00090     virtual 
00091     ~hashable() {};
00092     virtual size_t 
00093     hash() const = 0;
00094   };
00095 
00097   class copyable {
00098   public:
00099     virtual 
00100     ~copyable() {};
00101     virtual void 
00102     copy_from(const copyable&) = 0;
00103   };
00104 
00106   class printable {
00107   public:
00108     virtual 
00109     ~printable() {}
00110     virtual void 
00111     print(std::ostream& /*os*/) const { };
00112   };
00113 
00116 
00134   class feasible_solution
00135   {
00136   public:
00138     virtual
00139     ~feasible_solution() 
00140     { }
00141 
00142   };
00143 
00144 
00155   class evaluable_solution : public feasible_solution, 
00156                              public copyable
00157   { 
00158   public:
00166     virtual gol_type 
00167     cost_function() const = 0;
00168   };
00169 
00182   class permutation_problem: public evaluable_solution 
00183   {
00184   public:
00185     
00187     permutation_problem(); 
00188 
00190     permutation_problem(int n) : pi_m(n), cost_m(0.0)
00191     { std::generate(pi_m.begin(), pi_m.end(), sequence(0)); }
00192 
00198     void copy_from(const copyable& other);
00199 
00203     virtual gol_type
00204     compute_cost() const = 0;
00205 
00217     virtual gol_type
00218     evaluate_swap(int i, int j) const = 0;
00219 
00222     size_t 
00223     size() const
00224     { return pi_m.size(); }
00225 
00230     gol_type cost_function() const 
00231     { return cost_m; }
00232 
00235     void
00236     update_cost() 
00237     { cost_m = compute_cost(); }
00238     
00241     void
00242     apply_swap(int i, int j)
00243     { cost_m += evaluate_swap(i,j); std::swap(pi_m[i], pi_m[j]); }
00244     
00245 
00246   protected:
00247     std::vector<int> pi_m;
00248     gol_type cost_m;
00249     template<typename random_generator> 
00250     friend void random_shuffle(permutation_problem& p, random_generator& rng);
00251   };
00252 
00253 
00257   template<typename random_generator>
00258   void random_shuffle(permutation_problem& p, random_generator& rng)
00259   {
00260 #if defined (METSLIB_TR1_BOOST)
00261     boost::uniform_int<size_t> unigen;
00262     boost::variate_generator<random_generator&,
00263       boost::uniform_int<size_t> >gen(rng, unigen);
00264 #elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
00265     std::uniform_int<size_t> unigen;
00266     std::variate_generator<random_generator&, 
00267       std::uniform_int<size_t> >gen(rng, unigen);
00268 #else
00269     std::tr1::uniform_int<size_t> unigen;
00270     std::tr1::variate_generator<random_generator&, 
00271       std::tr1::uniform_int<size_t> >gen(rng, unigen);
00272 #endif
00273     std::random_shuffle(p.pi_m.begin(), p.pi_m.end(), gen);
00274     p.update_cost();
00275   }
00276   
00280   template<typename random_generator>
00281   void perturbate(permutation_problem& p, unsigned int n, random_generator& rng)
00282   {
00283 #if defined (METSLIB_TR1_BOOST)
00284     boost::uniform_int<> int_range;
00285 #elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
00286     std::uniform_int<> int_range;
00287 #else
00288     std::tr1::uniform_int<> int_range;
00289 #endif
00290     for(unsigned int ii=0; ii!=n;++ii) 
00291       {
00292         int p1 = int_range(rng, p.size());
00293         int p2 = int_range(rng, p.size());
00294         while(p1 == p2) 
00295           p2 = int_range(rng, p.size());
00296         p.apply_swap(p1, p2);
00297       }
00298   }
00299     
00309   class move
00310   {
00311   public:
00312 
00313     virtual 
00314     ~move() 
00315     { }; 
00316 
00324     virtual gol_type
00325     evaluate(const feasible_solution& sol) const = 0;
00326 
00331     virtual void
00332     apply(feasible_solution& sol) const = 0;
00333 
00334 
00335   };
00336 
00351   class mana_move : 
00352     public move, 
00353     public clonable, 
00354     public hashable
00355   {
00356   public:
00357     
00366     virtual mana_move*
00367     opposite_of() const 
00368     { return static_cast<mana_move*>(clone()); }
00369     
00372     virtual bool 
00373     operator==(const mana_move& other) const = 0;
00374     
00375   };
00376 
00377   template<typename rndgen> class swap_neighborhood; // fw decl
00378 
00386   class swap_elements : public mets::mana_move 
00387   {
00388   public:  
00389 
00391     swap_elements(int from, int to) 
00392       : p1(std::min(from,to)), p2(std::max(from,to)) 
00393     { }
00394     
00396     gol_type
00397     evaluate(const mets::feasible_solution& s) const
00398     { const permutation_problem& sol = 
00399         static_cast<const permutation_problem&>(s);
00400       return sol.cost_function() + sol.evaluate_swap(p1, p2); }
00401     
00403     void
00404     apply(mets::feasible_solution& s) const
00405     { permutation_problem& sol = static_cast<permutation_problem&>(s);
00406       sol.apply_swap(p1, p2); }
00407             
00409     clonable* 
00410     clone() const
00411     { return new swap_elements(p1, p2); }
00412 
00415     size_t
00416     hash() const
00417     { return (p1)<<16^(p2); }
00418     
00421     bool 
00422     operator==(const mets::mana_move& o) const;
00423     
00425     void change(int from, int to)
00426     { p1 = std::min(from,to); p2 = std::max(from,to); }
00427 
00428   protected:
00429     int p1; 
00430     int p2; 
00431 
00432     template <typename> 
00433     friend class swap_neighborhood;
00434   };
00435 
00441   class invert_subsequence : public mets::mana_move 
00442   {
00443   public:  
00444 
00446     invert_subsequence(int from, int to) 
00447       : p1(from), p2(to) 
00448     { }
00449     
00451     gol_type
00452     evaluate(const mets::feasible_solution& s) const;
00453 
00455     void
00456     apply(mets::feasible_solution& s) const;
00457         
00458     clonable* 
00459     clone() const
00460     { return new invert_subsequence(p1, p2); }
00461 
00464     size_t
00465     hash() const
00466     { return (p1)<<16^(p2); }
00467     
00470     bool 
00471     operator==(const mets::mana_move& o) const;
00472     
00473     void change(int from, int to)
00474     { p1 = from; p2 = to; }
00475     
00476   protected:
00477     int p1; 
00478     int p2; 
00479     
00480     // template <typename> 
00481     // friend class invert_full_neighborhood;
00482   };
00483 
00507   class move_manager
00508   {
00509   public:
00512     move_manager() 
00513       : moves_m() 
00514     { }
00515 
00517     virtual ~move_manager() 
00518     { }
00519 
00521     virtual void 
00522     refresh(mets::feasible_solution& s) = 0;
00523     
00525     typedef std::deque<move*>::iterator iterator;
00526     
00528     typedef std::deque<move*>::size_type size_type;
00529 
00531     iterator begin() 
00532     { return moves_m.begin(); }
00533 
00535     iterator end() 
00536     { return moves_m.end(); }
00537 
00539     size_type size() const 
00540     { return moves_m.size(); }
00541 
00542   protected:
00543     std::deque<move*> moves_m; 
00544     move_manager(const move_manager&);
00545   };
00546   
00547 
00549 #if defined (METSLIB_TR1_BOOST)
00550   template<typename random_generator = boost::minstd_rand0>
00551 #elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
00552   template<typename random_generator = std::minstd_rand0>
00553 #else
00554   template<typename random_generator = std::tr1::minstd_rand0>
00555 #endif
00556   class swap_neighborhood : public mets::move_manager
00557   {
00558   public:
00568     swap_neighborhood(random_generator& r, 
00569                       unsigned int moves);
00570 
00572     ~swap_neighborhood();
00573 
00575     void refresh(mets::feasible_solution& s);
00576     
00577   protected:
00578     random_generator& rng;
00579 
00580 #if defined (METSLIB_TR1_BOOST)
00581     boost::uniform_int<> int_range;
00582 #elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
00583     std::uniform_int<> int_range;
00584 #else
00585     std::tr1::uniform_int<> int_range;
00586 #endif
00587     unsigned int n;
00588 
00589     void randomize_move(swap_elements& m, unsigned int size);
00590   };
00591 
00592   //________________________________________________________________________
00593   template<typename random_generator>
00594   mets::swap_neighborhood< random_generator
00595                            >::swap_neighborhood(random_generator& r, 
00596                                                 unsigned int moves)
00597                              : mets::move_manager(), rng(r), int_range(0), n(moves)
00598   { 
00599     // n simple moves
00600     for(unsigned int ii = 0; ii != n; ++ii) 
00601       moves_m.push_back(new swap_elements(0,0));
00602   }  
00603   
00604   template<typename random_generator>
00605   mets::swap_neighborhood<random_generator>::~swap_neighborhood()
00606   {
00607     // delete all moves
00608     for(iterator ii = begin(); ii != end(); ++ii)
00609       delete (*ii);
00610   }
00611 
00612   template<typename random_generator>
00613   void
00614   mets::swap_neighborhood<random_generator>::refresh(mets::feasible_solution& s)
00615   {
00616     permutation_problem& sol = dynamic_cast<permutation_problem&>(s);
00617     iterator ii = begin();
00618     
00619     // the first n are simple qap_moveS
00620     for(unsigned int cnt = 0; cnt != n; ++cnt)
00621       {
00622         swap_elements* m = static_cast<swap_elements*>(*ii);
00623         randomize_move(*m, sol.size());
00624         ++ii;
00625       }
00626     
00627   }
00628   
00629   template<typename random_generator>
00630   void
00631   mets::swap_neighborhood<random_generator
00632                           >::randomize_move(swap_elements& m, unsigned int size)
00633   {
00634     int p1 = int_range(rng, size);
00635     int p2 = int_range(rng, size);
00636     while(p1 == p2) 
00637       p2 = int_range(rng, size);
00638     // we are friend, so we know how to handle the nuts&bolts of
00639     // swap_elements
00640     m.p1 = std::min(p1,p2); 
00641     m.p2 = std::max(p1,p2); 
00642   }
00643 
00645   class swap_full_neighborhood : public mets::move_manager
00646   {
00647   public:
00653     swap_full_neighborhood(int size) : move_manager()
00654     {
00655       for(int ii(0); ii!=size-1; ++ii)
00656         for(int jj(ii+1); jj!=size; ++jj)
00657           moves_m.push_back(new swap_elements(ii,jj));
00658     } 
00659 
00661     ~swap_full_neighborhood() { 
00662       for(move_manager::iterator it = moves_m.begin(); 
00663           it != moves_m.end(); ++it)
00664         delete *it;
00665     }
00666     
00668     void refresh(mets::feasible_solution& /*s*/) { }
00669     
00670   };
00671 
00672 
00674   class invert_full_neighborhood : public mets::move_manager
00675   {
00676   public:
00677     invert_full_neighborhood(int size) : move_manager()
00678     {
00679       for(int ii(0); ii!=size; ++ii)
00680         for(int jj(0); jj!=size; ++jj)
00681           if(ii != jj)
00682             moves_m.push_back(new invert_subsequence(ii,jj));
00683     } 
00684 
00686     ~invert_full_neighborhood() { 
00687       for(std::deque<move*>::iterator it = moves_m.begin(); 
00688           it != moves_m.end(); ++it)
00689         delete *it;
00690     }
00691 
00693     void 
00694     refresh(mets::feasible_solution& /*s*/)
00695     { }
00696 
00697   };
00698 
00700 
00702   class mana_move_hash 
00703   {
00704   public:
00705     size_t operator()(mana_move const* mov) const 
00706     {return mov->hash();}
00707   };
00708   
00710   template<typename Tp>
00711   struct dereferenced_equal_to 
00712   {
00713     bool operator()(const Tp l, 
00714                     const Tp r) const 
00715     { return l->operator==(*r); }
00716   };
00717 
00718 }
00719 
00720 //________________________________________________________________________
00721 inline void
00722 mets::permutation_problem::copy_from(const mets::copyable& other)
00723 {
00724   const mets::permutation_problem& o = 
00725     dynamic_cast<const mets::permutation_problem&>(other);
00726   pi_m = o.pi_m;
00727   cost_m = o.cost_m;
00728 }
00729 
00730 //________________________________________________________________________
00731 inline bool
00732 mets::swap_elements::operator==(const mets::mana_move& o) const
00733 {
00734   try {
00735     const mets::swap_elements& other = 
00736       dynamic_cast<const mets::swap_elements&>(o);
00737     return (this->p1 == other.p1 && this->p2 == other.p2);
00738   } catch (std::bad_cast& e) {
00739     return false;
00740   }
00741 }
00742 
00743 //________________________________________________________________________
00744 
00745 inline void
00746 mets::invert_subsequence::apply(mets::feasible_solution& s) const
00747 { 
00748   mets::permutation_problem& sol = 
00749     static_cast<mets::permutation_problem&>(s);
00750   int size = static_cast<int>(sol.size());
00751   int top = p1 < p2 ? (p2-p1+1) : (size+p2-p1+1);
00752   for(int ii(0); ii!=top/2; ++ii)
00753     {
00754       int from = (p1+ii)%size;
00755       int to = (size+p2-ii)%size;
00756       assert(from >= 0 && from < size);
00757       assert(to >= 0 && to < size);
00758       sol.apply_swap(from, to); 
00759     }
00760 }
00761 
00762 inline mets::gol_type
00763 mets::invert_subsequence::evaluate(const mets::feasible_solution& s) const
00764 { 
00765   const mets::permutation_problem& sol = 
00766     static_cast<const mets::permutation_problem&>(s);
00767   int size = static_cast<int>(sol.size());
00768   int top = p1 < p2 ? (p2-p1+1) : (size+p2-p1+1);
00769   mets::gol_type eval = 0.0;
00770   for(int ii(0); ii!=top/2; ++ii)
00771     {
00772       int from = (p1+ii)%size;
00773       int to = (size+p2-ii)%size;
00774       assert(from >= 0 && from < size);
00775       assert(to >= 0 && to < size);
00776       eval += sol.evaluate_swap(from, to); 
00777     }
00778   return eval;
00779 }
00780 
00781 inline bool
00782 mets::invert_subsequence::operator==(const mets::mana_move& o) const
00783 {
00784   try {
00785     const mets::invert_subsequence& other = 
00786       dynamic_cast<const mets::invert_subsequence&>(o);
00787     return (this->p1 == other.p1 && this->p2 == other.p2);
00788   } catch (std::bad_cast& e) {
00789     return false;
00790   }
00791 }
00792 
00793 #endif


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:25:40