'make doc' is now working also in case of external build.
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_SIMANN_H
20 #define LEMON_SIMANN_H
22 /// \ingroup experimental
24 /// \brief Simulated annealing framework.
26 /// \todo A test and some demo should be added
27 /// \todo Doc should be improved
28 /// \author Akos Ladanyi
33 #include <lemon/time_measure.h>
36 #include <lemon/bits/mingw32_rand.h>
41 /// \addtogroup experimental
46 /// \brief A base class for controllers.
47 class ControllerBase {
49 friend class SimAnnBase;
50 /// \brief Pointer to the simulated annealing base class.
52 /// \brief Initializes the controller.
53 virtual void init() {}
54 /// \brief This is called by the simulated annealing class when a
55 /// neighbouring state gets accepted.
56 virtual void acceptEvent() {}
57 /// \brief This is called by the simulated annealing class when the
58 /// accepted neighbouring state's cost is less than the best found one's.
59 virtual void improveEvent() {}
60 /// \brief This is called by the simulated annealing class when a
61 /// neighbouring state gets rejected.
62 virtual void rejectEvent() {}
63 /// \brief Decides whether to continue the annealing process or not.
64 virtual bool next() = 0;
65 /// \brief Decides whether to accept the current solution or not.
66 virtual bool accept() = 0;
67 /// \brief Destructor.
68 virtual ~ControllerBase() {}
71 /// \brief Skeleton of an entity class.
74 /// \brief Makes a minor change to the entity.
75 /// \return the new cost
76 virtual double mutate() = 0;
77 /// \brief Restores the entity to its previous state i.e. reverts the
78 /// effects of the last mutate().
79 virtual void revert() = 0;
80 /// \brief Makes a copy of the entity.
81 virtual EntityBase* clone() = 0;
82 /// \brief Makes a major change to the entity.
83 virtual void randomize() = 0;
84 /// \brief Destructor.
85 virtual ~EntityBase() {}
88 /// \brief Simulated annealing abstract base class.
89 /// Can be used to derive a custom simulated annealing class if \ref SimAnn
90 /// doesn't fit your needs.
93 /// \brief Pointer to the controller.
94 ControllerBase *controller;
95 /// \brief Cost of the current solution.
97 /// \brief Cost of the best solution.
99 /// \brief Cost of the previous solution.
101 /// \brief Cost of the solution preceding the previous one.
102 double prev_prev_cost;
103 /// \brief Number of iterations.
105 /// \brief Number of iterations which did not improve the solution since
106 /// the last improvement.
109 /// \brief Step to a neighbouring state.
110 virtual double mutate() = 0;
111 /// \brief Reverts the last mutate().
112 virtual void revert() = 0;
113 /// \brief Saves the current solution as the best one.
114 virtual void saveAsBest() = 0;
115 /// \brief Does initializations before each run.
116 virtual void init() {
118 curr_cost = prev_cost = prev_prev_cost = best_cost =
119 std::numeric_limits<double>::infinity();
120 iter = last_impr = 0;
123 /// \brief Sets the controller class to use.
124 void setController(ControllerBase &_controller) {
125 controller = &_controller;
126 controller->simann = this;
128 /// \brief Returns the cost of the current solution.
129 double getCurrCost() const { return curr_cost; }
130 /// \brief Returns the cost of the previous solution.
131 double getPrevCost() const { return prev_cost; }
132 /// \brief Returns the cost of the best solution.
133 double getBestCost() const { return best_cost; }
134 /// \brief Returns the number of iterations done.
135 long getIter() const { return iter; }
136 /// \brief Returns the ordinal number of the last iteration when the
137 /// solution was improved.
138 long getLastImpr() const { return last_impr; }
139 /// \brief Performs one iteration.
142 prev_prev_cost = prev_cost;
143 prev_cost = curr_cost;
144 curr_cost = mutate();
145 if (controller->accept()) {
146 controller->acceptEvent();
148 if (curr_cost < best_cost) {
149 best_cost = curr_cost;
151 controller->improveEvent();
156 curr_cost = prev_cost;
157 prev_cost = prev_prev_cost;
158 controller->rejectEvent();
160 return controller->next();
162 /// \brief Performs a given number of iterations.
163 /// \param n the number of iterations
165 for(; n > 0 && step(); --n) ;
168 /// \brief Starts the annealing process.
171 do { } while (step());
173 /// \brief Destructor.
174 virtual ~SimAnnBase() {}
177 /// \brief Simulated annealing class.
178 class SimAnn : public SimAnnBase {
180 /// \brief Pointer to the current entity.
181 EntityBase *curr_ent;
182 /// \brief Pointer to the best entity.
183 EntityBase *best_ent;
184 /// \brief Does initializations before each run.
187 if (best_ent) delete best_ent;
189 curr_ent->randomize();
192 /// \brief Constructor.
193 SimAnn() : curr_ent(NULL), best_ent(NULL) {}
194 /// \brief Destructor.
196 if (best_ent) delete best_ent;
198 /// \brief Step to a neighbouring state.
200 return curr_ent->mutate();
202 /// \brief Reverts the last mutate().
206 /// \brief Saves the current solution as the best one.
208 if (best_ent) delete best_ent;
209 best_ent = curr_ent->clone();
211 /// \brief Sets the current entity.
212 void setEntity(EntityBase &_ent) {
215 /// \brief Returns a copy of the best found entity.
216 EntityBase* getBestEntity() { return best_ent->clone(); }
219 /// \brief A simple controller for the simulated annealing class.
220 /// This controller starts from a given initial temperature and evenly
222 class SimpleController : public ControllerBase {
224 /// \brief Maximum number of iterations.
226 /// \brief Maximum number of iterations which do not improve the
229 /// \brief Temperature.
231 /// \brief Annealing factor.
233 /// \brief Constructor.
234 /// \param _max_iter maximum number of iterations
235 /// \param _max_no_impr maximum number of consecutive iterations which do
236 /// not yield a better solution
237 /// \param _temp initial temperature
238 /// \param _ann_fact annealing factor
240 SimpleController(long _max_iter = 500000, long _max_no_impr = 20000,
241 double _temp = 1000.0, double _ann_fact = 0.9999) : max_iter(_max_iter),
242 max_no_impr(_max_no_impr), temp(_temp), ann_fact(_ann_fact)
246 /// \brief This is called when a neighbouring state gets accepted.
247 void acceptEvent() {}
248 /// \brief This is called when the accepted neighbouring state's cost is
249 /// less than the best found one's.
250 void improveEvent() {}
251 /// \brief This is called when a neighbouring state gets rejected.
252 void rejectEvent() {}
253 /// \brief Decides whether to continue the annealing process or not. Also
254 /// decreases the temperature.
257 bool quit = (simann->getIter() > max_iter) ||
258 (simann->getIter() - simann->getLastImpr() > max_no_impr);
261 /// \brief Decides whether to accept the current solution or not.
263 double cost_diff = simann->getCurrCost() - simann->getPrevCost();
264 return (drand48() <= exp(-(cost_diff / temp)));
266 /// \brief Destructor.
267 virtual ~SimpleController() {}
270 /// \brief A controller with preset running time for the simulated annealing
272 /// With this controller you can set the running time of the annealing
273 /// process in advance. It works the following way: the controller measures
274 /// a kind of divergence. The divergence is the difference of the average
275 /// cost of the recently found solutions the cost of the best found one. In
276 /// case this divergence is greater than a given threshold, then we decrease
277 /// the annealing factor, that is we cool the system faster. In case the
278 /// divergence is lower than the threshold, then we increase the temperature.
279 /// The threshold is a function of the elapsed time which reaches zero at the
280 /// desired end time.
281 class AdvancedController : public ControllerBase {
283 /// \brief Timer class to measure the elapsed time.
285 /// \brief Calculates the threshold value.
286 /// \param time the elapsed time in seconds
287 virtual double threshold(double time) {
288 return (-1.0) * start_threshold / end_time * time + start_threshold;
290 /// \brief Parameter used to calculate the running average.
292 /// \brief Parameter used to decrease the annealing factor.
294 /// \brief Parameter used to increase the temperature.
296 /// \brief The time at the end of the algorithm.
298 /// \brief The time at the start of the algorithm.
300 /// \brief Starting threshold.
301 double start_threshold;
302 /// \brief Average cost of recent solutions.
304 /// \brief Temperature.
306 /// \brief Annealing factor.
308 /// \brief Initial annealing factor.
309 double init_ann_fact;
310 /// \brief True when the annealing process has been started.
313 /// \brief Constructor.
314 /// \param _end_time running time in seconds
315 /// \param _alpha parameter used to calculate the running average
316 /// \param _beta parameter used to decrease the annealing factor
317 /// \param _gamma parameter used to increase the temperature
318 /// \param _ann_fact initial annealing factor
319 AdvancedController(double _end_time, double _alpha = 0.2,
320 double _beta = 0.9, double _gamma = 1.6, double _ann_fact = 0.9999) :
321 alpha(_alpha), beta(_beta), gamma(_gamma), end_time(_end_time),
322 ann_fact(_ann_fact), init_ann_fact(_ann_fact), start(false)
326 /// \brief Does initializations before each run.
328 avg_cost = simann->getCurrCost();
330 /// \brief This is called when a neighbouring state gets accepted.
332 avg_cost = alpha * simann->getCurrCost() + (1.0 - alpha) * avg_cost;
337 // calculate starting threshold and starting temperature
338 start_threshold = 5.0 * fabs(simann->getBestCost() - avg_cost);
345 /// \brief Decides whether to continue the annealing process or not.
351 double elapsed_time = timer.realTime();
352 if (fabs(avg_cost - simann->getBestCost()) > threshold(elapsed_time)) {
353 // decrease the annealing factor
357 // increase the temperature
359 // reset the annealing factor
360 ann_fact = init_ann_fact;
363 return elapsed_time < end_time;
366 /// \brief Decides whether to accept the current solution or not.
372 double cost_diff = simann->getCurrCost() - simann->getPrevCost();
373 return (drand48() <= exp(-(cost_diff / temp)));
376 /// \brief Destructor.
377 virtual ~AdvancedController() {}