IMP  2.0.0
The Integrative Modeling Platform
kernel/declare_Model.h
Go to the documentation of this file.
1 /**
2  * \file IMP/kernel/declare_Model.h
3  * \brief Storage of a model, its restraints,
4  * constraints and particles.
5  *
6  * Copyright 2007-2013 IMP Inventors. All rights reserved.
7  *
8  */
9 
10 #ifndef IMPKERNEL_DECLARE_MODEL_H
11 #define IMPKERNEL_DECLARE_MODEL_H
12 
13 #include <IMP/kernel/kernel_config.h>
14 #include "ModelObject.h"
16 #include "declare_Restraint.h"
17 #include "declare_RestraintSet.h"
18 #include "ScoreState.h"
19 #include "container_macros.h"
20 #include "base_types.h"
21 #include "declare_Particle.h"
22 #include "Undecorator.h"
23 #include "internal/AttributeTable.h"
24 #include "internal/attribute_tables.h"
25 #include <IMP/base/Object.h>
26 #include <IMP/base/Pointer.h>
27 #include <IMP/base/tracking.h>
28 #include <IMP/base/map.h>
29 #include <IMP/base/set.h>
30 #include <IMP/base/tuple_macros.h>
31 #include <boost/iterator/transform_iterator.hpp>
32 #include <boost/iterator/filter_iterator.hpp>
33 
34 
35 #include <limits>
36 
37 
38 IMPKERNEL_BEGIN_NAMESPACE
39 
40 class ModelObject;
41 class Undecorator;
42 
43 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
44 namespace internal {
45  enum Stage {NOT_EVALUATING, BEFORE_EVALUATING, EVALUATING, AFTER_EVALUATING,
46  COMPUTING_DEPENDENCIES};
47 }
48 #endif
49 
50 /** A structure used for returning restraint statistics from the model.*/
51 /** \headerfile Model.h "IMP/Model.h"
52  */
54  double, minimum_score,
55  double, maximum_score,
56  double, average_score,
57  double, last_score,
58  double, average_time,);
59 
60 class Model;
61 
62 //! Class for storing model, its restraints, constraints, and particles.
63 /** The Model maintains a standard \imp container for each of Particle,
64  ScoreState and Restraint object types.
65 
66  Each Float attribute has an associated range which reflects the
67  range of values that it is expected to take on during optimization.
68  The optimizer can use these ranges to make the optimization process
69  more efficient. By default, the range estimates are simply the
70  range of values for that attribute in the various particles, but
71  it can be set to another value. For example, an attribute storing
72  an angle could have the range set to (0,PI).
73 
74  The ranges are not enforced; they are just guidelines. In order to
75  enforce ranges, see, for example,
76  IMP::example::ExampleSingletonModifier.
77 
78  \headerfile Model.h "IMP/Model.h"
79  */
80 class IMPKERNELEXPORT Model:
81 #ifdef IMP_DOXYGEN
82  public base::Object
83 #else
84  public RestraintSet
85 #endif
86 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
87  ,public base::Tracker<ModelObject>,
88  public internal::Masks,
89 // The attribute tables provide fast access to e.g. particle attributes, etc.
90  public internal::FloatAttributeTable,
91  public internal::StringAttributeTable,
92  public internal::IntAttributeTable,
93  public internal::ObjectAttributeTable,
94  public internal::WeakObjectAttributeTable,
95  public internal::IntsAttributeTable,
96  public internal::ObjectsAttributeTable,
97  public internal::ParticleAttributeTable,
98  public internal::ParticlesAttributeTable
99 #endif
100 {
101  public:
102 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
103  IMP_MODEL_IMPORT(internal::FloatAttributeTable);
104  IMP_MODEL_IMPORT(internal::StringAttributeTable);
105  IMP_MODEL_IMPORT(internal::IntAttributeTable);
106  IMP_MODEL_IMPORT(internal::ObjectAttributeTable);
107  IMP_MODEL_IMPORT(internal::WeakObjectAttributeTable);
108  IMP_MODEL_IMPORT(internal::IntsAttributeTable);
109  IMP_MODEL_IMPORT(internal::ObjectsAttributeTable);
110  IMP_MODEL_IMPORT(internal::ParticleAttributeTable);
111  IMP_MODEL_IMPORT(internal::ParticlesAttributeTable);
112 #endif
113  /** Clear all the cache attributes of a given particle.*/
115  internal::FloatAttributeTable::clear_caches(pi);
116  internal::StringAttributeTable::clear_caches(pi);
117  internal::IntAttributeTable::clear_caches(pi);
118  internal::ObjectAttributeTable::clear_caches(pi);
119  internal::WeakObjectAttributeTable::clear_caches(pi);
120  internal::IntsAttributeTable::clear_caches(pi);
121  internal::ObjectsAttributeTable::clear_caches(pi);
122  internal::ParticleAttributeTable::clear_caches(pi);
123  internal::ParticlesAttributeTable::clear_caches(pi);
124  }
125 private:
126  typedef base::Tracker<ModelObject> ModelObjectTracker;
127  struct Statistics {
128  double total_time_;
129  double total_time_after_;
130  unsigned int calls_;
131  double total_value_;
132  double min_value_;
133  double max_value_;
134  double last_value_;
135  Statistics(): total_time_(0), total_time_after_(0),
136  calls_(0), total_value_(0),
137  min_value_(std::numeric_limits<double>::max()),
138  max_value_(-std::numeric_limits<double>::max()),
139  last_value_(-1)
140  {}
141  };
142  mutable base::map<base::Object*, Statistics> stats_data_;
143 
144  // basic representation
145  base::map<FloatKey, FloatRange> ranges_;
146  ParticleIndexes free_particles_;
147  unsigned int next_particle_;
148  base::IndexVector<ParticleIndexTag, base::Pointer<Particle> > particle_index_;
149  base::IndexVector<ParticleIndexTag, Undecorators > undecorators_index_;
150  base::Vector<base::OwnerPointer<base::Object> > model_data_;
151  bool dependencies_dirty_;
152  DependencyGraph dependency_graph_;
153  DependencyGraphVertexIndex dependency_graph_index_;
154  base::map<ModelObject*, ScoreStatesTemp> required_score_states_;
155  void compute_required_score_states();
156 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
157  // things the evaluate template functions need, can't be bothered with friends
158 public:
159  bool first_call_;
160  void validate_computed_derivatives() const{}
161  void compute_dependencies();
162  internal::Stage cur_stage_;
163  unsigned int eval_count_;
164  bool has_good_score_;
165  void before_evaluate(const ScoreStatesTemp &states);
166  void after_evaluate(const ScoreStatesTemp &states, bool calc_derivs);
167 
168  bool gather_statistics_;
169 
170  void add_to_restraint_evaluate(Restraint *r, double t, double score) const;
171  void clear_caches();
172  internal::Stage get_stage() const {
173  return cur_stage_;
174  }
175  unsigned int get_evaluation() const {
176  IMP_USAGE_CHECK(get_stage() != internal::NOT_EVALUATING,
177  "Can only call get_evaluation() during evaluation");
178  return eval_count_;
179  }
180  void add_particle_internal(Particle *p, bool set_name);
181 #endif
182 
183  private:
184  void cleanup();
185  void show_it(std::ostream &out) const;
186  // statistics
187  void add_to_update_before_time(ScoreState *s, double t) const;
188  void add_to_update_after_time(ScoreState *s, double t) const;
189 
190 
191  // dependencies
192  RestraintsTemp scoring_restraints_;
193  ScoreStatesTemp ordered_score_states_;
194 
195 public:
196  /** Construct an empty model */
197  Model(std::string name="Model %1%");
198 
199  //! Add particle to the model
200  ParticleIndex add_particle(std::string name);
201 
202 #ifndef IMP_DOXYGEN
204  const DependencyGraphVertexIndex& get_dependency_graph_vertex_index();
205  const ScoreStatesTemp& get_required_score_states(ModelObject *o);
206 #endif
207 
208  /** Add the passed Undecorator to the particle.*/
209  void add_undecorator(ParticleIndex pi, Undecorator *d);
210 
211  /** @name States
212 
213  The Model stores a list of ScoreStates which are given an
214  opportunity to update the stored Particles and their internal
215  state before and after the restraints are evaluated. Use the
216  methods below to manipulate the list of ScoreState objects.
217 
218  The value type for the iterators is a ScoreState*.
219 
220  \note The order of addition of ScoreState objects does not matter.
221 
222  \advancedmethod
223  */
224  /**@{*/
225  IMP_LIST_ACTION(public, ScoreState, ScoreStates,
226  score_state, score_states, ScoreState*, ScoreStates,
227  {IMP_INTERNAL_CHECK(cur_stage_== internal::NOT_EVALUATING,
228  "The set of score states cannot be changed during"
229  << "evaluation.");
230  obj->set_model(this);
231  obj->set_was_used(true);
232  IMP_LOG_VERBOSE( "Added score state " << obj->get_name()
233  << std::endl);
235  base::set<ScoreState*> in(score_states_begin(),
236  score_states_end());
237  IMP_USAGE_CHECK(in.size() == get_number_of_score_states(),
238  "Score state already in model "
239  << obj->get_name());
240  }
241  },{},
242  {obj->set_model(nullptr);});
243  /**@}*/
244 
245  public:
246 
247 #if !defined(IMP_DOXYGEN)
248  ModelObjectsTemp get_optimized_particles() const;
249 
250  RestraintSet *get_root_restraint_set();
251 
252  bool get_has_dependencies() const;
253  double get_maximum_score(Restraint *r) const;
254  void set_maximum_score(Restraint *r, double s);
255  void set_maximum_score(double s);
256  double get_maximum_score() const;
257 
258  // make sure the whole model is updated for backwards compat
259  /**
260  @param tf - calculate derivatives if true
261  */
262  double evaluate(bool tf, bool warn=true);
263 #endif
264 
265  /** @name Float Attribute Ranges
266  Each Float attribute has an associated range which reflects the
267  range of values that it is expected to take on during optimization.
268  The optimizer can use these ranges to make the optimization process
269  more efficient. By default, the range estimates are simply the
270  range of values for that attribute in the various particles, but
271  it can be set to another value. For example, an attribute storing
272  an angle could have the range set to (0,PI).
273 
274  The ranges are not enforced; they are just guidelines. In order to
275  enforce ranges, see, for example,
276  IMP::example::ExampleSingletonModifier.
277  @{
278  */
279  /** @} */
280 
281  //! Create a scoring function object from the model restraints
282  /** Create a scoring function from the model restraints,
283  which can be used to evaluate the score over this model
284  particles.
285  */
286  ScoringFunction* create_model_scoring_function();
287 
288  //! Sometimes it is useful to be able to make sure the model is up to date
289  /** This method updates all the state but does not necessarily compute the
290  score. Use this to make sure that your containers and rigid bodies are
291  up to date.
292  */
293  void update();
294 
296 
297 #ifndef IMP_DOXYGEN
298  /** Remove a particle from the Model. The particle will then be inactive and
299  cannot be used for anything and all data stored in the particle is lost.
300  */
301  void remove_particle(Particle *p);
302  /** Make sure that we don't cache the ScoringFunction so as not to create
303  a ref count loop.*/
304  virtual ScoringFunction *create_scoring_function(double weight=1.0,
305  double max
306  = NO_MAX) const IMP_OVERRIDE;
307 #endif
308  /** Remove a particle from the Model. The particle will then be inactive and
309  cannot be used for anything and all data stored in the particle is lost.
310  */
311  void remove_particle(ParticleIndex pi);
312 
313  /** \name Statistics
314 
315  The Model can gather various statistics about the restraints and
316  score states used. To use this feature, first turn on statistics
317  gather and then run your optimization (or just call evaluate).
318 
319  \note Telling the model not to gather statistics does not clear
320  existing statistics.
321  @{
322  */
323  void clear_all_statistics();
324  void set_gather_statistics(bool tf);
325  bool get_gather_statistics() const {return gather_statistics_;}
326  void show_all_statistics(std::ostream &out=std::cout) const;
327  void show_restraint_time_statistics(std::ostream &out=std::cout) const;
328  void show_restraint_score_statistics(std::ostream &out=std::cout) const;
329  RestraintStatistics get_restraint_statistics(Restraint *r) const;
330  void show_score_state_time_statistics(std::ostream &out=std::cout) const;
331  /** @} */
332 
333 #ifdef IMP_DOXYGEN
334  /** \name Accessing attributes
335  All the attribute data associated with each Particle is stored in the
336  Model. For each type of attribute, there are the methods detailed below
337  (where, eg, TypeKey is FloatKey or StringKey)
338  @{
339  */
340  /** \pre get_has_attribute(attribute_key, particle) is false*/
341  void add_attribute(TypeKey attribute_key, ParticleIndex particle, Type value);
342 
343  /** \pre get_has_attribute(attribute_key, particle) is true*/
344  void remove_attribute(TypeKey attribute_key, ParticleIndex particle);
345 
346  bool get_has_attribute(TypeKey attribute_key, ParticleIndex particle) const;
347 
348  /** \pre get_has_attribute(attribute_key, particle) is true*/
349  void set_attribute(TypeKey attribute_key, ParticleIndex particle, Type value);
350 
351  /** \pre get_has_attribute(attribute_key, particle) is true*/
352  Type get_attribute(TypeKey attribute_key, ParticleIndex particle);
353 
354  /** Cache attributes, unklike normal attributes, can be added during
355  evaluation. They are also cleared by the clear_cache_attributes() method.
356  Cache attributes should be used when one is adding data to a particle
357  to aid scoring (eg cache the rigid body collision acceleration structure).
358 
359  When some pertinent aspect of the particle changes, the clear method
360  should
361  be called (yes, this is a bit vague). Examples where it should be cleared
362  include changing the set of members of a core::RigidBody or their
363  coordinates, changing the members of an atom::Hierarchy.
364  */
365  void add_cache_attribute(TypeKey attribute_key, ParticleIndex particle,
366  Type value);
367 
368  //! Optimized attributes are the parameters of the model
369  /** They will be modified by the samplers and optimizers.
370  */
371  void set_is_optimized(TypeKey attribute_key, ParticleIndex particle,
372  bool true_or_false);
373  /** @} */
374 #endif
375 
376  // kind of icky
377 #ifdef SWIG
378 #define IMP_MODEL_ATTRIBUTE_METHODS(Type, Value) \
379  void add_attribute(Type##Key attribute_key, \
380  ParticleIndex particle, Value value); \
381  void remove_attribute(Type##Key attribute_key, \
382  ParticleIndex particle); \
383  bool get_has_attribute(Type##Key attribute_key, \
384  ParticleIndex particle) const; \
385  void set_attribute(Type##Key attribute_key, \
386  ParticleIndex particle, Value value); \
387  Value get_attribute(Type##Key attribute_key, \
388  ParticleIndex particle); \
389  void add_cache_attribute(Type##Key attribute_key, \
390  ParticleIndex particle, \
391  Value value)
392 
393  IMP_MODEL_ATTRIBUTE_METHODS(Float, Float);
394  IMP_MODEL_ATTRIBUTE_METHODS(Int, Int);
395  IMP_MODEL_ATTRIBUTE_METHODS(Ints, Ints);
396  IMP_MODEL_ATTRIBUTE_METHODS(String, String);
397  IMP_MODEL_ATTRIBUTE_METHODS(ParticleIndexes, ParticleIndexes);
398  IMP_MODEL_ATTRIBUTE_METHODS(ParticleIndex, ParticleIndex);
399  IMP_MODEL_ATTRIBUTE_METHODS(Object, Object*);
400  IMP_MODEL_ATTRIBUTE_METHODS(WeakObject, Object*);
401  void set_is_optimized(FloatKey, ParticleIndex, bool);
402 #endif
403 
404  /** \name Model Data
405  Arbitrary non-particle data can be associated with the Model. This can
406  be used for Model-level caches and such.
407  @{ */
408  void add_data(ModelKey mk, base::Object *o);
409  base::Object *get_data(ModelKey mk) const;
410  void remove_data(ModelKey mk);
411  bool get_has_data(ModelKey mk) const;
412  /** @} */
413 
414 /** @name Methods to debug particles
415  It is sometimes useful to inspect the list of all particles when
416  debugging. These methods allow you to do that.
417  \note Only use this if you really know what you are doing as
418  Particles can be added to the object from many different places.
419 
420  The value type for the iterators is a Particle*.
421  @{
422  */
423  unsigned int get_number_of_particles() const;
424  ParticlesTemp get_particles() const;
425  inline Particle* get_particle(ParticleIndex p) const ;
426 #ifndef SWIG
427 #ifdef IMP_DOXYGEN
428  class ParticleIterator;
429 #else
430  struct NotNull{
431  bool operator()(const base::Pointer<Particle>& p) {
432  return p;
433  }
434  };
435  typedef boost::filter_iterator<NotNull,
436  base::Vector<base::Pointer<Particle> >
437  ::const_iterator> ParticleIterator;
438 
439 #endif
440  ParticleIterator particles_begin() const;
441  ParticleIterator particles_end() const;
442 #endif
443  /** @} */
444  /** Get all the ModelObjects associated with this Model.
445  */
446  ModelObjectsTemp get_model_objects() const;
447 };
448 
449 IMPKERNEL_END_NAMESPACE
450 
451 #endif /* IMPKERNEL_DECLARE_MODEL_H */