Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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& )
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& )
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
00236
00237
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
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
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 }
00274
00275 current_temp_m =
00276 cooling_schedule_m(current_temp_m, base_t::working_solution_m);
00277 }
00278 }
00279 #endif