IMP logo
IMP Manual  develop.5128fd965d,2024/12/03
Dependencies

IMP needs to keep track of how various IMP::Particle, IMP::ScoreState, IMP::Restraint and other things related to one another. For example, it needs to know that in order to evaluate a certain IMP::Restraint, the IMP::ScoreState managing the IMP::core::RigidBody that one of the restraint's input particles is an IMP::core::RigidMember of needs to be updated.

The set of objects that can be involved in the graph are ones derived from IMP::ModelObject. The IMP::ModelObject::get_inputs() and IMP::ModelObject::get_outputs() return the input and output model objects. These lists of inputs and outputs are used to build an IMP::DependencyGraph, a DAG that relates the data flow between IMP::ModelObject instances. As the most important type of IMP::ModelObject is IMP::ScoreState, IMP::ModelObject::get_required_score_states() returns all the score states that are upstream in the DAG from that IMP::ModelObject.

Dependencies are needed when restraints are evaluated. To get them, call IMP::Model::set_has_dependencies(true) (undocumented). That goes over all known IMP::ModelObject, asks them for their inputs and outputs and builds the graph. It then flows over the graph to compute the IMP::ScoreState that is upstream from each each IMP::ModelObject. These are stored in each IMP::ModelObject using the (private) IMP::ModelObject::set_has_dependencies(true, score_states) call.

When the graph changes, it must be updated. This is done by simply invalidating the graph when necessary. This invalidation occurs when

  • a new IMP::ModelObject is created that has a non-empty IMP::ModelObject::get_outputs().
  • when IMP::Model::set_has_dependencies(false) is called to deliberately invalidate all dependencies

Each IMP::ModelObject has a bit for whether its dependencies are valid (IMP::ModelObject::get_has_dependencies()). Its dependencies will be updated any time they are needed (particularly when its IMP::ModelObject::get_required_score_states() method is called. This occurs by having the IMP::Model create the dependency graph if needed and then for each input

  • add its IMP::ModelObject::get_required_score_state() to the list
  • if it is an IMP::ScoreState, add it to the list.

Code can often be made more efficient by caching any data structures that are derived from the dependency graph, since this graph rarely changes in many common workflows. To aid in this, use the IMP::Model::get_dependencies_updated() method, which returns the model age when the graph was last updated.