IMP logo
MonteCarlo.h
Go to the documentation of this file.
1 /**
2  * \file MonteCarlo.h \brief Simple Monte Carlo optimizer.
3  *
4  * Copyright 2007-2012 IMP Inventors. All rights reserved.
5  *
6  */
7 
8 #ifndef IMPCORE_MONTE_CARLO_H
9 #define IMPCORE_MONTE_CARLO_H
10 
11 #include "core_config.h"
12 #include "Mover.h"
13 #include "monte_carlo_macros.h"
15 #include <IMP/Optimizer.h>
16 #include <IMP/optimizer_macros.h>
17 #include <IMP/container_macros.h>
18 #include <IMP/internal/container_helpers.h>
20 #include <IMP/Configuration.h>
21 
22 #include <boost/random/uniform_real.hpp>
23 
24 IMPCORE_BEGIN_NAMESPACE
25 
26 
27 //! A Monte Carlo optimizer.
28 /** The optimizer uses a set of Mover objects to propose steps. Currently
29  each Mover is called at each Monte Carlo iteration. If you only want to
30  use one mover at a time, use a SerialMover.
31  The movers propose some modification, which is then
32  accepted or rejected based on the Metropolis criterion. Optionally, a
33  number of local optimization steps are taken before the MonteCarlo step
34  is accepted or rejected.
35 
36  By default, the lowest score state encountered is returned.
37 
38  \see Mover
39  */
40 class IMPCOREEXPORT MonteCarlo: public Optimizer
41 {
42 public:
43  MonteCarlo(Model *m=nullptr);
44 
46  public:
47  /** By default, the optimizer returns the lowest score state
48  found so far. If, instead, you wish to return the last accepted
49  state, set return best to false.
50  */
51  void set_return_best(bool tf) {
52  return_best_=tf;
53  }
54 
55  /** \name kT
56  The kT value has to be on the same scale as the differences
57  in energy between good and bad states (and so the default is
58  likely to not be a good choice).
59  @{
60  */
61  void set_kt(Float t) {
62  IMP_INTERNAL_CHECK(t>0, "Temperature must be positive");
63  temp_=t;
64  }
65  Float get_kt() const {
66  return temp_;
67  }
68  /** @} */
69  /** Return the energy of last accepted state.
70  */
71  double get_last_accepted_energy() const {
72  return last_energy_;
73  }
74 
75  /** If return best is on, you can get the best energy
76  found so far.*/
77  double get_best_accepted_energy() const {
78  IMP_USAGE_CHECK(return_best_, "Getting the best energy"
79  << " requires return best being on.");
80  return best_energy_;
81  }
82 
83  //! Set the probability of each move being made
84  /** Make this low if the space is rough and there are many particles.
85  The movers should make each individual move with this probability.
86  That is, a NormalMover with 100 particles will move each particle
87  with probability p.
88  */
89  void set_move_probability(Float p) {
90  IMP_USAGE_CHECK(p > 0 && p <= 1, "Not a valid probability");
91  probability_=p;
92  }
93  double get_move_probability() const {
94  return probability_;
95  }
96  /** \name Statistics
97  @{
98  */
99  //! Return how many times the optimizer has succeeded in taking a step
100  unsigned int get_number_of_forward_steps() const {
101  return stat_forward_steps_taken_;
102  }
103  //! Return how many times the optimizer has stepped to higher energy
104  unsigned int get_number_of_upward_steps() const {
105  return stat_upward_steps_taken_;
106  }
107  /** @} */
108 
109  /** Computations can be acceletating by throwing out
110  the tails of the distribution of accepted moves. To
111  do this, specific a maximum acceptable difference
112  between the before and after scores.
113  */
114  void set_maximum_difference(double d) {
115  max_difference_=d;
116  }
117 
118  double get_maximum_difference() const {
119  return max_difference_;
120  }
121  /** @name Movers
122 
123  The following methods are used to manipulate the list of Movers.
124  Each mover is called at each optimization step, giving it a chance
125  to change the current configuration.
126  @{
127  */
128  IMP_LIST_ACTION(public, Mover, Movers, mover, movers, Mover*, Movers,
129  {obj->set_optimizer(this);
130  obj->set_was_used(true);
131  },{},{obj->set_optimizer(nullptr);});
132  /** @} */
133 
134 
135  /** \name Incremental
136  Efficient evaluation of non-bonded list based restraints is
137  a bit tricky with incremental evaluation.
138  @{
139  */
140  /** Set whether to use incremental evaluate or evaluate all restraints
141  each time. This cannot be changed during optimization.
142  */
143  void set_incremental_scoring_function(IncrementalScoringFunction *isf);
144  bool get_use_incremental_scoring_function() const {
145  return isf_;
146  }
147  IncrementalScoringFunction* get_incremental_scoring_function() const {
148  return isf_;
149  }
150  /** @} */
151  protected:
152  /** Note that if return best is true, this will save the current
153  state of the model. Also, if the move is accepted, the
154  optimizer states will be updated.
155  */
156  bool do_accept_or_reject_move(double score, double last);
157  bool do_accept_or_reject_move(double score)
158  {
159  return do_accept_or_reject_move(score, get_last_accepted_energy());
160  }
161 
162  ParticlesTemp do_move(double probability);
163  //! a class that inherits from this should override this method
164  virtual void do_step();
165  //! Get the current energy
166  /** By default it just calls
167  Optimizer::get_scoring_function()->evaluate(false). However,
168  if an incremental scoring function is used, the list of moved
169  particles will be used to evaluate the score more efficiently.
170  Also, if there is a maximum allowed difference in scores
171  Optimizer::get_scoring_function()->evaluate_if_below()
172  will be called instead, allowing more efficient evaluation.
173  Classes which override this method should be similarly aware for
174  efficiency.
175 
176  The list of moved particles is passed.
177  */
178  virtual double do_evaluate(const ParticlesTemp &moved) const {
179  IMP_UNUSED(moved);
180  if (isf_ ) {
181  isf_->set_moved_particles(moved);
182  }
183  if (get_maximum_difference() < NO_MAX) {
184  return get_scoring_function()
185  ->evaluate_if_below(false, last_energy_+max_difference_);
186  } else {
187  return get_scoring_function()
188  ->evaluate(false);
189  }
190  }
191 private:
192  double temp_;
193  double last_energy_;
194  double best_energy_;
195  double max_difference_;
196  Float probability_;
197  unsigned int stat_forward_steps_taken_;
198  unsigned int stat_upward_steps_taken_;
199  unsigned int stat_num_failures_;
200  bool return_best_;
202  ::boost::uniform_real<> rand_;
203 
204  Pointer<IncrementalScoringFunction> isf_;
205 };
206 
207 
208 
209 //! This variant of Monte Carlo that relaxes after each move
210 class IMPCOREEXPORT MonteCarloWithLocalOptimization: public MonteCarlo
211 {
213  unsigned int num_local_;
214 public:
215  MonteCarloWithLocalOptimization(Optimizer *opt,
216  unsigned int steps);
217 
218  unsigned int get_number_of_steps() const {
219  return num_local_;
220  }
221 
222  Optimizer* get_local_optimizer() const {
223  return opt_;
224  }
225 
226  IMP_MONTE_CARLO(MonteCarloWithLocalOptimization);
227 };
228 
229 //! This variant of Monte Carlo uses basis hopping
230 /** Basin hopping is where, after a move, a local optimizer is used to relax
231  the model before the energy computation. However, the pre-relaxation state
232  of the model is used as the starting point for the next step. The idea
233  is that models are accepted or rejected based on the score of the nearest
234  local minima, but they can still climb the barriers in between as the model
235  is not reset to the minima after each step.
236  */
237 class IMPCOREEXPORT MonteCarloWithBasinHopping:
238 public MonteCarloWithLocalOptimization
239 {
240 public:
241  MonteCarloWithBasinHopping(Optimizer *opt, unsigned int ns);
242 
243  IMP_MONTE_CARLO(MonteCarloWithBasinHopping);
244 };
245 
246 
247 IMPCORE_END_NAMESPACE
248 
249 #endif /* IMPCORE_MONTE_CARLO_H */

Generated on Tue May 22 2012 23:33:15 for IMP by doxygen 1.8.1