00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef IMP_MODEL_H
00010 #define IMP_MODEL_H
00011
00012 #include "kernel_config.h"
00013 #include "Object.h"
00014 #include "Particle.h"
00015 #include "container_macros.h"
00016 #include "base_types.h"
00017 #include "VersionInfo.h"
00018
00019 #include <limits>
00020
00021 IMP_BEGIN_NAMESPACE
00022
00023 class Particle;
00024 class Restraint;
00025 IMP_OBJECTS(Restraint);
00026
00027
00028
00029
00030 class ScoreState;
00031 IMP_OBJECTS(ScoreState);
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 class IMPEXPORT Model: public Object
00046 {
00047 private:
00048 friend class Restraint;
00049 friend class Particle;
00050 friend class RestraintSet;
00051 typedef Particle::Storage ParticleStorage;
00052
00053 ParticleStorage particles_;
00054 bool incremental_update_;
00055
00056 bool first_incremental_;
00057 bool last_had_derivatives_;
00058 bool gather_statistics_;
00059 bool score_states_ordered_;
00060 std::map<FloatKey, FloatRange> ranges_;
00061 enum Stage {NOT_EVALUATING, BEFORE_EVALUATE, EVALUATE, AFTER_EVALUATE};
00062 mutable Stage cur_stage_;
00063
00064 Stage get_stage() const {
00065 return cur_stage_;
00066 }
00067
00068 void order_score_states();
00069
00070 void add_particle_internal(Particle *p) {
00071 IMP_CHECK_OBJECT(this);
00072 IMP_CHECK_OBJECT(p);
00073 p->set_was_used(true);
00074 particles_.push_back(p);
00075 p->ps_->iterator_= --particles_.end();
00076 IMP_USAGE_CHECK(!p->ps_->model_, "Particle " << p->get_name()
00077 << " is already in model.");
00078 p->ps_->model_= this;
00079 internal::ref(p);
00080
00081 first_incremental_=true;
00082 if (get_is_incremental()) {
00083 p->setup_incremental();
00084 }
00085 }
00086
00087
00088 typedef std::pair<double, Restraint*> WeightedRestraint;
00089 typedef std::vector<WeightedRestraint> WeightedRestraints;
00090
00091 void validate_attribute_values() const ;
00092 void validate_incremental_evaluate(const WeightedRestraints &restraints,
00093 bool calc_derivs,
00094 double score);
00095 void validate_computed_derivatives() const;
00096
00097 void before_evaluate(const ScoreStatesTemp &states) const;
00098
00099 void after_evaluate(const ScoreStatesTemp &states, bool calc_derivs) const;
00100
00101 void zero_derivatives(bool shadow_too=false) const;
00102
00103 double do_evaluate(const WeightedRestraints &restraints,
00104 const ScoreStatesTemp &states, bool calc_derivs);
00105
00106 enum WhichRestraints {ALL, INCREMENTAL, NONINCREMENTAL};
00107 double do_evaluate_restraints(const WeightedRestraints &restraints,
00108 bool calc_derivs,
00109 WhichRestraints incremental_restraints,
00110 bool incremental_evaluation) const;
00111
00112 void reset_dependencies();
00113
00114 void do_show(std::ostream& out) const;
00115
00116 #if defined(SWIG)
00117 public:
00118 #else
00119 private:
00120 IMP_NO_DOXYGEN(template <class T> friend void IMP::internal::unref(T*));
00121 #endif
00122
00123 virtual ~Model();
00124 public:
00125
00126 Model();
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 IMP_LIST(public, ScoreState, score_state, ScoreState*, ScoreStates);
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 IMP_LIST(public, Restraint, restraint, Restraint*, Restraints);
00155
00156 public:
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 void remove_particle(Particle *p) {
00170 IMP_OBJECT_LOG;
00171 IMP_CHECK_OBJECT(this);
00172 IMP_CHECK_OBJECT(p);
00173 IMP_USAGE_CHECK(p->get_model() == this,
00174 "The particle does not belong to this model");
00175 IMP_LOG(VERBOSE, "Removing particle " << p->get_name()
00176 << std::endl);
00177 IMP_INTERNAL_CHECK(get_stage() == Model::NOT_EVALUATING,
00178 "Particles cannot be removed from the model during evaluation");
00179 particles_.erase(p->ps_->iterator_);
00180 p->ps_->model_=NULL;
00181 internal::unref(p);
00182 }
00183
00184
00185
00186
00187
00188 void restore_particle(Particle *p) {
00189 add_particle_internal(p);
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 unsigned int get_number_of_particles() const {
00202 return particles_.size();
00203 }
00204 #ifdef IMP_DOXYGEN
00205 class ParticleInterator; class ParticleConstIterator;
00206 #else
00207 typedef ParticleStorage::const_iterator ParticleConstIterator;
00208 typedef ParticleStorage::iterator ParticleIterator;
00209 #endif
00210 ParticleIterator particles_begin() {
00211 return particles_.begin();
00212 }
00213 ParticleIterator particles_end() {
00214 return particles_.end();
00215 }
00216
00217 #ifndef SWIG
00218 ParticleConstIterator particles_begin() const {
00219 return particles_.begin();
00220 }
00221 ParticleConstIterator particles_end() const {
00222 return particles_.end();
00223 }
00224 #endif
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 FloatRange get_range(FloatKey k) const;
00243
00244 void set_range(FloatKey k, FloatRange range) {
00245 ranges_[k]=range;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 virtual Float evaluate(bool calc_derivs);
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 virtual Float evaluate(const RestraintsTemp &restraints, bool calc_derivs);
00278
00279 #ifndef IMP_DOXYGEN
00280 VersionInfo get_version_info() const {
00281 IMP_CHECK_OBJECT(this);
00282 return IMP::get_module_version_info();
00283 }
00284
00285 std::string get_type_name() const {
00286 return "Model";
00287 }
00288 #endif
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 void set_is_incremental(bool tf);
00299
00300 bool get_is_incremental() const {
00301 return incremental_update_;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 void set_gather_statistics(bool tf);
00317 void show_statistics_summary(std::ostream &out=std::cout) const;
00318
00319 };
00320
00321 IMP_OUTPUT_OPERATOR(Model);
00322
00323 #ifndef IMP_DOXYGEN
00324
00325
00326 inline void Particle::assert_values_mutable() const {
00327 IMP_INTERNAL_CHECK(get_model()->get_stage() != Model::EVALUATE,
00328 "Restraints are not allowed to change attribute values during "
00329 << "evaluation.");
00330 IMP_INTERNAL_CHECK(get_model()->get_stage() != Model::AFTER_EVALUATE,
00331 "ScoreStates are not allowed to change attribute values after "
00332 << "evaluation.");
00333 #if IMP_BUILD < IMP_FAST
00334 IMP_IF_CHECK(USAGE_AND_INTERNAL) {
00335 if (ps_->write_locked_) throw internal::WriteLockedParticleException(this);
00336 }
00337 #endif
00338 }
00339
00340 inline void Particle::assert_values_readable() const {
00341 #if IMP_BUILD < IMP_FAST
00342 IMP_IF_CHECK(USAGE_AND_INTERNAL) {
00343 if (ps_->read_locked_) throw internal::ReadLockedParticleException(this);
00344 }
00345 #endif
00346 }
00347
00348 inline void Particle::assert_can_change_optimization() const {
00349 IMP_INTERNAL_CHECK(get_model()->get_stage() == Model::NOT_EVALUATING,
00350 "The set of optimized attributes cannot be changed during "
00351 << "evaluation.");
00352 }
00353
00354 inline void Particle::assert_can_change_derivatives() const {
00355 IMP_INTERNAL_CHECK(get_model()->get_stage() == Model::EVALUATE
00356 || get_model()->get_stage() == Model::AFTER_EVALUATE
00357 || get_model()->get_stage() == Model::NOT_EVALUATING,
00358 "Derivatives can only be changed during restraint "
00359 << "evaluation and score state after evaluation calls.");
00360 }
00361
00362 inline void Particle::assert_valid_derivatives() const {
00363 IMP_INTERNAL_CHECK(get_model()->get_stage() == Model::AFTER_EVALUATE
00364 || get_model()->get_stage() == Model::NOT_EVALUATING,
00365 "Derivatives can only be changed during restraint "
00366 << "evaluation and score state after evaluation calls.");
00367 }
00368 #endif
00369
00370 IMP_OBJECTS(Model);
00371
00372 IMP_END_NAMESPACE
00373
00374 #endif