Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MPI_LoopHashRefine.cc
Go to the documentation of this file.
1 
2 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
3 // vi: set ts=2 noet:
4 //
5 // (c) Copyright Rosetta Commons Member Institutions.
6 // (c) This file is part of the Rosetta software suite and is made available under license.
7 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
8 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
9 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
10 
11 /// @file src/protocols/loophash/MPI_LoopHashRefine.cc
12 /// @brief
13 /// @author Mike Tyka
14 #define TRDEBUG TR.Debug
15 
16 // MPI headers
17 #ifdef USEMPI
18 #include <mpi.h> //keep this first
19 #endif
20 
26 // AUTO-REMOVED #include <core/io/pdb/pose_io.hh>
27 #include <core/pose/util.hh>
37 #include <basic/options/keys/constraints.OptionKeys.gen.hh>
42 #include <basic/options/keys/in.OptionKeys.gen.hh>
43 // AUTO-REMOVED #include <basic/options/keys/out.OptionKeys.gen.hh>
44 // AUTO-REMOVED #include <basic/options/keys/relax.OptionKeys.gen.hh>
45 #include <basic/options/keys/lh.OptionKeys.gen.hh>
46 #include <basic/options/option.hh>
47 #include <core/pose/Pose.hh>
50 #include <basic/Tracer.hh>
51 #include <ObjexxFCL/format.hh>
52 
53 /// ObjexxFCL headers
54 #include <ObjexxFCL/string.functions.hh>
55 
56 // Utility headers
57 #include <numeric/random/random.hh>
58 
59 // C/C++ headers
60 #ifndef _WIN32 // REQUIRED FOR WINDOWS
61 // AUTO-REMOVED #include <unistd.h>
62 #endif
63 
64 //Auto Headers
66 #include <utility/vector1.hh>
67 
68 using namespace ObjexxFCL;
69 using namespace ObjexxFCL::fmt;
70 
71 namespace protocols {
72 namespace loophash {
73 
74 using namespace protocols::wum;
75 
76 static basic::Tracer TR("MPI.LHR");
77 
78 static numeric::random::RandomGenerator RG(9788321); // <- Magic number, do not change it (and dont try and use it anywhere else)
79 
80 MPI_LoopHashRefine::MPI_LoopHashRefine( char machine_letter ):
81  MPI_WorkUnitManager( machine_letter ),
82  max_lib_size_(50),
83  save_state_interval_(300),
84  last_save_state_(0),
85  totaltime_loophash_(0),
86  n_loophash_(0),
87  totaltime_batchrelax_(0),
88  n_batchrelax_(0),
89  total_structures_(0),
90  total_structures_relax_(0),
91  total_metropolis_(1),
92  total_metropolis_accepts_(0),
93  ident_string_("ident")
94 {
95  set_defaults(); // constructors must must must call this!
96 }
97 
98 void
100  using namespace basic::options;
101  using namespace basic::options::OptionKeys;
102 
103  max_lib_size_ = option[ OptionKeys::lh::max_lib_size ]();
104  save_state_interval_ = option[ OptionKeys::lh::mpi_save_state_interval ]();
105  mpi_feedback_ = option[ OptionKeys::lh::mpi_feedback ]();
106  mpi_metropolis_temp_ = option[ OptionKeys::lh::mpi_metropolis_temp ]();
107  rms_limit_ = option[ OptionKeys::lh::rms_limit ]();
108  objective_function_ = option[ OptionKeys::lh::objective_function ]();
109  mpi_resume_ = "";
110  if( option[ OptionKeys::lh::mpi_resume ].user() ){
111  mpi_resume_ = option[ OptionKeys::lh::mpi_resume ]();
112  }
113  jobname_ = option[ OptionKeys::lh::jobname ]();
114 
115  // Make ident string:
116  // Make a medley of a string and the PID
117  ident_string_ = option[ lh::jobname ];
118  TR << "IDENT: " << ident_string_ << std::endl;
119 
120  // make sure the state saves are randomly staggered - otherwise all the masters dump several hundred megs at once!
121  last_save_state_ = time(NULL) + core::Size( RG.uniform() * (core::Real) save_state_interval_) ;
122  TR << "Interlace dumps: " << last_save_state_ << " " << time(NULL) << " " << last_save_state_ - time(NULL) << " " << save_state_interval_ << " " << std::endl;
123 }
124 
125 void
127 {
128  using namespace basic::options;
129  using namespace basic::options::OptionKeys;
130 
132  TR << "Reading in structures..." << std::endl;
133 
136 
138 
139  core::Size count = 0;
140  SilentStructStore temp_lib;
141 
142 
143  // Rescore input structures for fair comparison with whatever comes back from relax calls
145  scorefxn = core::scoring::getScoreFunction();
147 
148 
149  while( input.has_another_pose() ) {
150  core::pose::Pose pose;
151  input.fill_pose( pose, *rsd_set );
152 
153  if ( option[ OptionKeys::constraints::cst_fa_file ].user() ) {
155  TR << "Read constraints: " << ( cstset->has_constraints() ? "YES" : "NONE" ) << std::endl;
156  pose.constraint_set( cstset );
157  }
158 
159  (*scorefxn)(pose);
160 
162  core::io::silent::SilentStructOP ss = option[ OptionKeys::lh::bss]() ?
165  ss->fill_struct( pose, "empty_tag" );
166  ss->add_energy( "censcore", 0 ); // centroidscore of last time this structure was in centroid form
167  ss->add_energy( "extra_score", 0 ); // extra_score is used if a different scoring scheme is used to select structures then to actually repack/relax them
168  ss->add_energy( "combined_score", 0 ); // extra_score + score
169  ss->add_energy( "parent_score", 0 ); // fa score of parent
170  ss->add_energy( "lhcount", 0 ); // lh count is the number of times this structure has been used to generate new loophashed structures
171  ss->add_energy( "round", 0 ); // round is the number of consecutive loophashes this structure has gone through
172  ss->add_energy( "expire", 0 ); // how many times has this structure been retired to the temporor ? >1 means it's been sent out again
173  if( ss->get_string_value("usid") == "" ){
174  ss->add_string_value( "usid", "_" + string_of(count)); // A unique structure id (usid) that will identify the structure until it is modified.
175  }
176  ss->add_string_value( "husid", ss->get_string_value("usid") ); // history of usids
177  ss->add_energy( "state", 0 ); // state: 0 init, 1 loophashed, 2 relaxed
178  ss->add_energy( "ltime", time(NULL) ); // time when it became active. This is used to expire structures that havn't changed for a while.
179  ss->add_energy( "master", mpi_rank() ); // what master is it curretnly on ? (volatile)
180  ss->add_energy( "emperor_count", 0 ); // what master is it curretnly on ? (volatile)
181  temp_lib.add( ss );
182  count ++;
183  }
184 
185  if ( temp_lib.size() == 0 ){
186  TR.Error << "Error reading starting structures: 0 valid structures read. Check your input files and parameters" << std::endl;
187  utility_exit_with_message( "Error reading starting structures: 0 valid structures read. Check your input files and parameters" );
188  }
189 
190  TR << "Loaded " << temp_lib.size() << " starting structures" << std::endl;
191 
192  core::Size position = structure_read_offset % temp_lib.size();
193  count=1;
194  while( library_central_.size() < max_lib_size_ ){
196  ss = temp_lib.get_struct( position )->clone();
197  ss->add_energy( "ssid", count );
198  library_central_.add( ss );
199  position++;
200  if(position>=temp_lib.size()) position = 0;
201  count++;
202  }
203 
204  TR << "Added " << library_central_.size() << " structures to library " << std::endl;
205 
206  runtime_assert( library_central_.size() == max_lib_size_ );
208 }
209 
210 void
213  long starttime = time(NULL);
214  write_queues_to_file( prefix + "." + string_of(mpi_rank()) );
215  library_central_.serialize_to_file( prefix + "." + string_of(mpi_rank())+ ".lib.library_central" );
216  long endtime = time(NULL);
217  TR << "Saved state: " << endtime - starttime << "s " << inbound().size() << " + " << outbound().size() << " + " << library_central_.size() << " + " << ( inbound().size() + outbound().size() + library_central_.size() ) << std::endl;
219 }
220 
221 void
224  TR << "Saving state.. " << std::endl;
225  last_save_state_ = time(NULL);
227  }
228 }
229 
230 void
233  inbound().clear();
234  outbound().clear();
235  read_queues_from_file( prefix + "." + string_of(mpi_rank()) );
237  library_central_.read_from_file( prefix + "." + string_of(mpi_rank()) + ".lib.library_central" );
239 }
240 
241 void
243  static int lasttime = 0;
244  if( (time(NULL) - lasttime) < 300 ) return;
245  lasttime = time(NULL);
246 
247  TR << "STATL: "
248  << wall_time() << "s "
249  << total_structures_ << " "
252  << " CPU: " << int((totaltime_batchrelax_+totaltime_loophash_)/3600) << " hrs "
253  << " r/l: " << F(5,2, float(totaltime_batchrelax_)/(float(totaltime_loophash_)+0.1))
254  << " LHav: " << int(totaltime_loophash_/(n_loophash_+1)) << "s "
255  << " BRav: " << int(totaltime_batchrelax_/(n_batchrelax_+1)) << "s "
256  << " MEM: " << int(library_central_.mem_footprint()/1024) << " kB " << std::endl;
257 }
258 
259 bool
261  // reset the lhcount to 0
262  pss.add_energy( "lhcount", 0 );
263  pss.add_energy( "ltime", time(NULL) );
264 
265  bool result = false;
266 
267  // default algorithm is set by class wide parameter
268  if( add_algorithm == "" ) add_algorithm = mpi_feedback_;
269  if( add_algorithm == "no" ) result = false;
270  else if( add_algorithm == "add_n_limit" ) result = add_structure_to_library_direct( pss );
271  else if( add_algorithm == "add_n_replace" ) result = add_structure_to_library_add_n_replace( pss );
272  else if( add_algorithm == "single_replace" ) result = add_structure_to_library_single_replace( pss );
273  else {
274  utility_exit_with_message( "FATAL ERROR: Unknown adding algorithm: '" + add_algorithm + "'" );
275  }
276  return result;
277 }
278 
279 bool
281 {
282  library_central_.add( pss );
283  return true;
284 }
285 
286 bool
288 {
289  using namespace basic::options;
290  using namespace basic::options::OptionKeys;
291 
292  core::Real new_struct_score = objective_function(pss);
293  pss.add_energy( "lhcount", 0 );
295  TRDEBUG << "Checking for zero size .. " << std::endl;
296  if( library_central_.size() == 0 ){
297 
299  return true;
300  }
301 
303  // if energy is wrse then worst member - ignore structure
304  if ( new_struct_score > objective_function(library_central_.store().back()) ){
305  TR << "Ignoring struc: " << new_struct_score << " > " << format_silent_struct(library_central_.store().back()) << std::endl;
306  return false;
307  }
308 
309  // now find the closest RMS
310  core::Real closest_rms = 1000000;
311  SilentStructStore::iterator closest_struct;
312 
314  jt != library_central_.end(); jt ++ )
315  {
316  core::Real the_rms;
317  // downcast
318  if ( option[ OptionKeys::lh::bss]() ) {
320  core::io::silent::BinaryProteinSilentStruct *ss = dynamic_cast < core::io::silent::BinaryProteinSilentStruct * > ( &(pss) );
321  if ( jt_pss == NULL || ss == NULL ) utility_exit_with_message( "FATAL ERROR: This code only runs with Binary Protein SilentStructs " );
322  the_rms = ss->CA_rmsd( *jt_pss );
323  } else {
324  core::io::silent::ProteinSilentStruct *jt_pss = dynamic_cast < core::io::silent::ProteinSilentStruct * > ( &(*(*jt)) );
325  core::io::silent::ProteinSilentStruct *ss = dynamic_cast < core::io::silent::ProteinSilentStruct * > ( &(pss) );
326  if ( jt_pss == NULL || ss == NULL ) utility_exit_with_message( "FATAL ERROR: This code only runs with Protein SilentStructs " );
327  the_rms = ss->CA_rmsd( *jt_pss );
328  }
329  TRDEBUG << "The rms: " << the_rms << std::endl;
330  if ( the_rms < closest_rms ){
331  //TR << "Found better: " << the_rms;
332  closest_rms = the_rms;
333  closest_struct = jt;
334  }
335  }
336 
337  core::Real rms_time = start_timer( TIMING_CPU );
338  TR << "RMS_Time: " << rms_time << std::endl;
339 
340  if ( closest_rms < rms_limit_ ){
341  // replace if lower in energy
342  core::Real energy_old = objective_function(*closest_struct);
343  TR << "Enew vd Eold " << new_struct_score << " " << energy_old << std::endl;
344  if( new_struct_score < energy_old ){
345  pss.add_energy( "lhcount", 0 );
346  *(*closest_struct) = pss;
347  return true;
348  }
349  }else{
350  // add
351  pss.add_energy( "lhcount", 0 );
352  library_central_.add( pss );
354  return true;
355  }
356  TR << "No structure added" << std::endl;
357  return false;
358 }
359 
360 bool
362 {
363  core::Real ssid = pss.get_energy("ssid");
364 
365  // now find the library structure with the same ssid
366  find_SilentStructOPs predic("ssid", ssid);
367  SilentStructStore::iterator ssid_match = std::find_if( library_central_.begin(), library_central_.end(), predic );
368 
369  if( ssid_match == library_central_.end() ){
370  TR << "ssid expired: " + ObjexxFCL::string_of( ssid ) + " - rejected structure" << std::endl;
371  print_library();
372  return false;
373  }
374 
375 
376  bool replace_it = false;
377  // to get library replacement you must either: be of a more advanced round or have lower energy
378  if( pss.get_energy("round") > (*ssid_match)->get_energy("round") ) replace_it = true;
379  else {
380  if( objective_function(pss) < objective_function(*ssid_match)) replace_it = true;
381  }
382 
383  if( replace_it ){
384  core::Real new_energy = objective_function(pss);
385  core::Real old_energy = objective_function(*ssid_match);
386 
387  bool metropolis_replace = false;
388 
389  core::Real energy_diff_T = 0;
390  if( mpi_metropolis_temp_ > 0.0 ) energy_diff_T = old_energy - new_energy;
391 
392  if( ( energy_diff_T >= 0.0 ) ) metropolis_replace = true; // energy of new is simply lower
393  else if ( energy_diff_T > (-10.0) ){
394  core::Real random_float = RG.uniform();
395  if ( random_float < exp( energy_diff_T/mpi_metropolis_temp_ ) ) metropolis_replace = true;
396  }
398  if ( metropolis_replace ) {
400  TR << "ReplacingACC: " << format_silent_struct( *ssid_match) << " with " << format_silent_struct( pss ) << " " << energy_diff_T << std::endl;
401  *ssid_match = pss;
402  return true;
403  }else{
404  TR << "ReplacingREJ: " << format_silent_struct( *ssid_match) << " with " << format_silent_struct( pss ) << " " << energy_diff_T << std::endl;
405  }
406  }
407 
408  return false;
409 }
410 
411 void
413 {
414  TR << "N:" << library_central_.store().size() << " <ssid> <score> <censc> <rms> <round> <time> <master> <lhcount> ----" << std::endl;
416  TR << "LIB: " << format_silent_struct( *it ) << std::endl;
417  }
418 }
419 
420 // iterate through the structure store and add strucutres to the central library according to the algorithm specified or the default algorithm
421 bool
423 {
424  bool result = false;
425 
426  for( SilentStructStore::const_iterator it = new_structs.begin();
427  it != new_structs.end(); ++it )
428  {
429  runtime_assert( *it );
430  TR << "Add structure... " << format_silent_struct( *it ) << std::endl;
431  bool local_result = add_structure_to_library( *(*it), add_algorithm );
432  result = result || local_result;
433  }
434 
435  limit_library();
436  print_library();
437  return result;
438 }
439 
440 void
442 {
443  // now shave off the worst structres
445  while( library_central_.size() > max_lib_size_) {
446  library_central_.store().pop_back();
447  }
448 }
449 
450 void
451 MPI_LoopHashRefine::dump_structures( const SilentStructStore &new_structs, bool score_only ) const {
454  std::string filename = jobname_ + "." + string_of( mpi_rank() ) + ".out";
455  for( SilentStructStore::const_iterator it = new_structs.begin();
456  it != new_structs.end(); ++it )
457  {
458  // don't add round 0 structures (they have conflicting silent struct headers and
459  // mess up columns in the output
460  if( (*it)->get_energy("round") > 0 ){
461  sfd.write_silent_struct( *(*it), filename, score_only );
462  }else{
463  TR << "Trying to dump structure of round == 0. Refusing plainly. " << std::endl;
464  }
465  }
466  core::Real write_time = start_timer( TIMING_CPU );
467  TR << "Write time: " << write_time << std::endl;
468 }
469 
470 void
472  if( library_central_.size() == 0 ){
473  TR.Error << "ERROR: Havce no structure to send" << std::endl;
474  return;
475  }
476 
477  // now fabricate a return WU
479  resultpack->set_wu_type( "resultpack" );
481  new_struct->add_energy("ssid", newssid); // overwrite the ssid
482  resultpack->decoys().add( new_struct );
483  send_MPI_workunit( resultpack, dest_rank );
484 }
485 
486 core::Real
488  // by deafult, the rosetta energy is the objective function
489  return ss.get_energy(objective_function_);
490 }
491 
492 core::Real
494  // by deafult, the rosetta energy is the objective function
495  return ss.get_energy("score");
496 }
497 
500  std::stringstream sstream;
501  sstream << "["<<I(4, ss.get_energy("ssid") )
502  << " " << ss.get_string_value("usid")
503  << " |" << F(8,1, objective_function( ss ) )
504  << " |" << F(8,1, ss.get_energy("score"))
505  << " |" << F(8,1, ss.get_energy("censcore"))
506  << " |" << F(5,1, ss.get_energy("rms") )
507  << " |" << I(3, ss.get_energy("round") )
508  << " |" << I(5, time(NULL) - ss.get_energy("ltime") )
509  << " |" << I(3, ss.get_energy("master") )
510  << " |" << I(1, ss.get_energy("lhcount")) << "]";
511  return sstream.str();
512 }
513 
514 core::Real
516  return objective_function( *ss );
517 }
518 
519 core::Real
521  return score( *ss );
522 }
523 
526  return format_silent_struct( *ss );
527 }
528 
529 } // namespace loophash
530 } // namespace protocols