IMP logo
IMP Reference Guide  develop.1a04b19ae7,2021/11/27
The Integrative Modeling Platform
Restraint.h
Go to the documentation of this file.
1 /**
2  * \file IMP/Restraint.h
3  * \brief Abstract base class for all restraints.
4  *
5  * Copyright 2007-2021 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPKERNEL_RESTRAINT_H
10 #define IMPKERNEL_RESTRAINT_H
11 
12 #include <IMP/kernel_config.h>
13 #include "ModelObject.h"
14 #include "ScoreAccumulator.h"
15 #include "DerivativeAccumulator.h"
16 #include "constants.h"
17 #include "base_types.h"
18 #include <IMP/InputAdaptor.h>
19 #include <IMP/deprecation_macros.h>
20 #include <IMP/nullptr.h>
21 #include <IMP/RestraintInfo.h>
22 
23 IMPKERNEL_BEGIN_NAMESPACE
24 class DerivativeAccumulator;
25 
26 //! A restraint is a term in an \imp ScoringFunction.
27 /**
28  To implement a new restraint, just implement the two methods:
29  - IMP::Restraint::unprotected_evaluate()
30  - IMP::ModelObject::do_get_inputs();
31  and use the macro to handle IMP::Object
32  - IMP_OBJECT_METHODS()
33 
34  \note When logging is VERBOSE, restraints should print enough information
35  in evaluate to reproduce the entire flow of data in evaluate. When
36  logging is TERSE the restraint should print out only a constant number of
37  lines per evaluate call.
38 
39  \note Physical restraints should use the units of kcal/mol for restraint
40  values and kcal/mol/A for derivatives.
41 
42  When implementing an expensive restraint it makes sense to support early
43  abort of evaluation if the user is only interested in good scores or scores
44  below a threshold. To do this, look at the fields of the ScoreAccumulator
45  object such as
46  - ScoreAccumulator::get_is_evaluate_if_below(),
47  - ScoreAccumulator::get_is_evaluate_if_good()
48  - ScoreAccumulator::get_maximum()
49 
50  \headerfile Restraint.h "IMP/Restraint.h"
51 
52  See IMP::example::ExampleRestraint for an example.
53  */
54 class IMPKERNELEXPORT Restraint : public ModelObject {
55  public:
56  /** Create a restraint and register it with the model. The restraint is
57  not added to the implicit scoring function in the Model.*/
58  Restraint(Model *m, std::string name);
59 
60  /** Compute and return the current score for the restraint.
61  */
62  double get_score() const;
63 
64 #ifndef IMP_DOXYGEN
65  //! Return the score for this restraint for the current state of the model.
66  /** \return Current score.
67  */
68  double evaluate(bool calc_derivs) const;
69 
70  //! Score the restraint when some particles have moved.
71  /** No particles in the model other those listed should have been
72  changed (e.g. by Monte Carlo movers) since the last evaluation (although
73  ScoreStates may have moved particles not in this list, as a function of
74  particles that *are* in the list). This method should behave
75  identically to evaluate() but may be more efficient if it can
76  skip terms that involve unchanged particles.
77 
78  \param calc_derivs Whether to calculate first derivatives.
79  \param moved_pis Particles that have moved since the last
80  scoring function evaluation.
81  \param reset_pis Particles that have moved, but back to the
82  positions they had at the last-but-one evaluation
83  (e.g. due to a rejected Monte Carlo move).
84 
85  \return Current score.
86  */
87  double evaluate_moved(bool calc_derivs,
88  const ParticleIndexes &moved_pis,
89  const ParticleIndexes &reset_pis) const;
90 
91  double evaluate_moved_if_below(bool calc_derivatives,
92  const ParticleIndexes &moved_pis,
93  const ParticleIndexes &reset_pis, double max) const;
94 
95  double evaluate_moved_if_good(bool calc_derivatives,
96  const ParticleIndexes &moved_pis,
97  const ParticleIndexes &reset_pis) const;
98 
99  double evaluate_if_good(bool calc_derivatives) const;
100 
101  //! \see Model::evaluate_with_maximum()
102  double evaluate_if_below(bool calc_derivatives, double max) const;
103 
104  /** \name Evaluation implementation
105  These methods are called in order to perform the actual restraint
106  scoring. The restraints should assume that all appropriate ScoreState
107  objects have been updated and so that the input particles and containers
108  are up to date. The returned score should be the unweighted score.
109 
110  \note These functions probably should be called \c do_evaluate, but
111  were grandfathered in.
112  \note Although the returned score is unweighted, the DerivativeAccumulator
113  passed in should be properly weighted.
114  @{
115  */
116  //! Return the unweighted score for the restraint.
117  virtual double unprotected_evaluate(DerivativeAccumulator *da) const;
118 
119  //! Return the unweighted score, taking moving particles into account.
120  /** By default this just calls regular unprotected_evaluate(), but
121  may be overridden by restraints to be more efficient, e.g. by
122  skipping terms that involve unchanged particles.
123  */
124  virtual double unprotected_evaluate_moved(
125  DerivativeAccumulator *da, const ParticleIndexes &moved_pis,
126  const ParticleIndexes &reset_pis) const {
127  IMP_UNUSED(moved_pis);
128  IMP_UNUSED(reset_pis);
129  return unprotected_evaluate(da);
130  }
131 
132  /** The function calling this will treat any score >= get_maximum_score
133  as bad and so can return early as soon as such a situation is found.*/
134  virtual double unprotected_evaluate_if_good(DerivativeAccumulator *da,
135  double max) const {
136  IMP_UNUSED(max);
137  return unprotected_evaluate(da);
138  }
139 
140  //! The function calling this will treat any score >= max as bad.
141  virtual double unprotected_evaluate_if_below(DerivativeAccumulator *da,
142  double max) const {
143  IMP_UNUSED(max);
144  return unprotected_evaluate(da);
145  }
146 
147  virtual double unprotected_evaluate_moved_if_below(
148  DerivativeAccumulator *da, const ParticleIndexes &moved_pis,
149  const ParticleIndexes &reset_pis, double max) const {
150  IMP_UNUSED(max);
151  return unprotected_evaluate_moved(da, moved_pis, reset_pis);
152  }
153 
154  virtual double unprotected_evaluate_moved_if_good(
155  DerivativeAccumulator *da, const ParticleIndexes &moved_pis,
156  const ParticleIndexes &reset_pis, double max) const {
157  IMP_UNUSED(max);
158  return unprotected_evaluate_moved(da, moved_pis, reset_pis);
159  }
160 
161 /** @} */
162 
163 #endif
164 
165  //! \return static key:value information about this restraint, or null.
166  /** \return a set of key:value pairs that contain static information
167  about this restraint (i.e. information that doesn't change during
168  a sampling run, such as the type of restraint or filename from
169  which information is read). Usually this includes a "type" key with
170  the fully qualified classname (e.g. IMP.mymodule.MyRestraint).
171  If no such information is available, a null pointer is returned.
172  This information is used when writing restraints to files, e.g. by
173  the IMP.rmf module.
174  */
175  virtual RestraintInfo *get_static_info() const {
176  return nullptr;
177  }
178 
179  //! \return dynamic key:value information about this restraint, or null.
180  /** \return a set of key:value pairs that contain dynamic information
181  about this restraint (i.e. information that changes during a sampling
182  run, such as scores or cross correlations).
183  If no such information is available, a null pointer is returned.
184  This information is used when writing restraints to files, e.g. by
185  the IMP.rmf module.
186  */
187  virtual RestraintInfo *get_dynamic_info() const {
188  return nullptr;
189  }
190 
191  //! Perform the actual restraint scoring.
192  /** The restraints should assume that all appropriate ScoreState
193  objects have been updated and so that the input particles and containers
194  are up to date. The returned score should be the unweighted score.
195  */
196  void add_score_and_derivatives(ScoreAccumulator sa) const;
197 
198  void add_score_and_derivatives_moved(
199  ScoreAccumulator sa, const ParticleIndexes &moved_pis,
200  const ParticleIndexes &reset_pis) const;
201 
202  //! Decompose this restraint into constituent terms
203  /** Given the set of input particles, decompose the restraint into parts
204  that are as simple as possible. For many restraints, the simplest
205  part is simply the restraint itself.
206 
207  If a restraint can be decomposed, it should return a
208  RestraintSet so that the maximum score and weight can be
209  passed properly.
210 
211  The restraints returned have had set_model() called and so can
212  be evaluated.
213  */
215 
216  //! Decompose this restraint into constituent terms for the current conf
217  /** \return a decomposition that is value for the current conformation,
218  but will not necessarily be valid if any of the particles are
219  changed. This is the same as create_decomposition() for
220  non-conditional restraints.
221 
222  The restraints returned have had set_model() called and so can be
223  evaluated.
224  */
225  Restraint *create_current_decomposition() const;
226 
227  /** \name Weights
228  Each restraint's contribution to the model score is weighted. The
229  total weight for the restraint is the some over all the paths containing
230  it. That is, if a restraint is in a RestraintSet with weight .5 and
231  another with weight 2, and the restraint itself has weight 3, then the
232  total weight of the restraint is \f$.5 \cdot 3 + 2 \cdot 3 = 7.5 \f$.
233  @{
234  */
235  void set_weight(Float weight);
236  Float get_weight() const { return weight_; }
237  /** @} */
238  /** \name Filtering
239  We are typically only interested in "good" conformations of
240  the model. These are described by specifying maximum scores
241  per restraint (or RestraintSet). Samplers, optimizers
242  etc are free to ignore configurations they encounter which
243  go outside these bounds.
244 
245  \note The maximum score is for the unweighted restraint.
246  That is, the restraint evaluation is bad if the value
247  is greater than the maximum score divided by the weight.
248  @{
249  */
250  double get_maximum_score() const { return max_; }
251  void set_maximum_score(double s);
252 /** @} */
253 
254 //! Create a scoring function with only this restraint.
255 /** \note This method cannot be implemented in Python due to memory
256  management issues (and the question of why you would ever
257  want to).
258  */
259 #ifndef SWIG
260  virtual
261 #endif
262  ScoringFunction *
263  create_scoring_function(double weight = 1.0,
264  double max = NO_MAX) const;
265 #if !defined(IMP_DOXYGEN)
266  void set_last_score(double s) const {
267  last_last_score_ = last_score_;
268  last_score_ = s;
269  }
270  void set_last_last_score(double s) const { last_last_score_ = s; }
271 #endif
272 
273  /** Return the (unweighted) score for this restraint last time it was
274  evaluated.
275  \note If some sort of special evaluation (eg Model::evaluate_if_good())
276  was the last call, the score, if larger than the max, is not accurate.
277  */
278  virtual double get_last_score() const { return last_score_; }
279 
280  //! Get the unweighted score from the last-but-one time it was evaluated
281  /** \see get_last_score
282  */
283  virtual double get_last_last_score() const { return last_last_score_; }
284 
285  /** Return whether this restraint violated its maximum last time it was
286  evaluated.
287  */
288  bool get_was_good() const { return get_last_score() < max_; }
289 
291 
292  protected:
293  /** A Restraint should override this if it wants to decompose itself
294  for domino and other purposes. The returned restraints will be made
295  into a RestraintSet if needed, with suitable weight and maximum score.
296  */
298  return Restraints(1, const_cast<Restraint *>(this));
299  }
300  /** A Restraint should override this if it wants to decompose itself
301  for display and other purposes. The returned restraints will be made
302  into a RestraintSet if needed, with suitable weight and maximum score.
303 
304  The returned restraints should be only the non-zero terms and should
305  have their last scores set appropriately.
306  */
308  return do_create_decomposition();
309  }
310 
311  virtual void do_add_score_and_derivatives(ScoreAccumulator sa) const;
312 
313  virtual void do_add_score_and_derivatives_moved(
314  ScoreAccumulator sa, const ParticleIndexes &moved_pis,
315  const ParticleIndexes &reset_pis) const;
316 
317  /** No outputs. */
319  return ModelObjectsTemp();
320  }
321 
322  private:
323  ScoringFunction *create_internal_scoring_function() const;
324 
325  double weight_;
326  double max_;
327  mutable double last_score_;
328  mutable double last_last_score_;
329  // cannot be released outside the class
330  mutable Pointer<ScoringFunction> cached_internal_scoring_function_;
331 };
332 
333 //! Provide a consistent interface for things that take Restraints as arguments.
334 /**
335  \note Passing an empty list of restraints should be supported, but problems
336  could arise, so be alert (the problems would not be subtle).
337 */
338 class IMPKERNELEXPORT RestraintsAdaptor :
339 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
340  public Restraints
341 #else
342  public InputAdaptor
343 #endif
344  {
345  static Restraint *get(Restraint *r) { return r; }
346 
347  public:
348  RestraintsAdaptor() {}
349  RestraintsAdaptor(const Restraints &sf) : Restraints(sf) {}
351  : Restraints(sf.begin(), sf.end()) {}
352  RestraintsAdaptor(Restraint *sf) : Restraints(1, sf) {}
353 #ifndef IMP_DOXYGEN
354  template <class T>
355  RestraintsAdaptor(internal::PointerBase<T> t)
356  : Restraints(1, get(t)) {}
357 #endif
358 };
359 
360 //! Return the decomposition of a list of restraints.
361 IMPKERNELEXPORT Restraints create_decomposition(const RestraintsTemp &rs);
362 
363 IMPKERNEL_END_NAMESPACE
364 
365 #endif /* IMPKERNEL_RESTRAINT_H */
Control display of deprecation information.
const double NO_MAX
Use this value when you want to turn off maximum for restraint evaluation.
Basic types used by IMP.
IMP::Vector< IMP::Pointer< Restraint > > Restraints
Definition: base_types.h:86
Class for adding scores from restraints to the model.
virtual RestraintInfo * get_static_info() const
Definition: Restraint.h:175
Various useful constants.
virtual RestraintInfo * get_dynamic_info() const
Definition: Restraint.h:187
Class for adding derivatives from restraints to the model.
virtual Restraints do_create_decomposition() const
Definition: Restraint.h:297
ModelObjectsTemp do_get_outputs() const
Definition: Restraint.h:318
#define IMP_REF_COUNTED_DESTRUCTOR(Name)
Ref counted objects should have private destructors.
A smart pointer to a reference counted object.
Definition: Pointer.h:87
ScoringFunction * create_scoring_function(RestraintType *rs, double weight=1.0, double max=NO_MAX, std::string name=std::string())
Create a ScoringFunction on a single restraint.
Definition: generic.h:23
IMP::Vector< IMP::WeakPointer< ModelObject > > ModelObjectsTemp
Definition: base_types.h:89
Class for storing model, its restraints, constraints, and particles.
Definition: Model.h:73
Base class for objects in a Model that depend on other objects.
Definition: ModelObject.h:26
Convenience class to accept multiple input types.
virtual Restraints do_create_current_decomposition() const
Definition: Restraint.h:307
Provide a nullptr keyword analog.
#define IMP_UNUSED(variable)
Provide a consistent interface for things that take Restraints as arguments.
Definition: Restraint.h:338
Class for adding up scores during ScoringFunction evaluation.
Restraints create_decomposition(const RestraintsTemp &rs)
Return the decomposition of a list of restraints.
Report key:value information on restraints.
Definition: RestraintInfo.h:35
Base class for objects in a Model that depend on other objects.
virtual double get_last_score() const
Definition: Restraint.h:278
bool get_was_good() const
Definition: Restraint.h:288
Represents a scoring function on the model.
Report key:value information on restraints.
double Float
Basic floating-point value (could be float, double...)
Definition: types.h:20
virtual double get_last_last_score() const
Get the unweighted score from the last-but-one time it was evaluated.
Definition: Restraint.h:283
Convenience class to accept multiple input types.
Definition: InputAdaptor.h:25
#define IMP_OVERRIDE
Cause a compile error if this method does not override a parent method.
Class for adding derivatives from restraints to the model.
A restraint is a term in an IMP ScoringFunction.
Definition: Restraint.h:54