Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

simann.h

Go to the documentation of this file.
00001 #ifndef LEMON_SIMANN_H
00002 #define LEMON_SIMANN_H
00003 
00011 
00012 #include <cstdlib>
00013 #include <cmath>
00014 #include <lemon/time_measure.h>
00015 
00016 namespace lemon {
00017 
00020 
00022   class ControllerBase {
00023     friend class SimAnnBase;
00024   public:
00026     SimAnnBase *simann;
00028     virtual void init() {}
00030     virtual void acceptEvent() {}
00034     virtual void improveEvent() {}
00036     virtual void rejectEvent() {}
00038     virtual bool next() = 0;
00040     virtual bool accept() = 0;
00041   };
00042 
00044   class EntityBase {
00045   public:
00049     virtual double mutate() = 0;
00053     virtual void revert() = 0;
00055     virtual EntityBase* clone() = 0;
00057     virtual void randomize() = 0;
00058   };
00059 
00061   class SimAnnBase {
00062   private:
00064     ControllerBase *controller;
00066     double curr_cost;
00068     double best_cost;
00070     double prev_cost;
00072     double prev_prev_cost;
00074     long iter;
00077     long last_impr;
00078   protected:
00080     virtual double mutate() = 0;
00082     virtual void revert() = 0;
00084     virtual void saveAsBest() = 0;
00086     virtual void init() {
00087       controller->init();
00088       curr_cost = prev_cost = prev_prev_cost = best_cost =
00089         std::numeric_limits<double>::infinity();
00090       iter = last_impr = 0;
00091     }
00092   public:
00094     void setController(ControllerBase &_controller) {
00095       controller = &_controller;
00096       controller->simann = this;
00097     }
00099     double getCurrCost() const { return curr_cost; }
00101     double getPrevCost() const { return prev_cost; }
00103     double getBestCost() const { return best_cost; }
00105     long getIter() const { return iter; }
00109     long getLastImpr() const { return last_impr; }
00111     bool step() {
00112       iter++;
00113       prev_prev_cost = prev_cost;
00114       prev_cost = curr_cost;
00115       curr_cost = mutate();
00116       if (controller->accept()) {
00117         controller->acceptEvent();
00118         last_impr = iter;
00119         if (curr_cost < best_cost) {
00120           best_cost = curr_cost;
00121           saveAsBest();
00122           controller->improveEvent();
00123         }
00124       }
00125       else {
00126         revert();
00127         curr_cost = prev_cost;
00128         prev_cost = prev_prev_cost;
00129         controller->rejectEvent();
00130       }
00131       return controller->next();
00132     }
00136     bool step(int n) {
00137       for(; n > 0 && step(); --n) ;
00138       return !n;
00139     }
00141     void run() {
00142       init();
00143       do { } while (step());
00144     }
00145   };
00146 
00148   class SimAnn : public SimAnnBase {
00149   private:
00151     EntityBase *curr_ent;
00153     EntityBase *best_ent;
00155     void init() {
00156       SimAnnBase::init();
00157       if (best_ent) delete best_ent;
00158       best_ent = NULL;
00159       curr_ent->randomize();
00160     }
00161   public:
00163     SimAnn() : curr_ent(NULL), best_ent(NULL) {}
00165     virtual ~SimAnn() {
00166       if (best_ent) delete best_ent;
00167     }
00169     double mutate() {
00170       return curr_ent->mutate();
00171     }
00173     void revert() {
00174       curr_ent->revert();
00175     }
00177     void saveAsBest() { 
00178       if (best_ent) delete best_ent;
00179       best_ent = curr_ent->clone();
00180     }
00182     void setEntity(EntityBase &_ent) {
00183       curr_ent = &_ent;
00184     }
00186     EntityBase* getBestEntity() { return best_ent->clone(); }
00187   };
00188 
00190   class SimpleController : public ControllerBase {
00191   public:
00193     long max_iter;
00196     long max_no_impr;
00198     double temp;
00200     double ann_fact;
00208     SimpleController(long _max_iter = 500000, long _max_no_impr = 20000,
00209     double _temp = 1000.0, double _ann_fact = 0.9999) : max_iter(_max_iter),
00210       max_no_impr(_max_no_impr), temp(_temp), ann_fact(_ann_fact)
00211     {
00212       srand48(time(0));
00213     }
00215     void acceptEvent() {}
00219     void improveEvent() {}
00221     void rejectEvent() {}
00224     bool next() {
00225       temp *= ann_fact;
00226       bool quit = (simann->getIter() > max_iter) ||
00227         (simann->getIter() - simann->getLastImpr() > max_no_impr);
00228       return !quit;
00229     }
00231     bool accept() {
00232       double cost_diff = simann->getPrevCost() - simann->getCurrCost();
00233       return (drand48() <= exp(cost_diff / temp));
00234     }
00235   };
00236 
00250   class AdvancedController : public ControllerBase {
00251   private:
00252     Timer timer;
00254     virtual double threshold(double time) {
00255       return (-1.0) * start_threshold / end_time * time + start_threshold;
00256     }
00257   public:
00258     double alpha;
00259     double beta;
00260     double gamma;
00262     double end_time;
00264     double start_time;
00266     double start_threshold;
00268     double avg_cost;
00270     double temp;
00272     double ann_fact;
00274     double init_ann_fact;
00275     bool warmup;
00283     AdvancedController(double _end_time, double _alpha = 0.2,
00284     double _beta = 0.9, double _gamma = 1.6, double _ann_fact = 0.9999) :
00285     alpha(_alpha), beta(_beta), gamma(_gamma), end_time(_end_time),
00286     ann_fact(_ann_fact), init_ann_fact(_ann_fact), warmup(true)
00287     {
00288       srand48(time(0));
00289     }
00290     void init() {
00291       avg_cost = simann->getCurrCost();
00292     }
00294     void acceptEvent() {
00295       avg_cost = alpha * simann->getCurrCost() + (1.0 - alpha) * avg_cost;
00296       if (warmup) {
00297         static int cnt = 0;
00298         cnt++;
00299         if (cnt >= 100) {
00300           // calculate starting threshold and starting temperature
00301           start_threshold = 5.0 * fabs(simann->getBestCost() - avg_cost);
00302           temp = 10000.0;
00303           warmup = false;
00304           timer.reset();
00305         }
00306       }
00307     }
00309     bool next() {
00310       if (warmup) {
00311         return true;
00312       }
00313       else {
00314         double elapsed_time = timer.getRealTime();
00315         if (fabs(avg_cost - simann->getBestCost()) > threshold(elapsed_time)) {
00316           // decrease the annealing factor
00317           ann_fact *= beta;
00318         }
00319         else {
00320           // increase the temperature
00321           temp *= gamma;
00322           // reset the annealing factor
00323           ann_fact = init_ann_fact;
00324         }
00325         temp *= ann_fact;
00326         return elapsed_time < end_time;
00327       }
00328     }
00330     bool accept() {
00331       if (warmup) {
00332         // we accept eveything during the "warm up" phase
00333         return true;
00334       }
00335       else {
00336         double cost_diff = simann->getPrevCost() - simann->getCurrCost();
00337         if (cost_diff < 0.0) {
00338           return (drand48() <= exp(cost_diff / temp));
00339         }
00340         else {
00341           return true;
00342         }
00343       }
00344     }
00345   };
00346 
00348 
00349 }
00350 
00351 #endif

Generated on Sat Aug 27 14:14:54 2005 for LEMON by  doxygen 1.4.4