/home/docs/checkouts/readthedocs.org/user_builds/ratpac/checkouts/latest/src/util/include/RAT/SimulatedAnnealing.hh Source File

Ratpac-two: /home/docs/checkouts/readthedocs.org/user_builds/ratpac/checkouts/latest/src/util/include/RAT/SimulatedAnnealing.hh Source File
Ratpac-two
SimulatedAnnealing.hh
1 #ifndef __RAT_SimulatedAnnealing__
2 #define __RAT_SimulatedAnnealing__
3 
4 #include <TRandom.h>
5 
6 #include <RAT/Log.hh>
7 #include <cfloat>
8 #include <cmath>
9 #include <iostream>
10 #include <vector>
11 
12 namespace RAT {
13 
14 class Minimizable {
15  public:
16  virtual double operator()(double *args) = 0;
17 };
18 
19 template <int D>
21  protected:
22  double temp;
23 
24  Minimizable *funk;
25 
26  double simplex[D + 1][D], val[D + 1];
27  double global_best_pt[D], global_best_val;
28 
29  public:
30  SimulatedAnnealing(Minimizable *funk_) : funk(funk_) {}
31 
32  ~SimulatedAnnealing() {}
33 
34  void SetSimplexPoint(size_t pt, std::vector<double> &point) {
35  for (size_t j = 0; j < D; j++) {
36  simplex[pt][j] = point[j];
37  }
38  val[pt] = (*funk)(simplex[pt]);
39  }
40 
41  void Anneal(double temp0, size_t nAnneal, size_t nEval, double alpha) {
42  global_best_val = DBL_MAX;
43  for (size_t cycle = 0; cycle < nAnneal; cycle++) {
44  temp = temp0 * pow(1 - (double)cycle / nAnneal, alpha);
45  int iter = nEval;
46  amoeba(&iter);
47  }
48  }
49 
50  void GetBestPoint(std::vector<double> &point) {
51  for (size_t j = 0; j < D; j++) {
52  point[j] = global_best_pt[j];
53  }
54  }
55 
56  protected:
57  inline double replace_project(const double (&offset)[D], const double (&by)[D], const double factor,
58  double (&into)[D]) {
59  for (size_t j = 0; j < D; j++) {
60  into[j] = offset[j] + factor * by[j];
61  }
62  double val_try = (*funk)(into);
63  if (val_try < global_best_val) {
64  global_best_val = val_try;
65  for (size_t j = 0; j < D; j++) {
66  global_best_pt[j] = into[j];
67  }
68  }
69  return val_try;
70  }
71 
72  void amoeba(int *iter) {
73  // best, worst, and next worst points
74  size_t i_best, i_worst, i_nextworst;
75  double val_best, val_worst, val_nextworst;
76 
77  const double alpha = 1.0;
78  const double gamma = 2.0;
79  const double rho = -0.5;
80  const double sigma = 0.5;
81 
82  double centroid[D]; // centroid of all but worst
83  double dworst[D]; // vector from worst to centroid
84  double try_pt[D]; // temporary vector for test point
85 
86  // info << "*******************************" << newline;
87 
88  for (; *iter > 0;) {
89  // find best, worst, nextworst (can optomize a lot of this later)
90  i_best = i_worst = i_nextworst = -1;
91  val_best = DBL_MAX, val_worst = val_nextworst = -DBL_MAX;
92  for (size_t i = 0; i <= D; i++) {
93  const double val_thermal = val[i] - temp * log(gRandom->Rndm());
94  // info << val[i] << ' ';
95  if (val_thermal < val_best) {
96  i_best = i;
97  val_best = val_thermal;
98  }
99  if (val_thermal > val_worst) {
100  i_nextworst = i_worst;
101  val_nextworst = val_worst;
102  i_worst = i;
103  val_worst = val_thermal;
104  } else if (val_thermal > val_nextworst) {
105  i_nextworst = i;
106  val_nextworst = val_thermal;
107  }
108  }
109  // info << "~ " << i_best << '/' << i_nextworst << '/' << i_worst <<
110  // " & "; info << val_best << '/' << val_nextworst << '/' <<
111  // val_worst << newline;
112 
113  // update centroid, dworst
114  for (size_t j = 0; j < D; j++) {
115  centroid[j] = 0.0;
116  for (size_t i = 0; i <= D; i++) {
117  if (i == i_worst) continue;
118  centroid[j] += simplex[i][j];
119  }
120  centroid[j] /= D;
121  dworst[j] = centroid[j] - simplex[i_worst][j];
122  }
123 
124  // info << "+++++++++++" << newline;
125  // definitely replacing the worst point, try with reflecting
126  val[i_worst] = replace_project(centroid, dworst, alpha, simplex[i_worst]);
127  const double val_ref_therm = val[i_worst] + temp * log(gRandom->Rndm());
128  // info << "\tRef: " << val_ref_therm << newline;
129  (*iter)--;
130  if (val_ref_therm < val_nextworst && val_ref_therm >= val_best) {
131  // reflected point was better than the two worst and replaced
132  // the worst point, so continue
133  // info << "reflected (okay)" << newline;
134  continue;
135  } else if (val_ref_therm < val_best) {
136  // reflecting was really good, try further
137  const double val_try = replace_project(centroid, dworst, gamma, try_pt);
138  // info << "\tExp: " << val_try << newline;
139  if (val_try + temp * log(gRandom->Rndm()) < val_ref_therm) {
140  // further is better, replace
141  for (size_t j = 0; j < D; j++) {
142  simplex[i_worst][j] = try_pt[j];
143  }
144  val[i_worst] = val_try;
145  // info << "expanded" << newline;
146  } else {
147  // info << "reflected (best)" << newline;
148  }
149  (*iter)--;
150  } else {
151  // reflection didn't work so well, try contracting
152  const double val_con = replace_project(centroid, dworst, rho, simplex[i_worst]);
153  val[i_worst] = val_con;
154  // info << "\tCon: " << val_con << newline;
155  if (val_con + temp * log(gRandom->Rndm()) >= val_worst) {
156  // contracting didn't replace worst
157  // we're near the minimum, so shrink towards best
158  for (size_t i = 0; i <= D; i++) {
159  if (i == i_best) continue;
160  for (size_t j = 0; j < D; j++) {
161  simplex[i][j] = (1.0 - sigma) * simplex[i_best][j] + sigma * simplex[i][j];
162  }
163  val[i] = (*funk)(simplex[i]);
164  // info << "\tShr: " << val[i] << newline;
165  }
166  // info << "shrink" << newline;
167  } else {
168  // info << "contracted" << newline;
169  }
170  (*iter)--;
171  }
172  }
173  }
174 };
175 
176 } // namespace RAT
177 
178 #endif
Definition: SimulatedAnnealing.hh:14
Definition: SimulatedAnnealing.hh:20
Definition: CCCrossSecMessenger.hh:29