src/work/akos/simann.h
author ladanyi
Thu, 04 Nov 2004 13:32:44 +0000
changeset 956 0ff924405d21
parent 942 75fdd0c6866d
child 957 4dd4eaee28e7
permissions -rw-r--r--
Added the SimpleController class, and removed the first version of SimAnn in favour of the second.
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@942
    25
    void setController(Controller &_controller) { controller = &_controller; }
ladanyi@942
    26
    double getBestCost() { return best_cost; }
ladanyi@942
    27
    void run() {
ladanyi@942
    28
      while (controller->next()) {
ladanyi@942
    29
        mutate();
ladanyi@942
    30
        if (controller->accept(prev_cost - curr_cost)) {
ladanyi@942
    31
          controller->acceptEvent();
ladanyi@942
    32
          if (curr_cost < best_cost) {
ladanyi@942
    33
            saveAsBest();
ladanyi@942
    34
            controller->improveEvent();
ladanyi@942
    35
          }
ladanyi@942
    36
        }
ladanyi@942
    37
        else {
ladanyi@942
    38
          revert();
ladanyi@942
    39
          controller->rejectEvent();
ladanyi@942
    40
        }
ladanyi@918
    41
      }
ladanyi@918
    42
    }
ladanyi@918
    43
ladanyi@942
    44
    class Controller {
ladanyi@942
    45
    public:
ladanyi@942
    46
      virtual void acceptEvent() {}
ladanyi@942
    47
      virtual void improveEvent() {}
ladanyi@942
    48
      virtual void rejectEvent() {}
ladanyi@942
    49
      virtual bool next() = 0;
ladanyi@942
    50
      virtual bool accept(double cost_diff) = 0;
ladanyi@942
    51
    };
ladanyi@942
    52
  };
ladanyi@918
    53
ladanyi@942
    54
  template <typename E>
ladanyi@942
    55
  class SimAnn : public SimAnnBase {
ladanyi@942
    56
  private:
ladanyi@942
    57
    E *curr_ent;
ladanyi@942
    58
    E *best_ent;
ladanyi@942
    59
  public:
ladanyi@942
    60
    SimAnn2() : SimAnnBase() {}
ladanyi@942
    61
    void setEntity(E &Ent) {
ladanyi@942
    62
      curr_ent = new E(Ent);
ladanyi@942
    63
      best_ent = new E(Ent);
ladanyi@942
    64
    }
ladanyi@942
    65
    E getBestEntity() { return *best_ent; }
ladanyi@942
    66
    void mutate() {
ladanyi@942
    67
      curr_ent->mutate();
ladanyi@942
    68
    }
ladanyi@942
    69
    void revert() {
ladanyi@942
    70
      curr_ent->revert();
ladanyi@942
    71
    }
ladanyi@942
    72
    void saveAsBest() {
ladanyi@942
    73
      *best_ent = *curr_ent;
ladanyi@942
    74
      best_cost = curr_cost;
ladanyi@942
    75
    }
ladanyi@942
    76
  };
ladanyi@942
    77
ladanyi@956
    78
  class EntitySkeleton {
ladanyi@942
    79
  public:
ladanyi@942
    80
    // returns the new cost
ladanyi@942
    81
    double mutate() { return 0.0; }
ladanyi@942
    82
    // restores the entity to its previous state i.e. reverts the effects of
ladanyi@942
    83
    // the last mutate()
ladanyi@942
    84
    void revert() {}
ladanyi@942
    85
  };
ladanyi@942
    86
ladanyi@956
    87
  class SimpleController : public SimAnnBase::Controller {
ladanyi@956
    88
  public:
ladanyi@956
    89
    long iter, last_impr, max_iter, max_no_impr;
ladanyi@956
    90
    double temp, annealing_factor;
ladanyi@956
    91
    MyController() {
ladanyi@956
    92
      iter = last_impr = 0;
ladanyi@956
    93
      max_iter = 500000;
ladanyi@956
    94
      max_no_impr = 20000;
ladanyi@956
    95
      annealing_factor = 0.9999;
ladanyi@956
    96
      temp = 1000;
ladanyi@956
    97
    }
ladanyi@956
    98
    void acceptEvent() {
ladanyi@956
    99
      iter++;
ladanyi@956
   100
    }
ladanyi@956
   101
    void improveEvent() {
ladanyi@956
   102
      last_impr = iter;
ladanyi@956
   103
    }
ladanyi@956
   104
    void rejectEvent() {
ladanyi@956
   105
      iter++;
ladanyi@956
   106
    }
ladanyi@956
   107
    bool next() {
ladanyi@956
   108
      temp *= annealing_factor;
ladanyi@956
   109
      bool quit = (iter > max_iter) || (iter - last_impr > max_no_impr);
ladanyi@956
   110
      return !quit;
ladanyi@956
   111
    }
ladanyi@956
   112
    bool accept(double cost_diff) {
ladanyi@956
   113
      return (drand48() <= exp(cost_diff / temp));
ladanyi@956
   114
    }
ladanyi@956
   115
  };
ladanyi@956
   116
ladanyi@942
   117
}
ladanyi@918
   118
ladanyi@918
   119
#endif