Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FixbbCoupledRotamerSimAnnealer.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/FixbbCoupledRotamerSimAnnealer.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
18 // AUTO-REMOVED #include <core/pack/rotamer_set/RotamerSets.hh>
22 
25 
26 #include <basic/Tracer.hh>
27 
28 //#include "after_opts.h"
29 //#include "FixbbCoupledRotamerSimAnnealer.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 #include <utility/vector0.hh>
43 #include <utility/vector1.hh>
44 
45 //Auto Headers
47 
48 using namespace ObjexxFCL;
49 static numeric::random::RandomGenerator FBBCRSA_RG(63556); // <- Magic number, do not change it!!!
50 
51 namespace core {
52 namespace pack {
53 namespace annealer {
54 
55 static basic::Tracer TR("core.pack.annealer.FixbbCoupledRotamerSimAnnealer",basic::t_info );
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 /// @begin FixbbCoupledRotamerSimAnnealer::FixbbCoupledRotamerSimAnnealer()
59 ///
60 /// @brief
61 /// constructor
62 ///
63 /// @detailed
64 ///
65 /// @global_read
66 ///
67 /// @global_write
68 ///
69 /// @remarks
70 ///
71 /// @references
72 ///
73 /// @authors
74 ///
75 /// @last_modified
76 
77 ////////////////////////////////////////////////////////////////////////////////
78 FixbbCoupledRotamerSimAnnealer::FixbbCoupledRotamerSimAnnealer(
79  utility::vector0<int> & rot_to_pack,
80  FArray1D_int & bestrotamer_at_seqpos,
81  core::PackerEnergy & bestenergy,
82  bool start_with_current, // start simulation with current rotamers
84  FixbbRotamerSetsCOP rotamer_sets,
85  FArray1_int & current_rot_index,
86  bool calc_rot_freq,
87  FArray1D< core::PackerEnergy > & rot_freq,
88  RotamerCouplingsCOP rotamer_couplings
89 ):
90  RotamerAssigningAnnealer(
91  rot_to_pack,
92  (int) rot_to_pack.size(),
93  bestrotamer_at_seqpos,
94  bestenergy,
95  start_with_current, // start simulation with current rotamers
96  rotamer_sets,
97  current_rot_index,
98  calc_rot_freq,
99  rot_freq
100  ), ig_(ig)
101 {
102  setup_rotamer_couplings( rotamer_couplings );
103 }
104 
106  FArray1D_int & bestrotamer_at_seqpos,
107  core::PackerEnergy & bestenergy,
108  bool start_with_current, // start simulation with current rotamers
110  FixbbRotamerSetsCOP rotamer_set,
111  FArray1_int & current_rot_index,
112  bool calc_rot_freq,
113  FArray1D< core::PackerEnergy > & rot_freq,
114  RotamerCouplingsCOP rotamer_couplings
115 ):
116  RotamerAssigningAnnealer(
117  (ig->get_num_total_states()),
118  bestrotamer_at_seqpos,
119  bestenergy,
120  start_with_current, // start simulation with current rotamers
121  rotamer_set,
122  current_rot_index,
123  calc_rot_freq,
124  rot_freq
125  ), ig_(ig)
126 {
127  setup_rotamer_couplings( rotamer_couplings );
128 }
129 
130 
131 void
133  RotamerCouplingsCOP rotamer_couplings
134 )
135 {
136  // setup the rotamer couplings
137  // for each moltenres
139  rotamer_couplings_->resize( rotamer_sets()->nmoltenres() );
140 
141  for ( Size moltenres_id=1; moltenres_id<= rotamer_sets()->nmoltenres(); ++moltenres_id ) {
142  uint const resid( rotamer_sets()->moltenres_2_resid( moltenres_id ) );
143  uint const other_resid( (*rotamer_couplings)[ resid ].first );
144 
145  if ( other_resid && rotamer_sets()->resid_2_moltenres( other_resid ) ) {
146  // both are molten
147  (*rotamer_couplings_)[ moltenres_id ].first = rotamer_sets()->resid_2_moltenres( other_resid );
148  (*rotamer_couplings_)[ moltenres_id ].second = (*rotamer_couplings)[ resid ].second;
149 
150  //std::cout << "packing with coupling between: " << resid << " and " << other_resid << std::endl;
151 
152  } else {
153  (*rotamer_couplings_)[ moltenres_id ].first = 0; // signal no pairwise couplings
154  }
155  }
156 
157 }
158 
159 
160 /// @brief virtual destructor
162 {}
163 
164 
166 {
167  int const nmoltenres = ig_->get_num_nodes();
168 
169  FArray1D_int state_on_node( nmoltenres,0 ); // parallel representation of interaction graph's state
170  FArray1D_int best_state_on_node( nmoltenres,0 );
171  FArray1D< core::PackerEnergy > loopenergy(maxouteriterations,0.0);
172 
173  //bk variables for calculating rotamer frequencies during simulation
174  int nsteps = 0;
175  FArray1D_int nsteps_for_rot( ig_->get_num_total_states(), 0 );
176 
177  //--------------------------------------------------------------------
178  //initialize variables
179 
180  core::PackerEnergy currentenergy = 0.0;
181 
182  ig_->prepare_for_simulated_annealing();
183  ig_->blanket_assign_state_0();
184 
185  //--------------------------------------------------------------------
186  if ( num_rots_to_pack() == 0 ) return;
187 
189 
190  FArray1D< core::PackerEnergy > previous_nsteps_for_rot( rotamer_sets()->nrotamers(), 0.0);
191 
192  int outeriterations = get_outeriterations();
193 
194 
195  //std::ofstream annealer_trajectory;
196  //static bool const record_annealer_trajectory( truefalseoption("record_annealer_trajectory") ); //look up once
197  //if ( record_annealer_trajectory )
198  //{
199  // std::string trajectory_file_name( stringafteroption("record_annealer_trajectory" ) );
200  // annealer_trajectory.open(trajectory_file_name.c_str() );
201  //}
202 
203  //outer loop
204  for (int nn = 1; nn <= outeriterations; ++nn ){
205  setup_temperature(loopenergy,nn);
206  if ( quench() ){
207  currentenergy = bestenergy();
208  state_on_node = best_state_on_node;
209  ig_->set_network_state( state_on_node );
210  }
211  //rh std::cout << "Sim Annealer Temperature: " << get_temperature() << std::endl;
212 
213  int inneriterations = get_inneriterations();
214 
215  core::PackerEnergy treshold_for_deltaE_inaccuracy = std::sqrt( get_temperature() );
216  ig_->set_errorfull_deltaE_threshold( treshold_for_deltaE_inaccuracy );
217 
218  //inner loop
219  for (int n = 1; n <= inneriterations; ++n ){
220  int const ranrotamer = pick_a_rotamer( n );
221  if (ranrotamer == -1) continue;
222 
223  int const moltenres_id = rotamer_sets()->moltenres_for_rotamer( ranrotamer );
224  int const rotamer_state_on_moltenres = rotamer_sets()->rotid_on_moltenresidue( ranrotamer );
225  int const prevrotamer_state = state_on_node(moltenres_id);
226 
227  if (rotamer_state_on_moltenres == prevrotamer_state ) continue; //skip iteration
228 
229  core::PackerEnergy previous_energy_for_node, delta_energy;
230 
231  ig_->consider_substitution( moltenres_id, rotamer_state_on_moltenres,
232  delta_energy, previous_energy_for_node);
233 
234  // specialize to the case of coupled pairs in this first pass implementation
235 
236  // assume all couplings are between moltenres -- couplings between fixed and moltenres could
237  // have been used to trim the residueset
238 
239  int const other_moltenres_id( (*rotamer_couplings_)[ moltenres_id ].first );
240 
241  if ( other_moltenres_id >= 1 ) {
242  TR.Trace << "moltenres_id " << moltenres_id << " coupled to moltenres_id " << other_moltenres_id << std::endl;
243  conformation::ResidueMatcherCOP matcher( (*rotamer_couplings_)[ moltenres_id ].second );
244 
245  RotamerSetCOP rotamer_set( rotamer_sets()->rotamer_set_for_moltenresidue( moltenres_id ) );
246  conformation::ResidueCOP new_rotamer( rotamer_set->rotamer( rotamer_state_on_moltenres ) );
247 
248  // check if new rotamer is compatible with current rotamer
249  int const other_prevrotamer_state( state_on_node( other_moltenres_id ) );
250  RotamerSetCOP other_rotamer_set( rotamer_sets()->rotamer_set_for_moltenresidue( other_moltenres_id ) );
251  conformation::ResidueCOP other_rotamer( other_prevrotamer_state == 0 ? conformation::ResidueCOP(0) :
252  other_rotamer_set->rotamer( other_prevrotamer_state ) );
253 
254  if ( !( other_rotamer && (*matcher)( *new_rotamer, *other_rotamer ) ) ) {
255  // need to try a double substitution!!
256  TR.Trace << "Picked rotamer incompatible, trying double substitution" << std::endl;
257  int other_rotamer_state(0);
258  int const other_nrotamers( other_rotamer_set->num_rotamers() );
259  int tries(0);
260  while ( true ) {
261  ++tries;
262  if ( tries > 1000 ) TR.Trace << "tries: " << tries << '\n';
263  // pick a new rotamer at the other position
264  other_rotamer_state = static_cast<int>( other_nrotamers * FBBCRSA_RG.uniform() + 1 );
265  other_rotamer = other_rotamer_set->rotamer( other_rotamer_state );
266 
267  if ( (*matcher)(*new_rotamer, *other_rotamer ) ) {
268  TR.Trace << "matching rotamer found" << std::endl;
269  break;
270  }
271  }
272 
273  // now make the double substitution
274  core::PackerEnergy tmp_currentenergy = ig_->commit_considered_substitution();
275  { // debugging
276  Real const dev( std::abs( tmp_currentenergy - currentenergy - delta_energy ) );
277  if ( dev > 0.01 ) {
278  TR << "equal1? " << dev << ' ' << tmp_currentenergy - currentenergy << ' ' << delta_energy <<
279  '\n';
280  }
281  } // scope
282 
283  core::PackerEnergy delta_energy2, previous_energy_for_node2;
284  ig_->consider_substitution( other_moltenres_id, other_rotamer_state,
285  delta_energy2, previous_energy_for_node2 );
286 
287  core::PackerEnergy previous_energy_average = ( previous_energy_for_node + previous_energy_for_node2 ) / 2.0;
288  core::PackerEnergy delta_energy_average = ( delta_energy + delta_energy2 ) / 2.0;
289 
290  if ( prevrotamer_state == 0 || other_prevrotamer_state == 0 ||
291  pass_metropolis( previous_energy_average, delta_energy_average ) ) {
292  // accept !!!!!!!
293  TR.Trace << "accepting coupled rotamer substitution" << std::endl;
294  currentenergy = ig_->commit_considered_substitution();
295 
296  { // debugging
297  Real const dev( std::abs( currentenergy - tmp_currentenergy - delta_energy2 ) );
298  if ( dev > 0.01 ) {
299  TR << "equal2? " << dev << ' ' << currentenergy - tmp_currentenergy << ' ' << delta_energy2 <<
300  '\n';
301  }
302  } // scope
303 
304  state_on_node( moltenres_id ) = rotamer_state_on_moltenres;
305  state_on_node( other_moltenres_id ) = other_rotamer_state;
306 
307 
308 
309  if ( ( prevrotamer_state == 0 ) || ( other_prevrotamer_state == 0 ) || ( currentenergy < bestenergy() )) {
310  bestenergy() = currentenergy;
311  best_state_on_node = state_on_node;
312  if ( false ) { // hacking ///////////////////////////////////////////
313  TR << "best-accept: ";
314  for ( Size i=1; i<= Size(nmoltenres); ++i ) {
315  if ( state_on_node( i ) == 0 ) {
316  TR << '.';
317  } else {
318  RotamerSetCOP rotamer_set( rotamer_sets()->rotamer_set_for_moltenresidue( i ) );
319  conformation::ResidueCOP rotamer( rotamer_set->rotamer( state_on_node( i ) ) );
320  if ( rotamer->is_DNA() ) TR << rotamer->name1();
321  }
322  }
323  TR << ' ' << nn << ' ' << n << ' ' << currentenergy << '\n';
324  } // end hacking ///////////////////////////////////////
325  }
326 
327  } else {
328  // reject
329  TR.Trace << "rejecting coupled rotamer substitution" << std::endl;
330  ig_->consider_substitution( moltenres_id, prevrotamer_state, delta_energy, previous_energy_for_node );
331  tmp_currentenergy = ig_->commit_considered_substitution();
332 
333  { // debugging
334  Real const dev( std::abs( tmp_currentenergy - currentenergy ) );
335  if ( dev > 0.01 ) {
336  TR << "equal3? " << dev << ' ' << tmp_currentenergy << ' ' << currentenergy << '\n';
337  }
338  } // scope
339  currentenergy = tmp_currentenergy;
340  } // accept or reject?
341 
342  loopenergy(nn) = currentenergy;
343 
344  assert( !calc_rot_freq() );
345  continue; // skip the logic below for single-rotamer substitution ////////////////////////////////////
346  }
347  }
348 
349 
350  //std::cerr << "mres: " << moltenres_id << ", state: ";
351  //std::cerr << rotamer_state_on_moltenres << ", deltaE: " << delta_energy << std::endl;
352 
353  //bk keep new rotamer if it is lower in energy or accept it at some
354  //bk probability if it is higher in energy, if it is the first
355  //bk rotamer to be tried at this position automatically accept it.
356  if ( (prevrotamer_state == 0) || pass_metropolis(previous_energy_for_node,delta_energy) )
357  {
358  //std::cerr << "Accepted" << std::endl;
359  currentenergy = ig_->commit_considered_substitution();
360  state_on_node(moltenres_id) = rotamer_state_on_moltenres;
361  if ((prevrotamer_state == 0)||(currentenergy < bestenergy() ))
362  {
363  bestenergy() = currentenergy;
364  best_state_on_node = state_on_node;
365  }
366  } // accept
367 
368  loopenergy(nn) = currentenergy;
369  core::PackerEnergy const temperature = get_temperature();
370 
371  if ( calc_rot_freq() && ( temperature <= calc_freq_temp ) )
372  {
373  ++nsteps;
374  for (int ii = 1; ii <= nmoltenres; ++ii )
375  {
376  int iistate = state_on_node(ii);
377  if (iistate != 0)
378  {
379  ++nsteps_for_rot( rotamer_sets()->moltenres_rotid_2_rotid(ii, iistate) );
380  }
381  }
382  }
383 
384  } // end of inneriteration loop
385  } //end of outeriteration loop
386 
387  if ( ig_->any_vertex_state_unassigned() )
388  {
389  std::cerr << "Critical error -- In FixbbCoupledRotamerSimAnnealer, one or more vertex states unassigned at annealing's completion." << std::endl;
390  std::cerr << "Critical error -- assignment and energy of assignment meaningless" << std::endl;
391 
392  FArray1D_int nstates_for_moltenres( rotamer_sets()->nmoltenres(), 0 );
393  for ( uint ii = 0; ii < num_rots_to_pack(); ++ii)
394  {
395  ++nstates_for_moltenres( rotamer_sets()->res_for_rotamer( rot_to_pack()[ ii ] ) );
396  }
397 
398  for ( uint ii = 1; ii <= rotamer_sets()->nmoltenres(); ++ii)
399  {
400  if ( best_state_on_node( ii ) == 0 )
401  {
402  std::cout << "Molten res " << ii << " (residue " << rotamer_sets()->moltenres_2_resid( ii );
403  std::cout << " ) assigned state 0 despite having " << nstates_for_moltenres( ii ) << " states to choose from" << std::endl;
404  }
405  }
406  assert( ! ig_->any_vertex_state_unassigned() );
407  utility_exit();
408 
409 
410  }
411 
412  //convert best_state_on_node into best_rotamer_at_seqpos
413  for (int ii = 1; ii <= nmoltenres; ++ii){
414  int const iiresid = rotamer_sets()->moltenres_2_resid( ii );
415  bestrotamer_at_seqpos()( iiresid ) = rotamer_sets()->moltenres_rotid_2_rotid( ii, best_state_on_node(ii));
416  }
417 
418 
419 }
420 
421 }//end namespace annealer
422 }//end namespace pack
423 }//end namespace core