Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SimAnnealerBase.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/SimAnnealerBase.cc
11 /// @brief Packer's simulated annealing base class implementation
12 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
13 
14 // Unit Headers
16 
17 // AUTO-REMOVED #include <basic/options/util.hh>
18 
19 // Package Headers
20 // AUTO-REMOVED #include <core/pack/rotamer_set/RotamerSets.hh>
21 
22 // ObjexxFCL headers
23 // AUTO-REMOVED #include <ObjexxFCL/FArray1A.hh>
24 #include <ObjexxFCL/FArray1D.hh>
25 // AUTO-REMOVED #include <ObjexxFCL/Fmath.hh>
26 
27 // NUmeric headers
28 #include <numeric/random/random.hh>
29 
30 // C++ headers
31 #include <algorithm>
32 
33 // option key includes
34 
35 #include <basic/options/keys/packing.OptionKeys.gen.hh>
36 
37 #include <utility/vector1.hh>
38 #include <basic/options/option.hh>
39 
40 
41 
42 
43 using namespace ObjexxFCL;
44 static numeric::random::RandomGenerator sab_RG(42454); // <- Magic number, do not change it!!!
45 
46 namespace core {
47 namespace pack {
48 namespace annealer {
49 
50 const core::PackerEnergy SimAnnealerBase::hightemp = 100.0;
51 const core::PackerEnergy SimAnnealerBase::lowtemp = 0.3;
52 const core::PackerEnergy SimAnnealerBase::calc_freq_temp = 1.0;
53 //bool annealing_starts_at_low_temperature = false;
54 
55 /// @brief constructor
56 SimAnnealerBase::SimAnnealerBase
57 (
58  int num_rots_to_pack,
59  FArray1D_int & bestrotamer_at_seqpos,
60  core::PackerEnergy & bestenergy,
61  bool start_with_current, // start simulation with current rotamers
62  FArray1_int & current_rot_index,
63  bool calc_rot_freq,
64  FArray1D< core::PackerEnergy > & rot_freq
65 ) :
66  num_rots_to_pack_( num_rots_to_pack ),
67  bestrotamer_at_seqpos_(bestrotamer_at_seqpos),
68  bestenergy_(bestenergy),
69  start_with_current_(start_with_current),
70  current_rot_index_(current_rot_index),
71  calc_rot_freq_(calc_rot_freq),
72  rot_freq_(rot_freq),
73  outeriterations_( 0 ),
74  inneriterations_( 0 ),
75  quench_( false ),
76  //hightemp_( annealing_starts_at_low_temperature ? 10 : hightemp ),
77  hightemp_( hightemp ),
78  lowtemp_( lowtemp ),
79  temperature_( hightemp_ ),
80  jump_(0),
81  outeriterations_scaling_(1.),
82  inneriterations_scaling_(1.),
83  low_temp_annealing_( false ),
84  disallow_quench_( false )
85 {
87 
88  using namespace basic::options;
89  using namespace basic::options::OptionKeys;
90  outeriterations_scaling_ = option[ OptionKeys::packing::outeriterations_scaling ]();
91  inneriterations_scaling_ = option[ OptionKeys::packing::inneriterations_scaling ]();
92 }
93 
94 
95 ////////////////////////////////////////////////////////////////////////////////
96 /// @begin SimAnnealerBase::~SimAnnealerBase()
97 ///
98 /// @brief
99 /// virtual destructor
100 ///
101 /// @detailed
102 ///
103 /// @global_read
104 ///
105 /// @global_write
106 ///
107 /// @remarks
108 ///
109 /// @references
110 ///
111 /// @authors
112 ///
113 /// @last_modified
114 ////////////////////////////////////////////////////////////////////////////////
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 /// @begin SimAnnealerBase::get_outeriterations()
119 ///
120 /// @brief
121 /// get the iterations number for simulation
122 ///
123 /// @detailed
124 ///
125 /// @global_read
126 ///
127 /// @global_write
128 ///
129 /// @remarks
130 ///
131 /// @references
132 ///
133 /// @authors
134 ///
135 /// @last_modified
136 ////////////////////////////////////////////////////////////////////////////////
137 
139 {
141 }
142 
143 ////////////////////////////////////////////////////////////////////////////////
144 /// @begin SimAnnealerBase::get_inneriterations()
145 ///
146 /// @brief
147 ///
148 /// @detailed
149 ///
150 /// @global_read
151 ///
152 /// @global_write
153 ///
154 /// @remarks
155 ///
156 /// @references
157 ///
158 /// @authors
159 ///
160 /// @last_modified
161 ////////////////////////////////////////////////////////////////////////////////
162 
164 {
165  if ( low_temp_annealing_ )
166  {
167  return int (inneriterations_scaling_ *
168  (get_temperature() > 3.0f ? inneriterations_ * 0.5 : inneriterations_ ));
169  }
170  else
171  {
173  }
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 /// @begin SimAnnealerBase::setup_iterations(bool start_with_current)
178 ///
179 /// @brief
180 ///
181 /// @detailed
182 ///
183 /// @global_read
184 ///
185 /// @global_write
186 ///
187 /// @remarks
188 ///
189 /// @references
190 ///
191 /// @authors
192 ///
193 /// @last_modified
194 ////////////////////////////////////////////////////////////////////////////////
196 {
198 }
199 
200 
201 void SimAnnealerBase::setup_iterations( const int & num_of_state_changes )
202 {
203 
204  if ( start_with_current_ ){
205  inneriterations_ = std::max( num_of_state_changes, (int) current_rot_index_.size1() );
206  outeriterations_ = 10;
207  }
208  else
209  {
210  if ( low_temp_annealing_ ){
211  inneriterations_ = std::max( 10 * num_of_state_changes, 2 * ((int) current_rot_index_.size1()) );
212  outeriterations_ = 10;
213  }
214  else
215  {
216  inneriterations_ = std::max( 5 * num_of_state_changes, (int) current_rot_index_.size1() );
217  outeriterations_ = 20;
218  }
219  }
220 
221  //std::cerr << "SimAnnealerBase::setup iterations(); inner = " << inneriterations_ << " outer: " << outeriterations_ << std::endl;
222 }
223 
225 {
228  jump_++;
229 }
230 
231 void SimAnnealerBase::setup_temperature(const FArray1D< core::PackerEnergy > & loopenergy,int nn)
232 {
234  core::PackerEnergy avgloopE = 0.0f;
235  if (( nn == get_outeriterations() )&&(!calc_rot_freq) && !disallow_quench_ )
236  {
237  set_to_quench();
239  }
240  else if ( jump_ > 3)
241  {
242  avgloopE = (loopenergy( nn - 4 ) + loopenergy( nn -3 ) + loopenergy( nn - 2 ))/3.0;
243  //std::cout << "avgloopE: " << avgloopE << " vs " << loopenergy( nn - 1) << std::endl;
244  if (( loopenergy( nn - 1) - avgloopE ) > -1.0)
245  {
246  //std::cout << "High temp!" << std::endl;
248  jump_ = 1;
249  }
250  else
251  {
253  jump_++;
254  //std::cout << "Cool " << temperature_ << std::endl;
255  }
256  }
257  // This is terrible. If instructions are to be passed to the packer, they are to be passed through the PackerTask.
258  // Do not insert code into the middle of a low level function like this such that it can go totally unnoticed
259  // by people who rely upon it.
260  //else if( pKa_mode::get_pKa_flag() && pKa_mode::pKa_packer_flags::packer_set_temp )
261  //{
262  // temperature_ = pKa_mode::pKa_packer_flags::packer_temp;
263  //}
264  else
265  {
267  jump_++;
268 
269 
270  if (calc_rot_freq && (temperature_ < calc_freq_temp)){
272  }
273  }
274 }
275 
276 // SimAnnealerBase::clear
277 void
279  jump_ = 0;
280 }
281 
283 
287 bool SimAnnealerBase::quench() const { return quench_; }
290 
293 FArray1D_int const & SimAnnealerBase::bestrotamer_at_seqpos() const { return bestrotamer_at_seqpos_; }
297 FArray1_int const & SimAnnealerBase::current_rot_index() const { return current_rot_index_;}
300 FArray1D< core::PackerEnergy >& SimAnnealerBase::rot_freq() { return rot_freq_; }
301 FArray1D< core::PackerEnergy > const & SimAnnealerBase::rot_freq() const { return rot_freq_; }
302 
305 
306 void SimAnnealerBase::set_disallow_quench( bool const & setting ){ disallow_quench_ = setting; }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// @begin SimAnnealerBase::pass_metropolis
310 ///
311 ///
312 /// @brief
313 /// accept or reject movement based on Metropolis criterion
314 /// if this is the first movement, accept by default.
315 /// @detailed
316 ///
317 /// @global_read
318 ///
319 /// @global_write
320 ///
321 /// @remarks
322 ///
323 /// @references
324 ///
325 /// @authors
326 ///
327 /// @last_modified
328 ////////////////////////////////////////////////////////////////////////////////
330 {
331  const core::PackerEnergy GOOD_ENERGY = 0.0;
332  return pass_metropolis( GOOD_ENERGY, delta_energy );
333 }
334 
335 bool SimAnnealerBase::pass_metropolis( core::PackerEnergy previous_energy, core::PackerEnergy delta_energy ) const
336 {
337 
338  // skip evaluating random number generator if quenching
339  if ( quench_ ) {
340  if ( delta_energy < 0 ) return true;
341  else return false;
342  }
343 
344  core::PackerEnergy lnprob = 0.0f;
345  core::PackerEnergy beta = 1.0/temperature_;
346  core::PackerEnergy probability = 0.0f;
347 
348  /// call this every time, for better numerical stability. Otherwise delta_energies ~ 0 can lead to
349  /// instability in the number of calls to the random number generator
350 
351  core::PackerEnergy const rg_uniform( sab_RG.uniform() );
352 
353  if ( delta_energy < 0 ) {
354  return true;
355  } else { //evaluate prob of substitution
356  lnprob = beta * delta_energy;
357  if ( previous_energy > 1.0 ) // this is specific to FixbbSimAnnealer
358  {
359  //if both previous energy and new energy are poor
360  //increase the probability of accept
361  lnprob /= previous_energy;
362  }
363  if ( lnprob < 10.0 )
364  {
365  probability = std::exp(-lnprob);
366  if ( probability > rg_uniform ) return true;
367  }
368  }
369  return false;
370 }
371 
372 } // namespace annealer
373 } // namespace pack
374 } // namespace core