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