10 const double INFTY = 1e24;
16 Controller *controller;
22 virtual void mutate() = 0;
23 virtual void revert() = 0;
24 virtual void saveAsBest() = 0;
27 curr_cost = prev_cost = best_cost = INFTY;
29 void setController(Controller &_controller) {
30 controller = &_controller;
31 controller->setBase(this);
33 double getCurrCost() { return curr_cost; }
34 double getPrevCost() { return prev_cost; }
35 double getBestCost() { return best_cost; }
38 while (controller->next()) {
40 if (controller->accept()) {
41 controller->acceptEvent();
42 if (curr_cost < best_cost) {
44 controller->improveEvent();
49 controller->rejectEvent();
54 /*! \brief A base class for controllers. */
58 virtual void init() {}
59 /*! \brief This is called when a neighbouring state gets accepted. */
60 virtual void acceptEvent() {}
61 /*! \brief This is called when the accepted neighbouring state's cost is
62 * less than the best found one's.
64 virtual void improveEvent() {}
65 /*! \brief This is called when a neighbouring state gets rejected. */
66 virtual void rejectEvent() {}
67 virtual void setBase(SimAnnBase *_base) { base = _base; }
69 virtual bool next() = 0;
71 virtual bool accept() = 0;
76 class SimAnn : public SimAnnBase {
81 SimAnn() : SimAnnBase() {}
82 void setEntity(E &ent) {
83 curr_ent = new E(ent);
84 best_ent = new E(ent);
86 E getBestEntity() { return *best_ent; }
94 *best_ent = *curr_ent;
95 best_cost = curr_cost;
99 class EntitySkeleton {
101 /*! \brief Makes a minor change to the entity.
102 * \return the new cost
104 double mutate() { return 0.0; }
105 /*! \brief Restores the entity to its previous state i.e. reverts the
106 * effects of the last mutate.
111 /*! \brief A simple controller for the simulated annealing class.
112 * \todo Find a way to set the various parameters.
114 class SimpleController : public SimAnnBase::Controller {
116 long iter, last_impr, max_iter, max_no_impr;
117 double temp, ann_fact;
118 /*! \param _max_iter maximum number of iterations
119 * \param _max_no_impr maximum number of consecutive iterations which do
120 * not yield a better solution
121 * \param _temp initial temperature
122 * \param _ann_fact annealing factor
124 SimpleController(long _max_iter = 500000, long _max_no_impr = 20000,
125 double _temp = 1000, double _ann_fact = 0.9999) : iter(0), last_impr(0),
126 max_iter(_max_iter), max_no_impr(_max_no_impr), temp(_temp),
127 ann_fact(_ann_fact) {}
131 void improveEvent() {
139 bool quit = (iter > max_iter) || (iter - last_impr > max_no_impr);
143 return (drand48() <= exp(base->getPrevCost() - base->getCurrCost() /
148 /*! \brief A controller with preset running time for the simulated annealing
150 * \todo Find a better name.
152 class AdvancedController : public SimAnnBase::Controller {
154 /*! \param time the elapsed time in seconds */
155 double threshold(double time) { return 0.0; }
157 double alpha, beta, gamma;
158 double end_time, start_time;
160 double temp, ann_fact;
161 /*! \param _end_time running_time
162 * \param _alpha parameter used to calculate the running average
163 * \param _beta parameter used to decrease the annealing factor
164 * \param _gamma parameter used to increase the temperature
166 AdvancedController(double _end_time, double _alpha = 0.2,
167 double _beta = 0.9, double _gamma = 1.2) : alpha(_alpha), beta(_beta),
168 gamma(_gamma), end_time(_end_time) {}
171 gettimeofday(&tv, 0);
172 start_time = tv.tv_sec + double(tv.tv_usec) / 1e6;
175 avg_cost = alpha * base->getCurrCost() + (1.0 - alpha) * avg_cost;
177 void improveEvent() {
183 gettimeofday(&tv, 0);
184 double elapsed_time = tv.tv_sec + double(tv.tv_usec) / 1e6 - start_time;
185 if (fabs(avg_cost - base->getBestCost()) > threshold(elapsed_time)) {
186 // decrease the annealing factor
190 // increase the temperature
194 return elapsed_time < end_time;
197 return (drand48() <= exp(base->getPrevCost() - base->getCurrCost() /