IMP logo
IMP Reference Guide  2.19.0
The Integrative Modeling Platform
Model.h
Go to the documentation of this file.
1 /**
2  * \file IMP/Model.h
3  * \brief Storage of a model, its restraints, constraints and particles.
4  *
5  * Copyright 2007-2022 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPKERNEL_MODEL_H
10 #define IMPKERNEL_MODEL_H
11 
12 #include <IMP/kernel_config.h>
13 #include "ModelObject.h"
14 #include "ScoringFunction.h"
15 #include "Restraint.h"
16 #include "RestraintSet.h"
17 #include "ScoreState.h"
18 #include "container_macros.h"
19 #include "base_types.h"
20 //#include "Particle.h"
21 #include "Undecorator.h"
22 #include "internal/AttributeTable.h"
23 #include "internal/attribute_tables.h"
24 #include "internal/moved_particles_cache.h"
25 #include "internal/KeyVector.h"
26 #include <IMP/Object.h>
27 #include <IMP/Pointer.h>
28 #include <IMP/internal/IDGenerator.h>
29 #include <boost/unordered_map.hpp>
30 #include <boost/unordered_set.hpp>
31 #include <IMP/tuple_macros.h>
32 #include <boost/iterator/transform_iterator.hpp>
33 #include <boost/iterator/filter_iterator.hpp>
34 #include <cereal/access.hpp>
35 #include <cereal/types/polymorphic.hpp>
36 
37 #include <limits>
38 
39 IMPKERNEL_BEGIN_NAMESPACE
40 
41 class ModelObject;
42 class Undecorator;
43 class Particle;
44 
45 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
46 namespace internal {
47 enum Stage {
48  NOT_EVALUATING,
49  BEFORE_EVALUATING,
50  EVALUATING,
51  AFTER_EVALUATING,
52  COMPUTING_DEPENDENCIES
53 };
54 }
55 #endif
56 
57 class Model;
58 
59 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
60 // This is needed as NodeInfo (below) needs to be showable, and Edges are not
61 inline std::ostream &operator<<(
62  std::ostream &out, const std::set<ModelObject *> &) {
63  out << "(set of ModelObject)";
64  return out;
65 }
66 #endif
67 
68 //! Class for storing model, its restraints, constraints, and particles.
69 /** The Model maintains a standard \imp container for each of Particle,
70  ScoreState and Restraint object types.
71 
72  Each Float attribute has an associated range which reflects the
73  range of values that it is expected to take on during optimization.
74  The optimizer can use these ranges to make the optimization process
75  more efficient. By default, the range estimates are simply the
76  range of values for that attribute in the various particles, but
77  it can be set to another value. For example, an attribute storing
78  an angle could have the range set to (0,PI).
79 
80  The ranges are not enforced; they are just guidelines. In order to
81  enforce ranges, see, for example,
82  IMP::example::ExampleSingletonModifier.
83 
84  \headerfile Model.h "IMP/Model.h"
85  */
86 class IMPKERNELEXPORT Model : public Object
87 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
88  ,
89  public internal::Masks,
90  // The attribute tables provide fast access to
91  // e.g. particle attributes, etc.
92  public internal::FloatAttributeTable,
93  public internal::StringAttributeTable,
94  public internal::IntAttributeTable,
95  public internal::ObjectAttributeTable,
96  public internal::WeakObjectAttributeTable,
97  public internal::IntsAttributeTable,
98  public internal::FloatsAttributeTable,
99  public internal::ObjectsAttributeTable,
100  public internal::ParticleAttributeTable,
101  public internal::ParticlesAttributeTable
102 #endif
103  {
104  typedef std::set<ModelObject *> Edges;
105  // must be up top
106  // we don't want any liveness checks
107  IMP_NAMED_TUPLE_5(NodeInfo, NodeInfos, Edges, inputs, Edges, input_outputs,
108  Edges, outputs, Edges, readers, Edges, writers, );
109  typedef boost::unordered_map<const ModelObject *, NodeInfo> DependencyGraph;
110  DependencyGraph dependency_graph_;
111  boost::unordered_set<const ModelObject *> no_dependencies_;
112  boost::unordered_map<const ModelObject *, ScoreStatesTemp>
113  required_score_states_;
114 
115  // basic representation
116  boost::unordered_map<FloatKey, FloatRange> ranges_;
117 
118  ParticleIndexes free_particles_;
121 
122  internal::KeyVector<ModelKey, PointerMember<Object> > model_data_;
123 
124 #if !defined(IMP_DOXYGEN)
125  // Map unique ID to Model*
126  class ModelMap {
127  std::map<uint32_t, Model*> map_;
128  internal::IDGenerator id_gen_;
129  public:
130  ModelMap() {}
131  uint32_t add_new_model(Model *m);
132  void add_model_with_id(Model *m, uint32_t id);
133  void remove_model(Model *m);
134  Model *get(uint32_t id) const;
135  };
136 
137  static ModelMap model_map_;
138  uint32_t unique_id_;
139 #endif
140 
141  void do_add_dependencies(const ModelObject *mo);
142  void do_clear_required_score_states(ModelObject *mo);
143  void do_check_required_score_states(const ModelObject *mo) const;
144  void do_check_update_order(const ScoreState *ss) const;
145  void do_check_inputs_and_outputs(const ModelObject *mo) const;
146  void do_check_readers_and_writers(const ModelObject *mo) const;
147  void do_check_not_in_readers_and_writers(const ModelObject *mo) const;
148  void do_clear_dependencies(const ModelObject *mo);
149 
150  // used to track time when triggers are activated
151  unsigned age_counter_;
152  // all triggers
153  Vector<unsigned> trigger_age_;
154  // time when dependencies were last changed, or 0
155  unsigned dependencies_age_;
156 
157  // allow skipping updating dependencies_age_ for temporary ModelObjects
158  bool dependencies_saved_;
159  unsigned saved_dependencies_age_;
160  // We don't use ModelObjectsTemp here because these objects might get freed
161  // under us, which would cause WeakPointer to raise an exception
162  std::vector<ModelObject *> mos_added_since_save_, mos_removed_since_save_;
163 
164  // cache of restraints that are affected by each moved particle,
165  // used for evaluate_moved() and related functions
166  internal::MovedParticlesRestraintCache moved_particles_restraint_cache_;
167  // cache of particles that are affected by each moved particle
168  internal::MovedParticlesParticleCache moved_particles_particle_cache_;
169  // time when moved_particles_*_cache_ were last updated, or 0
170  unsigned moved_particles_cache_age_;
171 
172  void register_unique_id();
173 
174  friend class cereal::access;
175 
176  template<class Archive> void serialize(Archive &ar,
177  std::uint32_t const version) {
178  ar(cereal::base_class<Object>(this));
179  // We need to get unique_id_ early on read, so that any ModelObjects
180  // that reference it get correctly associated with this model
181  ar(unique_id_);
182  if (std::is_base_of<cereal::detail::InputArchiveBase, Archive>::value) {
183  register_unique_id();
184  }
185  ar(cereal::base_class<internal::FloatAttributeTable>(this),
186  cereal::base_class<internal::StringAttributeTable>(this),
187  cereal::base_class<internal::IntAttributeTable>(this),
188  cereal::base_class<internal::IntsAttributeTable>(this),
189  cereal::base_class<internal::FloatsAttributeTable>(this),
190  cereal::base_class<internal::ParticleAttributeTable>(this),
191  cereal::base_class<internal::ParticlesAttributeTable>(this));
192 
193  if (std::is_base_of<cereal::detail::InputArchiveBase, Archive>::value) {
194  size_t count;
195  free_particles_.clear();
196  ar(count);
197  particle_index_.clear();
198  while(count-- > 0) {
199  std::string name;
200  ar(name);
201  add_particle(name);
202  }
203  ParticleIndexes to_free;
204  ar(to_free);
205  for (auto pi : to_free) {
206  remove_particle(pi);
207  }
208  } else {
209  size_t count = particle_index_.size();
210  ar(count);
211  for (size_t i = 0; i < count; ++i) {
212  std::string name;
213  if (get_has_particle(ParticleIndex(i))) {
214  name = get_particle_name(ParticleIndex(i));
215  }
216  ar(name);
217  }
218  ar(free_particles_);
219  }
220 
221  // Need particle info before anything that might refer to a particle
222  // (ScoreState, or arbitrary Object)
223  ar(cereal::base_class<internal::ObjectAttributeTable>(this),
224  cereal::base_class<internal::ObjectsAttributeTable>(this),
225  cereal::base_class<internal::WeakObjectAttributeTable>(this),
226  model_data_, mutable_access_score_states());
227 
228  if (std::is_base_of<cereal::detail::InputArchiveBase, Archive>::value) {
229  // clear caches
230  age_counter_ = 1;
231  trigger_age_.clear();
232  dependencies_age_ = 0;
233  saved_dependencies_age_ = 0;
234  dependencies_saved_ = false;
235  moved_particles_cache_age_ = 0;
236  }
237  }
238 
239  // update model age (can never be zero, even if it wraps)
240  void increase_age() {
241  age_counter_++;
242  if (age_counter_ == 0) {
243  age_counter_ = 1;
244  }
245  }
246 
247  template <class MOType, class MOVector>
248  void do_get_dependent(ModelObject *mo, MOVector &ret) {
249  const auto &node = dependency_graph_.find(mo);
251  "Object " << mo->get_name()
252  << " does not have dependencies.");
253  IMP_INTERNAL_CHECK(node != dependency_graph_.end(),
254  "Node not in dependency_graph.");
255  MOType *r = dynamic_cast<MOType *>(mo);
256  if (r) {
257  ret.push_back(r);
258  }
259  for (ModelObject *cur : node->second.get_outputs()) {
260  do_get_dependent<MOType, MOVector>(cur, ret);
261  }
262  for (ModelObject *cur : node->second.get_readers()) {
263  do_get_dependent<MOType, MOVector>(cur, ret);
264  }
265  }
266 
267 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
268  // things the evaluate template functions need, can't be bothered with friends
269  public:
270 #endif
271  // check more things on the first call
272  bool first_call_;
273  // the stage of evaluation
274  internal::Stage cur_stage_;
275 
276  //! Get all Restraints that depend on the given particle
277  const std::set<Restraint *> &get_dependent_restraints(ParticleIndex pi) {
278  return moved_particles_restraint_cache_.get_dependent_restraints(pi);
279  }
280 
281  //! Get all particles that depend on the given particle
282  const ParticleIndexes &get_dependent_particles(ParticleIndex pi) {
283  return moved_particles_particle_cache_.get_dependent_particles(pi);
284  }
285 
286  ModelObjectsTemp get_dependency_graph_inputs(const ModelObject *mo) const;
287  ModelObjectsTemp get_dependency_graph_outputs(const ModelObject *mo) const;
288  bool do_get_has_dependencies(const ModelObject *mo) const {
289  return no_dependencies_.find(mo) == no_dependencies_.end();
290  }
291  void do_set_has_dependencies(const ModelObject *mo, bool tf);
292  void do_set_has_all_dependencies(bool tf);
293 
294  void validate_computed_derivatives() const {}
295  void set_has_all_dependencies(bool tf);
296  bool get_has_all_dependencies() const;
297  void check_dependency_invariants() const;
298  void check_dependency_invariants(const ModelObject *mo) const;
299  ScoreStatesTemp get_ancestor_score_states(const ModelObject *mo) const;
300  ScoreStatesTemp get_descendent_score_states(const ModelObject *mo) const;
301 
302  void before_evaluate(const ScoreStatesTemp &states);
303  void after_evaluate(const ScoreStatesTemp &states, bool calc_derivs);
304 
305  internal::Stage get_stage() const { return cur_stage_; }
306  ParticleIndex add_particle_internal(Particle *p);
307  static void do_remove_score_state(ScoreState *obj);
308  void do_add_score_state(ScoreState *obj);
309  void do_remove_particle(ParticleIndex pi);
310  bool do_get_has_required_score_states(const ModelObject *mo) const;
311  void do_set_has_required_score_states(ModelObject *mo, bool tf);
312  const ScoreStatesTemp &do_get_required_score_states(const ModelObject *mo)
313  const {
314  IMP_USAGE_CHECK(do_get_has_required_score_states(mo),
315  "Doesn't have score states");
316  return required_score_states_.find(mo)->second;
317  }
318  void do_add_model_object(ModelObject *mo);
319  void do_remove_model_object(ModelObject *mo);
320 
321  public:
322  //! Construct an empty model
323  Model(std::string name = "Model %1%");
324 
325  public:
326 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
327  IMP_MODEL_IMPORT(internal::FloatAttributeTable);
328  IMP_MODEL_IMPORT(internal::StringAttributeTable);
329  IMP_MODEL_IMPORT(internal::IntAttributeTable);
330  IMP_MODEL_IMPORT(internal::ObjectAttributeTable);
331  IMP_MODEL_IMPORT(internal::WeakObjectAttributeTable);
332  IMP_MODEL_IMPORT(internal::IntsAttributeTable);
333  IMP_MODEL_IMPORT(internal::FloatsAttributeTable);
334  IMP_MODEL_IMPORT(internal::ObjectsAttributeTable);
335  IMP_MODEL_IMPORT(internal::ParticleAttributeTable);
336  IMP_MODEL_IMPORT(internal::ParticlesAttributeTable);
337 #endif
338  //! Clear all the cache attributes of a given particle.
339  void clear_particle_caches(ParticleIndex pi);
340 
341  //! Add particle to the model
342  ParticleIndex add_particle(std::string name);
343 
344  //! Get the name of a particle
345  std::string get_particle_name(ParticleIndex pi);
346 
347  //! Add the passed Undecorator to the particle.
348  void add_undecorator(ParticleIndex pi, Undecorator *d);
349 
350 #if !defined(IMP_DOXYGEN)
351  RestraintsTemp get_dependent_restraints_uncached(ParticleIndex pi);
352 
353  ParticlesTemp get_dependent_particles_uncached(ParticleIndex pi);
354 
355  ScoreStatesTemp get_dependent_score_states_uncached(ParticleIndex pi);
356 #endif
357 
358  /** @name States
359 
360  ScoreStates maintain invariants in the Model (see ScoreState
361  for more information.)
362 
363  ScoreStates do not need to be explicitly added to the Model, but they
364  can be if desired in order to keep them alive as long as the model is
365  alive.
366 
367  \advancedmethod
368  */
369  /**@{*/
370  IMP_LIST_ACTION(public, ScoreState, ScoreStates, score_state, score_states,
371  ScoreState *, ScoreStates, do_add_score_state(obj), {},
372  do_remove_score_state(obj));
373  /**@}*/
374 
375  public:
376 #ifndef SWIG
377  using Object::clear_caches;
378 #endif
379 
380  //! Sometimes it is useful to be able to make sure the model is up to date
381  /** This method updates all the state but does not necessarily compute the
382  score. Use this to make sure that your containers and rigid bodies are
383  up to date.
384  */
385  void update();
386 
387 #ifdef IMP_DOXYGEN
388  /** \name Accessing attributes
389  \anchor model_attributes
390  All the attribute data associated with each Particle are stored in the
391  Model. For each type of attribute, there are the methods detailed below
392  (where, eg, TypeKey is FloatKey or StringKey)
393  @{
394  */
395  //! add particle atribute with the specied key and initial value
396  /** \pre get_has_attribute(attribute_key, particle) is false*/
397  void add_attribute(TypeKey attribute_key, ParticleIndex particle, Type value);
398 
399  //! remove particle attribute with the specied key
400  /** \pre get_has_attribute(attribute_key, particle) is true*/
401  void remove_attribute(TypeKey attribute_key, ParticleIndex particle);
402 
403  //! return true if particle has attribute with the specified key
404  bool get_has_attribute(TypeKey attribute_key, ParticleIndex particle) const;
405 
406  //! set the value of particle attribute with the specified key
407  /** \pre get_has_attribute(attribute_key, particle) is true*/
408  void set_attribute(TypeKey attribute_key, ParticleIndex particle, Type value);
409 
410  //! get the value of the particle attribute with the specified key
411  /** \pre get_has_attribute(attribute_key, particle) is true*/
412  Type get_attribute(TypeKey attribute_key, ParticleIndex particle);
413 
414  /** Cache attributes, unlike normal attributes, can be added during
415  evaluation. They are also cleared by the clear_cache_attributes() method.
416  Cache attributes should be used when one is adding data to a particle
417  to aid scoring (eg cache the rigid body collision acceleration structure).
418 
419  When some pertinent aspect of the particle changes, the clear method
420  should
421  be called (yes, this is a bit vague). Examples where it should be cleared
422  include changing the set of members of a core::RigidBody or their
423  coordinates, changing the members of an atom::Hierarchy.
424  */
425  void add_cache_attribute(TypeKey attribute_key, ParticleIndex particle,
426  Type value);
427 
428  //! Optimized attributes are the parameters of the model that are
429  //! allowed to be modified by samplers and optimizers
430  void set_is_optimized(TypeKey attribute_key, ParticleIndex particle,
431  bool true_or_false);
432 /** @} */
433 #endif
434 
435 #ifdef SWIG
436 #define IMP_MODEL_ATTRIBUTE_METHODS(Type, Value) \
437  void add_attribute(Type##Key attribute_key, ParticleIndex particle, \
438  Value value); \
439  void remove_attribute(Type##Key attribute_key, ParticleIndex particle); \
440  bool get_has_attribute(Type##Key attribute_key, \
441  ParticleIndex particle) const; \
442  void set_attribute(Type##Key attribute_key, ParticleIndex particle, \
443  Value value); \
444  Value get_attribute(Type##Key attribute_key, ParticleIndex particle); \
445  void add_cache_attribute(Type##Key attribute_key, ParticleIndex particle, \
446  Value value)
447 
448  IMP_MODEL_ATTRIBUTE_METHODS(Float, Float);
449  IMP_MODEL_ATTRIBUTE_METHODS(Int, Int);
450  IMP_MODEL_ATTRIBUTE_METHODS(Floats, Floats);
451  IMP_MODEL_ATTRIBUTE_METHODS(Ints, Ints);
452  IMP_MODEL_ATTRIBUTE_METHODS(String, String);
453  IMP_MODEL_ATTRIBUTE_METHODS(ParticleIndexes, ParticleIndexes);
454  IMP_MODEL_ATTRIBUTE_METHODS(ParticleIndex, ParticleIndex);
455  IMP_MODEL_ATTRIBUTE_METHODS(Object, Object *);
456  IMP_MODEL_ATTRIBUTE_METHODS(WeakObject, Object *);
457  void set_is_optimized(FloatKey, ParticleIndex, bool);
458  void add_to_derivative(FloatKey k, ParticleIndex particle, double v,
459  const DerivativeAccumulator &da);
460 #endif
461 
462  //! Get the particle from an index.
464  IMP_USAGE_CHECK(get_has_particle(p), "Invalid particle requested");
465  return particle_index_[p];
466  }
467 
468  //! Check whether a given particle index exists.
470  if (particle_index_.size() <= get_as_unsigned_int(p)) return false;
471  return particle_index_[p];
472  }
473 
474  //! Get all particle indexes
476 
477  //! Get all the ModelObjects associated with this Model.
478  ModelObjectsTemp get_model_objects() const;
479 
480  //! Remove a particle from the Model.
481  /** The particle will then be inactive and cannot be used for anything
482  and all data stored in the particle is lost.
483  */
484  void remove_particle(ParticleIndex pi);
485 
486  /** \name Storing data in the model
487 
488  One can store data associated with the model. This is used, for example,
489  to keep a central ScoreState to normalize rigid body rotational variables.
490  @{ */
491  //! Store a piece of data in the model referenced by the key.
492  void add_data(ModelKey mk, Object *o);
493  //! Get back some data stored in the model.
494  Object *get_data(ModelKey mk) const;
495  //! Remove data stored in the model.
496  void remove_data(ModelKey mk);
497  //! Check if the model has a certain piece of data attached.
498  bool get_has_data(ModelKey mk) const;
499  /** @} */
500 
501  /** \name Model triggers
502 
503  Triggers can be used to track when to clear and rebuild caches
504  of derived model properties. For example, a Restraint may restrain
505  two particles as a function of the number of chemical bonds between
506  them. To speed up this restraint, the bond graph can be cached; however,
507  this graph needs to be rebuilt if bonds are created or removed. This
508  can be achieved by checking that the model time (see get_age()) of the
509  cache matches the time when the 'bond added/removed' Trigger was last
510  updated (see get_trigger_last_updated()), either when the Restraint is
511  evaluated or in an associated ScoreState.
512 
513  Triggers are intended for events that are rare during a typical
514  optimization. Triggers can be created by any IMP module in either C++
515  or Python by creating a new TriggerKey, much as model attributes
516  are handled. To avoid name collisions, it is recommended to prepend
517  the module and/or class name to the trigger, e.g. "atom.Bond.changed".
518 
519  For an example, see IMP::score_functor::OrientedSoap, which uses
520  a cache built from the molecular hierarchy, which is cleared when the
521  IMP::core::Hierarchy::get_changed_key() trigger is updated.
522 
523  @{ */
524 
525  //! Get the current 'model time'.
526  /** This is a number 1 or more that tracks the 'age' of the model;
527  it is incremented every time before_evaluate() is called.
528  It may wrap (and so should not be assumed to always increase)
529  but will never be 0. */
530  unsigned get_age() { return age_counter_; }
531 
532  //! Get the time when the given trigger was last updated, or 0.
533  /** Return the 'model time' (as given by get_age()) when the given
534  trigger was last updated on this model, or 0 if never. */
536  if (trigger_age_.size() > tk.get_index()) {
537  return trigger_age_[tk.get_index()];
538  } else {
539  return 0;
540  }
541  }
542 
543  //! Update the given trigger
545  if (tk.get_index() >= trigger_age_.size()) {
546  trigger_age_.resize(tk.get_index() + 1, 0);
547  }
548  trigger_age_[tk.get_index()] = age_counter_;
549  }
550  /** @} */
551 
552  //! Get the model age when ModelObject dependencies were last changed, or 0.
553  /** This gives the Model age (see get_age()) when Particles, Restraints,
554  or ScoreStates were last added or removed. It is typically used to
555  help maintain caches that depend on the model's dependency graph. */
556  unsigned get_dependencies_updated() { return dependencies_age_; }
557 
558  //! Mark a 'restore point' for ModelObject dependencies.
559  /** \see restore_dependencies() */
561  dependencies_saved_ = true;
562  saved_dependencies_age_ = dependencies_age_;
564  mos_added_since_save_.clear();
565  mos_removed_since_save_.clear();
566  }
567  }
568 
569  //! Restore ModelObject dependencies to previous restore point.
570  /** This method, when paired with save_dependencies(), can be used to
571  avoid triggering a model dependency update due to a temporary change
572  in the model dependency graph, for example due to adding a temporary
573  restraint, evaluating it, then removing that same restraint. It should
574  only be called in cases where it is known that the dependency graph
575  is the same as when save_dependencies() was called (this is only checked
576  in debug mode). Save/restore call pairs cannot be nested, although it
577  is OK to skip the call to restore_dependencies(), e.g. if an exception
578  occurs.
579 
580  \see get_dependencies_updated()
581  \see save_dependencies()
582  */
584  if (dependencies_saved_) {
585  dependencies_saved_ = false;
586  dependencies_age_ = saved_dependencies_age_;
588  // Need to sort pointers since we may not add/remove in the same order
589  std::sort(mos_added_since_save_.begin(), mos_added_since_save_.end());
590  std::sort(mos_removed_since_save_.begin(),
591  mos_removed_since_save_.end());
592  IMP_INTERNAL_CHECK(mos_added_since_save_ == mos_removed_since_save_,
593  "ModelObjects added do not match those removed");
594  }
595  }
596  }
597 
598  //! Get an upper bound on the number of particles in the Model.
599  /** This value is guaranteed to be at least the number of particles in
600  the model (there may be fewer particles if any have been removed)
601  and every ParticleIndex will be smaller than this value. */
602  unsigned get_particles_size() const { return particle_index_.size(); }
603 
604  //! Get the unique ID of this Model.
605  /** When multiple Models exist simultaneously, each has a different unique ID.
606  */
607  uint32_t get_unique_id() const {
608  return unique_id_;
609  }
610 
611  //! Return the Model with the given unique ID.
612  /** If no Model with this ID exists, nullptr is returned. */
613  static Model* get_by_unique_id(uint32_t id) {
614  return model_map_.get(id);
615  }
616 
618 
619  public:
620 #if !defined(IMP_DOXYGEN)
621  virtual void do_destroy() override;
622 #endif
623 };
624 
625 IMPKERNEL_END_NAMESPACE
626 
627 CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(
628  IMP::Model, cereal::specialization::member_serialize);
629 
630 CEREAL_CLASS_VERSION(IMP::Model, 1);
631 
632 // This is needed for per cpp compilations, a not even sure why
633 // (perhaps cause Model returns ParticleIterator here and there?)
634 // - Feel free to remove if you *really* know what you're doing
635 #include "IMP/Particle.h"
636 
637 #endif /* IMPKERNEL_MODEL_H */
Particle * get_particle(ParticleIndex p) const
Get the particle from an index.
Definition: Model.h:463
Basic types used by IMP.
#define IMP_IF_CHECK(level)
Execute the code block if a certain level checks are on.
Definition: check_macros.h:104
Used to hold a set of related restraints.
boost::graph DependencyGraph
Directed graph on the interactions between the various objects in the model.
The base class for undecorators.
#define IMP_OBJECT_METHODS(Name)
Define the basic things needed by any Object.
Definition: object_macros.h:25
void restore_dependencies()
Restore ModelObject dependencies to previous restore point.
Definition: Model.h:583
Index< ParticleIndexTag > ParticleIndex
Definition: base_types.h:161
void add_particle(RMF::FileHandle fh, Particle *hs)
Macros to help in defining tuple classes.
virtual void clear_caches()
Definition: Object.h:270
unsigned get_dependencies_updated()
Get the model age when ModelObject dependencies were last changed, or 0.
Definition: Model.h:556
A more IMP-like version of the std::vector.
Definition: Vector.h:42
unsigned get_particles_size() const
Get an upper bound on the number of particles in the Model.
Definition: Model.h:602
unsigned get_age()
Get the current 'model time'.
Definition: Model.h:530
bool get_has_particle(ParticleIndex p) const
Check whether a given particle index exists.
Definition: Model.h:469
Macros to define containers of objects.
unsigned get_trigger_last_updated(TriggerKey tk)
Get the time when the given trigger was last updated, or 0.
Definition: Model.h:535
#define IMP_INTERNAL_CHECK(expr, message)
An assertion to check for internal errors in IMP. An IMP::ErrorException will be thrown.
Definition: check_macros.h:139
Class for storing model, its restraints, constraints, and particles.
Definition: Model.h:86
Base class for objects in a Model that depend on other objects.
Definition: ModelObject.h:28
virtual void do_destroy()
Definition: Object.h:274
Common base class for heavy weight IMP objects.
Definition: Object.h:111
ParticleIndexes get_particle_indexes(ParticlesTemp const &particles)
ScoreStates maintain invariants in the Model.
Definition: ScoreState.h:56
static Model * get_by_unique_id(uint32_t id)
Return the Model with the given unique ID.
Definition: Model.h:613
uint32_t get_unique_id() const
Get the unique ID of this Model.
Definition: Model.h:607
Implements a vector tied to a particular index of type Index<Tag>.
Definition: Index.h:81
Shared score state.
Base class for objects in a Model that depend on other objects.
Classes to handle individual model particles. (Note that implementation of inline functions is in int...
A nullptr-initialized pointer to an IMP Object.
void save_dependencies()
Mark a 'restore point' for ModelObject dependencies.
Definition: Model.h:560
A shared base class to help in debugging and things.
Represents a scoring function on the model.
double Float
Basic floating-point value (could be float, double...)
Definition: types.h:19
Class to handle individual particles of a Model object.
Definition: Particle.h:43
bool get_has_dependencies() const
Return whether this object has dependencies computed.
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:168
Abstract base class for all restraints.
int Int
Basic integer value.
Definition: types.h:34
void set_trigger_updated(TriggerKey tk)
Update the given trigger.
Definition: Model.h:544
std::string String
Basic string value.
Definition: types.h:43
Class for adding derivatives from restraints to the model.