Rivet  3.1.0
MendelMin.hh
1 #ifndef RIVET_MendelMin_H
2 #define RIVET_MendelMin_H
3 
4 #include "Rivet/Tools/Random.hh"
5 #include <valarray>
6 #include <random>
7 #include <functional>
8 #include <map>
9 #include <vector>
10 #include <cmath>
11 #include <iostream>
12 #include <iomanip>
13 
14 namespace Rivet {
15 
16  using std::valarray;
17 
18 
24  class MendelMin {
25  public:
26 
28  using Params = std::valarray<double>;
30  using FuncT = std::function<double(const Params&, const Params&)>;
32  using FuncNoFixedT = std::function<double(const Params&)>;
33  // /// Typedef for the [0,1] random number generator
34  // using RndT = std::function<double()>;
35 
36 
46  MendelMin(const FuncT& fin, unsigned int ndim,
47  const Params& fixpar, //const RndT & rndin,
48  unsigned int npop=20, unsigned int ngen=20,
49  double margin=0.1)
50  : _f(fin), _q(fixpar), //_rnd(rndin),
51  _NDim(ndim), _margin(margin),
52  _pop(npop), _fit(npop, -1.0), showTrace(false) {}
53 
54 
63  MendelMin(const FuncNoFixedT& fin, unsigned int ndim,
64  //const RndT & rndin,
65  unsigned int npop=20, unsigned int ngen=20,
66  double margin=0.1)
67  : MendelMin([&](const Params& ps, const Params&) -> double { return fin(ps); },
68  ndim, {}, npop, ngen, margin)
69  { }
70 
71 
74  void guess(const Params & p) {
75  _pop.push_back(p);
76  limit01(_pop.back());
77  _fit.push_back(-1.0);
78  }
79 
80 
83  double evolve(unsigned int NGen) {
84  for ( unsigned n = 0; n < NGen; ++n ) {
85  // Calculate the fitness.
86  auto mm = minmax();
87  // Always kill the fittest individual.
88  if ( showTrace ) _debug();
89  for ( unsigned int i = 1; i < _pop.size(); ++i ) {
90  if ( _fit[i] > rnd()*(mm.second - mm.first) )
91  // Kill all individuals that have low fitness or are just unlucky.
92  _fit[i] = -1.0;
93  else
94  // Improve This individual to be more like the fittest.
95  move(_pop[i],_pop[0]);
96  }
97  }
98  return _fit[0];
99  }
100 
102  Params fittest() const {
103  return _pop[0];
104  }
105 
107  double fit() const {
108  return _fit[0];
109  }
110 
112  double rnd() const {
113  return rand01(); //_rnd();
114  }
115 
117  Params rndParams() const {
118  Params ret(_NDim);
119  for ( unsigned int i = 0; i < _NDim; ++i ) ret[i] = rnd();
120  return ret;
121  }
122 
124  void limit01(Params & p) const {
125  for ( unsigned int i = 0; i < _NDim; ++i )
126  p[i] = std::max(0.0, std::min(p[i], 1.0));
127  }
128 
133  void move(Params & bad, const Params & better) const {
134  bad += (better - bad)*(rndParams()*(1.0 + 2.0*_margin) - _margin);
135  limit01(bad);
136  }
137 
139  double f(const Params & p) const {
140  return _f(p, _q);
141  }
142 
143 
146  std::pair<double, double> minmax() {
147  std::pair<double,double> mm(std::numeric_limits<double>::max(), 0.0);
148  unsigned int iwin = 0;
149  for ( unsigned int i = 0; i < _pop.size(); ++i ) {
150  double & v = _fit[i];
151  // negative fitness value means the individual is dead, so we
152  // welocme a new immigrant.
153  if ( v < 0.0 ) _pop[i] = rndParams();
154 
155  // The calculated fitness value cannot be negative.
156  v = std::max(0.0, f(_pop[i]));
157 
158  // Compare to the best and worst fitness so far.
159  if ( v < mm.first ) iwin = i;
160  mm.first = std::min(v, mm.first);
161  mm.second = std::max(mm.second, v);
162  }
163 
164  // Move the winner to the top.
165  if ( iwin != 0 ) {
166  std::swap(_pop[0], _pop[iwin]);
167  std::swap(_fit[0], _fit[iwin]);
168  }
169  return mm;
170  }
171 
173  void _debug() {
174  std::cout << "GenAlgMax population status:" << std::endl;
175  for ( unsigned int i = 0; i < _pop.size(); ++i ) {
176  std::cout << std::setw(10) << _fit[i] << " (" << _pop[i][0];
177  for ( unsigned int ip = 1; ip < _NDim; ++ip )
178  std::cout << "," << _pop[i][ip];
179  std::cout << ")" << std::endl;
180  }
181  }
182 
183 
184  private:
185 
187  const FuncT _f;
188 
190  Params _q;
191 
193  // const double _q;
194 
196  //const RndT _rnd;
197 
199  unsigned int _NDim;
200 
205  double _margin;
206 
208  std::vector<Params> _pop;
209 
210 
212  std::vector<double> _fit;
213 
214  public:
215 
217  bool showTrace;
218 
219  };
220 
221 
229  // template <typename FuncT, typename RndT>
230  // MendelMin <FuncT, RndT>
231  // makeMendelMin(const FuncT & f, const RndT & rnd, unsigned int ndim,
232  // unsigned int npop = 20, double margin = 0.1) {
233  // return MendelMin<FuncT, RndT>(f, rnd, ndim, npop, margin);
234  // }
235 
236 }
237 
238 #endif // RIVET_MendelMin_H
Definition: MC_Cent_pPb.hh:10
void move(Params &bad, const Params &better) const
Definition: MendelMin.hh:133
double f(const Params &p) const
Simple wrapper around the function to be minimised.
Definition: MendelMin.hh:139
Params fittest() const
Return the fittest parameter point found.
Definition: MendelMin.hh:102
std::function< double(const Params &, const Params &)> FuncT
Typedef for the function to be minimised.
Definition: MendelMin.hh:30
double rnd() const
Simple wrapper around the random number generator.
Definition: MendelMin.hh:112
A genetic algorithm functional minimizer.
Definition: MendelMin.hh:24
bool showTrace
Set true to get a verbose record of the evolution.
Definition: MendelMin.hh:217
MendelMin(const FuncNoFixedT &fin, unsigned int ndim, unsigned int npop=20, unsigned int ngen=20, double margin=0.1)
Definition: MendelMin.hh:63
MendelMin(const FuncT &fin, unsigned int ndim, const Params &fixpar, unsigned int npop=20, unsigned int ngen=20, double margin=0.1)
Definition: MendelMin.hh:46
std::pair< double, double > minmax()
Definition: MendelMin.hh:146
double max(const vector< double > &in, double errval=DBL_NAN)
Find the maximum value in the vector.
Definition: Utils.hh:612
double evolve(unsigned int NGen)
Definition: MendelMin.hh:83
void limit01(Params &p) const
Limit a parameter point to inside the unit hypercube.
Definition: MendelMin.hh:124
void guess(const Params &p)
Definition: MendelMin.hh:74
double fit() const
Return the fittest value found.
Definition: MendelMin.hh:107
std::valarray< double > Params
Typedef for a valaray of parameters to the function to be minimised.
Definition: MendelMin.hh:28
std::function< double(const Params &)> FuncNoFixedT
Typedef for the function to be minimised.
Definition: MendelMin.hh:32
double min(const vector< double > &in, double errval=DBL_NAN)
Find the minimum value in the vector.
Definition: Utils.hh:606
double rand01()
Return a uniformly sampled random number between 0 and 1.
Params rndParams() const
Return a random parameter point in the unit hypercube.
Definition: MendelMin.hh:117