simulated-annealing.hh
Go to the documentation of this file.
00001 // METSlib source file - simulated-annealing.hh                  -*- C++ -*-
00002 /*
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2006-2012, Mirko Maischberger <mirko.maischberger@gmail.com>
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *
00019  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00027  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00028  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00029  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030  *  POSSIBILITY OF SUCH DAMAGE.
00031  *
00032  */
00033 
00034 #ifndef METS_SIMULATED_ANNEALING_HH_
00035 #define METS_SIMULATED_ANNEALING_HH_
00036 
00037 namespace mets {
00038 
00041 
00049   class abstract_cooling_schedule
00050   {
00051   public:
00053     abstract_cooling_schedule() 
00054     { }
00055 
00057     virtual
00058     ~abstract_cooling_schedule() 
00059     { }
00060 
00066     virtual double
00067     operator()(double temp, feasible_solution& fs) = 0;
00068   };
00069 
00071   template<typename move_manager_type>
00072   class simulated_annealing : public mets::abstract_search<move_manager_type>
00073   {
00074   public:
00075     typedef simulated_annealing<move_manager_type> search_type;
00105     simulated_annealing(evaluable_solution& starting_point,
00106                         solution_recorder& recorder,
00107                         move_manager_type& moveman,
00108                         termination_criteria_chain& tc,
00109                         abstract_cooling_schedule& cs,
00110                         double starting_temp,
00111                         double stop_temp = 1e-7,
00112                         double K = 1.0);
00113     
00115     simulated_annealing(const simulated_annealing&);
00116     simulated_annealing& operator=(const simulated_annealing&);
00117     
00123     virtual void
00124     search()
00125       throw(no_moves_error);
00126 
00127     void setApplyAndEvaluate(bool b) {
00128       apply_and_evaluate = b;
00129     }
00130 
00134     double 
00135     current_temp() const 
00136     { return current_temp_m; }
00137 
00141     const abstract_cooling_schedule& 
00142     cooling_schedule() const
00143     { return cooling_schedule_m; }
00144 
00145   protected:
00146     termination_criteria_chain& termination_criteria_m;
00147     abstract_cooling_schedule& cooling_schedule_m;
00148     double starting_temp_m;
00149     double stop_temp_m;
00150     double current_temp_m;
00151     double K_m;
00152 
00153 #if defined (METSLIB_TR1_BOOST)
00154     boost::uniform_real<double> ureal;
00155     boost::mt19937 rng;
00156     boost::variate_generator< boost::mt19937, boost::uniform_real<double> > gen;
00157 #elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
00158     std::uniform_real<double> ureal;
00159     std::mt19937 rng;
00160     std::variate_generator< std::mt19937, std::uniform_real<double> > gen;
00161 #else
00162     std::tr1::uniform_real<double> ureal;
00163     std::tr1::mt19937 rng;
00164     std::tr1::variate_generator< std::tr1::mt19937, std::tr1::uniform_real<double> > gen;
00165 #endif
00166 
00167     bool apply_and_evaluate;
00168   };
00169     
00171   class exponential_cooling
00172     : public abstract_cooling_schedule
00173   {
00174   public:
00175     exponential_cooling(double alpha = 0.95)
00176       : abstract_cooling_schedule(), factor_m(alpha) 
00177     { if(alpha >= 1) throw std::runtime_error("alpha must be < 1"); }
00178     double
00179     operator()(double temp, feasible_solution& /*fs*/)
00180     { return temp*factor_m; }
00181   protected:
00182     double factor_m;
00183   };
00184 
00186   class linear_cooling
00187     : public abstract_cooling_schedule
00188   {
00189   public:
00190     linear_cooling(double delta = 0.1)
00191       : abstract_cooling_schedule(), decrement_m(delta)
00192     { if(delta <= 0) throw std::runtime_error("delta must be > 0"); }
00193     double
00194     operator()(double temp, feasible_solution& /*fs*/)
00195     { return std::max(0.0, temp-decrement_m); }
00196   protected:
00197     double decrement_m;
00198   };
00199 
00201 }
00202 
00203 template<typename move_manager_t>
00204 mets::simulated_annealing<move_manager_t>::
00205 simulated_annealing(evaluable_solution& working,
00206                     solution_recorder& recorder,
00207                     move_manager_t& moveman,
00208                     termination_criteria_chain& tc,
00209                     abstract_cooling_schedule& cs,
00210                     double starting_temp, 
00211                     double stop_temp,
00212                     double K)
00213   : abstract_search<move_manager_t>(working, recorder, moveman),
00214     termination_criteria_m(tc), cooling_schedule_m(cs),
00215     starting_temp_m(starting_temp), stop_temp_m(stop_temp),
00216     current_temp_m(), K_m(K),
00217     ureal(0.0,1.0), rng(), gen(rng, ureal), apply_and_evaluate(false)
00218 { 
00219 }
00220 
00221 template<typename move_manager_t>
00222 void
00223 mets::simulated_annealing<move_manager_t>::search()
00224   throw(no_moves_error)
00225 {
00226   typedef abstract_search<move_manager_t> base_t;
00227 
00228   current_temp_m = starting_temp_m;
00229   while(!termination_criteria_m(base_t::working_solution_m) 
00230         && current_temp_m > stop_temp_m)
00231     {
00232       gol_type actual_cost = 
00233         static_cast<mets::evaluable_solution&>(base_t::working_solution_m)
00234         .cost_function();
00235       /*gol_type best_cost =
00236         static_cast<mets::evaluable_solution&>(base_t::working_solution_m)
00237         .cost_function();*/
00238 
00239       base_t::moves_m.refresh(base_t::working_solution_m);
00240       for(typename move_manager_t::iterator movit = base_t::moves_m.begin(); 
00241           movit != base_t::moves_m.end(); ++movit)
00242       {
00243         // apply move and record proposed cost function
00244         gol_type cost;
00245         if(apply_and_evaluate) {
00246           cost = (*movit)->apply_and_evaluate(base_t::working_solution_m);
00247         } else {
00248           cost = (*movit)->evaluate(base_t::working_solution_m);
00249         }
00250 
00251         double delta = (static_cast<double>(cost-actual_cost));
00252         if(delta < 0 || gen() < exp(-delta/(K_m*current_temp_m)))
00253         {
00254           // accepted: apply, record, exit for and lower temperature
00255           if(!apply_and_evaluate)
00256             (*movit)->apply(base_t::working_solution_m);
00257 
00258           base_t::current_move_m = movit;
00259           if(base_t::solution_recorder_m.accept(base_t::working_solution_m))
00260           {
00261             base_t::step_m = base_t::IMPROVEMENT_MADE;
00262             this->notify();
00263           }
00264 
00265           base_t::step_m = base_t::MOVE_MADE;
00266           this->notify();
00267           break;
00268         }
00269         else if(apply_and_evaluate)
00270         {
00271           (*movit)->unapply(base_t::working_solution_m);
00272         }
00273       } // end for each move
00274       
00275       current_temp_m = 
00276       cooling_schedule_m(current_temp_m, base_t::working_solution_m);
00277     }
00278 }
00279 #endif


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:33:37