Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MonteCarlo.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file
11 /// @brief
12 /// @author Phil Bradley
13 
14 // Unit Headers
17 
18 // Project Headers
19 #include <core/pose/Pose.hh>
20 #include <core/scoring/Energies.hh>
22 
23 // ObjexxFCL Headers
24 #include <ObjexxFCL/format.hh>
25 #include <ObjexxFCL/string.functions.hh> //Pretty output.
26 
27 // Numeric Headers
28 #include <numeric/numeric.functions.hh>
29 #include <numeric/random/random.hh>
30 
31 // Utility Headers
32 #include <basic/Tracer.hh>
33 #include <basic/prof.hh>
34 
35 #include <basic/options/option.hh>
36 #include <basic/options/keys/mc.OptionKeys.gen.hh>
37 
39 #include <utility/vector1.hh>
40 
41 
42 // for rosetta++ like boinc graphics
43 #ifdef BOINC_GRAPHICS
44 #include <protocols/boinc/boinc.hh>
45 #endif
46 
47 using basic::T;
48 using basic::Error;
49 using basic::Warning;
50 
51 static basic::Tracer TR("protocols.moves.MonteCarlo");
52 static numeric::random::RandomGenerator mc_RG(62452); // <- Magic number, do not change it!!!
53 
54 namespace protocols {
55 namespace moves {
56 
57 using namespace core;
58 using namespace ObjexxFCL::fmt;
59 
60 /// @details The copy constructor does not copy the OPs, but rather creates new objects using the copy
61 /// constructors or the clone() methods of the objects being pointed at. This is important, since otherwise,
62 /// a copy of a Monte Carlo object could corrupt the state held in the original MonteCarlo object.
64  utility::pointer::ReferenceCount(),
65  last_accepted_pose_( src.last_accepted_pose_ ? new core::pose::Pose( * src.last_accepted_pose_ ) : 0 ),
66  lowest_score_pose_( src.lowest_score_pose_ ? new core::pose::Pose( * src.lowest_score_pose_ ) : 0 ),
67  temperature_( src.temperature_ ),
68  score_function_( src.score_function_ ? src.score_function_->clone() : static_cast< core::scoring::ScoreFunction * > (0) ),
69  autotemp_( src.autotemp_ ),
70  quench_temp_( src.quench_temp_ ),
71  last_accept_( src.last_accept_ ),
72  mc_accepted_( src.mc_accepted_ ),
73  counter_( src.counter_ ),
74  update_boinc_( src.update_boinc_ ),
75  total_score_of_last_considered_pose_( src.total_score_of_last_considered_pose_ ),
76  last_accepted_score_( src.last_accepted_score_ ),
77  lowest_score_( src.lowest_score_ ),
78  heat_after_cycles_( src.heat_after_cycles_ ),
79  convergence_checks_( src.convergence_checks_ ),
80  last_check_( src.last_check_ ),
81  check_frequency_( src.check_frequency_ )
82 {
83 }
84 
85 
86 // constructor for monte_carlo object
88  Pose const & init_pose, // PoseCOP init_pose,
89  ScoreFunction const & scorefxn, // ScoreFunctionCOP scorefxn,
90  Real const temperature
91 ):
92  temperature_( temperature ),
93  autotemp_( false ),
94  quench_temp_( 0.0 ),
95  last_accept_( 0 ),
96  mc_accepted_( MCA_accepted_score_beat_last ), // init_pose beats the absence of a pose
97  update_boinc_( true ),
98  total_score_of_last_considered_pose_( 0.0 ),
99  last_accepted_score_( 0.0 ),
100  lowest_score_( 0.0 ),
101  heat_after_cycles_( 150 )
102 {
103  last_accepted_pose_ = new Pose();
104  lowest_score_pose_ = new Pose();
105  // score_function_ = new ScoreFunction(scorefxn);
106  score_function_ = scorefxn.clone();
107  reset( init_pose );
108 
109  last_check_ = 0;
110  check_frequency_ = basic::options::option[ basic::options::OptionKeys::mc::convergence_check_frequency ]();
111 }
112 
114  ScoreFunction const & scorefxn, // ScoreFunctionCOP scorefxn,
115  Real const temperature
116 ):
117  temperature_( temperature ),
118  autotemp_( false ),
119  quench_temp_( 0.0 ),
120  last_accept_( 0 ),
121  mc_accepted_( MCA_accepted_score_beat_last ), // an empty pose beats the absence of a pose
122  update_boinc_( true ),
123  total_score_of_last_considered_pose_( 0.0 ),
124  last_accepted_score_( 0.0 ),
125  lowest_score_( 0.0 ),
126  heat_after_cycles_( 150 )
127 {
128  last_accepted_pose_ = new Pose();
129  lowest_score_pose_ = new Pose();
130  // score_function_ = new ScoreFunction(scorefxn);
131  score_function_ = scorefxn.clone();
132  last_check_ = 0;
133  check_frequency_ = basic::options::option[ basic::options::OptionKeys::mc::convergence_check_frequency ]();
134 }
135 
136 
138 {
139 }
140 
141 
143  last_accepted_pose_ = new Pose();
144  lowest_score_pose_ = new Pose();
145 }
146 
147 void
149  Pose const & init_pose,
150  ScoreFunction const & scorefxn
151 ){
152  // score_function_ = new ScoreFunction(scorefxn);
153  score_function_ = scorefxn.clone();
154  reset(init_pose);
155 }
156 
157 void
159 {
160  temperature_ = temp;
161 }
162 
163 /// return the simulation state to the lowest energy structure we've seen
164 void
166 {
167  ( pose ) = ( *lowest_score_pose_ );
169  //last_accepted_pose_ = new Pose( *lowest_score_pose_ );
170  last_accepted_score_ = last_accepted_pose_->energies().total_energy();
171 }
172 
173 
174 void
176 {
177  TR << "MC: " << temperature_
178  << " " << (*score_function_)(*last_accepted_pose_)
179  << " " << (*score_function_)(*lowest_score_pose_)
180  << " " << last_accepted_score()
181  << " " << lowest_score()
182  << " " << last_accept_
183  << " " << autotemp_
184  << " " << quench_temp_
185  << " " << mc_accepted_
186  << std::endl;
187  show_counters();
188 }
189 
190 /////////////////////////////////////////////////////////////////////////////
191 
192 void
194 {
195  TR << "MonteCarlo:: last_accepted_score,lowest_score: " <<
196  last_accepted_score() << ' ' << lowest_score() << std::endl;
197 }
198 /////////////////////////////////////////////////////////////////////////////
199 void
201 {
202  counter_.reset();
203 }
204 
205 ///@detail return number of trials since last reset
208  return counter_.total_trials();
209 }
210 /////////////////////////////////////////////////////////////////////////////
211 void
213  counter_.show();
214 }
215 
216 
217 /// set the scorefxn, re-scores last-accepted and lowest-score pose
218 void
220 {
221  using namespace scoring;
222 
223  // *score_function_ = scorefxn;
224  // score_function_ = new ScoreFunction(scorefxn);
225  score_function_ = scorefxn.clone();
226  //TR << "new score_function_ within mc!" << std::endl;
227 
228  lowest_score_ = (*score_function_)( *lowest_score_pose_ );
229  //TR << "lowest_score: " << lowest_score_ << " total: " << lowest_score_pose_->energies().total_energy() << std::endl;
230  /// Now handled automatically. score_function_->accumulate_residue_total_energies( *lowest_score_pose_ );
231 
232  if ( false ) { // DEBUG
233  pose::Pose copy_pose;
234  copy_pose = *lowest_score_pose_;
235  copy_pose.energies().clear();
236  TR << "score copy" << std::endl;
237  Real const copy_score = (*score_function_)( copy_pose );
238  if ( std::abs( copy_score - lowest_score_ ) > 1E-6) {
239  TR << "Score discrepancy. lowest_score: " << lowest_score_ << " vs copy score: " << copy_score << std::endl;
240  TR << "pose score: ";
241  lowest_score_pose_->energies().total_energies().show_if_nonzero_weight( TR , score_function_->weights() );
242  TR << std::endl;
243 
244  TR << "copy score: ";
245  copy_pose.energies().total_energies().show_if_nonzero_weight( TR , score_function_->weights() );
246  TR << std::endl;
247 
248  TR << "Difference: ";
249  core::scoring::EnergyMap emap = lowest_score_pose_->energies().total_energies();
250  emap -= copy_pose.energies().total_energies();
251  emap.show_if_nonzero_weight( TR, score_function_->weights() );
252  TR << std::endl;
253  }
254  }
255 
256  //T("protocols.moves.MonteCarlo.score_function") << "lowest_score";
257  //score_function_->show( T("protocols.moves.MonteCarlo.score_function"), *lowest_score_pose_ );
258  //T("protocols.moves.MonteCarlo.score_function");
259 
260  last_accepted_score_ = (*score_function_)( *last_accepted_pose_ );
261  //TR << "last_accepted_score: " << last_accepted_score << " total: " << last_accepted_pose_->energies().total_energy() << std::endl;
262  /// Now handled automatically. score_function_->accumulate_residue_total_energies( *last_accepted_pose_ );
263 
264 
265  if ( false ) { // DEBUG
266  pose::Pose copy_pose;
267  copy_pose = *last_accepted_pose_;
268  copy_pose.energies().clear();
269  TR << "score copy" << std::endl;
270  Real const copy_score = (*score_function_)( copy_pose );
271  if ( std::abs( copy_score - last_accepted_score_ ) > 1E-6) {
272  TR << "Score discrepancy. last_accepted_score: " << last_accepted_score_ << " vs copy score: " << copy_score << std::endl;
273  TR << "pose score: ";
274  last_accepted_pose_->energies().total_energies().show_if_nonzero_weight( TR, score_function_->weights() );
275  TR << std::endl;
276 
277  TR << "copy score: ";
278  copy_pose.energies().total_energies().show_if_nonzero_weight( TR, score_function_->weights() );
279  TR << std::endl;
280 
281  TR << "Difference: ";
282  core::scoring::EnergyMap emap = last_accepted_pose_->energies().total_energies();
283  emap -= copy_pose.energies().total_energies();
284  emap.show_if_nonzero_weight( TR, score_function_->weights() );
285  TR << std::endl;
286  }
287  }
288 
289 
290  //T("protocols.moves.MonteCarlo.score_function") << "last_accepted";
291  //score_function_->show( T("protocols.moves.MonteCarlo.score_function"), *last_accepted_pose_ );
292  //T("protocols.moves.MonteCarlo.score_function") << " finished!";
293 
294  ///SML 6/25/08 - if last accepted is now better than lowest, change it!
295  ///explicit this-> necessary to resolve function name against identically named local variables
296  if ( this->last_accepted_score() < this->lowest_score() ) {
297  PROF_START( basic::MC_ACCEPT );
300  PROF_STOP( basic::MC_ACCEPT );
301  }
302 
303 }
304 
305 
306 
307 /////////////////////////////////////////////////////////////////////////////
308 //////////////////////////////
309 // behavior depends on setting of temperature
310 //
311 // return true for an accept, false otherwise
312 //
313 // mc_accepted
314 // 3 = accepted:score beat low score and last_accepted score
315 // 2 = accepted:score beat last_accepted score
316 // 1 = thermally accepted: score worse than last_accepted score
317 // 0 = not accepted
318 
319 bool
321  Pose & pose,
322  std::string const & move_type, // = unk
323  core::Real const proposal_density_ratio, // = 1
324  core::Real const inner_score_temperature_delta // = 0
325 )
326 {
327 
328 // Work around a current bug in the pose observer classes..
329 #ifdef BOINC_GRAPHICS
330  if( update_boinc_ )
331  boinc::Boinc::update_graphics_current( pose );
332 #endif
333 
334 
335  // score the pose:
336  Real const score( (*score_function_)( pose ) );
337  total_score_of_last_considered_pose_ = score; // save this for the TrialMover so that it may keep statistics.
338 
339  if ( false ) { // DEBUG
340  pose::Pose copy_pose;
341  copy_pose = pose;
342  copy_pose.energies().clear();
343  TR << "score copy" << std::endl;
344  Real const copy_score = (*score_function_)( copy_pose );
345  if ( std::abs( copy_score - score ) > 1E-6) {
346  TR << "Score discrepancy. score: " << score << " vs copy score: " << copy_score << std::endl;
347  TR << "pose score: ";
349  TR << std::endl;
350 
351  TR << "copy score: ";
352  copy_pose.energies().total_energies().show_if_nonzero_weight( TR, score_function_->weights() );
353  TR << std::endl;
354 
355  TR << "Difference: ";
357  emap -= copy_pose.energies().total_energies();
358  emap.show_if_nonzero_weight( TR, score_function_->weights() );
359  TR << std::endl;
360  }
361  }
362 
363  counter_.count_trial( move_type );
364 
365 
366 #ifdef BOINC_GRAPHICS
367  if( update_boinc_ )
368  boinc::Boinc::update_mc_trial_info( counter_.trial( move_type ), move_type );
369 #endif
370 
371  Real const boltz_factor = ( last_accepted_score() - score ) / temperature_ + inner_score_temperature_delta;
372  Real const probability = std::exp( std::min (40.0, std::max(-40.0,boltz_factor)) ) * proposal_density_ratio;
373  if ( probability < 1 ) {
374  if ( mc_RG.uniform() >= probability ) {
375  mc_accepted_ = MCA_rejected; // rejected
376  autotemp_reject();
377  evaluate_convergence_checks( pose, true /*reject*/, false /* not final*/ );
378  pose = ( *last_accepted_pose_ );
379 
380  //TR << "Rejected with score = " << score
381  // << " ( prob = " << probability << " ) last_accepted scrore: " << last_accepted_score() << std::endl;
382  // score_function_->show( T("protocols.moves.MonteCarlo.boltzmann"), pose );
383 
384  return false; // rejected
385 
386 
387  }
388  mc_accepted_ = MCA_accepted_thermally; // accepted thermally
389 
390  //TR << "thermally accepted with score = " << score
391  // << " ( prob = " << probability << " ) last_accepted scrore: " << last_accepted_score() << std::endl;
392  // score_function_->show( T("protocols.moves.MonteCarlo.boltzmann"), pose );
393  } else {
394 
395  mc_accepted_ = MCA_accepted_score_beat_last; // energy is lower than last_accepted
396  }
397 
398  // these are useful but cost a little time to get
399  /// Now handled automatically. score_function_->accumulate_residue_total_energies( pose );
400 
401  counter_.count_accepted( move_type );
402  counter_.count_energy_drop( move_type, score - last_accepted_score() );
403  PROF_START( basic::MC_ACCEPT );
404  *last_accepted_pose_ = pose;
405  last_accepted_score_ = score;
406 
407 #ifdef BOINC_GRAPHICS
408  if( update_boinc_ )
409  boinc::Boinc::update_graphics_last_accepted( pose, last_accepted_score() );
410 #endif
411 
412 // last_accepted_pose_ = new Pose( *pose );
413 
414  autotemp_accept();
415 
416  if ( score < lowest_score() ) {
417  *lowest_score_pose_ = pose;
418  lowest_score_ = score;
419  evaluate_convergence_checks( pose, false /*not reject*/, false /*not final*/ );
420 
421 #ifdef BOINC_GRAPHICS
422  if( update_boinc_ )
423  boinc::Boinc::update_graphics_low_energy( pose, lowest_score() );
424 #endif
425 
426  //lowest_score_pose_ = new Pose ( pose );
428  }
429  PROF_STOP( basic::MC_ACCEPT );
430  return true; // accept!
431 }
432 
433 
434 bool
436  core::Real score_delta,
437  std::string const & move_type, // = "unk"
438  core::Real const proposal_density_ratio // = 1
439 )
440 {
441  // score the pose:
442  Real const score( last_accepted_score_ + score_delta );
443  total_score_of_last_considered_pose_ = score; // save this for the TrialMover so that it may keep statistics.
444 
445  counter_.count_trial( move_type );
446 
447  Real const boltz_factor = ( last_accepted_score() - score ) / temperature_;
448  Real const probability = std::exp( std::min (40.0, std::max(-40.0,boltz_factor)) ) * proposal_density_ratio;
449  if ( probability < 1 ) {
450  if ( mc_RG.uniform() >= probability ) {
451  mc_accepted_ = MCA_rejected; // rejected
452  autotemp_reject();
453 
454  //TR << "Rejected with score = " << score
455  // << " ( prob = " << probability << " ) last_accepted scrore: " << last_accepted_score() << std::endl;
456  // score_function_->show( T("protocols.moves.MonteCarlo.boltzmann"), pose );
457 
458  return false; // rejected
459  }
460  mc_accepted_ = MCA_accepted_thermally; // accepted thermally
461 
462  //TR << "thermally accepted with score = " << score
463  // << " ( prob = " << probability << " ) last_accepted scrore: " << last_accepted_score() << std::endl;
464  // score_function_->show( T("protocols.moves.MonteCarlo.boltzmann"), pose );
465  } else {
466 
467  mc_accepted_ = MCA_accepted_score_beat_last; // energy is lower than last_accepted
468  }
469 
470  counter_.count_accepted( move_type );
471  counter_.count_energy_drop( move_type, score - last_accepted_score() );
472  PROF_START( basic::MC_ACCEPT );
473  last_accepted_score_ = score;
474 
475  autotemp_accept();
476 
477  if ( score < lowest_score() ) {
478  lowest_score_ = score;
480  }
481  PROF_STOP( basic::MC_ACCEPT );
482  return true; // accept!
483 }
484 
485 
486 void
487 MonteCarlo::reset( Pose const & pose )
488 {
489  PROF_START( basic::MC_ACCEPT );
490  *last_accepted_pose_ = pose;
491  PROF_STOP( basic::MC_ACCEPT );
492 
493  Real const score( (*score_function_)( *last_accepted_pose_ ) );
494  /// Now handled automatically. score_function_->accumulate_residue_total_energies( *last_accepted_pose_ );
495 
496  PROF_START( basic::MC_ACCEPT );
498  PROF_STOP( basic::MC_ACCEPT );
499 
500  last_accepted_score_ = score;
501  lowest_score_ = score;
502 }
503 
504 
505 void
507 {
508  PROF_START( basic::MC_ACCEPT );
509  *last_accepted_pose_ = pose;
510  PROF_STOP( basic::MC_ACCEPT );
511 
512  Real const score( (*score_function_)( *last_accepted_pose_ ) );
513  /// Now handled automatically. score_function_->accumulate_residue_total_energies( *last_accepted_pose_ );
514  last_accepted_score_ = score;
515 
516  // if the last accepted pose has a lower energy that the lowest score pose, set that as well
517  if (last_accepted_pose_->energies().total_energy() < lowest_score_pose_->energies().total_energy()) {
518  PROF_START( basic::MC_ACCEPT );
520  PROF_STOP( basic::MC_ACCEPT );
521  }
522 }
523 
524 
525 
526 /////////////////////////////////////////////////////////////////////////////
527 void
529  bool const setting,
530  Real const quench_temp
531 )
532 {
533  autotemp_ = setting;
534  quench_temp_ = quench_temp;
535  last_accept_ = 0;
536 }
537 
538 
539 // for recovering from a checkpoint
540 void
542 {
543  *last_accepted_pose_ = pose;
544  last_accepted_score_ = last_accepted_pose_->energies().total_energy();
545 }
546 
547 // for recovering from a checkpoint
548 void
550 {
551  *lowest_score_pose_ = pose;
552  lowest_score_ = lowest_score_pose_->energies().total_energy();
553 }
554 
557 {
558  return *score_function_;
559 }
560 
561 Real
563 {
564  //if (last_accepted_pose_->energies().total_energy() != last_accepted_score_) {
565  // TR << "Last: " << last_accepted_pose_->energies().total_energy() << " != " << last_accepted_score_ << " diff " << last_accepted_pose_->energies().total_energy() - last_accepted_score_ << std::endl;
566  //}
567  //return last_accepted_pose_->energies().total_energy();
568  return last_accepted_score_;
569 }
570 
571 
572 Real
574 {
575  //if (lowest_score_pose_->energies().total_energy() != lowest_score_) {
576  // TR << "Low: " << lowest_score_pose_->energies().total_energy() << " != " << lowest_score_ << " diff " << lowest_score_pose_->energies().total_energy() - lowest_score_ << std::endl;
577  //}
578  //return lowest_score_pose_->energies().total_energy();
579  return lowest_score_;
580 }
581 
582 
583 MCA
585 {
586  return mc_accepted_;
587 }
588 
589 
590 /////////////////////////////////////////////////////////////////////////////
591 // replicate logic from monte_carlo.cc
592 //
593 // should probably make these parameters ( 150, 1.0 )
594 void
596 {
597  // int const heat_after_cycles( 150 );
598  Real const heat_delta( quench_temp_ * 0.5 );
599  Real const max_temperature( quench_temp_ * 10.0 );
600 
601  if ( !autotemp_ ) return;
602  if ( last_accept_ >= (int) heat_after_cycles_ ) {
603  //if ( temperature_ > max_temperature * 0.25 )
604  TR << "autotemp_reject -- heat: " << last_accept_<< ' ' << temperature_ << std::endl;
605  last_accept_ = -1;
606  temperature_ = std::min( temperature_ + heat_delta, max_temperature );
607  }
608  ++last_accept_;
609 }
610 
611 /////////////////////////////////////////////////////////////////////////////
612 // replicate logic from monte_carlo.cc
613 void
615 {
616  if ( !autotemp_ ) return;
617  if ( temperature_ != quench_temp_ ) {
619  TR << "autotemp_accept: reset temperature_ = " << temperature_ << std::endl;
620  }
621 
622  last_accept_ = 0;
623 }
624 
625 void
627  if ( !reject || numeric::mod( last_check_++, check_frequency_ ) == 0 ) {
629  (**it)( pose, *this, reject );
630  }
631  }
632 }
633 
634 void
636  convergence_checks_.push_back( check );
637 }
638 
639 // for Python bindings
640 std::ostream & operator << ( std::ostream & os, MonteCarlo const & mc)
641 {
642  os << "protocols.moves.MonteCarlo:\n";
643  os << "\"Temperature\" (kT): " << mc.temperature() << "\n";
644  os << "Total Trials: " << mc.total_trials() << "\n";
645  os << "Lowest Score: " << mc.lowest_score() << "\n";
646  os << "Last Accepted Score: " << mc.last_accepted_score() << "\n";
647  os << "last_accept = " << mc.lowest_score() << std::endl;
648  return os;
649 }
650 
651 } // namespace moves
652 } // namespace core