Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FixbbLinkingRotamerSimAnnealer.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 core/pack/annealer/FixbbLinkingRotamerSimAnnealer.cc
11 /// @brief Packer's standard simulated annealing class implementation
12 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
13 
14 // Unit Headers
16 
17 // Package Headers
22 
25 
26 #include <basic/Tracer.hh>
27 
28 //#include "after_opts.h"
29 //#include "FixbbLinkingRotamerSimAnnealer.h"
30 //#include "RotamerAssigningAnnealer.h"
31 //#include "random_numbers.h"
32 //#include "param.h"
33 //#include "RotamerSet.h"
34 
35 #include <utility/exit.hh>
36 #include <numeric/random/random.hh>
37 
38 // AUTO-REMOVED #include <ObjexxFCL/Fmath.hh>
39 
40 #include <iostream>
41 
42 using namespace ObjexxFCL;
43 static numeric::random::RandomGenerator FBBCRSA_RG(63546); // <- Magic number, do not change it!!!
44 
45 namespace core {
46 namespace pack {
47 namespace annealer {
48 
49 static basic::Tracer TR("core.pack.annealer.FixbbLinkingRotamerSimAnnealer",basic::t_info );
50 
51 ////////////////////////////////////////////////////////////////////////////////
52 /// @begin FixbbLinkingRotamerSimAnnealer::FixbbLinkingRotamerSimAnnealer()
53 ///
54 /// @brief
55 /// constructor
56 ///
57 /// @detailed
58 ///
59 /// @global_read
60 ///
61 /// @global_write
62 ///
63 /// @remarks
64 ///
65 /// @references
66 ///
67 /// @authors
68 ///
69 /// @last_modified
70 
71 ////////////////////////////////////////////////////////////////////////////////
72 FixbbLinkingRotamerSimAnnealer::FixbbLinkingRotamerSimAnnealer(
73  utility::vector0<int> & rot_to_pack,
74  FArray1D_int & bestrotamer_at_seqpos,
75  core::PackerEnergy & bestenergy,
76  bool start_with_current, // start simulation with current rotamers
78  FixbbRotamerSetsCOP rotamer_sets,
79  FArray1_int & current_rot_index,
80  bool calc_rot_freq,
81  FArray1D< core::PackerEnergy > & rot_freq,
82  RotamerLinksCOP rotamer_links
83 ):
84  RotamerAssigningAnnealer(
85  rot_to_pack,
86  (int) rot_to_pack.size(),
87  bestrotamer_at_seqpos,
88  bestenergy,
89  start_with_current, // start simulation with current rotamers
90  rotamer_sets,
91  current_rot_index,
92  calc_rot_freq,
93  rot_freq
94  ), ig_(ig)
95 {
96  setup_rotamer_links( rotamer_links );
97 }
98 
100  FArray1D_int & bestrotamer_at_seqpos,
101  core::PackerEnergy & bestenergy,
102  bool start_with_current, // start simulation with current rotamers
104  FixbbRotamerSetsCOP rotamer_set,
105  FArray1_int & current_rot_index,
106  bool calc_rot_freq,
107  FArray1D< core::PackerEnergy > & rot_freq,
108  RotamerLinksCOP rotamer_links
109 ):
110  RotamerAssigningAnnealer(
111  (ig->get_num_total_states()),
112  bestrotamer_at_seqpos,
113  bestenergy,
114  start_with_current, // start simulation with current rotamers
115  rotamer_set,
116  current_rot_index,
117  calc_rot_freq,
118  rot_freq
119  ), ig_(ig)
120 {
121  setup_rotamer_links( rotamer_links );
122 }
123 
124 // rotamer links provide a map for each position and all the positions linking
125 // together, including itself.
126 
127 void
129  RotamerLinksCOP rotamer_links
130 )
131 {
132  // setup the rotamer links
133  // for each moltenres
135  rotamer_links_->resize( rotamer_sets()->nmoltenres() );
136 
137  //std::cout << "nmoltenres " << rotamer_sets()->nmoltenres()<< std::endl;
138 
139  for ( Size moltenres_id=1; moltenres_id<= rotamer_sets()->nmoltenres(); ++moltenres_id ) {
140  uint const resid( rotamer_sets()->moltenres_2_resid( moltenres_id ) );
141  //std::cout << "RESID: " << resid << std::endl;
142  //init anything linking to it locally
143  //iterate over the associated set to check the positions, if molten
144  //std::cout << "linking positions: ";
145  if (rotamer_links->has(resid)){ // not a null
146  //std::cout << " linked IN " << std::endl;
147  utility::vector1<int> copies = rotamer_links->get_equiv(resid);
148  for (Size i = 1; i <= copies.size(); ++i ){
149  if ( rotamer_sets()->resid_2_moltenres( copies[i] )) {
150  // rotamer_links_->set_equiv(resid, copies[i]);
151  rotamer_links_->set_equiv(moltenres_id, rotamer_sets()->resid_2_moltenres(copies[i]));
152  //std::cout << copies[i];
153  //std::cout << ":" << rotamer_sets()->resid_2_moltenres(copies[i]) << std::endl;
154  }
155  else {
156  std::cout << "a position in the link isn't to be changed" << std::endl;
157  }
158  }
159  }
160  else {
161  std::cout << "singular unlinked position" << std::endl;
162  }
163  }
164 }
165 
166 
167 /// @brief virtual destructor
169 {}
170 
171 
173 {
174  using namespace core::conformation;
175 
176  int const nmoltenres = ig_->get_num_nodes();
177 
178  FArray1D_int state_on_node( nmoltenres,0 ); // parallel representation of interaction graph's state
179  FArray1D_int best_state_on_node( nmoltenres,0 );
180  FArray1D< core::PackerEnergy > loopenergy(maxouteriterations,0.0);
181 
182  //bk variables for calculating rotamer frequencies during simulation
183  int nsteps = 0;
184  FArray1D_int nsteps_for_rot( ig_->get_num_total_states(), 0 );
185 
186  //--------------------------------------------------------------------
187  //initialize variables
188 
189  core::PackerEnergy currentenergy = 0.0;
190 
191  ig_->prepare_for_simulated_annealing();
192  ig_->blanket_assign_state_0();
193 
194  //--------------------------------------------------------------------
195  if ( num_rots_to_pack() == 0 ) return;
196 
197  //experimental
198  utility::vector1<int> segmentTest = rotamer_links_->get_equiv(nmoltenres);
199  // get the first element of the last repeat. it should be segment length
200  //std::cout<< "SEGMENTLENGTH from ROTAMER LINK" << segmentTest[1] << std::endl;
201  //Size repeat_number = segmentTest.back()/segmentTest[1];
202  //std::cout<< "number of repeats" << repeat_number << std::endl;
203 
204 
205  int totalrot = 0;
206  for (int res = segmentTest[1]; res <= segmentTest[1]*2 ; res++){
207  totalrot += rotamer_sets()->nrotamers_for_moltenres(res);
208  }
209  //std::cout << "TOTAL ROTAMER " << totalrot << std::endl;
210 /*
211  int totalrot1 = 0;
212  for (int res = 1; res <= segmentTest[1] ; res++){
213  totalrot1 += rotamer_sets()->nrotamers_for_moltenres(res);
214  }
215  std::cout << "TOTAL ROTAMER1 " << totalrot1 << std::endl;
216 
217  int totalrot2 = 0;
218  for (int res = segmentTest[1]; res <= segmentTest[2] ; res++){
219  totalrot2 += rotamer_sets()->nrotamers_for_moltenres(res);
220  }
221  std::cout << "TOTAL ROTAMER2 " << totalrot2 << std::endl;
222 
223  int totalrot3 = 0;
224  for (int res = segmentTest[2]; res <= segmentTest[3] ; res++){
225  totalrot3 += rotamer_sets()->nrotamers_for_moltenres(res);
226  }
227  std::cout << "TOTAL ROTAMER3 " << totalrot3 << std::endl;
228 
229  int totalrot4 = 0;
230  for (int res = segmentTest[3]; res <= segmentTest[4] ; res++){
231  totalrot4 += rotamer_sets()->nrotamers_for_moltenres(res);
232  }
233  std::cout << "TOTAL ROTAMER4 " << totalrot4 << std::endl;
234 */
235 
236 
237 
238  //setup_iterations();
239  //setup_iterations(num_rots_to_pack()/repeat_number);
240  setup_iterations(totalrot*2);
241 
242  FArray1D< core::PackerEnergy > previous_nsteps_for_rot( rotamer_sets()->nrotamers(), 0.0);
243 
244  int outeriterations = get_outeriterations();
245 
246 
247  //std::ofstream annealer_trajectory;
248  //static bool const record_annealer_trajectory( truefalseoption("record_annealer_trajectory") ); //look up once
249  //if ( record_annealer_trajectory )
250  //{
251  // std::string trajectory_file_name( stringafteroption("record_annealer_trajectory" ) );
252  // annealer_trajectory.open(trajectory_file_name.c_str() );
253  //}
254 
255 
256  // some rotamer may not exist on other repeats, and use a new vector to
257  // iterate the "good" rotamers
258 
259 
260  int allrot = rotamer_sets()->nrotamers();
261  utility::vector1<bool> rot_valid(allrot, true);
262  //std::cout << "outer iteration: " << outeriterations << std::endl;
263 
264 
265  //outer loop
266  for (int nn = 1; nn <= outeriterations; ++nn ){
267  setup_temperature(loopenergy,nn);
268  if ( quench() ){
269  currentenergy = bestenergy();
270  state_on_node = best_state_on_node;
271  ig_->set_network_state( state_on_node );
272  }
273  //rh std::cout << "Sim Annealer Temperature: " << get_temperature() << std::endl;
274 
275  int inneriterations = get_inneriterations();
276  //std::cout << "inner iteration: " << inneriterations << std::endl;
277 
278  core::PackerEnergy treshold_for_deltaE_inaccuracy = std::sqrt( get_temperature() );
279  ig_->set_errorfull_deltaE_threshold( treshold_for_deltaE_inaccuracy );
280 
281  //inner loop
282  for (int n = 1; n <= inneriterations; ++n ){
283 
284  int ranrotamer = -1;
285  bool invalid_rotamer = false;
286  while (!invalid_rotamer){
287  ranrotamer = static_cast<int>( FBBCRSA_RG.random_range(1, allrot ));
288  if (rot_valid[ ranrotamer ]){
289  invalid_rotamer = true;
290  }
291  }
292 
293  //int const ranrotamer = pick_a_rotamer( n );
294  if (ranrotamer == -1) continue;
295 
296  int const moltenres_id = rotamer_sets()->moltenres_for_rotamer( ranrotamer );
297  int const rotamer_state_on_moltenres = rotamer_sets()->rotid_on_moltenresidue( ranrotamer );
298  int const prevrotamer_state = state_on_node(moltenres_id);
299 
300  if (rotamer_state_on_moltenres == prevrotamer_state ) continue; //skip iteration
301 
302  core::PackerEnergy previous_energy_for_node, delta_energy;
303 
304  ig_->consider_substitution( moltenres_id, rotamer_state_on_moltenres,
305  delta_energy, previous_energy_for_node);
306 
307  // specialize to the case of coupled pairs in this first pass implementation
308 
309  // assume all couplings are between moltenres -- couplings between fixed and moltenres could
310  // have been used to trim the residueset
311  utility::vector1<int> linked_residues = rotamer_links_->get_equiv(moltenres_id);
312 
313  RotamerSetCOP rotamer_set( rotamer_sets()->rotamer_set_for_moltenresidue( moltenres_id ) );
314  ResidueCOP new_rotamer( rotamer_set->rotamer( rotamer_state_on_moltenres ) );
315 
316  //core::PackerEnergy tmp_currentenergy;
317 
318  //setup energy to keep track of changes
319  core::PackerEnergy delta_energy_accumulated=0, previous_energy_for_node_accumulated=0;
320 
321  std::map<Size, Size> resid_states;
322 
323  //record the seeding position
324  resid_states[moltenres_id] = rotamer_state_on_moltenres;
325 
326  int other_prevrotamer_state(0);
327 
328  bool found_rotamer = false;
329  Size num_linked_res =0;
330  for (utility::vector1<int>::iterator itr = linked_residues.begin(), ite = linked_residues.end(); itr != ite; itr++ ){
331  num_linked_res++;
332  if ( (*itr != 0) && (*itr != moltenres_id )){
333  TR.Trace << "moltenres_id " << moltenres_id << " coupled to moltenres_id " << *itr << std::endl;
334 
335  //try multiple substitutions
336 
337  TR.Trace << "Picked rotamer incompatible, trying multiple substitution" << std::endl;
338 
339  other_prevrotamer_state = state_on_node(*itr);
340 
341  //pick a rotamer at a linked position
342  RotamerSetCOP other_rotamer_set( rotamer_sets()->rotamer_set_for_moltenresidue( *itr ) );
343  ResidueCOP other_rotamer( other_prevrotamer_state == 0 ? ResidueCOP(0) : other_rotamer_set->rotamer( other_prevrotamer_state ) );
344 
345  int other_rotamer_state(0);
346  int const other_nrotamers( other_rotamer_set->num_rotamers() );
347  int tries = other_nrotamers;
348  found_rotamer = false;
349  while ( tries ) {
350  // pick a rotamer at the other position
351  other_rotamer_state = tries;
352 
353  other_rotamer = other_rotamer_set->rotamer(other_rotamer_state);
354  --tries;
355 
356  if ( new_rotamer->is_similar_rotamer( *other_rotamer ) ) { //found the same rotamer, move on
357  //if ( new_rotamer->is_similar_aa( *other_rotamer ) ) { //found the same rotamer, move on
358  //std::cout << "found the same rotamer for " << moltenres_id << " and " << *itr << "of types " << new_rotamer->aa() << " and " << other_rotamer->aa() << std::endl;
359  found_rotamer = true;
360 
361  // record the state
362  resid_states[*itr] = other_rotamer_state;
363 
364  break;
365  }
366  }
367  if (!found_rotamer){ // any of the linked position without the same rotamer should be passed
368  //std::cout << "same rotamer not found for " << moltenres_id << " and " << *itr << std::endl;
369  break;
370  }
371 
372  }
373  } // for linked residues
374 
375  if (!found_rotamer){ // any of the linked position without the same rotamer should be passed
376  //invalidate all the linked positions
377  //std::cout << "invalidate " ;
378  for (std::map<Size, Size>::iterator it = resid_states.begin(), ite = resid_states.end(); it != ite; it++){
379  rot_valid[ rotamer_sets()->moltenres_rotid_2_rotid( (*it).first, (*it).second ) ] = false;
380  // std::cout << (*it).first << "(" << (*it).second << ")" ;
381  }
382  //std::cout << std::endl;
383  continue;
384 
385  }
386 
387  //score the good rotamers and pass through metropolis
388  //std::cout << "summing energies: " ;
389 
390  for (std::map<Size, Size>::iterator it = resid_states.begin(), ite = resid_states.end(); it != ite; it++){
391 
392  //std::cout << (*it).first << "(" << (*it).second << ")" ;
393 
394  core::PackerEnergy delta_energy_temp, previous_energy_for_node_temp;
395  ig_->consider_substitution( (*it).first, (*it).second,
396  delta_energy_temp, previous_energy_for_node_temp );
397 
398  //tmp_currentenergy = currentenergy; // set but never used ~Labonte
399  currentenergy = ig_->commit_considered_substitution();
400 
401  { // debugging
402  //Real const dev( std::abs( currentenergy - tmp_currentenergy - delta_energy_temp ) );
403  //std::cout << (*it).first << "(" << (*it).second << ")" ;
404  //if ( dev > 0.01 ) {
405  // std::cout << "equal2? " << dev << ' ' << currentenergy << " " << tmp_currentenergy << ' ' << delta_energy_temp <<
406  // '\n';
407  //}
408  } // scope
409 
410 
411  delta_energy_accumulated += delta_energy_temp;
412  previous_energy_for_node_accumulated += previous_energy_for_node_temp;
413 
414  // std::cout << "delta_energy_temp " << delta_energy_temp << " previous_energy_for_node_temp " << previous_energy_for_node_temp ;
415 
416  }
417  //std::cout << " accumulated " << previous_energy_for_node_accumulated << " delta_accumulated" << delta_energy_accumulated;
418  //std::cout << std::endl;
419 
420 
421  //core::PackerEnergy previous_energy_average = ( previous_energy_for_node + previous_energy_for_node_accumulated )/(num_linked_res+1);
422  //core::PackerEnergy delta_energy_average = ( delta_energy + delta_energy_accumulated )/(num_linked_res+1);
423  core::PackerEnergy previous_energy_average = ( previous_energy_for_node + previous_energy_for_node_accumulated );
424  core::PackerEnergy delta_energy_average = ( delta_energy + delta_energy_accumulated );
425 
426  //std::cout << prevrotamer_state << " " << other_prevrotamer_state << " " << previous_energy_average << " " << delta_energy_average << std::endl;
427 
428  if ( prevrotamer_state == 0 || other_prevrotamer_state == 0 ||
429  pass_metropolis( previous_energy_average, delta_energy_average ) ) {
430  // accept !!!!!!!
431  TR.Trace << "accepting multiple rotamer substitution" << std::endl;
432 
433 
434  //std::cout << "ACCEPT: substitution on ";
435  //set state
436  for (std::map<Size, Size>::iterator it = resid_states.begin(), ite = resid_states.end(); it != ite; it++){
437  /* core::PackerEnergy dE, oldE;
438  ig_->consider_substitution( (*it).first, (*it).second,
439  dE, oldE );
440  tmp_currentenergy = currentenergy;
441  currentenergy = ig_->commit_considered_substitution();
442 
443  { // debugging
444  Real const dev( std::abs( currentenergy - tmp_currentenergy - dE ) );
445  std::cout << (*it).first << "(" << (*it).second << ")" ;
446  // if ( dev > 0.01 ) {
447  std::cout << "equal2? " << dev << ' ' << currentenergy << " " << tmp_currentenergy << ' ' << dE <<
448  '\n';
449  // }
450  } // scope
451 
452  std::cout << "RUNNING CURRENT " << currentenergy << std::endl;
453  // std::cout << (*it).first << "(" << (*it).second << ")" ;
454 */
455  state_on_node( (*it).first ) = (*it).second;
456  }
457  //std::cout << "ACCEPT: currentenergy " << currentenergy << std::endl;
458  //std::cout << std::endl;
459 
460  //std::cout << "CURRENT: " << currentenergy << "BEST: " << bestenergy() << std::endl;
461  if ( ( prevrotamer_state == 0 ) || ( other_prevrotamer_state == 0 ) || ( currentenergy <= bestenergy() )) {
462  bestenergy() = currentenergy;
463  best_state_on_node = state_on_node;
464  if ( false ) { // hacking ///////////////////////////////////////////
465  std::cout << "best-accept: ";
466  for ( Size i=1; i<= Size(nmoltenres); ++i ) {
467  if ( state_on_node( i ) == 0 ) {
468  std::cout << '.';
469  } else {
470  RotamerSetCOP rotamer_set( rotamer_sets()->rotamer_set_for_moltenresidue( i ) );
471  conformation::ResidueCOP rotamer( rotamer_set->rotamer( state_on_node( i ) ) );
472  if ( rotamer->is_DNA() ) TR << rotamer->name1();
473  }
474  }
475  std::cout << ' ' << nn << ' ' << n << ' ' << currentenergy << '\n';
476  } // end hacking ///////////////////////////////////////
477  }
478 
479  } else {
480  // reject
481  TR.Trace << "rejecting multiple rotamer substitution" << std::endl;
482  //revert changes:
483 
484  for (std::map<Size, Size>::iterator it = resid_states.begin(), ite = resid_states.end(); it != ite; it++){
485 
486  core::PackerEnergy dE, oldE;
487  ig_->consider_substitution( (*it).first, state_on_node((*it).first),
488  dE, oldE );
489  //tmp_currentenergy = currentenergy; // set but never used ~Labonte
490  currentenergy = ig_->commit_considered_substitution();
491  }
492  //std::cout << "REJECT: currentenergy " << currentenergy << std::endl;
493  // { // debugging
494  // Real const dev( std::abs( tmp_currentenergy - currentenergy ) );
495  // if ( dev > 0.01 ) {
496  // TR << "equal3? " << dev << ' ' << tmp_currentenergy << ' ' << currentenergy << '\n';
497  // }
498  // } // scope
499  // currentenergy = previous_energy_average + delta_energy_average;
500  } // accept or reject?
501 
502  loopenergy(nn) = currentenergy;
503 
504  assert( !calc_rot_freq() );
505  continue; // skip the logic below for single-rotamer substitution ////////////////////////////////////
506 
507 
508 
509 
510  //std::cerr << "mres: " << moltenres_id << ", state: ";
511  //std::cerr << rotamer_state_on_moltenres << ", deltaE: " << delta_energy << std::endl;
512 
513  //bk keep new rotamer if it is lower in energy or accept it at some
514  //bk probability if it is higher in energy, if it is the first
515  //bk rotamer to be tried at this position automatically accept it.
516  if ( (prevrotamer_state == 0) || pass_metropolis(previous_energy_for_node,delta_energy) )
517  {
518 
519  //std::cerr << "Accepted" << std::endl;
520 // currentenergy = ig_->commit_considered_substitution();
521  state_on_node(moltenres_id) = rotamer_state_on_moltenres;
522  if ((prevrotamer_state == 0)||(currentenergy < bestenergy() ))
523  {
524  bestenergy() = currentenergy;
525  best_state_on_node = state_on_node;
526  }
527  } // accept
528 
529  loopenergy(nn) = currentenergy;
530  core::PackerEnergy const temperature = get_temperature();
531 
532  if ( calc_rot_freq() && ( temperature <= calc_freq_temp ) )
533  {
534  ++nsteps;
535  for (int ii = 1; ii <= nmoltenres; ++ii )
536  {
537  int iistate = state_on_node(ii);
538  if (iistate != 0)
539  {
540  ++nsteps_for_rot( rotamer_sets()->moltenres_rotid_2_rotid(ii, iistate) );
541  }
542  }
543  }
544 
545 
546  } // end of inneriteration loop
547  } //end of outeriteration loop
548 
549  if ( ig_->any_vertex_state_unassigned() )
550  {
551  std::cerr << "Critical error -- In FixbbLinkingRotamerSimAnnealer, one or more vertex states unassigned at annealing's completion." << std::endl;
552  std::cerr << "Critical error -- assignment and energy of assignment meaningless" << std::endl;
553 
554  FArray1D_int nstates_for_moltenres( rotamer_sets()->nmoltenres(), 0 );
555  for ( uint ii = 0; ii < num_rots_to_pack(); ++ii)
556  {
557  ++nstates_for_moltenres( rotamer_sets()->res_for_rotamer( rot_to_pack()[ ii ] ) );
558  }
559 
560  for ( uint ii = 1; ii <= rotamer_sets()->nmoltenres(); ++ii)
561  {
562  if ( best_state_on_node( ii ) == 0 )
563  {
564  std::cout << "Molten res " << ii << " (residue " << rotamer_sets()->moltenres_2_resid( ii );
565  std::cout << " ) assigned state 0 despite having " << nstates_for_moltenres( ii ) << " states to choose from" << std::endl;
566  }
567  }
568  assert( ! ig_->any_vertex_state_unassigned() );
569  utility_exit();
570 
571 
572  }
573 
574  //convert best_state_on_node into best_rotamer_at_seqpos
575  for (int ii = 1; ii <= nmoltenres; ++ii){
576  int const iiresid = rotamer_sets()->moltenres_2_resid( ii );
577  bestrotamer_at_seqpos()( iiresid ) = rotamer_sets()->moltenres_rotid_2_rotid( ii, best_state_on_node(ii));
578  }
579 
580 
581 }
582 
583 }//end namespace annealer
584 }//end namespace pack
585 }//end namespace core