Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FASTERInteractionGraph.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/interaction_graph/FASTERInteractionGraph.cc
11 /// @brief
12 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
13 
14 // Unit Headers
16 
17 // Package Headers
20 
21 // Utility headers
22 #include <utility/string_util.hh>
23 
24 // ObjexxFCL Headers
25 #include <ObjexxFCL/FArray1D.hh>
26 #include <ObjexxFCL/FArray2D.hh>
27 #include <ObjexxFCL/FArray2A.hh>
28 
29 // STL Headers
30 #include <list>
31 #include <algorithm>
32 #include <iostream>
33 #include <cassert>
34 
35 // Numeric headers
36 #include <numeric/random/random.hh>
37 
38 
39 #include <utility/vector1.hh>
40 
41 
42 using namespace ObjexxFCL;
43 
44 namespace core {
45 namespace pack {
46 namespace interaction_graph {
47 
48 static numeric::random::RandomGenerator RG(6425); // <- Magic number, do not change it!!!
49 
50 /// @brief main constructor, no default or copy constructors
51 ///
52 /// allocates one-body energy array and initializes it to zero.
53 ///
54 FASTERNode::FASTERNode(
55  InteractionGraphBase * owner,
56  int node_id,
57  int num_states
58 ) :
59  PrecomputedPairEnergiesNode( owner, node_id, num_states ),
60  one_body_energies_(num_states + 1, core::PackerEnergy( 0.0 )),
61  curr_state_total_energy_( 0.0 ),
62  alternate_state_is_being_considered_( false ),
63  have_prepared_once_for_FASTER_( false ),
64  in_FASTER_mode_( false ),
65  perturbed_( false ),
66  have_relaxed_since_neighbors_perturbation_( true ),
67  have_contributed_deltaE_following_perturbation_( true ),
68  relaxed_state_( 0 )
69 {}
70 
71 /// @brief destructor
72 ///
73 /// not responsible for any dynamically allocated memory, so node does nothing
74 /// it's member variables, of course, are implicitly destructed
76 {}
77 
78 /// @brief prints a description of the node and all of it's one-body energies
79 void FASTERNode::print() const
80 {
81  std::cout << "NODE: " << get_node_index() << " with " <<
82  get_num_states() << " states" << std::endl;
83  for (int ii = 1; ii <= get_num_states(); ++ii ) {
84  std::cout << "(" << ii << ", ";
85  std::cout << one_body_energies_[ ii ] << ") ";
86  if ( ii % 3 == 0 ) std::cout << std::endl;
87  }
88  std::cout << std::endl << "-----------------" << std::endl;
89 }
90 
91 
92 /// @brief update energy to the one-body energy for state
93 ///
94 ///
95 /// @param state - [in] - one-based index of the state
96 /// @param energy - [in] - the energy that should be set.
98 {
99  one_body_energies_[ state ] = energy;
100  return;
101 }
102 
103 /// @brief set all the one-body energies for this node
104 ///
105 /// @param energies - [in] - the array of energies. Must hold num_states_ entries
106 void FASTERNode::update_one_body_energies( FArray1< core::PackerEnergy > & energies )
107 {
108  assert( energies.size() == (unsigned int) get_num_states() );
109  for (int ii = 1; ii <= get_num_states(); ++ii)
110  {
111  one_body_energies_[ ii ] = energies( ii );
112  }
113  return;
114 }
115 
116 /// @brief adds energy to the one-body energy for state state
117 ///
118 /// @param state - [in] - one-based index of the state
119 /// @param energy - [in] - the energy that should be added.
121 {
122  one_body_energies_[ state ] += energy;
123  return;
124 }
125 
126 /// @brief adds all the energies in energies to the one-body energies for this node
127 ///
128 /// @param energies - [in] - the array of energies. Must hold num_states_ entries
129 void FASTERNode::add_to_one_body_energies( FArray1< core::PackerEnergy > & energies )
130 {
131  assert( energies.size() == (unsigned int) get_num_states() );
132  for ( int ii = 1; ii <= get_num_states(); ++ii ) {
133  one_body_energies_[ ii ] += energies( ii );
134  }
135  return;
136 }
137 
138 /// @brief sets all of the one-body energies for this node to zero
140 {
141  for (int ii = 1; ii <= get_num_states(); ++ii) {
142  one_body_energies_[ ii ] = core::PackerEnergy( 0.0 );
143  }
144 }
145 
146 /// @brief returns the one body energy for a state
147 ///
148 /// @param state - [in]
150 {
151  return one_body_energies_[ state ];
152 }
153 
154 /// @brief prepares node for simulated annealing
155 ///
156 /// updates internal edge vector + other vectorized edge information
158 {
160  in_FASTER_mode_ = false;
161  return;
162 }
163 
164 void
166 {
168  in_FASTER_mode_ = true;
169 
170  //allocate arrays if necessary;
177  }
178 
179  //get all rotamer's total energies for current state assignment
181 }
182 
183 /// @brief assigns node's state to it's zero, or "unassigned" state.
184 ///
185 /// zeros the edge-energy array, informs neighbors that it's in its unassigned
186 /// state
188 {
189 
190  //std::cout << "assign_state: node - " << get_node_index() <<
191  // " new state " << 0 << "...";
192 
193  current_state_ = 0;
194  relaxed_state_ = 0;
195  alternate_state_ = 0;
197 
199  //fills from [1] to end
200  std::vector< core::PackerEnergy >::iterator position1 = curr_state_two_body_energies_.begin();
201  ++position1;
202  std::fill( position1, curr_state_two_body_energies_.end(), core::PackerEnergy( 0.0 ));
204 
205  for (int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
207  }
208 
209  return;
210 }
211 
212 
213 /// @brief assigns node a new_state
214 ///
215 /// node updates its curr_state one and two body energies
216 ///
217 /// @param new_state - [in] - the new state the node should be assigned
218 void FASTERNode::assign_state(int new_state)
219 {
220  assert( new_state >= 0 && new_state <= get_num_states());
221 
222  if (new_state == 0) {
224  } else {
225  //std::cout << "assign_state: node - " << get_node_index() <<
226  // " new state " << new_state << "...";
227  current_state_ = new_state;
228  relaxed_state_ = new_state;
232 
233  for (int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
235  get_node_index(),
238 
240  }
241  //std::cout<< "..done" << std::endl;
242  }
243  return;
244 }
245 
246 /// @brief returns the state the node is currently assigned
248 {
249  return current_state_;
250 }
251 
252 /// @brief returns the one body energy for the state the node is currently assigned
254 { return curr_state_one_body_energy_; }
255 
256 /// @brief tells the node that it should change its state to the last state it was
257 /// asked to consider (from a call to project_deltaE_for_substitution)
258 ///
259 /// updates edge energy vector, iterates across neighbors having them update
260 /// their edge energies. Bookkeeping recaptures performance lost by
261 /// leaving energy2b structure
263 {
265 
270 
271  //copies from [1] to end
272  std::vector< core::PackerEnergy >::iterator alt_position1 = alternate_state_two_body_energies_.begin();
273  ++alt_position1;
274  std::vector< core::PackerEnergy >::iterator curr_position1 = curr_state_two_body_energies_.begin();
275  ++curr_position1;
276 
277  std::copy( alt_position1, alternate_state_two_body_energies_.end(), curr_position1 );
278 
279  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
281  get_node_index(),
284  );
285  }
286 
288  return;
289 }
290 
291 
292 /// @brief outputs to standard error the bookkeeping energies for the node in its
293 /// current state assignment
295 {
296  std::cout << "curr_state " << current_state_ << " ";
297  std::cout << "curr_state_one_body_energy_ ";
298  std::cout << curr_state_one_body_energy_ << " ";
299  std::cout << "curr_state_total_energy_" << curr_state_total_energy_ << " ";
300  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
301  std::cout << "(" << get_index_of_adjacent_node( ii ) << ": " <<
302  curr_state_two_body_energies_[ ii ] << ") ";
303  }
304  std::cout << std::endl;
305 }
306 
307 /// @brief removes numerical drift long stretches of efficient bookkeeping
308 /// produces
310 {
311  assert( get_edge_vector_up_to_date() );
313  for (int ii = 1; ii <= get_num_incident_edges(); ++ii) {
315  }
317  return;
318 }
319 
320 /// @brief If FASTERNode is the most-derived class being used, then this function
321 /// will be called and will return the amount of memory statically allocated by
322 /// a single FASTERNode.
323 unsigned int
325 {
326  return sizeof( FASTERNode );
327 }
328 
329 /// @brief Called either by the IGBase if the FASTERNode is the most-derived class, or
330 /// called recursively by a derived class. Called to account for the dynamically allocated
331 /// memory that this node uses.
332 unsigned int
334 {
335  unsigned int dynamic_memory = 0;
336  dynamic_memory += one_body_energies_.size() * sizeof( core::PackerEnergy );
337  dynamic_memory += neighbors_curr_state_.size() * sizeof( int );
338  dynamic_memory += edge_matrix_ptrs_.size() * sizeof ( FArray2< core::PackerEnergy > );
339  dynamic_memory += curr_state_two_body_energies_.size() * sizeof ( core::PackerEnergy );
340  dynamic_memory += alternate_state_two_body_energies_.size() * sizeof ( core::PackerEnergy );
341  dynamic_memory += state_energies_in_current_state_assignment_.size() * sizeof ( core::PackerEnergy );
342  dynamic_memory += state_energies_in_current_context_.size() * sizeof ( core::PackerEnergy );
343  dynamic_memory += neighbor_relaxed_in_sBR_.size() * sizeof ( core::PackerEnergy );
344  dynamic_memory += perturbed_two_body_energies_.size() * sizeof ( core::PackerEnergy );
345 
346  dynamic_memory += NodeBase::count_dynamic_memory();
347  return dynamic_memory;
348 }
349 
350 /// @brief updates bookkeeping arrays that correspond to edge-list.
351 ///
352 /// calls base class update_edge_vector function, and then proceeds to create
353 /// appropriate bookkeeping arrays used in simulated annealing
355 {
357  //aa_offsets_for_this_lookup_.resize( get_num_incident_edges() + 1);
359 
360  edge_matrix_ptrs_.clear();
362  edge_matrix_ptrs_.push_back( FArray2A< core::PackerEnergy >() ); //occupy the 0th position
363 
364  for (int ii = 1; ii <= get_num_incident_edges(); ++ii) {
365  edge_matrix_ptrs_.push_back( get_incident_faster_edge(ii)->get_edge_table_ptr() );
366  }
367 
370  return;
371 }
372 
373 
374 void
376 {
377  std::copy(one_body_energies_.begin(),
378  one_body_energies_.end(),
380  );
381  int const local_num_states = get_num_states();
382 
383  for ( int ii = 1; ii <= get_num_edges_to_smaller_indexed_nodes(); ++ii ) {
384 
385  if ( neighbors_curr_state_[ ii ] == 0 ) continue;
386  // Lower neighbor;
387  // since the edge table is allocated( node2_nstates, node1_nstates )
388  // and we're "node 2", we can walk across the row very efficiently
389 
390  FArray2A< core::PackerEnergy > const & edge_table( edge_matrix_ptrs_[ ii ] );
391  int li_curr = edge_table.index( 1, neighbors_curr_state_[ ii ] );
392  for ( int jj = 1; jj <= local_num_states; ++jj, ++li_curr ) {
393  state_energies_in_current_state_assignment_[ jj ] += edge_table[ li_curr ];
394  }
395  }
396  for ( int ii = get_num_edges_to_smaller_indexed_nodes() + 1; ii <= get_num_incident_edges(); ++ii) {
397  if ( neighbors_curr_state_[ ii ] == 0 ) continue;
398 
399  // Upper neighbor;
400  // Since the edge table is allocated( node2_nstates, node1_nstates )
401  // and we're "node 1", we have to take strides across the table with the
402  // step size equal to the number of states on the other node.
403 
404  FArray2A< core::PackerEnergy > const & edge_table( edge_matrix_ptrs_[ ii ] );
405  int const stride = edge_table.size1();
406  int li_curr = edge_table.index( neighbors_curr_state_[ ii ], 1 );
407  for ( int jj = 1; jj <= local_num_states; ++jj, li_curr += stride ) {
408  state_energies_in_current_state_assignment_[ jj ] += edge_table[ li_curr ];
409  }
410  }
411 }
412 
414 {
415  core::PackerEnergy best_one_body_energy( 12345 );
416  int state_with_best_one_body_energy( 0 );
417  for ( int ii = 1; ii <= get_num_states(); ++ii ) {
418  if ( ii == 1 || one_body_energies_[ ii ] < best_one_body_energy ) {
419  best_one_body_energy = one_body_energies_[ ii ];
420  state_with_best_one_body_energy = ii;
421  }
422  }
423  partial_assign_state( state_with_best_one_body_energy );
424 }
425 
427 {
428  bool accept = prob < 1.0 ? (RG.uniform() < prob) : true;
429 
430  if ( accept ) {
432  } else {
434  }
435 }
436 
437 void FASTERNode::partial_assign_state( int new_state )
438 {
439  current_state_ = new_state;
440  relaxed_state_ = new_state;
443 
444  for (int ii = 1; ii <= get_num_incident_edges(); ++ii) {
446  get_node_index(),
448  );
449  }
450 }
451 
453  int which_neighbor,
454  int neighbors_new_state
455 )
456 {
457  neighbors_curr_state_[ which_neighbor ] = neighbors_new_state;
458 }
459 
461 {
462  for (int ii = 1; ii <= get_num_incident_edges(); ++ii)
463  {
467  }
468 
469  if ( in_FASTER_mode_ )
470  {
472  }
473 }
474 
476  int which_neighbor,
477  int const neighbors_perturbed_state
478 )
479 {
480  int const local_num_states = get_num_states();
481 
482  if ( perturbed_ ) return;
483 
485  FArray2A< core::PackerEnergy > const & edge_table( edge_matrix_ptrs_[ which_neighbor ] );
486  /*int li_curr = edge_table.index( 1, neighbors_curr_state_[ which_neighbor ] );
487  int li_pert = edge_table.index( 1, perturbed_state );
488 
489  /// This loop is the most time consuming step of FASTER -- it is made as minimal as possible.
490  for ( int ii = 1; ii <= local_num_states; ++ii, ++li_curr, ++li_pert ) {
491  state_energies_in_current_context_[ ii ] += edge_table[ li_pert ] - edge_table[ li_curr ];
492  }*/
493 
494  int const neighbors_current_state = neighbors_curr_state_[ which_neighbor ];
495  if ( which_neighbor <= get_num_edges_to_smaller_indexed_nodes() ) {
496  /*for ( int ii = 1; ii <= local_num_states; ++ii ) {
497  state_energies_in_current_context_[ ii ] +=
498  get_incident_faster_edge( which_neighbor )->get_two_body_energy(
499  neighbors_perturbed_state, ii )
500  -
501  get_incident_faster_edge( which_neighbor )->get_two_body_energy(
502  neighbors_curr_state, ii );
503 
504  }*/
505 
506  // Lower neighbor;
507  // since the edge table is allocated( node2_nstates, node1_nstates )
508  // and we're "node 2", we can walk across the row very efficiently
509  int li_curr = edge_table.index( 1, neighbors_current_state );
510  int li_pert = edge_table.index( 1, neighbors_perturbed_state );
511 
512  /// This loop is the most time consuming step of FASTER -- it is made as minimal as possible.
513  for ( int ii = 1; ii <= local_num_states; ++ii, ++li_curr, ++li_pert ) {
514  state_energies_in_current_context_[ ii ] += edge_table[ li_pert ] - edge_table[ li_curr ];
515  }
516  } else {
517  /*for ( int ii = 1; ii <= local_num_states; ++ii ) {
518  state_energies_in_current_context_[ ii ] +=
519  get_incident_faster_edge( which_neighbor )->get_two_body_energy(
520  ii, neighbors_perturbed_state );
521  -
522  get_incident_faster_edge( which_neighbor )->get_two_body_energy(
523  ii, neighbors_current_state);
524  }*/
525 
526  // Upper neighbor;
527  // Since the edge table is allocated( node2_nstates, node1_nstates )
528  // and we're "node 1", we have to take strides across the table with the
529  // step size equal to the number of states on the other node.
530  int const stride = edge_table.size1();
531  int li_curr = edge_table.index( neighbors_current_state, 1 );
532  int li_pert = edge_table.index( neighbors_perturbed_state, 1 );
533  for ( int ii = 1; ii <= local_num_states; ++ii, li_curr += stride, li_pert += stride ) {
534  state_energies_in_current_context_[ ii ] += edge_table[ li_pert ] - edge_table[ li_curr ];
535  }
536 
537  }
538 
539 }
540 
541 void
543 {
544  perturbed_ = true;
546 }
547 
548 void
550 {
551  perturbed_ = false;
552 }
553 
554 void
555 FASTERNode::set_perturbed_state( int perturbed_state )
556 {
557  relaxed_state_ = perturbed_state;
558 
559  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
561  get_energy_for_perturbed_state( get_node_index(), relaxed_state_ );
563  }
564 }
565 
567 {
568  for (int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
569  if ( neighbor_relaxed_in_sBR_[ ii ] ) {
572  }
573  }
574 
575 }
576 
578 {
579  int const local_num_states = get_num_states();
580 
581  core::PackerEnergy best_relaxed_energy = state_energies_in_current_context_[ 1 ];
582  relaxed_state_ = 1;
583  for ( int ii = 2; ii <= local_num_states; ++ii ) {
584  if ( state_energies_in_current_context_[ ii ] < best_relaxed_energy ) {
585  best_relaxed_energy = state_energies_in_current_context_[ ii ];
586  relaxed_state_ = ii;
587  }
588  }
589 
590 }
591 
593 {
594  reset_relaxed();
595  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
597  }
598 }
599 
600 
601 
603 {
605 }
606 
607 
608 
610 {
611  int const num_to_relax = 10;
612 
613 
614  core::PackerEnergy top10[ num_to_relax ];
615  int which10[ num_to_relax ];
616  core::PackerEnergy bottom_of_top10;
617  int whichBottom;
618  for ( int ii = 0; ii < num_to_relax; ++ii ) {
619  top10[ ii ] = 0;
620  which10[ ii ] = 0;
621  }
622 
623  //decide which neighbors to relax
624  if ( get_num_incident_edges() > num_to_relax ) {
625  for ( int ii = 1; ii <= num_to_relax; ++ii ) {
626  top10[ ii - 1 ] = std::abs(perturbed_two_body_energies_[ ii ]);
627  which10[ ii - 1] = ii;
628  if ( ii == 1 || bottom_of_top10 > top10[ ii-1 ] ) {
629  bottom_of_top10 = top10[ ii-1 ];
630  whichBottom = ii-1;
631  }
632  }
633 
634  for ( int ii = 11; ii <= get_num_incident_edges(); ++ii ) {
635  core::PackerEnergy iiabs = std::abs( perturbed_two_body_energies_[ ii ] );
636  if ( iiabs > bottom_of_top10 ) {
637  top10[ whichBottom ] = iiabs;
638  which10[ whichBottom ] = ii;
639  for ( int jj = 0; jj < num_to_relax; ++jj) {
640  if ( jj == 0 || bottom_of_top10 > top10[ jj ] ){
641  whichBottom = jj;
642  bottom_of_top10 = top10[ jj ];
643  }
644  }
645  }
646  }
647  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
648  neighbor_relaxed_in_sBR_[ ii ] = false;
649  }
650  //std::cout << "neighbors: ";
651  for ( int ii = 0; ii < num_to_relax; ++ii ) {
652  //std::cout << which10[ ii ] << " " ;
653  neighbor_relaxed_in_sBR_[ which10[ ii ] ] = true;
654  }
655  //std::cout << std::endl;
656  } else {
657  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
658  neighbor_relaxed_in_sBR_[ ii ] = true;
659  }
660  }
661 
662 
663  //std::cout << "peturbed: " << get_node_index() << " relaxing: ";
664  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
665  if ( neighbor_relaxed_in_sBR_[ ii ] ) {
667  //std::cout << get_index_of_adjacent_node( ii ) << " ";
668  }
669  }
670  //std::cout << std::endl;
671 }
672 
674 {
675  if ( perturbed_ ) return;
676 
679 
683  );
684  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
686  }
687  }
688 
689 }
690 
692 {
695 
696  int const local_num_states = get_num_states();
697  core::PackerEnergy best_relaxed_energy = state_energies_in_current_context_[ 1 ];
698  relaxed_state_ = 1;
699  for ( int ii = 2; ii <= local_num_states; ++ii ) {
700  if ( state_energies_in_current_context_[ ii ] < best_relaxed_energy ) {
701  best_relaxed_energy = state_energies_in_current_context_[ ii ];
702  relaxed_state_ = ii;
703  }
704  }
705 }
706 
709 {
711 
713 
714  core::PackerEnergy deltaE = core::PackerEnergy( 0.0 );
715  if ( perturbed_ ) {
716  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
718 
719  if ( neighbor_relaxed_in_sBR_[ ii ] ) {
720  deltaE += get_incident_faster_edge( ii )->
721  get_deltaE_for_neighbor_following_perturbation( get_node_index() );
722  neighbor_relaxed_in_sBR_[ ii ] = false;
723  }
724  }
725  } else {
726  for (int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
728  }
729  }
731  return deltaE;
732 }
733 
734 
735 
737 {
739 }
740 
741 int
743 {
744  return relaxed_state_;
745 }
746 
747 
749 {
750  if (get_num_incident_edges() == 0 ) return 0;
751 
752  int ran_neighbor = ((int) (RG.uniform() * get_num_incident_edges() )) + 1;
753  return get_index_of_adjacent_node( ran_neighbor );
754 }
755 
756 
757 /// @brief main constructor - no default nor copy constructors provided
758 ///
759 /// @param owner - [in] - pointer to the graph that created this node
760 /// @param first_node_ind - [in] - the index of the smaller-indexed node
761 /// @param second_node_ind - [in] - the index of the larger-indexed node
763  InteractionGraphBase * owner,
764  int first_node_ind,
765  int second_node_ind
766 ) :
767  parent( owner, first_node_ind, second_node_ind),
768  two_body_energies_(
769  get_faster_node(1)->get_num_states(),
770  get_faster_node(0)->get_num_states(),
771  core::PackerEnergy( 0.0 )
772  ),
773  curr_state_energy_( core::PackerEnergy( 0.0 )),
774  energies_updated_since_last_prep_for_simA_( true ),
775  have_contributed_deltaE_following_perturbation_( false ),
776  partial_state_assignment_( false )
777 {
778 }
779 
780 /// @brief destructor. All dynamically allocated memory is managed by the objects contained
781 /// inside the FASTEREdge, so there is no work to be (explicitly) done.
783 {}
784 
785 /// @brief adds the input energy to the two body energy for state1 on the node with the
786 /// smaller index and state2 on the node with the larger index.
788 (
789  int const state1,
790  int const state2,
791  core::PackerEnergy const energy
792 )
793 {
794  two_body_energies_(state2, state1) += edge_weight() * energy;
795  energies_updated_since_last_prep_for_simA_ = true;
796  return;
797 }
798 
799 /// @brief Adds all the energies stored in the oversized_res_res_energy array to the
800 /// two body energy table for those states whose amion acid types were
801 /// previoudsly declared to be amino-acid neighbors. The res-res array
802 /// should have the dimension (node1->get_num_states() x node2->get_num_states());
803 ///
804 /// @param res_res_energy_array - [in] - an array containing the state pair energies
806 (
807  FArray2< core::PackerEnergy > const & res_res_energy_array
808 )
809 {
810  assert( res_res_energy_array.size1() == two_body_energies_.size1() );
811  assert( res_res_energy_array.size2() == two_body_energies_.size2() );
812  for ( Size ii = 1, iie = two_body_energies_.size2(); ii <= iie; ++ii ) {
813  for ( Size jj = 1, jje = two_body_energies_.size1(); jj <= jje; ++jj ) {
814  two_body_energies_( jj, ii ) += edge_weight() * res_res_energy_array( jj, ii );
815  }
816  }
817  energies_updated_since_last_prep_for_simA_ = true;
818  return;
819 }
820 
821 /// @brief Sets the two-body energy for a pair of states. That is, it overwrites
822 /// whatever two-body energy there was previously for that state pair with
823 /// a new energy. Ignores non-neighboring state pairs.
824 ///
825 /// @param state1 - [in] - state index for the node with the smaller index
826 /// @param state2 - [in] - state index for the node with the larger index
827 /// @param energy - [in] - the energy which replaces the old two-body energy
829 (
830  int const state1,
831  int const state2,
832  core::PackerEnergy const energy
833 )
834 {
835  two_body_energies_( state2, state1 ) = edge_weight() * energy;
836  energies_updated_since_last_prep_for_simA_ = true;
837  return;
838 }
839 
840 /// @brief Sets the two-body energy for a pair of states. That is, it overwrites
841 /// whatever two-body energy there was previously for that state pair with
842 /// a new energy. Ignores non-neighboring state pairs.
843 ///
844 /// @param state1 - [in] - state index for the node with the smaller index
845 /// @param state2 - [in] - state index for the node with the larger index
846 /// @param energy - [in] - the energy which replaces the old two-body energy
848 (
849  int const state1,
850  int const state2
851 )
852 {
853  two_body_energies_(state2,state1) = core::PackerEnergy( 0.0 );
854  energies_updated_since_last_prep_for_simA_ = true;
855  return;
856 }
857 
858 /// @brief returns the two body energy for a pair of states: 0 if those states are
859 /// not neighbors
860 ///
861 /// @param state1 - [in] - state index for the node with the smaller index
862 /// @param state2 - [in] - state index for the node with the larger index
863 core::PackerEnergy FASTEREdge::get_two_body_energy( int const state1, int const state2 ) const
864 {
865  return two_body_energies_(state2, state1);
866 }
867 
868 /// @brief If all of the energies for an edge have been added in, then declare the edge energies
869 /// final. This may mean that the edge deletes itself.
871 {
873 }
874 
875 /// @brief looks at all pair energies, and if they are all 0, deletes itself
877 {
879 
880 
882 
883  bool any_non_zero = false;
884  Size const num_energies = two_body_energies_.size();
885  for ( Size ii = 0; ii < num_energies; ++ii ) {
886  if ( two_body_energies_[ ii ] != core::PackerEnergy( 0.0 ) ) { any_non_zero = true; break;}
887  }
888 
889  if ( ! any_non_zero ) delete this;
890 }
891 
893 {
895 }
896 
897 
898 /// @brief returns the two body energy corresponding to the current states assigned to
899 /// the nodes this edge is incident upon.
901 {
902  return curr_state_energy_;
903 
904 }
905 
907  int node,
908  int new_state
909 )
910 {
911  int const other = node == get_node_index(0) ? 1 : 0;
912 
916  new_state
917  );
918 }
919 
920 /// @brief updates bookkeeping information when one of the two nodes changes its state
921 ///
922 /// @param node_ind - [in] - the index of the node that changed its state
923 /// @param node_state - [in] - the index of the new state it assumed
924 /// @param new_energy - [out] - the two body energy produced by the new state and
925 /// the current state on the other node
926 void
928 (
929  int node_ind,
930  int new_state,
931  core::PackerEnergy & new_energy
932 )
933 {
934  int node_substituted = ( node_ind == get_node_index(0) ? 0 : 1);
935  int node_not_substituted = ! node_substituted;
936 
937  int nodes_curr_states[2];
938 
939  nodes_curr_states[ node_substituted ] = new_state;
940 
941  nodes_curr_states[ node_not_substituted ] =
942  get_faster_node( node_not_substituted )->get_current_state();
943 
944  bool one_node_in_zero_state = ( nodes_curr_states[0] == 0 || nodes_curr_states[1] == 0 );
945 
946  if ( one_node_in_zero_state ) {
947  curr_state_energy_ = core::PackerEnergy( 0.0 );
948  } else {
949  curr_state_energy_ = two_body_energies_( nodes_curr_states[ 1 ], nodes_curr_states[ 0 ] );
950  }
951  new_energy = curr_state_energy_;
952 
953  get_faster_node( node_not_substituted )->acknowledge_neighbors_state_substitution (
954  get_edges_position_in_nodes_edge_vector( node_not_substituted ),
955  curr_state_energy_,
956  new_state
957  );
958 
959  return;
960 }
961 
962 /// @brief updates bookkeeping information when one of the two nodes enters its
963 /// "unassigned" state.
964 ///
965 /// @param node_ind - [in] - the index of the node that has just entered its 0 state
967 {
968  int node_substituted = ( node_ind == get_node_index(0) ? 0 : 1);
969  int node_not_substituted = ! node_substituted;
970 
972 
974  get_edges_position_in_nodes_edge_vector( node_not_substituted ),
976  0
977  );
978 }
979 
980 
981 
982 
983 
984 /// @brief Returns a reference to the first element in the dense two-body energy
985 /// table. Used to create a proxy array on the nodes for cache efficiency.
986 
987 FArray2A< core::PackerEnergy >
989  return FArray2A< core::PackerEnergy >( two_body_energies_( 1, 1 ),
992 }
993 
994 
995 /// @brief returns the memory usage of the two body energy table for this edge
997 {
998  return two_body_energies_.size();
999 }
1000 
1001 /// @brief returns sizeof FASTEREdge if this is the most-derived instance of the class
1002 unsigned int
1004 {
1005  return sizeof( FASTEREdge );
1006 }
1007 
1008 /// @brief returns the amount of memory dynamically allocated by the edge and
1009 /// recurses on its parent (in this case, the EdgeBase class)
1010 unsigned int
1012 {
1013  unsigned int dynamic_memory = 0;
1014  dynamic_memory += two_body_energies_.size() * sizeof( core::PackerEnergy );
1015  dynamic_memory += parent::count_dynamic_memory();
1016  return dynamic_memory;
1017 }
1018 
1020 {
1021  return get_two_body_energy(
1022  get_faster_node( 0 )->get_relaxed_state(),
1023  get_faster_node( 1 )->get_relaxed_state() );
1024 }
1025 
1028 {
1030 
1031  partial_state_assignment_ = false;
1033  get_faster_node( 0 )->get_current_state(),
1034  get_faster_node( 1 )->get_current_state() );
1035  return curr_state_energy_;
1036 }
1037 
1038 
1039 //returns energy of perturbed state with neighbors current state
1041  int node,
1042  int nodes_perturbed_state
1043 )
1044 {
1045  return ( node == get_node_index(0) ?
1046  get_two_body_energy( nodes_perturbed_state, get_faster_node(1)->get_current_state() ) :
1047  get_two_body_energy( get_faster_node(0)->get_current_state(), nodes_perturbed_state ) );
1048 }
1049 
1051  int node,
1052  int neighbors_context_state
1053 )
1054 {
1055  int other_node = node == get_node_index(0) ? 1 : 0;
1058  neighbors_context_state);
1059 }
1060 
1061 
1062 void
1064 {
1066 }
1067 
1070 {
1074 }
1075 
1078 {
1079  int other_node = node_index == get_node_index(0) ? 1 : 0;
1081 }
1082 
1083 
1084 /// @details DANGER: If for some reason one were to reweight edges during simulated annealing
1085 /// then some of the cached energies in the adjacent nodes would be out-of-date; data integrity
1086 /// would be violated an all hell would break loose. The same thing is true if one were to
1087 /// change the energies on any edge during simulated annealing. One simple solution: call
1088 /// blanket_assign_state0 to wipe all cahced energies stored on nodes and then assign_network_state
1089 /// to the state just before the reweighting.
1090 /// Of course, since the annealer itself is tracking the "best" network state, you'd have to worry
1091 /// about its data integrity as well. General advice: don't change energies during simA.
1092 void
1094 {
1095  if ( weight == 0.0 ) {
1096  utility_exit_with_message( "Error: set edge weight to 0 not a legal operation. Delete this edge instead" );
1097  }
1098  Real rescale = weight / edge_weight();
1099  two_body_energies_ *= rescale;
1100  curr_state_energy_ *= rescale;
1101  edge_weight( weight ); // set base-class data
1102 
1103 }
1104 
1105 
1106 void
1108  ObjexxFCL::FArray2D< core::PackerEnergy > & new_edge_table
1109 )
1110 {
1111  if ( two_body_energies_.size1() != new_edge_table.size1() ) {
1112  utility_exit_with_message( "swap_edge_energies failed as size1 does not match: two_body_energies_.size1()= "
1113  + utility::to_string( two_body_energies_.size1() ) + " new_edge_table.size1()= "
1114  + utility::to_string( new_edge_table.size1() ) );
1115  }
1116  if ( two_body_energies_.size2() != new_edge_table.size2() ) {
1117  utility_exit_with_message( "swap_edge_energies failed as size2 does not match: two_body_energies_.size2()= "
1118  + utility::to_string( two_body_energies_.size2() ) + " new_edge_table.size2()= "
1119  + utility::to_string( new_edge_table.size2() ) );
1120  }
1121  two_body_energies_.swap( new_edge_table );
1122 }
1123 
1124 
1125 
1126 /// @brief main constructor: no default nor copy constructors provided.
1127 ///
1128 /// @param num_nodes - [in] - the number of nodes in this graph
1131  num_commits_since_last_update_(0),
1132  total_energy_current_state_assignment_(0),
1133  total_energy_alternate_state_assignment_(0),
1134  node_considering_alt_state_( -1 ),
1135  sBR_( false ),
1136  dBR_( false ),
1137  relaxed1_( -1 ),
1138  relaxed2_( -1 )
1139 {}
1140 
1141 /// @brief The FASTERIG only needs to know how many states each node has.
1142 /// This function causes the downstream instantiation of the FASTERNodes.
1143 void
1145 {
1146  rotamer_set::RotamerSets const & rot_sets( static_cast< rotamer_set::RotamerSets const & > (rot_sets_base) );
1147  for ( uint ii = 1; ii <= rot_sets.nmoltenres(); ++ii ) {
1148  set_num_states_for_node( ii, rot_sets.rotamer_set_for_moltenresidue( ii )->num_rotamers() );
1149  }
1150 
1151 }
1152 
1153 /// @brief returns the one body energy for a particular state on a node
1156 {
1157  return get_faster_node( node )->get_one_body_energy( state );
1158 }
1159 
1160 /// @brief assigns the state of all nodes in the interaction graph to their unassigned
1161 /// or zero states.
1163 {
1164  //a state assignment of 0 means "unassigned".
1165  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
1167  }
1169  return;
1170 }
1171 
1172 /// @brief sets the state on node node_ind to new_state
1173 ///
1174 /// @param node_ind - [in] - the index of the node in question
1175 /// @param new_state - [in] - the new state the node is being assigned to
1177 {
1178  get_faster_node( node_ind )->assign_state(new_state);
1181 }
1182 
1184 {
1185  return get_faster_node( node_ind )->get_current_state();
1186 }
1187 
1188 
1189 /// @brief takes in a vector of states, one state per node, and sets the state for
1190 /// each of the nodes to the specified state.
1191 ///
1192 /// also calls "update internal energy totals" to undo any numerical noise
1193 /// accumulated during the transition.
1194 ///
1195 /// @param node_states - [in] - array of states, one for each node.
1197 {
1198  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
1199  get_faster_node( ii )->assign_state( node_states(ii) );
1200  }
1203 }
1204 
1205 /// @brief considers altering the state of a particular node; returns the
1206 /// change in energy that the state substitution would produce
1207 ///
1208 /// to avoid too much numerical drift from accumulating, the bookkeeping
1209 /// arrays are updated once every 2^10 state commits
1210 ///
1211 /// @param node_ind - [in] - the index of the node considering a state change
1212 /// @param new_state - [in] - the new state that node is considering
1213 /// @param alt_total_energy - [out] - the total network energy produced under the
1214 /// new state
1215 /// @param delta_energy - [out] - the change in energy produced under the substitution
1216 /// @param prev_energy_for_node - [out] - the sum of the one and two body energies
1217 /// for this node under the current state assignment
1218 void
1221  int node_ind,
1222  int new_state,
1223  core::PackerEnergy & delta_energy,
1224  core::PackerEnergy & prev_energy_for_node
1225 )
1226 {
1227  node_considering_alt_state_ = node_ind;
1228  delta_energy = get_faster_node( node_ind )->
1229  project_deltaE_for_substitution( new_state, prev_energy_for_node );
1230 
1231  //numerical drift accumulates in the following assignment
1232  total_energy_alternate_state_assignment_ =
1233  total_energy_current_state_assignment_ + delta_energy;
1234 
1235  return;
1236 }
1237 
1238 
1239 /// @details to avoid too much numerical drift from accumulating, the bookkeeping
1240 /// arrays are updated once every 2^10 state commits
1243 {
1248 
1252  }
1253 
1255 }
1256 
1258 {
1261 }
1262 
1263 
1264 
1265 /// @details Iterates across nodes and then edges to look-up the energies
1266 /// for the current state assignmnet removing any numerical drift which
1267 /// accumulated in the member variable total_energy_current_state_assignment_.
1269 {
1271 
1272  //std::cout << "updating internal energy totals: " << std::endl;
1273  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
1274  //std::cout << " ig_node " << ii << " = " << ((FASTERNode *) ig_nodes_[ ii ])
1275  // ->get_one_body_energy_current_state();
1276 
1278  get_one_body_energy_current_state();
1279  }
1280 
1281  //int counter = 0;
1282  for (std::list<EdgeBase*>::iterator iter = get_edge_list_begin();
1283  iter != get_edge_list_end(); ++iter) {
1284  //std::cout << " ig_edge " << ++counter << " =" <<
1285  //((FASTEREdge*) *iter)->get_current_two_body_energy();
1287  ((FASTEREdge*) *iter)->get_current_two_body_energy();
1288  }
1289 
1290  //std::cout << std::endl;
1291 
1293  return;
1294 }
1295 
1296 
1298 {
1299  int sum = 0;
1300  for (std::list< EdgeBase* >::const_iterator iter = get_edge_list_begin();
1301  iter != get_edge_list_end(); ++iter) {
1302  sum += ((FASTEREdge*) *iter)->get_two_body_table_size();
1303  }
1304  return sum;
1305 }
1306 
1307 /// @brief returns the amount of static memory allocated for a single FASTERInteractionGraph.
1308 /// Does not account for any of the edges or nodes that the graph contains: that part of the
1309 /// algorithm is implemented by the InteractionGraphBase class.
1310 unsigned int
1312 {
1313  return sizeof( FASTERInteractionGraph );
1314 }
1315 
1316 /// @brief returns the amount of dynamic memory allocated for a single FASTERInteractionGraph
1317 /// and recurses on the parent class.
1318 /// Does not account for any of the edges or nodes that the graph contains: that part of the
1319 /// algorithm is implemented by the InteractionGraphBase class.
1320 unsigned int
1322 {
1324 }
1325 
1327 {
1328  for (std::list< EdgeBase* >::iterator iter = get_edge_list_begin();
1329  iter != get_edge_list_end();
1330  //note: no increment statement here
1331  ){
1332  std::list< EdgeBase* >::iterator next_iter = iter;
1333  next_iter++;
1334  //edges sometimes delete themselves, invalidating iterators, so
1335  //get the next iterator before calling prepare_for_simulated_annealing
1336  ((FASTEREdge* ) (*iter))->prepare_for_FASTER();
1337  iter = next_iter;
1338  }
1339 
1340  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
1342  }
1343  return;
1344 }
1345 
1347 {
1348  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
1350  }
1351  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
1353  }
1355 }
1356 
1358 {
1359  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
1360  get_faster_node( ii )->relax();
1361  }
1362 }
1363 
1365 {
1366  core::PackerEnergy energy_total = 0;
1367  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
1368  energy_total += get_faster_node( ii )->get_one_body_energy_for_relaxed_state();
1369  }
1370 
1371  for ( std::list< EdgeBase* >::iterator edge_iter = get_edge_list_begin();
1372  edge_iter != get_edge_list_end(); ++edge_iter ) {
1373  energy_total += ((FASTEREdge*) (*edge_iter))->get_two_body_energies_for_relaxed_states();
1374  }
1375 
1376  return energy_total;
1377 }
1378 
1380 {
1381  if (sBR_) {
1383  sBR_ = false;
1384  }
1385 
1386  if (dBR_) {
1389  dBR_ = false;
1390  }
1391 }
1392 
1393 
1395 {
1396  sBR_ = dBR_= false;
1397  for ( int ii = 1; ii <= get_num_nodes(); ++ii ) {
1399  }
1400 
1401  for ( int ii = 1; ii <= get_num_nodes() ; ++ii ) {
1403  }
1405 }
1406 
1408 {
1409  for ( int ii = 1; ii <= get_num_nodes() ; ++ii ) {
1410  get_faster_node( ii )->partial_assign_relaxed_state( probability );
1411  }
1412  for ( int ii = 1; ii <= get_num_nodes() ; ++ii ) {
1414  }
1416 }
1417 
1419 {
1420  for ( int ii = 1; ii <= get_num_nodes() ; ++ii ) {
1421  netstate( ii ) = get_faster_node( ii )->get_current_state();
1422  }
1423 }
1424 
1427  int node,
1428  int perturbed_state
1429 )
1430 {
1431  sBR_ = true;
1432  relaxed1_ = node;
1433 
1435  get_faster_node( node )->set_perturbed_state( perturbed_state );
1437  get_faster_node( node )->relax_neighbors();
1438 
1441 
1442  return deltaE;
1443 }
1444 
1447  int node1,
1448  int perturbed_state1,
1449  int node2,
1450  int perturbed_state2
1451 )
1452 {
1453  dBR_ = true;
1454  relaxed1_ = node1;
1455  relaxed2_ = node2;
1456 
1459 
1460  get_faster_node( node1 )->set_perturbed_state( perturbed_state1 );
1461  get_faster_node( node2 )->set_perturbed_state( perturbed_state2 );
1462 
1465 
1466  get_faster_node( node1 )->relax_neighbors();
1467  get_faster_node( node2 )->relax_neighbors();
1468 
1469  core::PackerEnergy deltaE = 0;
1472 
1475 
1476  return deltaE;
1477 }
1478 
1480 {
1481  return get_faster_node( node )->get_random_neighbor();
1482 }
1483 
1484 
1486 {
1487  std::cout << "Curr States: ";
1488  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
1489  std::cout << "(" << ii << ", ";
1490  std::cout << get_faster_node(ii)->get_current_state() << ") ";
1492  }
1493  std::cout << std::endl;
1494 }
1495 
1496 
1497 /// @details For instance in a graph with 6 vertices,
1498 /// {a,b,c,d,e,f}
1499 /// a user may be interested in the sum of the one- and two-body energies
1500 /// for vertices {a,b,c}. The graph will return sum of the one body energies
1501 /// for vertices a b and c and also any two-body energies for the edges in the
1502 /// subgraph induced by a,b, and c. (In this case, edges {a,b}, {a,c} and {b,c}
1503 /// if these edges are part of the graph. The edge {a,d} will not be counted
1504 /// if it is part of the graph.)
1505 /// ask the graph for the energies of the induced subgraph defined
1506 /// by a particular group.
1507 ///
1508 /// @param group_id - [in] - the groups for which you're interested in retrieving
1509 /// energies of the induced subgraph
1512 {
1513  core::PackerEnergy esum = core::PackerEnergy( 0.0 );
1514  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
1515  if ( get_vertex_member_of_energy_sum_group( ii, group_id ) ) {
1517  }
1518  }
1519 
1520  for ( std::list< EdgeBase* >::iterator edge_iter = get_edge_list_begin();
1521  edge_iter != get_edge_list_end(); ++edge_iter) {
1522  int first_node_ind = (*edge_iter)->get_first_node_ind();
1523  int second_node_ind = (*edge_iter)->get_second_node_ind();
1524 
1525  if ( get_vertex_member_of_energy_sum_group( first_node_ind, group_id )
1526  && get_vertex_member_of_energy_sum_group( second_node_ind, group_id )) {
1527  esum += ((FASTEREdge*) (*edge_iter))->get_current_two_body_energy();
1528  }
1529  }
1530  return esum;
1531 }
1532 
1533 
1534 void
1536  int node1,
1537  int node2,
1538  ObjexxFCL::FArray2D< core::PackerEnergy > & new_edge_table
1539 )
1540 {
1541  get_faster_edge( node1, node2 )->swap_edge_energies( new_edge_table );
1542 }
1543 
1544 
1545 /// @brief factory method that instantiates a FASTERNode.
1546 ///
1547 /// @param node_index - [in] - the index of the node being created
1548 /// @param num_states - [in] - the total number of states for the new node
1549 NodeBase* FASTERInteractionGraph::create_new_node( int node_index, int num_states)
1550 {
1551  FASTERNode* new_node = new FASTERNode(this, node_index, num_states);
1552  assert( new_node != NULL );
1553  return new_node;
1554 }
1555 
1556 /// @brief factory method that instantiates a FASTEREdge
1557 ///
1558 /// @param index1 - [in] - the smaller-indexed node this edge is incident upon
1559 /// @param index2 - [in] - the larger-indexed node this edge is incident upon
1561 {
1562  return new FASTEREdge(this, index1, index2);
1563 }
1564 
1565 } // namespace interaction_graph
1566 } // namespace pack
1567 } // namespace core
1568