src/work/akos/simann.h
author ladanyi
Thu, 04 Nov 2004 21:28:55 +0000
changeset 960 908a1a6f0752
parent 956 0ff924405d21
child 966 5e865c5c8a87
permissions -rw-r--r--
Renamed simann_test.cc to simann_demo.cc.
ladanyi@942
     1
#ifndef LEMON_SIMANN_H
ladanyi@942
     2
#define LEMON_SIMANN_H
ladanyi@918
     3
ladanyi@942
     4
namespace lemon {
ladanyi@918
     5
ladanyi@942
     6
  const double INFTY = 1e24;
ladanyi@918
     7
ladanyi@942
     8
  class SimAnnBase {
ladanyi@918
     9
  public:
ladanyi@942
    10
    class Controller;
ladanyi@942
    11
  private:
ladanyi@942
    12
    Controller *controller;
ladanyi@942
    13
  protected:
ladanyi@942
    14
    double curr_cost;
ladanyi@942
    15
    double prev_cost;
ladanyi@942
    16
    double best_cost;
ladanyi@918
    17
ladanyi@942
    18
    virtual void mutate() = 0;
ladanyi@942
    19
    virtual void revert() = 0;
ladanyi@942
    20
    virtual void saveAsBest() = 0;
ladanyi@942
    21
  public:
ladanyi@942
    22
    SimAnnBase() {
ladanyi@942
    23
      curr_cost = prev_cost = best_cost = INFTY;
ladanyi@942
    24
    }
ladanyi@957
    25
    void setController(Controller &_controller) {
ladanyi@957
    26
      controller = &_controller;
ladanyi@957
    27
      controller->setBase(this);
ladanyi@957
    28
    }
ladanyi@957
    29
    double getCurrCost() { return curr_cost; }
ladanyi@957
    30
    double getPrevCost() { return prev_cost; }
ladanyi@942
    31
    double getBestCost() { return best_cost; }
ladanyi@942
    32
    void run() {
ladanyi@942
    33
      while (controller->next()) {
ladanyi@942
    34
        mutate();
ladanyi@957
    35
        if (controller->accept()) {
ladanyi@942
    36
          controller->acceptEvent();
ladanyi@942
    37
          if (curr_cost < best_cost) {
ladanyi@942
    38
            saveAsBest();
ladanyi@942
    39
            controller->improveEvent();
ladanyi@942
    40
          }
ladanyi@942
    41
        }
ladanyi@942
    42
        else {
ladanyi@942
    43
          revert();
ladanyi@942
    44
          controller->rejectEvent();
ladanyi@942
    45
        }
ladanyi@918
    46
      }
ladanyi@918
    47
    }
ladanyi@918
    48
ladanyi@942
    49
    class Controller {
ladanyi@942
    50
    public:
ladanyi@957
    51
      SimAnnBase *base;
ladanyi@942
    52
      virtual void acceptEvent() {}
ladanyi@942
    53
      virtual void improveEvent() {}
ladanyi@942
    54
      virtual void rejectEvent() {}
ladanyi@957
    55
      virtual void setBase(SimAnnBase *_base) { base = _base; }
ladanyi@942
    56
      virtual bool next() = 0;
ladanyi@957
    57
      virtual bool accept() = 0;
ladanyi@942
    58
    };
ladanyi@942
    59
  };
ladanyi@918
    60
ladanyi@942
    61
  template <typename E>
ladanyi@942
    62
  class SimAnn : public SimAnnBase {
ladanyi@942
    63
  private:
ladanyi@942
    64
    E *curr_ent;
ladanyi@942
    65
    E *best_ent;
ladanyi@942
    66
  public:
ladanyi@957
    67
    SimAnn() : SimAnnBase() {}
ladanyi@957
    68
    void setEntity(E &ent) {
ladanyi@957
    69
      curr_ent = new E(ent);
ladanyi@957
    70
      best_ent = new E(ent);
ladanyi@942
    71
    }
ladanyi@942
    72
    E getBestEntity() { return *best_ent; }
ladanyi@942
    73
    void mutate() {
ladanyi@942
    74
      curr_ent->mutate();
ladanyi@942
    75
    }
ladanyi@942
    76
    void revert() {
ladanyi@942
    77
      curr_ent->revert();
ladanyi@942
    78
    }
ladanyi@942
    79
    void saveAsBest() {
ladanyi@942
    80
      *best_ent = *curr_ent;
ladanyi@942
    81
      best_cost = curr_cost;
ladanyi@942
    82
    }
ladanyi@942
    83
  };
ladanyi@942
    84
ladanyi@956
    85
  class EntitySkeleton {
ladanyi@942
    86
  public:
ladanyi@942
    87
    // returns the new cost
ladanyi@942
    88
    double mutate() { return 0.0; }
ladanyi@942
    89
    // restores the entity to its previous state i.e. reverts the effects of
ladanyi@942
    90
    // the last mutate()
ladanyi@942
    91
    void revert() {}
ladanyi@942
    92
  };
ladanyi@942
    93
ladanyi@956
    94
  class SimpleController : public SimAnnBase::Controller {
ladanyi@956
    95
  public:
ladanyi@956
    96
    long iter, last_impr, max_iter, max_no_impr;
ladanyi@956
    97
    double temp, annealing_factor;
ladanyi@957
    98
    SimpleController() {
ladanyi@956
    99
      iter = last_impr = 0;
ladanyi@956
   100
      max_iter = 500000;
ladanyi@956
   101
      max_no_impr = 20000;
ladanyi@956
   102
      annealing_factor = 0.9999;
ladanyi@956
   103
      temp = 1000;
ladanyi@956
   104
    }
ladanyi@956
   105
    void acceptEvent() {
ladanyi@956
   106
      iter++;
ladanyi@956
   107
    }
ladanyi@956
   108
    void improveEvent() {
ladanyi@956
   109
      last_impr = iter;
ladanyi@956
   110
    }
ladanyi@956
   111
    void rejectEvent() {
ladanyi@956
   112
      iter++;
ladanyi@956
   113
    }
ladanyi@956
   114
    bool next() {
ladanyi@956
   115
      temp *= annealing_factor;
ladanyi@956
   116
      bool quit = (iter > max_iter) || (iter - last_impr > max_no_impr);
ladanyi@956
   117
      return !quit;
ladanyi@956
   118
    }
ladanyi@957
   119
    bool accept() {
ladanyi@957
   120
      return (drand48() <= exp(base->getPrevCost() - base->getCurrCost() / temp));
ladanyi@956
   121
    }
ladanyi@956
   122
  };
ladanyi@956
   123
ladanyi@942
   124
}
ladanyi@918
   125
ladanyi@918
   126
#endif