Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HPatchInteractionGraph.hh
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/HPatchInteractionGraph.hh
11 /// @brief Interaction graph which implements a non-PD score that optimizes against surface hydrophobic patches.
12 /// @author Ron Jacak (ron.jacak@gmail.com)
13 /// @author Andrew Leaver-Fay
14 
15 #ifndef INCLUDED_core_pack_interaction_graph_HPatchInteractionGraph_hh
16 #define INCLUDED_core_pack_interaction_graph_HPatchInteractionGraph_hh
17 
18 //Rosetta Headers
21 // AUTO-REMOVED #include <core/chemical/ResidueTypeSet.hh>
23 // AUTO-REMOVED #include <core/chemical/ChemicalManager.hh>
24 
26 // AUTO-REMOVED #include <core/id/AtomID.hh>
27 // AUTO-REMOVED #include <core/id/AtomID_Map.hh>
28 
30 
39 
40 #include <core/pose/Pose.hh>
41 
42 #include <core/scoring/sasa.hh>
44 
45 #include <basic/Tracer.hh>
46 
47 //Utility Headers
48 // AUTO-REMOVED #include <numeric/xyzVector.io.hh>
49 #include <utility/vector1.hh>
50 // AUTO-REMOVED #include <utility/vector1.functions.hh> // to get arg_max
51 #include <utility/exit.hh>
52 // AUTO-REMOVED #include <utility/string_util.hh>
53 
54 //ObjexxFCL Headers
55 #include <ObjexxFCL/FArray1D.hh>
56 // AUTO-REMOVED #include <ObjexxFCL/FArray1.io.hh>
57 // AUTO-REMOVED #include <ObjexxFCL/format.hh>
58 
59 //C++ Headers
60 #include <vector>
61 
62 //Auto Headers
63 //#define DOUBLE_CHECK_COUNTS 1
64 //#define FILE_DEBUG 1
65 
66 namespace core {
67 namespace pack {
68 namespace interaction_graph {
69 
70 struct
72 {
73  exposed_hydrophobic_data( Size fc_bg, Size node_ind, Size exhphobe_ind ) :
74  fc_bg_( fc_bg ),
75  node_index_( node_ind ),
76  exhphobe_index_( exhphobe_ind )
77  {}
78 
79  Size fc_bg_; // 1 for first-class node; 2 for background node
80  Size node_index_; // the node index
81  Size exhphobe_index_; // the exposed hydrophobic index on that node
82 };
83 
84 /// Tracer instance for this file
85 static basic::Tracer TR_NODE("core.pack.hpatchig.node");
86 static basic::Tracer TR_EDGE("core.pack.hpatchig.edge");
87 static basic::Tracer TR_BGNODE("core.pack.hpatchig.bgnode");
88 static basic::Tracer TR_BGEDGE("core.pack.hpatchig.bgedge");
89 static basic::Tracer TR_HIG("core.pack.hpatchig.ig");
90 static basic::Tracer TR_STATS("core.pack.hpatchig.stats");
91 
92 
93 template < typename V, typename E, typename G > class HPatchNode;
94 template < typename V, typename E, typename G > class HPatchBackgroundNode;
95 template < typename V, typename E, typename G > class HPatchEdge;
96 template < typename V, typename E, typename G > class HPatchBackgroundEdge;
97 template < typename V, typename E, typename G > class HPatchInteractionGraph;
98 
99 
100 //----------------------------------------------------------------------------//
101 //---------------------------- HPatch Node Class -------------------------------//
102 //----------------------------------------------------------------------------//
103 
104 ///
105 /// @begin HPatchNode
106 ///
107 /// @brief
108 /// Defines a FirstClass node which will keep track of changes in the SASA and hpatch score.
109 /// FirstClassNode is defined and implemented in AdditionalBackgroundNodesInteractionGraph.
110 ///
111 /// @remarks
112 /// No public default constructor makes this class uncopyable.
113 ///
114 template < typename V, typename E, typename G >
115 class HPatchNode : public FirstClassNode< V, E, G > {
116 
117  public:
119  typedef V grandparent;
120 
121  public:
122  HPatchNode( G* owner, int node_index, int num_states );
123  virtual ~HPatchNode();
124 
125  // setter for the rotamers object. called at the very beginning of the HIG::initialize() method
126  void set_rotamers( rotamer_set::RotamerSetCOP rotamers );
127  conformation::ResidueCOP get_rotamer( int state ) const;
129  return rotamers_vector_[ parent::get_current_state() ];
130  }
131 
133  return rotamers_vector_[ parent::get_alternate_state() ];
134  }
135 
136  virtual void set_rotamer_dots_for_state( Size state, RotamerDots const & rd );
137 
138  bool overlaps( HPatchNode< V, E, G >* neighbor );
139  bool detect_any_overlap_with_rotamer( RotamerDots const & rotamer ) const;
140 
141  virtual void prepare_for_simulated_annealing();
143  RotamerDots const & bg_rotamer,
144  std::vector< RotamerDotsCache > & overlap,
145  std::vector< utility::vector1< utility::vector1< bool > > > & states_atom_atom_overlap_on_bg_res
146  );
147 
148  // for HIG entry point blanket_assign_state_0()
149  virtual void assign_zero_state();
151 
152  core::PackerEnergy calculate_PD_deltaE_for_substitution( int alternate_state, core::PackerEnergy & prev_PDenergies_for_node );
156  Real get_current_state_sasa( Size atom_index ) const;
157  Real get_alternate_state_sasa( Size atom_index ) const;
158 
160 
163 
164  inline
165  int wt_seqpos_for_node() const {
166  return get_hpatch_owner()->rotamer_sets().moltenres_2_resid( parent::get_node_index() );
167  }
168 
169  inline
171  return get_hpatch_owner()->pose().residue( (get_hpatch_owner()->rotamer_sets().moltenres_2_resid( parent::get_node_index() )) );
172  }
173 
174  Real update_state_for_neighbors_substitution( HPatchNode<V,E,G>* node_considering_substitution,
175  RotamerDots & neighbors_alternate_state,
176  RotamerDotsCache const & neighbors_curr_state_overlap_with_this,
177  RotamerDotsCache & this_overlap_with_neighbors_alternate,
178  RotamerDotsCache & neighbors_alternate_overlap_with_this,
179  utility::vector1< utility::vector1< bool > > & alt_state_atom_atom_overlaps_cache
180  );
181 
182  void reset_alt_state_dots();
183 
185 
186  virtual unsigned int getMemoryUsageInBytes() const;
187  virtual unsigned int count_static_memory() const;
188  virtual unsigned int count_dynamic_memory() const;
189 
190  //void write_dot_kinemage( std::ofstream & output_kin );
191  virtual void print() const;
192 
193  // Extra methods only used only for the unit tests.
196 
199  return curr_state_inv_dots_;
200  }
203  return alt_state_inv_dots_;
204  }
205 
206  Size
208  return max_hphobes_;
209  }
210 
213  return hphobe_ats_for_restype_group_[ restype_group_for_rotamers_[ grandparent::get_current_state() ]];
214  }
215 
218  return hphobe_ats_for_restype_group_[ restype_group_for_rotamers_[ grandparent::get_alternate_state() ]];
219  }
220 
221  Size n_curr_state_hphobes() const { return curr_state_hphobes().size(); }
222  Size n_alt_state_hphobes() const { return alt_state_hphobes().size(); }
223 
228 
229  protected:
230  inline
232  return (HPatchEdge< V, E, G > *) parent::get_incident_edge( index );
233  }
234 
235  inline
238  }
239 
240  inline
242  return (HPatchInteractionGraph< V, E, G > *) parent::get_owner();
243  }
244 
245  Real get_sasa_difference() const;
246 
247  private:
251 
252  // no default constructor, uncopyable
253  HPatchNode();
256 
257  private:
262 
263  // outer vector is all states possible at this Node, inner two vectors are ii and jj atoms
265 
266  // vector1 of RotamerDots objects. for every state on every molten residue there is a RotamerDots object.
268 
271 
274 
277 
279 
280 };
281 
282 
283 
284 //----------------------------------------------------------------------------//
285 //------------------------- HPatch Background Node Class -----------------------//
286 //----------------------------------------------------------------------------//
287 
288 ///
289 /// @begin HPatchBackgroundNode
290 ///
291 /// @brief
292 /// Defines a Background Node which will contribute to changes in SASA/hpatchE due to state changes on neighboring nodes,
293 /// and not because of state changes to it.
294 /// No default constructor makes this class uncopyable
295 ///
296 template < typename V, typename E, typename G >
297 class HPatchBackgroundNode : public BackgroundNode< V, E, G > {
298 
299  public:
301 
302  public:
304  virtual ~HPatchBackgroundNode();
305 
306  void set_rotamer( conformation::ResidueOP const & rotamer );
308 
309  void set_rotamer_dots( RotamerDots const & bg_rd );
310 
311  bool detect_overlap( HPatchNode< V, E, G >* node ) const;
312  virtual void prepare_for_simulated_annealing();
313 
315 
317  HPatchNode< V, E, G >* fc_node_changing,
318  RotamerDotsCache const & nodes_curr_overlap_with_bg_res,
319  RotamerDotsCache const & nodes_alt_overlap_with_bg_res
320  );
321 
322  void reset_alt_state_dots();
324  Real get_current_sasa() const;
325  Real get_current_sasa( Size atom_index ) const;
326  Real get_alternate_sasa() const;
327  Real get_alternate_sasa( Size atom_index ) const;
328 
331  Size n_hphobes() const { return n_hphobes_; }
332 
333  virtual unsigned int count_static_memory() const;
334  virtual unsigned int count_dynamic_memory() const;
335 
336  //void write_dot_kinemage( std::ofstream & output_kin );
337  virtual void print() const;
338 
339  // Only used for the unit tests.
342 
345  return curr_state_inv_dots_;
346  }
347 
350  return alt_state_inv_dots_;
351  }
352 
355 
358 
359  protected:
360  inline
363  }
364 
365  inline
368  }
369 
370  private:
374 
378 
380 
383 
386 
389 
391 
393 
397 
398 };
399 
400 
401 //----------------------------------------------------------------------------//
402 //------------------------------ HPatch Edge Class -----------------------------//
403 //----------------------------------------------------------------------------//
404 
405 ///
406 /// @begin HPatchEdge
407 ///
408 /// @brief
409 /// Defines a HPatch Edge which connects two first-class HPatch Nodes. Edges have to keep some state so that updates
410 /// to SASA and the hpatch score can be done fast.
411 ///
412 template < typename V, typename E, typename G >
413 class HPatchEdge : public FirstClassEdge< V, E, G > {
414 
415  public:
417 
418  public:
419  HPatchEdge( G * owner, int node1, int node2 );
420  virtual ~HPatchEdge();
421 
422  virtual void prepare_for_simulated_annealing();
423 
424  void acknowledge_state_zeroed( int node_index );
425 
427  int node_considering_substitution,
428  int alt_state,
429  RotamerDots & alt_state_dots
430  );
431 
433 
436 
437  // Virtual methods from EdgeBase
438  virtual void declare_energies_final();
439 
440  virtual unsigned int getMemoryUsageInBytes() const;
441  virtual unsigned int count_static_memory() const;
442  virtual unsigned int count_dynamic_memory() const;
443 
445 
446  protected:
447  inline
449  return (HPatchNode< V, E, G >*) E::get_node( index );
450  }
451 
452  private:
454 
455  //no default constructor, uncopyable
456  HPatchEdge();
459 
460  private:
465 
468 
471 
472  /// pairs of hphobes that have exposed overlap
475 
476 };
477 
478 
479 
480 //----------------------------------------------------------------------------//
481 //------------------- HPatch Background Edge Class -----------------------//
482 //----------------------------------------------------------------------------//
483 
484 ///
485 /// @begin HPatchBackgroundEdge
486 ///
487 /// @brief
488 /// Defines an edge between a FirstClass (HPatchNode) and a background node (HPatchBackgroundNode)
489 ///
490 /// @details
491 /// In addition to implementing the virtual base class methods, this class additionally defines methods
492 /// relating to keeping track of data relating to SASA/hpatch.
493 ///
494 template < typename V, typename E, typename G >
495 class HPatchBackgroundEdge : public BackgroundToFirstClassEdge< V, E, G > {
496 
497  public:
499 
500  public:
501  HPatchBackgroundEdge( AdditionalBackgroundNodesInteractionGraph< V, E, G >* owner, int first_class_node_index, int background_node_index );
502  virtual ~HPatchBackgroundEdge();
503 
505  void initialize_overlap_cache( RotamerDots const & bg_residue );
506 
507  void acknowledge_state_change( int new_state );
508 
509  Real update_state_at_neighbor( int alt_state );
511 
513 
514  virtual unsigned int count_static_memory() const;
515  virtual unsigned int count_dynamic_memory() const;
516 
517  protected:
518  inline
521  }
522 
523  inline
526  }
527 
528  private:
529  //no default constructor, uncopyable
533 
534  private:
537 
538  //uses index 0; do not change to utility::vector1
539  std::vector< RotamerDotsCache > node_states_coverage_of_bg_res_;
540 
543 
546 
547  // uses index 0; do not change
548  std::vector< utility::vector1< utility::vector1< bool > > > node_states_overlap_with_bg_res_;
549 
550  /// pairs of hphobes that have exposed overlap
553 
554 };
555 
556 
557 
558 //----------------------------------------------------------------------------//
559 //--------------------- HPatch Interaction Graph -------------------------//
560 //----------------------------------------------------------------------------//
561 
562 ///
563 /// @begin HPatchInteractionGraph
564 ///
565 /// @brief
566 /// Defines the interaction graph that will keep track of changes to the hpatch score.
567 ///
568 /// @details
569 /// In addition to implementing the virtual base class methods, this class additionally defines methods
570 /// relating to keeping track of data relating to hpatch.
571 ///
572 template < typename V, typename E, typename G >
574 
575  public:
577 
578  public:
579  HPatchInteractionGraph( int num_nodes );
580  virtual ~HPatchInteractionGraph();
581 
582  pose::Pose const & pose() const { return *pose_; }
583  void set_pose( pose::Pose const & pose );
584 
585  task::PackerTask const & packer_task() const { return *packer_task_; }
586  void set_packer_task( task::PackerTask const & task );
587 
589  void set_rotamer_sets( rotamer_set::RotamerSets const & rotsets );
590 
591  void set_score_weight( Real weight ) { hpatch_score_weight_ = weight; }
592 
593  void initialize( rotamer_set::RotamerSetsBase const & rot_sets );
594 
595  void set_num_residues_in_protein( Size num_res );
596  void set_num_background_residues( Size num_background_residues );
597  void set_residue_as_background_residue( int residue );
598  void set_background_residue_rotamer_dots( Size residue, conformation::Residue const & rotamer );
599  void set_rotamer_dots_for_node_state( Size node_index, Size state, conformation::Residue const & rotamer );
600 
601  virtual void prepare_for_simulated_annealing();
602 
603  virtual void blanket_assign_state_0();
605  virtual void set_errorfull_deltaE_threshold( core::PackerEnergy deltaE );
606 
607  static void print_hpatch_avoidance_stats();
608  static void reset_hpatch_avoidance_stats();
609 
610  virtual void consider_substitution( int node_ind, int new_state, core::PackerEnergy & delta_energy, core::PackerEnergy & prev_energy_for_node );
612 
614  void register_fc_node_affected_by_rotsub( int fc_node_ind );
615  void register_bg_node_affected_by_rotsub( int bg_node_ind );
616 
617  // used only for intra-residue connections
619  conformation::Residue const & rsd,
620  InvRotamerDots const & invdots,
621  utility::vector1< Size > const & exp_hphobes,
622  Size residue_djs_offset,
623  utility::vector1< utility::vector1< bool > > const & atom_atom_self_overlap,
625  );
626 
627  // used for inter-residue connections
629  conformation::Residue const & rsd1,
630  InvRotamerDots const & invdots1,
631  utility::vector1< Size > const & exp_hphobes1,
632  Size djs_offset_1,
633  conformation::Residue const & rsd2,
634  InvRotamerDots const & invdots2,
635  utility::vector1< Size > const & exp_hphobes2,
636  Size djs_offset_2,
637  utility::vector1< utility::vector1< bool > > const & atom_atom_overlaps,
639  );
640 
642  //void blanket_reset_alt_state_dots();
643 
645 
646  virtual core::PackerEnergy set_network_state( FArray1_int & node_states );
647 
649  virtual int get_edge_memory_usage() const;
650  virtual unsigned int count_static_memory() const;
651  virtual unsigned int count_dynamic_memory() const;
652 
653  using parent::get_energy_sum_for_vertex_group;
654 
655  //virtual void print_current_state_assignment() const;
656  virtual Real get_energy_sum_for_vertex_group( Size group_id );
657 
659  //void write_dot_kinemage( std::ofstream & output_kin );
660 
661  void print() const;
662 
663  // method used only by unit tests
664  int bg_node_2_resid( Size node_index );
665  std::vector<int> get_network_state() const;
667  void get_all_sasas( utility::vector1< Real > & node_sasas, utility::vector1< Real > & bgnode_sasas );
668 
669  /*utility::vector1< Size > const & get_fc_nodes_near_rotsub();
670  utility::vector1< bool > const & get_fc_nodes_near_rotsub_bool();
671  utility::vector1< Size > const & get_bg_nodes_near_rotsub();
672  utility::vector1< bool > const & get_bg_nodes_near_rotsub_bool();
673 
674  utility::vector1< Size > const & get_fc_n_exp_hphobes();
675  utility::vector1< Size > const & get_bg_n_exp_hphobes();
676 
677  utility::vector1< Size > const & get_fc_exp_hphobe_djs_offsets();
678  utility::vector1< Size > const & get_bg_exp_hphobe_djs_offsets();*/
679 
680  // need to make these method public for the unit tests
681  inline
683  return (HPatchNode< V, E, G > *) G::get_node( index );
684  }
685 
686  inline
689  }
690 
691  protected:
692  virtual NodeBase* create_new_node( int node_index, int num_states);
693  virtual EdgeBase* create_new_edge( int index1, int index2);
694  virtual BackgroundNode< V, E, G >* create_background_node( int node_index );
695  virtual BackgroundToFirstClassEdge< V, E, G >* create_background_edge( int fc_node_index, int bg_node_index);
696 
697  void track_hpatch_E_min();
698 
700 
701  private:
703  bool decide_procrastinate_hpatch_computations( Real const pd_deltaE, Real const threshold ) const;
704 
709 
711 
712 #ifdef DOUBLE_CHECK_COUNTS
713  void verify_sasas_correct();
714 #endif
715 
719 
720  private:
724 
726 
731 
736 
737  // keep track of which residues are effected by a considered rotamer substitution
743 
744  /// "djs" for DisJoint Sets. An abuse of the idea of an acronym.
749 
751  //utility::vector1< Real > sasa_for_djs_node_;
753 
754  /// extract the disjoint sets connected component information by hand (faster)
758 
760 
762 
766 
770 
773 
778 
781 
784 
787  static const int COMMIT_LIMIT_BETWEEN_UPDATES = 4096;
788 
791 };
792 
793 
794 
795 //----------------------------------------------------------------------------//
796 //-------------------------------- HPatch Node Class ---------------------------//
797 //----------------------------------------------------------------------------//
798 
799 ///
800 /// @begin HPatchNode< V, E, G >::HPatchNode
801 ///
802 /// @brief
803 /// HPatchNode constructor
804 ///
805 template < typename V, typename E, typename G >
806 HPatchNode< V, E, G >::HPatchNode( G* owner, int node_index, int num_states ) :
807  FirstClassNode< V, E, G > ( owner, node_index, num_states ),
808  current_state_rotamer_dots_(), // does this call the RD constructor? Yes!
809  alt_state_rotamer_dots_(),
810  alt_state_dots_matches_current_state_dots_( true )
811 {
812  rotamers_vector_.resize( num_states );
813  restype_group_for_rotamers_.resize( num_states, 0 );
814  self_and_bg_dots_for_states_.resize( parent::get_num_states() );
815 }
816 
817 
818 ///
819 /// @begin HPatchNode< V, E, G >::~HPatchNode
820 ///
821 /// @brief
822 /// destructor -- no dynamically allocated data, does nothing
823 ///
824 template < typename V, typename E, typename G >
826  //TR_NODE << "called destructor" << std::endl;
827 }
828 
829 
830 ///
831 /// @begin HPatchNode::set_rotamers
832 ///
833 /// @details
834 /// Need to save a reference to the rotamer_set so that we can determine what a particular state change will do to the score
835 ///
836 template < typename V, typename E, typename G >
838 
839  // get_num_states should call the parent graph's method?
840  if ( rotamers->num_rotamers() != (Size) parent::get_num_states() ) {
841  utility_exit_with_message( "Number of rotamers is not equal to parents number of states. Quitting.");
842  }
843 
844 #ifdef FILE_DEBUG
845  TR_NODE << "set_rotamers: adding " << rotamers->num_rotamers() << " to local rotamers vector." << std::endl;
846 #endif
847 
848  for ( Size ii = 1; ii <= rotamers->num_rotamers(); ++ii ) {
849  rotamers_vector_[ ii ] = rotamers->rotamer( ii );
850  restype_group_for_rotamers_[ ii ] = rotamers->get_residue_group_index_for_rotamer( ii );
851  }
852 
853  { // scope -- I should make this a function
854  std::string carbon( "C" ), sulfur( "S" );
855  max_hphobes_ = 0;
856 
857  // here we set every index of hphobe_ats_for_restype_group_ with the atom ids of the hydrophobic atoms in that restype.
858  // this is done by first looking at that residue type and counting up the number of C and S atoms to reserve that number
859  // of elements in the inner vector and then going back over the list of heavy atoms and setting the index of that atom id.
860  // this can't be done in one loop because we also want to set the max_hphobes_ variable and this function only runs once
861  // at initializations so it's ok.
862 
863  hphobe_ats_for_restype_group_.resize( restype_group_for_rotamers_[ rotamers->num_rotamers() ] );
864  for ( Size ii = 1; ii <= hphobe_ats_for_restype_group_.size(); ++ii ) {
865  chemical::ResidueType const & ii_restype = rotamers_vector_[ rotamers->get_residue_type_begin( ii ) ]->type();
866  Size count_cs = 0;
867  for ( Size jj = 1; jj <= ii_restype.nheavyatoms(); ++jj ) {
868  if ( ii_restype.atom_type( jj ).element() == carbon || ii_restype.atom_type( jj ).element() == sulfur ) {
869  ++count_cs;
870  }
871  }
872  if ( max_hphobes_ < count_cs ) {
873  max_hphobes_ = count_cs;
874  }
875  hphobe_ats_for_restype_group_[ ii ].reserve( count_cs );
876  for ( Size jj = 1; jj <= ii_restype.nheavyatoms(); ++jj ) {
877  if ( ii_restype.atom_type( jj ).element() == carbon || ii_restype.atom_type( jj ).element() == sulfur ) {
878  hphobe_ats_for_restype_group_[ ii ].push_back( jj );
879  }
880  }
881  }
882  } // end scope
883 
884  curr_state_exp_hphobes_.reserve( max_hphobes_ );
885  alt_state_exp_hphobes_.reserve( max_hphobes_ );
886 
887 #ifdef FILE_DEBUG
888  /*TR_NODE << "rotamers_vector_: [ ";
889  for ( Size ii = 1; ii <= rotamers_vector_.size(); ++ii ) {
890  TR_NODE << ii << ":" << rotamers_vector_[ ii ]->name1() << "-" << rotamers_vector_[ ii ]->seqpos() << ", ";
891  }
892  TR_NODE << "]" << std::endl;*/
893 #endif
894 
895 }
896 
897 ///
898 /// @begin HPatchNode::get_rotamer
899 ///
900 /// @brief
901 /// Returns a constant OP to the rotamer/residue object for the given state.
902 ///
903 /// @details
904 /// Need to save a reference to the rotamer_set so that we can determine what a particular state change will do to the score
905 ///
906 template < typename V, typename E, typename G >
909  return rotamers_vector_[ state ];
910 }
911 
912 
913 ///
914 /// @begin HPatchNode::set_rotamer_dots_for_state
915 ///
916 /// @brief
917 /// stores the coordinates for a state.
918 ///
919 /// @detailed
920 /// Currently RotamerCoords stores the atoms in the order they are created for the pose. In the future, this might be
921 /// changes to store the atoms in special trie order to reduce the number of sphere calculations necessary.
922 ///
923 /// self_and_bg_dots_for_states_ is a vector1 of RotamerDots objects. the size of the vector is set during Node
924 /// construction to parent::get_num_states().
925 ///
926 ///
927 template < typename V, typename E, typename G >
929  assert( state > 0 && state <= (Size)parent::get_num_states() );
930  self_and_bg_dots_for_states_[ state ] = rd;
931 }
932 
933 
934 ///
935 /// @begin HPatchNode::overlaps
936 ///
937 /// @brief
938 /// returns true if any sphere for any atom of any state on this vertex overlaps with any atom on any sphere on a neighboring vertex.
939 ///
940 /// @detailed
941 /// neighbor - [in] - the vertex that neighbors this vertex
942 ///
943 /// @remarks
944 /// This method could be faster if I built a rotamer trie for each vertex, so I've got code in here to measure just how
945 /// much time I spend on this task. In a complete redesign of UBQ, I spend 8 to 10 seconds in this method.
946 /// In comparison, I spend 15 minutes in simulated annealing. (apl)
947 ///
948 template < typename V, typename E, typename G >
950 
951  //static double time_spent_here( 0.0 );
952  bool found_overlap = false;
953 
954  //TR_NODE << "overlaps(): num_states: " << parent::get_num_states() << ", neighbors num_states: " << neighbor->get_num_states() << std::endl;
955 
956  //std::clock_t starttime = clock();
957  for ( Size ii = 1; ii <= (Size)parent::get_num_states(); ++ii ) {
958  //for (Size jj = 1; jj <= (Size)parent::get_num_states(); ++jj ) { // WRONG!
959  for (Size jj = 1; jj <= (Size)neighbor->get_num_states(); ++jj ) {
960  if ( self_and_bg_dots_for_states_[ ii ].overlaps( neighbor->self_and_bg_dots_for_states_[ jj ] ) ) {
961  found_overlap = true;
962  break;
963  }
964  }
965  if (found_overlap)
966  break;
967  }
968  //std::clock_t stoptime = clock();
969  //time_spent_here += ((double)(stoptime - starttime)) / CLOCKS_PER_SEC;
970  //TR_NODE << "time spent computing overlaps: " << time_spent_here << ", found overlap? " << found_overlap << std::endl;
971 
972  return found_overlap;
973 }
974 
975 
976 ///
977 /// @begin HPatchNode::detect_any_overlap_with_rotamer
978 ///
979 /// @brief
980 /// determines if any atom for any rotamer of this vertex overlaps with any atom from some background residue.
981 /// called by BGNodes for the detect_background_residue_and_first_class_residue_overlap phase of the prep for simA
982 /// call in the HPatchIG.
983 ///
984 template < typename V, typename E, typename G >
986 
987  // for every rotamer possible at this molten res position/node...
988  for ( Size ii = 1; ii <= (Size)parent::get_num_states(); ++ii ) {
989  // RotamerDots objects know how to determine if they overlap with another RotamerDots object
990  if ( self_and_bg_dots_for_states_[ ii ].overlaps( bg_dots ) ) {
991  //TR_NODE << "state " << ii << " of node " << parent::get_node_index() << " overlaps with bg node." << std::endl;
992  return true; // as soon as one overlap is found, this method immediately returns
993  }
994  }
995  return false;
996 }
997 
998 
999 ///
1000 /// @begin HPatchNode::prepare_for_simulated_annealing
1001 ///
1002 /// @brief
1003 /// invokes V's prep_for_simA method. Also computes the "self-overlap" that each of its rotamers has.
1004 ///
1005 template < typename V, typename E, typename G >
1006 void
1008 
1009 #ifdef FILE_DEBUG
1010  TR_NODE << "prepare_for_simulated_annealing(): calling V::prep for simA for node " << parent::get_node_index() << std::endl;
1011 #endif
1012 
1013  // parent is AddtlBGNodesIG; V is either PDIG or LinmemIG; here we want to call the templated classes prep_for_simA
1014  // method so that it can get ready for all the pairwise-decomposable energy term stuff
1015  // PDIG::prep_for_simA() calls update_edge_vectors which eventually leads to a seq fault when it requests the edge
1016  // table pointer.
1017  V::prepare_for_simulated_annealing();
1018 
1019  if ( ! parent::get_bg_edge_vector_up_to_date_() ) {
1020 #ifdef FILE_DEBUG
1021  TR_NODE << "prepare_for_simulated_annealing(): bg edge vector not up to date, calling parent::update_bg_edge_vector()" << std::endl;
1022 #endif
1023  parent::update_bg_edge_vector();
1024  }
1025 
1026 #ifdef FILE_DEBUG
1027  TR_NODE << "prepare_for_simulated_annealing(): calling initialize_self_overlap()" << std::endl;
1028 #endif
1029  initialize_self_overlap();
1030 #ifdef FILE_DEBUG
1031  TR_NODE << "prepare_for_simulated_annealing(): ... done incrementing self overlap for all states" << std::endl;
1032 #endif
1033 
1034  initialize_atom_atom_overlap_cache();
1035 }
1036 
1037 
1038 ///
1039 /// @begin HPatchNode::initialize_self_overlap
1040 ///
1041 /// @brief
1042 /// Initializes rotamer self overlap; called by HPatchInteractionGraph;:prepare_for_sim_annealing right before simulated
1043 /// annealing begins.
1044 ///
1045 template < typename V, typename E, typename G >
1047 
1048  for ( Size ii=1; ii <= (Size)parent::get_num_states(); ++ii ) {
1049  //TR_NODE << "initialize_self_overlap(): self_and_bg_dots_for_states_[ " << ii << " ]..." << std::endl;
1050  self_and_bg_dots_for_states_[ ii ].increment_self_overlap();
1051  }
1052 
1053 }
1054 
1055 
1056 ///
1057 /// @begin HPatchNode::initialize_atom_atom_overlap_cache
1058 ///
1059 /// @brief
1060 /// Initializes the atom_atom_overlaps vector.
1061 ///
1062 /// @detailed
1063 /// The atom_atom_overlaps vector stores a boolean for the intra-residue atom-atom overlap for every state possible at
1064 /// this Node. During simulated annealing, the IG has to determine the connected components after every sub. To do this,
1065 /// it has to know which atoms are exposed as well as overlapping. Instead of recomputing atom-atom overlaps after every
1066 /// sub, do it once and cache the values on the Node.
1067 ///
1068 template < typename V, typename E, typename G >
1070 
1071  // resize the outer-most vector to the number of states possible
1072  self_atom_atom_overlaps_.resize( (Size)parent::get_num_states() );
1073 
1074  for ( Size state = 1; state <= (Size)parent::get_num_states(); ++state ) {
1075 
1076  //get_rotamer( state ) returns a ResidueCOP; we can use that to get residue info
1077  conformation::ResidueCOP rotamer_ = get_rotamer( state );
1078 
1079  self_atom_atom_overlaps_[ state ].resize( rotamer_->nheavyatoms(), utility::vector1< bool >( rotamer_->nheavyatoms(), false ) );
1080 
1081  std::string carbon_atom = "C";
1082  std::string sulfur_atom = "S";
1083  Real const probe_radius = 1.4;
1084 
1085  RotamerDots const & rd = self_and_bg_dots_for_states_[ state ]; // the same RD object can be used for both res ii and jj
1086 
1087  for ( Size iia=1; iia <= rotamer_->nheavyatoms(); ++iia ) {
1088  // immediately continue if not a hydrophobic atom; no point in computing overlaps for polar atoms
1089  if ( rotamer_->atom_type( iia ).element() != carbon_atom && rotamer_->atom_type( iia ).element() != sulfur_atom )
1090  continue;
1091 
1092  Real const iia_atom_radius = rd.get_atom_radius( iia ) + probe_radius;
1093 
1094  // for intra-residue we only have iterate over the greater-indexed heavyatoms
1095  for ( Size jja = iia + 1; jja <= rotamer_->nheavyatoms(); ++jja ) {
1096  if ( rotamer_->atom_type( jja ).element() != carbon_atom && rotamer_->atom_type( jja ).element() != sulfur_atom )
1097  continue;
1098 
1099  Real const jja_atom_radius = rd.get_atom_radius( jja ) + probe_radius;
1100 
1101  // check if the two atoms overlap, and if that degree of overlap exceeds the threshold
1102  Vector const & iia_atom_xyz = rotamer_->atom( iia ).xyz();
1103  Vector const & jja_atom_xyz = rotamer_->atom( jja ).xyz();
1104 
1105  // exit if large probe radii do not touch
1106  Real const distance_squared = iia_atom_xyz.distance_squared( jja_atom_xyz );
1107  //if ( distance_squared <= (iia_atom_radius + iia_atom_radius) * (jja_atom_radius + jja_atom_radius) ) {
1108  if ( distance_squared <= (iia_atom_radius + jja_atom_radius) * (iia_atom_radius + jja_atom_radius) ) {
1109 
1110  Real const distance_ijxyz = std::sqrt( distance_squared );
1111  int degree_of_overlap;
1112  core::scoring::get_overlap( iia_atom_radius, jja_atom_radius, distance_ijxyz, degree_of_overlap );
1113  if ( degree_of_overlap >= 15 ) {
1114 
1115  self_atom_atom_overlaps_[ state ][ iia ][ jja ] = true;
1116 #ifdef FILE_DEBUG
1117  //TR_NODE << "initialize_atom_atom_overlap_cache(): overlapping intra-residue atom pair: "
1118  // << rotamer_->seqpos() << "/" << utility::trim( rotamer_->atom_name( iia ) ) << " - " << rotamer_->seqpos() << "/" << utility::trim( rotamer_->atom_name( jja ) )
1119  // << ", degree of overlap: " << degree_of_overlap << std::endl;
1120 #endif
1121 
1122  }
1123  } // end if distance
1124  } // for loop over all jj heavyatoms
1125  } // for loop over all ii heavyatoms
1126  } // for loop over all states
1127 
1128 
1129 /*
1130 #ifdef FILE_DEBUG
1131  TR_NODE << "node " << parent::get_node_index() << std::endl;
1132  for ( Size state = 1; state <= (Size)parent::get_num_states(); ++state ) {
1133  TR_NODE << "state " << state << " self_atom_atom_overlaps_: [ " << std::endl;
1134  for ( Size aa=1; aa <= self_atom_atom_overlaps_[ state ].size(); ++aa ) {
1135  TR_NODE << "self_atom_atom_overlaps_[ " << aa << " ]: [ ";
1136  for ( Size bb=1; bb <= self_atom_atom_overlaps_[ state ][ aa ].size(); ++bb ) {
1137  TR_NODE << self_atom_atom_overlaps_[ state ][ aa ][ bb ] << ", ";
1138  }
1139  TR_NODE << "]" << std::endl;
1140  }
1141  TR_NODE << "]" << std::endl;
1142  }
1143  TR_NODE << std::endl;
1144 #endif
1145 */
1146 
1147 }
1148 
1149 
1150 ///
1151 /// @begin HPatchNode< V, E, G >::initialize_overlap_with_background
1152 ///
1153 /// @brief
1154 /// This method computes and caches each set of overlaps this node's states have with a background residue.
1155 ///
1156 /// @detailed
1157 /// The node stores these overlaps in two places: 1) in the input vector from the HPatchBackgroundEdge object, and 2) in
1158 /// its own array of dot coverage counts for the self-and-background sphere overlaps.
1159 ///
1160 /// @param
1161 /// bg_rotamer - [in] - the RotamerDots object for the background residue
1162 /// node_states_coverage_of_bg_res_ -[out] - the array of RotamerDotsCache objects that the HPatchBackgroundEdge stores for the overlap of each state in this residue on the background residue.
1163 /// states_atom_atom_overlap_on_bg_res -[out] - an array that holds the atom-atom overlap each state on this Node has on the background residue
1164 ///
1165 template < typename V, typename E, typename G >
1167  RotamerDots const & bg_rotamer_dots,
1168  std::vector< RotamerDotsCache > & node_states_coverage_of_bg_res_,
1169  std::vector< utility::vector1< utility::vector1< bool > > > & states_atom_atom_overlap_on_bg_res
1170 ) {
1171 
1172  std::vector< RotamerDotsCache* > v_dots_for_bg_res( (Size)parent::get_num_states() + 1, static_cast< RotamerDotsCache* >(0) );
1173 
1174  // since there's no way to default init the atom-atom overlap vector, we have to make sure we set every index, even 0
1175  utility::vector1< utility::vector1< bool > > zero_vector( bg_rotamer_dots.get_num_atoms(), utility::vector1< bool >( bg_rotamer_dots.get_num_atoms(), false ) );
1176  states_atom_atom_overlap_on_bg_res[ 0 ] = zero_vector;
1177 
1178  // too much output during initialization
1179  //TR_NODE << "initialize_overlap_with_background(): states on FC node " << parent::get_node_index() << " which overlap bg residue include: ";
1180  for ( Size ii = 1; ii <= (Size)parent::get_num_states(); ++ii ) {
1181 
1182  // now resize the atom-atom overlap vector to the right sizes. the values will get filled by the Dots method increment_this_and_cache().
1183  Size ii_state_num_atoms = self_and_bg_dots_for_states_[ ii ].get_num_atoms();
1184  states_atom_atom_overlap_on_bg_res[ ii ].resize( ii_state_num_atoms, utility::vector1< bool >( bg_rotamer_dots.get_num_atoms(), false ) );
1185 
1186  // do any of the states possible at this FCNode overlap with the bg_rotamer?
1187  if ( self_and_bg_dots_for_states_[ ii ].overlaps( bg_rotamer_dots ) ) {
1188  v_dots_for_bg_res[ ii ] = new RotamerDotsCache( bg_rotamer_dots.get_num_atoms() );
1189  //self_and_bg_dots_for_states_[ ii ].increment_this_and_cache( bg_rotamer_dots, *v_dots_for_bg_res[ ii ], states_atom_atom_overlap_on_bg_res[ ii ] );
1190  // can't just make this increment_this_and_cache call because then the atom_atom_overlap array is in the wrong "order"
1191 
1192  utility::vector1< utility::vector1< bool > > temp_atat_overlap( bg_rotamer_dots.get_num_atoms(), utility::vector1< bool >( ii_state_num_atoms, false ) );
1193  self_and_bg_dots_for_states_[ ii ].increment_this_and_cache( bg_rotamer_dots, *v_dots_for_bg_res[ ii ], temp_atat_overlap );
1194 
1195  /// now transpose the table for future use.
1196  for ( Size jj = 1; jj <= bg_rotamer_dots.get_num_atoms(); ++jj ) {
1197  for ( Size kk = 1; kk <= ii_state_num_atoms; ++kk ) {
1198  states_atom_atom_overlap_on_bg_res[ ii ][ kk ][ jj ] = temp_atat_overlap[ jj ][ kk ];
1199  }
1200  }
1201 
1202  // now save this overlap to the passed in (by reference) vector - BUT ALLOCATE SPACE FOR IT FIRST
1203  node_states_coverage_of_bg_res_[ ii ] = *(v_dots_for_bg_res[ ii ]);
1204  //TR_NODE << ii << ", ";
1205 
1206  // 'delete' RotamerDotsCache objects; frees the memory allocated to RotamerDotsCache objects created with 'new' above
1207  delete v_dots_for_bg_res[ ii ];
1208  }
1209 
1210  }
1211  //TR_NODE << std::endl;
1212 
1213 }
1214 
1215 
1216 ///
1217 /// @begin HPatchNode::assign_zero_state
1218 ///
1219 /// @brief
1220 /// Assign the node to state 0 -- the "unassigned" state.
1221 ///
1222 /// @detailed
1223 /// A node in state 0 produces no hpatch score. Its neighbors have to adjust their scores appropriately. This method
1224 /// iterates over all the edges emanating from this node and tells them to acknowledge that they've been zeroed out.
1225 ///
1226 template < typename V, typename E, typename G >
1228 
1229  // depending on the type of interaction graph (linmem, standard pd) used for the simulation, this will call
1230  // the appropriate assign_zero_state() method and initialize the one- and two-body energy term variables to zero
1231  // parent refers to the AddtlBGNodesIG; G refers to either PDIG or LinmemIG. AddtlBGNodesIG doesn't define
1232  // a assign_zero_state() method! But it extends from the other two classes so it will eventually find the right method.
1233  parent::assign_zero_state(); // was this a bug previously? Shouldn't it be V? apparently not...
1234  //V::assign_zero_state();
1235 
1236 #ifdef FILE_DEBUG
1237  TR_NODE << "assign_zero_state(): calling acknowledge_state_zeroed() on all incident edges." << std::endl;
1238 #endif
1239  for ( Size ii = 1; ii <= (Size)parent::get_num_incident_edges(); ++ii ) {
1240  get_incident_hpatch_edge( ii )->acknowledge_state_zeroed( parent::get_node_index() );
1241  }
1242 
1243  parent::update_bg_edge_vector();
1244 
1245 #ifdef FILE_DEBUG
1246  TR_NODE << "assign_zero_state(): calling acknowledge_state_change() on all incident bg edges." << std::endl;
1247 #endif
1248  for ( Size ii = 1; ii <= (Size)parent::get_num_edges_to_background_nodes(); ++ii ) {
1249  get_edge_to_hpatch_bg_node( ii )->acknowledge_state_change( 0 );
1250  }
1251 
1252  RotamerDots rd; // create an empty, uninit'd RotamerDots object
1253  current_state_rotamer_dots_ = rd;
1254  alt_state_rotamer_dots_ = rd;
1255  alt_state_dots_matches_current_state_dots_ = true;
1256  // is setting alt_state dots necessary? Yes! Because when other FC nodes enter the unassigned state, they will
1257  // trigger calls to acknowledge_neighbors_sub which sets current state to alt state. in theory, I could even put
1258  // just alt_state = emtpy RD and the current state dots would eventually get overwritten.
1259 
1260  get_hpatch_owner()->register_fc_node_in_state0();
1261 
1262 }
1263 
1264 
1265 ///
1266 /// @begin HPatchNode::acknowledge_neighbors_substitution
1267 ///
1268 /// @brief
1269 /// bookkeeping to follow a neighbors state substitution. this method gets called when a HPatchNode commits a sub
1270 /// and then broadcasts that change to all its neighboring fc nodes via the incident HPatchEdges. basically we need
1271 /// to set current state equal to alt state here. (Hopefully alt state is still correct!!) Since there's no way for
1272 /// a HPatchNode to know what other HPatchNodes are connected to it except via HPatchEdges, the calls seem a bit
1273 /// complicated. A HPatchNode has to call acknowledge_state on each Edge. The Edges have to figure out which Node
1274 /// is changing/not changing and then they call an inform_non_changing node of change method. That method then makes
1275 /// the call to this method on the correct HPatchNode. The inform_non_changing method can not be removed, because
1276 /// it's used during the substitution evaluations as well.
1277 ///
1278 template < typename V, typename E, typename G >
1280 
1281 #ifdef FILE_DEBUG
1282  // too much output...
1283  //if ( current_state_rotamer_dots_ != alt_state_rotamer_dots_ ) {
1284  // TR_NODE << "acknowledge_neighbors_substitution - node " << parent::get_node_index() << " changing curr_state_dots from "
1285  // << current_state_rotamer_dots_ << " to " << alt_state_rotamer_dots_ << std::endl;
1286  //}
1287 #endif
1288 
1289  current_state_rotamer_dots_ = alt_state_rotamer_dots_; // what happens here in the 0-state case?
1290  curr_state_inv_dots_ = alt_state_inv_dots_;
1291  curr_state_exp_hphobes_ = alt_state_exp_hphobes_;
1292  alt_state_dots_matches_current_state_dots_ = true;
1293 }
1294 
1295 
1296 ///
1297 /// @begin HPatchNode::get_current_state_sasa()
1298 ///
1299 /// @brief
1300 /// returns the amount of sasa this node has in its current state assignment
1301 ///
1302 /// @detailed
1303 /// RotamerDots objects know when they are in the unassigned state, so nothing special needs to be done to handle
1304 /// the 0 state. But, we could also query parent using get_current_state() to check if it's nonzero as an alternative.
1305 ///
1306 template < typename V, typename E, typename G >
1308  return current_state_rotamer_dots_.get_sasa();
1309 }
1310 
1311 
1312 ///
1313 /// @begin HPatchNode::get_current_state_sasa()
1314 ///
1315 /// @brief
1316 /// Returns the current state SASA for the passed in atom index.
1317 ///
1318 template < typename V, typename E, typename G >
1320  return current_state_rotamer_dots_.get_atom_sasa( atom_index );
1321 }
1322 
1323 
1324 ///
1325 /// @begin HPatchNode::get_alternate_state_sasa()
1326 ///
1327 /// @brief
1328 /// Returns the alternate state SASA for the passed in atom index.
1329 ///
1330 template < typename V, typename E, typename G >
1332  return alt_state_rotamer_dots_.get_atom_sasa( atom_index );
1333 }
1334 
1335 
1336 ///
1337 /// @begin HPatchNode< V, E, G >::get_atom_atom_self_overlaps_for_state
1338 ///
1339 /// @brief
1340 /// Returns a const reference to the atom-x-atom-pair vector-of-vectors of bools that specifies which atoms are overlapping, in the given state.
1341 ///
1342 template < typename V, typename E, typename G >
1345  return self_atom_atom_overlaps_[ state ];
1346 }
1347 
1348 
1349 ///
1350 /// @begin HPatchNode::calculate_PD_deltaE_for_substitution
1351 ///
1352 /// @brief
1353 /// Returns the change in energy induced by changing a node from its current state into some alternate state for the PD energy terms only.
1354 ///
1355 /// @detailed
1356 /// This function always gets called for every substitution. Only the consider_alt_state() call can get procrastinated.
1357 ///
1358 template < typename V, typename E, typename G >
1360 
1361  assert( alternate_state > 0 && alternate_state <= parent::get_num_states() );
1362 
1363  prev_PDenergies_for_node = parent::get_curr_pd_energy_total();
1364 
1365  // have base class perform deltaE computations for PD portion of energy function
1366  // parent refers to AddtlBGNodesIG; G refers to either PDIG or LinmemIG. Which do I want here? AddtlBGNodesIG doesn't
1367  // implement the calc_deltaEpd method but it extends either PDIG or LinmemIG so the runtime will eventually find the
1368  // right function to call.
1369  parent::calc_deltaEpd( alternate_state );
1370 
1371  return get_pd_energy_delta();
1372 
1373 }
1374 
1375 
1376 ///
1377 /// @begin HPatchNode< V, E, G >::get_pd_energy_delta()
1378 ///
1379 /// @brief
1380 /// Returns the deltaE for just the PD terms. Separate method from the one above because this one can be called from within
1381 /// a commit_sub call that didn't go through consider_sub().
1382 ///
1383 template < typename V, typename E, typename G >
1385  return ( parent::get_alt_pd_energy_total() - parent::get_curr_pd_energy_total() );
1386 }
1387 
1388 
1389 ///
1390 /// @begin HPatchNode< V, E, G >::consider_alternate_state()
1391 ///
1392 /// @brief
1393 /// Instructs the Node to update the alt state information held by it and its neighbors in response to switching from the
1394 /// current state to an alternate state.
1395 ///
1396 template < typename V, typename E, typename G >
1398 
1399  get_hpatch_owner()->register_fc_node_affected_by_rotsub( parent::get_node_index() );
1400 
1401 #ifdef FILE_DEBUG
1402  TR_NODE << "consider_alternate_state(): current_state:" << parent::get_current_state();
1403  if ( parent::get_current_state() == 0 ) {
1404  TR_NODE << " (" << wt_residue_for_node().name3() << "-";
1405  if ( wt_residue_for_node().is_polar() ) { TR_NODE << "P)"; } else { TR_NODE << "HP)"; }
1406  } else {
1407  TR_NODE << " (" << get_rotamer( parent::get_current_state() )->name() << "-";
1408  if ( get_rotamer( parent::get_current_state() )->is_polar() ) { TR_NODE << "P)"; } else { TR_NODE << "HP)"; }
1409  }
1410  TR_NODE << ", alternate_state: " << parent::get_alternate_state() << " (" << get_rotamer( parent::get_alternate_state() )->name() << "-";
1411  if ( get_rotamer( parent::get_alternate_state() )->is_polar() ) { TR_NODE << "P)"; } else { TR_NODE << "HP)"; }
1412  TR_NODE << std::endl;
1413 #endif
1414 
1415  // self_and_bg_dots_for_states has the RotamerDots object for a state, with the overlap counts set for all BG nodes
1416  // that overlap with that state
1417  assert( alt_state_dots_matches_current_state_dots_ );
1418  alt_state_dots_matches_current_state_dots_ = false;
1419 
1420  alt_state_rotamer_dots_ = self_and_bg_dots_for_states_[ parent::get_alternate_state() ];
1421 
1422  Real delta_sasa = 0;
1423  for ( Size ii = 1; ii <= (Size)parent::get_num_incident_edges(); ++ii ) {
1424  delta_sasa += get_incident_hpatch_edge(ii)->update_state_at_neighbor( parent::get_node_index(), parent::get_alternate_state(), alt_state_rotamer_dots_ );
1425  }
1426  for ( Size ii = 1; ii <= (Size)parent::get_num_edges_to_background_nodes(); ++ii ) {
1427  delta_sasa += get_edge_to_hpatch_bg_node( ii )->update_state_at_neighbor( parent::get_alternate_state() );
1428  }
1429 
1430  update_alt_state_exphphobes();
1431 
1432  //alt_state_inv_dots_.setup_from_rotamer_dots( alt_state_rotamer_dots_ );
1433  alt_state_inv_dots_.setup_from_rotamer_dots( alt_state_rotamer_dots_, alt_state_exp_hphobes_ );
1434 
1435 #ifdef FILE_DEBUG
1436  if ( get_sasa_difference() != 0 ) {
1437  TR_NODE << "consider_alternate_state(): curr state dots: " << current_state_rotamer_dots_.get_sasa()
1438  << ", alt state dots: " << alt_state_rotamer_dots_.get_sasa()
1439  << ", sasa difference: " << get_sasa_difference() << std::endl;
1440  }
1441 #endif
1442  delta_sasa += get_sasa_difference();
1443 
1444  return delta_sasa;
1445 }
1446 
1447 
1448 ///
1449 /// @begin HPatchNode< V, E, G >::update_alt_state_exphphobes
1450 ///
1451 /// @brief
1452 /// Updates the vector alt_state_exp_hphobes_ by checking the sasa of every atom in the residue currently on this Node.
1453 ///
1454 template < typename V, typename E, typename G >
1456  utility::vector1< Size > const & alt_hphobes( alt_state_hphobes() ); // get all the hydrophobic atoms in this residue first
1457  alt_state_exp_hphobes_.clear();
1458  for ( Size ii = 1; ii <= alt_hphobes.size(); ++ii ) { // then figure out if they're exposed by checking their SASA
1459  Size const ii_atom = alt_hphobes[ ii ];
1460  if ( alt_state_rotamer_dots_.get_atom_sasa( ii_atom ) > 0.0 ) {
1461  alt_state_exp_hphobes_.push_back( ii_atom );
1462  }
1463  }
1464 }
1465 
1466 
1467 ///
1468 /// @begin HPatchNode< V, E, G >::update_state_for_neighbors_substitution
1469 ///
1470 /// @brief
1471 /// returns the change in sasa for this node induced by a state substitution at a neighboring node. The node
1472 /// increments the dot coverage count for the RotamerDots object representing the alternate state dots for that neighbor.
1473 ///
1474 /// @detailed
1475 /// The procedure is simple at heart -- the caching makes it complex.
1476 ///
1477 /// alt_state_rotamer_dots_ = current_state_rotamer_dots_; //copy dot coverage counts
1478 /// alt_state_rotamer_dots_.decrement( neighbors_curr_state_overlap_with_this );
1479 /// alt_state_rotamer_dots_.increment_both( neighbors_alternate_state );
1480 /// return ( alt_state_rotamer_dots_.get_score() - current_state_rotamer_dots_.get_score() );
1481 ///
1482 /// Extensive caching techniques save time. Each HPatchEdge stores the dot coverage for each pair of HPatchNodes in their
1483 /// current state. These are stored in the RotamerDotsCache objects. Let's name the vertices: this vertex is vertex B.
1484 /// Vertex B is projecting its hpatch deltaE while vertex A is considering a substitution from one state to another.
1485 /// The edge connecting A and B provides node B with the set of masks for the overlap by the atoms of A's alternate
1486 /// state on all atoms of vertex B.
1487 ///
1488 /// @param
1489 /// neighbors_alternate_state - [in/out] - the RotamerDots object representing the alternate state vertex A (the neighbor) is considering.
1490 /// neighbors_curr_state_overlap_with_this - [in] - the RotamerDotsCache object held by the HPatchEdge connecting A and B that represents the coverage of A's current state of B's atoms.
1491 /// this_overlap_with_neighbors_alternate - [out] - the dot cache to store the results of computing the overlap of B's current state on A's alt state
1492 /// neighbors_alternate_overlap_with_this - [out] - the dot cache to store the results of computing the overlap of A's alt state on B's current state
1493 /// mask_this_covered_by_other - [in/out] - starting set of overlaps
1494 /// mask_other_covered_by_this - [in/out] - starting set of overlaps
1495 /// num_atoms_same - [in] - the number of atoms shared between A's current and alternate states.
1496 ///
1497 /// What do we do when the current state is unassigned. Then that results in the alt_state starting from being unassigned
1498 /// and we get problems because the RotamerDots object doesn't have any memory assigned to it if it's in the unassigned state.
1499 ///
1500 /// it's probable that a sub that was considered before wasn't committed, so the alt state count at this node needs to go
1501 /// back to what the current state count is. the problem that may crop up with the reset here is that on a previous consider
1502 /// call, a set of nodes will update their counts. if commit is not called, and a second consider is called, then this node
1503 /// will have its alt state count reset but what about all the other nodes in the previous set. how will their counts get
1504 /// reset to the current state count? perhaps a check in the commit method can be added. nope, a new method has been
1505 /// added to Nodes and BGNodes to handle this case.
1506 /// alt_state_total_hASA_ = curr_state_total_hASA_;
1507 ///
1508 ///
1509 template < typename V, typename E, typename G >
1511  HPatchNode<V,E,G>* node_considering_substitution,
1512  RotamerDots & neighbors_alternate_state,
1513  RotamerDotsCache const & neighbors_curr_state_overlap_with_this,
1514  RotamerDotsCache & this_overlap_with_neighbors_alternate,
1515  RotamerDotsCache & neighbors_alternate_overlap_with_this,
1516  utility::vector1< utility::vector1< bool > > & atom_atom_overlaps_cache
1517 )
1518 {
1519  get_hpatch_owner()->register_fc_node_affected_by_rotsub( parent::get_node_index() );
1520  parent::set_alternate_state( parent::get_current_state() );
1521 
1522  // don't bother doing sasa updates if this node is in the unassigned state. things really only start to get interesting
1523  // once all nodes have something for their current state.
1524  if ( current_state_rotamer_dots_.state_unassigned() ) {
1525 #ifdef FILE_DEBUG
1526  TR_NODE << "update_state_for_neighbors_substitution(): node " << parent::get_node_index() << " in unassigned state. skipping sasa calculations." << std::endl;
1527 #endif
1528  return 0.0;
1529  }
1530 
1531 #ifdef FILE_DEBUG
1532  //TR_NODE << "update_state_for_neighbors_substitution(): current_state_rotamer_dots_" << std::endl;
1533  //current_state_rotamer_dots_.print( std::cout );
1534 #endif
1535 
1536  // everything has to start from the current state. then we'll update the alt state to be correct.
1537  assert( alt_state_dots_matches_current_state_dots_ );
1538  /// APL -- this should be unnecessary
1539  /// APL TEMP alt_state_rotamer_dots_ = current_state_rotamer_dots_;
1540  alt_state_dots_matches_current_state_dots_ = false;
1541 
1542 #ifdef FILE_DEBUG
1543  //TR_NODE << "update_state_for_neighbors_substitution(): set alt_state dots to curr_state dots: " << std::endl;
1544  //alt_state_rotamer_dots_.print( std::cout );
1545 #endif
1546 
1547  // at the beginning of annealing, nodes are in the unassigned state.
1548  // there will be times when the overlap cached on the edge between this node and the one undergoing substitution will not be
1549  // initialized. those times will be when the node undergoing substitution is going from state 0 to some other state.
1550  // in that case, we have to skip this call because the neighbors curr_state overlap is uninit'd and will results in bus errors.
1551 
1552  if ( node_considering_substitution->get_current_state() != 0 ) {
1553  // subtract out the cached overlap that the current state (on the other node) had with this node
1554  alt_state_rotamer_dots_.decrement_from_cached( neighbors_curr_state_overlap_with_this );
1555 #ifdef FILE_DEBUG
1556  //TR_NODE << "update_state_for_neighbors_substitution(): decrementing neighbors_curr_state_overlap_with_this" << std::endl;
1557  //neighbors_curr_state_overlap_with_this.print( std::cout );
1558 #endif
1559  }
1560 
1561  // then add in the overlap that the alt state (on the other node) would have on this nodes state and cache the overlap.
1562  // the outer vector of alt_state_atom_atom_overlaps_cache has the changing nodes atoms, the inner vector has this nodes
1563  // (the non-changing nodes) atoms.
1564  alt_state_rotamer_dots_.increment_both_and_cache( neighbors_alternate_state, this_overlap_with_neighbors_alternate,
1565  neighbors_alternate_overlap_with_this, atom_atom_overlaps_cache );
1566 
1567  update_alt_state_exphphobes();
1568  alt_state_inv_dots_.setup_from_rotamer_dots( alt_state_rotamer_dots_, alt_state_exp_hphobes_ );
1569 
1570 #ifdef FILE_DEBUG
1571  //TR_NODE << "update_state_for_neighbors_substitution(): neighbors_alternate_overlap_on_this: " << std::endl;
1572  //neighbors_alternate_overlap_with_this.print( std::cout );
1573 #endif
1574 
1575 #ifdef FILE_DEBUG
1576  // this is almost certaintly going to print, right?
1577  if ( current_state_rotamer_dots_ != alt_state_rotamer_dots_ ) {
1578  TR_NODE << "update_state_for_neighbors_substitution(): node " << parent::get_node_index()
1579  << " calc. deltaE for changing node " << node_considering_substitution->get_node_index()
1580  << ", curr state sasa: " << current_state_rotamer_dots_.get_sasa() << ", alt state sasa: " << alt_state_rotamer_dots_.get_sasa()
1581  << ", sasa difference: " << get_sasa_difference() << std::endl;
1582  }
1583 #endif
1584 
1585  return get_sasa_difference();
1586 }
1587 
1588 
1589 ///
1590 /// @begin HPatchNode::get_sasa_difference
1591 ///
1592 /// @brief
1593 /// Returns alt_state_rotamer_dots_.get_sasa() - curr_state_dots.get_sasa() except when either the current state or the
1594 /// alternate state is the unassigned state; state 0.
1595 ///
1596 /// @detailed
1597 /// This method requires that the variables current_state_ and alternate_state_ correspond to the rotamers held in
1598 /// current_state_rotamer_dots_ and alt_state_rotamer_dots_. Usually, alternate_state_ holds meaningful data only if a vertex is considering
1599 /// a state substitution. This method will be invoked by a vertex as it considers a state substitition; it will also be
1600 /// invoked by each of its neighbors. That means the statement alternate_state_ = current_state_; must be present in
1601 /// HPatchNode::update_state_for_neighbors_substitution().
1602 ///
1603 template < typename V, typename E, typename G >
1605 
1606  if ( parent::get_current_state() == 0 && parent::get_alternate_state() == 0 )
1607  return 0.0;
1608  else if ( parent::get_current_state() != 0 && parent::get_alternate_state() == 0 )
1609  return -1 * current_state_rotamer_dots_.get_sasa();
1610  else if ( parent::get_current_state() == 0 && parent::get_alternate_state() != 0 )
1611  return alt_state_rotamer_dots_.get_sasa();
1612 
1613  // both current and alt are nonzero
1614  return alt_state_rotamer_dots_.get_sasa() - current_state_rotamer_dots_.get_sasa();
1615 }
1616 
1617 
1618 ///
1619 /// @begin HPatchNode::reset_alt_state_dots
1620 ///
1621 /// @brief
1622 /// Sets the alt state rotamer dots to the current state rotamer dots. See comments in SIG and commit_considered_substitution
1623 /// for more information about why this method exists.
1624 ///
1625 template < typename V, typename E, typename G >
1627 
1628  if ( alt_state_rotamer_dots_.state_unassigned() && current_state_rotamer_dots_.state_unassigned() ) return;
1629  // since we're only incrementing and decrementing the alt_state hASA, we need a way to reset it each iteration of consider()
1630  // so we don't get alt_state SASA/overlaps of nonsensical values which screw up the score.
1631  //
1632  //if ( alt_state_rotamer_dots_ != current_state_rotamer_dots_ ) { // alot of time is spent doing RotamerDots comparison
1633  if ( ! alt_state_dots_matches_current_state_dots_ ) {
1634  alt_state_rotamer_dots_ = current_state_rotamer_dots_;
1635  alt_state_inv_dots_ = curr_state_inv_dots_;
1636  alt_state_exp_hphobes_ = curr_state_exp_hphobes_;
1637  alt_state_dots_matches_current_state_dots_ = true;
1638 #ifdef FILE_DEBUG
1639  TR_NODE << "reset_alt_state_dots(): alt state dots set equal to current state dots." << std::endl;
1640 #endif
1641  }
1642 
1643 }
1644 
1645 
1646 ///
1647 /// @begin HPatchNode::commit_considered_substitution
1648 ///
1649 /// @brief
1650 /// Sets the current state to the alternate state this node was asked to
1651 /// consider. Copies appropriate score information. Notifies all of its
1652 /// neighbors that it is going through with the state substitution it had been
1653 /// considering.
1654 ///
1655 /// @detailed
1656 /// There's a potential situation with considers() and commits() that needs to be checked for here. It's possible that
1657 /// a consider() call is made which causes a set of Nodes to update their alt states correspondingly. Since the
1658 /// consider() only gets processed by (or actually the call only goes out to) Nodes which are neighbor graph neighbors,
1659 /// only those Nodes will have their counts updated. Assume that the first consider() is really bad and no commit goes out.
1660 /// If we then consider() another sub, the alt state counts at the previous consider()'s set of nodes are incorrect. If
1661 /// get_deltaE is called by this consider() on some of those nodes, some of them will have their alt states reset. But
1662 /// when the commit goes out to ALL Nodes that are neighbors (NOT just the neighbor graph neighbors) it's possible that
1663 /// some of the Nodes will save the wrong alt state count. One way I think this can be avoided to is check at this node,
1664 /// if the alt state count is different from current, whether the node that originally changed is a neighbor graph neighbor
1665 /// of this node. If it is, that means the counts changed because of that node. If it's not, then this Node must have
1666 /// been one of the ones that fell out of sync.
1667 ///
1668 /// Oooooh, I just thought of another way. When the SIG consider() method is called, I could have a reset alt state
1669 /// counts method that will deal with Nodes that are out of sync. That's more elegant than yet another if statement here!
1670 ///
1671 /// I'm not sure the above is really a problem in the case of this IG. It seems like even if a non-committed consider()
1672 /// call occurs that alters the alt state counts/dots at some set of nodes, when a following sub does get commit'd(), then
1673 /// the nodes that will get the commit message should have all been updated. Some nodes will still have alt_state counts
1674 /// that are weird, but when a consider() call comes back around to them, it should reset the alt_state before doing anything.
1675 ///
1676 template < typename V, typename E, typename G >
1678 
1679  assert( parent::considering_alternate_state() );
1680 
1681  if ( parent::get_alternate_state() == 0 ) {
1682  assign_zero_state();
1683  return;
1684  }
1685 
1686  //call base class method
1687  parent::commit_considered_substitution();
1688 
1689  current_state_rotamer_dots_ = alt_state_rotamer_dots_;
1690  curr_state_inv_dots_ = alt_state_inv_dots_;
1691  curr_state_exp_hphobes_ = alt_state_exp_hphobes_;
1692  alt_state_dots_matches_current_state_dots_ = true;
1693 #ifdef FILE_DEBUG
1694  TR_NODE << "Committed substitution node " << parent::get_node_index() << std::endl;
1695  //current_state_rotamer_dots_.print( std::cout );
1696 #endif
1697 
1698  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
1699  get_incident_hpatch_edge(ii)->acknowledge_substitution();
1700  }
1701  for (int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii) {
1702  get_edge_to_hpatch_bg_node( ii )->acknowledge_substitution();
1703  }
1704 
1705 }
1706 
1707 
1708 ///
1709 /// @begin HPatchNode::getMemoryUsageInBytes
1710 ///
1711 /// @brief
1712 /// Not implemented, but needs to be!
1713 ///
1714 template < typename V, typename E, typename G >
1716  return 0;
1717 }
1718 
1719 ///
1720 /// @begin HPatchNode::count_static_memory
1721 ///
1722 /// @brief
1723 /// Returns the amount of static memory used by this Node object
1724 ///
1725 template < typename V, typename E, typename G >
1727  return sizeof ( HPatchNode< V, E, G > );
1728 }
1729 
1730 ///
1731 /// @begin HPatchNode::count_dynamic_memory
1732 ///
1733 /// @brief
1734 /// Returns the amount of dynamic memory used by this Node object
1735 ///
1736 template < typename V, typename E, typename G >
1738  unsigned int total_memory = parent::count_dynamic_memory();
1739 
1740  total_memory += rotamers_vector_.size() * sizeof( conformation::ResidueCOP );
1741  total_memory += self_and_bg_dots_for_states_.size() * sizeof( RotamerDots );
1742 
1743  return total_memory;
1744 }
1745 
1746 
1747 ///
1748 /// @begin HPatchNode::write_dot_kinemage
1749 ///
1750 /// @brief
1751 /// useful for debugging
1752 ///
1753 //template < typename V, typename E, typename G >
1754 //void HPatchNode< V, E, G >::write_dot_kinemage( std::ofstream & output_kin ) {
1755 // current_state_rotamer_dots_.write_dot_kinemage( output_kin );
1756 //}
1757 
1758 
1759 ///
1760 /// @begin HPatchNode::print
1761 ///
1762 /// @brief
1763 /// useful for debugging - writes information about a node to the tracer
1764 ///
1765 template < typename V, typename E, typename G >
1767  TR_NODE << "node " << parent::get_node_index() << ", current_state: " << parent::get_current_state()
1768  << ", one body energy: " << parent::get_one_body_energy_current_state() << std::endl;
1769  current_state_rotamer_dots_.print( std::cout );
1770  alt_state_rotamer_dots_.print( std::cout );
1771 }
1772 
1773 
1774 //----------------------------------------------------------------------------//
1775 //----------------------- HPatch Background Residue Node Class -----------------//
1776 //----------------------------------------------------------------------------//
1777 
1778 ///
1779 /// @begin HPatchBackgroundNode::HPatchBackgroundNode
1780 ///
1781 /// @brief
1782 /// main constructor. No default constructor, copy constructor or assignment operator
1783 ///
1784 template < typename V, typename E, typename G >
1786  BackgroundNode< V, E, G > ( owner, node_index ),
1787  prepared_for_simA_( false ),
1788  current_state_rotamer_dots_(),
1789  alt_state_rotamer_dots_(),
1790  alt_state_dots_matches_current_state_dots_( true )
1791 {}
1792 
1793 
1794 ///
1795 /// @begin HPatchBackgroundNode::~HPatchBackgroundNode
1796 ///
1797 template < typename V, typename E, typename G >
1799  //TR_BGNODE << "called destructor" << std::endl;
1800 }
1801 
1802 
1803 ///
1804 /// @begin HPatchBackgroundNode::set_rotamer
1805 ///
1806 /// @brief
1807 /// inits the RotamerOP held by a background node. called in the HPatchIG::initialize method.
1808 ///
1809 template < typename V, typename E, typename G >
1811  rotamer_ = rotamer;
1812  { // scope -- I should make this a function
1813  std::string carbon( "C" ), sulfur( "S" );
1814  n_hphobes_ = 0;
1815  chemical::ResidueType const & restype = rotamer_->type();
1816  for ( Size ii = 1; ii <= restype.nheavyatoms(); ++ii ) {
1817  if ( restype.atom_type( ii ).element() == carbon || restype.atom_type( ii ).element() == sulfur ) {
1818  ++n_hphobes_;
1819  }
1820  }
1821  hphobe_ats_.reserve( n_hphobes_ );
1822  for ( Size ii = 1; ii <= restype.nheavyatoms(); ++ii ) {
1823  if ( restype.atom_type( ii ).element() == carbon || restype.atom_type( ii ).element() == sulfur ) {
1824  hphobe_ats_.push_back( ii );
1825  }
1826  }
1827  } // end scope
1828  curr_state_exp_hphobes_.reserve( n_hphobes_ );
1829  alt_state_exp_hphobes_.reserve( n_hphobes_ );
1830 
1831 
1832 }
1833 
1834 
1835 ///
1836 /// @begin HPatchBackgroundNode::get_rotamer
1837 ///
1838 /// @brief
1839 /// returns a const reference to the ResidueOP object held by this background Node. needed by the initialize_bg_bg_overlap
1840 /// call in this class so that one BGNode can get at the residue/rotamer information on another BGNode instance.
1841 ///
1842 template < typename V, typename E, typename G >
1844  return rotamer_;
1845 }
1846 
1847 
1848 ///
1849 /// @begin HPatchBackgroundNode::set_rotamer_dots
1850 ///
1851 /// @brief
1852 /// inits the RotamerDots object held by a background node. called in the HPatchIG::initialize method.
1853 ///
1854 template < typename V, typename E, typename G >
1856  current_state_rotamer_dots_ = bg_rd;
1857  alt_state_dots_matches_current_state_dots_ = false;
1858 }
1859 
1860 
1861 ///
1862 /// @begin HPatchBackgroundNode::detect_overlap
1863 ///
1864 /// @brief
1865 /// returns true if this background residue overlaps with any atom on any rotamer of a HPatchNode.
1866 ///
1867 /// @detailed
1868 /// Uses the HPatchNode function detect_any_overlap_with_rotamer. It calls the function on the passed in HPatchNode with the
1869 /// RotamerDots object this BGNode keeps in current_state_rotamer_dots_.
1870 ///
1871 template < typename V, typename E, typename G >
1873  return node->detect_any_overlap_with_rotamer( current_state_rotamer_dots_ );
1874 }
1875 
1876 
1877 ///
1878 /// @begin HPatchBackgroundNode::prepare_for_simulated_annealing
1879 ///
1880 /// @brief
1881 /// detects self overlap and asks its incident HPatchBackgroundEdges to compute and cache the overlaps of this residue
1882 /// with all states on the neighboring HPatchNode.
1883 ///
1884 /// @detailed
1885 /// if we've already gone through this method once, then don't update the parent classes edge vectors. but we do need to
1886 /// reinitialize the self overlap on the BGNode as well as the overlap caused by all other bg nodes.
1887 ///
1888 template < typename V, typename E, typename G >
1890 
1891  if ( ! prepared_for_simA_ ) {
1892  if ( ! parent::get_edge_vector_up_to_date() )
1893  parent::update_edge_vector();
1894 
1895  prepared_for_simA_ = true;
1896  }
1897 
1898  // this call is not necessary the first time through packing, but is necessary the 2nd and higher times through because
1899  // the current state rotamer dots will have overlap from FC nodes mixed in with self and bg node overlap.
1900  current_state_rotamer_dots_.zero();
1901  alt_state_dots_matches_current_state_dots_ = false;
1902 
1903  initialize_self_overlap();
1904  initialize_atom_atom_overlaps();
1905 //#ifdef FILE_DEBUG
1906 // TR_BGNODE << "prepare_for_simulated_annealing(): initializing overlap on bg node " << parent::get_node_index() << std::endl;
1907 //#endif
1908  for ( Size ii = 1; ii <= (Size)parent::get_num_incident_edges(); ++ii ) {
1909  get_hpatch_bg_edge( ii )->initialize_overlap_cache( current_state_rotamer_dots_ );
1910  }
1911 
1912 }
1913 
1914 
1915 ///
1916 /// @begin HPatchBackgroundNode::initialize_self_overlap
1917 ///
1918 /// @brief
1919 /// initializes the self overlap for its RotamerDots object
1920 ///
1921 template < typename V, typename E, typename G >
1923 //#ifdef FILE_DEBUG
1924 // if ( parent::get_node_index() == 5 ) {
1925 // TR_BGNODE << "initialize_self_overlap(): current_state_rotamer_dots_: " << std::endl;
1926 // current_state_rotamer_dots_.print( std::cout );
1927 // }
1928 //#endif
1929 
1930  alt_state_dots_matches_current_state_dots_ = false;
1931  current_state_rotamer_dots_.increment_self_overlap();
1932 
1933 //#ifdef FILE_DEBUG
1934 // if ( parent::get_node_index() == 5 ) {
1935 // TR_BGNODE << "initialize_self_overlap(): current_state_rotamer_dots_ after increment_self_overlap: " << std::endl;
1936 // current_state_rotamer_dots_.print( std::cout );
1937 // }
1938 //#endif
1939 
1940 }
1941 
1942 
1943 ///
1944 /// @begin HPatchBackgroundNode::initialize_atom_atom_overlaps
1945 ///
1946 /// @brief
1947 /// initializes the atom-atom overlap vector stored by this background node. called once during prep_for_simA.
1948 ///
1949 template < typename V, typename E, typename G >
1951 
1952  self_atom_atom_overlaps_.resize( rotamer_->nheavyatoms(), utility::vector1< bool >( rotamer_->nheavyatoms(), false ) );
1953 
1954  std::string carbon_atom = "C";
1955  std::string sulfur_atom = "S";
1956  Real const probe_radius = 1.4;
1957 
1958  for ( Size iia=1; iia <= rotamer_->nheavyatoms(); ++iia ) {
1959  // immediately continue if not a hydrophobic atom; no point in computing overlaps for polar atoms
1960  if ( rotamer_->atom_type( iia ).element() != carbon_atom && rotamer_->atom_type( iia ).element() != sulfur_atom )
1961  continue;
1962 
1963  Real const iia_atom_radius = current_state_rotamer_dots_.get_atom_radius( iia ) + probe_radius;
1964 
1965  // for intra-residue we only have iterate over the greater-indexed heavyatoms
1966  for ( Size jja = iia + 1; jja <= rotamer_->nheavyatoms(); ++jja ) {
1967  if ( rotamer_->atom_type( jja ).element() != carbon_atom && rotamer_->atom_type( jja ).element() != sulfur_atom )
1968  continue;
1969 
1970  Real const jja_atom_radius = current_state_rotamer_dots_.get_atom_radius( jja ) + probe_radius;
1971 
1972  // check if the two atoms overlap, and if that degree of overlap exceeds the threshold
1973  Vector const & iia_atom_xyz = rotamer_->atom( iia ).xyz();
1974  Vector const & jja_atom_xyz = rotamer_->atom( jja ).xyz();
1975 
1976  Real const distance_squared = iia_atom_xyz.distance_squared( jja_atom_xyz );
1977  //if ( distance_squared <= (iia_atom_radius + iia_atom_radius) * (jja_atom_radius + jja_atom_radius) ) {
1978  if ( distance_squared <= (iia_atom_radius + jja_atom_radius) * (iia_atom_radius + jja_atom_radius) ) {
1979 
1980  Real const distance_ijxyz = std::sqrt( distance_squared );
1981  int degree_of_overlap;
1982  core::scoring::get_overlap( iia_atom_radius, jja_atom_radius, distance_ijxyz, degree_of_overlap );
1983  if ( degree_of_overlap >= 15 ) {
1984 #ifdef FILE_DEBUG
1985  //TR_BGNODE << "initialize_self_overlap(): overlapping intra-residue atom pair: "
1986  // << rotamer_->seqpos() << "/" << utility::trim( rotamer_->atom_name( iia ) ) << " - " << rotamer_->seqpos() << "/" << utility::trim( rotamer_->atom_name( jja ) )
1987  // << ", degree of overlap: " << degree_of_overlap << std::endl;
1988 #endif
1989  self_atom_atom_overlaps_[ iia ][ jja ] = true;
1990  }
1991  } // end if distance
1992  } // for loop over all jj heavyatoms
1993  } // for loop over all ii heavyatoms
1994 
1995 
1996 /*
1997 #ifdef FILE_DEBUG
1998  TR_BGNODE << "background node " << parent::get_node_index() << " self_atom_atom_overlaps_: [ " << std::endl;
1999  for ( Size aa=1; aa <= self_atom_atom_overlaps_.size(); ++aa ) {
2000  TR_BGNODE << "self_atom_atom_overlaps_[ " << aa << " ]: [ ";
2001  for ( Size bb=1; bb <= self_atom_atom_overlaps_[ aa ].size(); ++bb ) {
2002  TR_BGNODE << self_atom_atom_overlaps_[ aa ][ bb ] << ", ";
2003  }
2004  TR_BGNODE << "]" << std::endl;
2005  }
2006  TR_BGNODE << std::endl;
2007 #endif
2008 */
2009 
2010 }
2011 
2012 
2013 ///
2014 /// @begin HPatchBackgroundNode::initialize_bg_bg_overlap
2015 ///
2016 /// @brief
2017 /// stores the sphere overlap for a pair of background nodes
2018 ///
2019 template < typename V, typename E, typename G >
2021  current_state_rotamer_dots_.increment_both( other.current_state_rotamer_dots_ );
2022  alt_state_dots_matches_current_state_dots_ = false;
2023 
2024 //#ifdef FILE_DEBUG
2025 // if ( parent::get_node_index() == 5 ) {
2026 // TR_BGNODE << "initialize_bg_bg_overlap(): current_state_rotamer_dots_ after adding in others overlap: " << std::endl;
2027 // current_state_rotamer_dots_.print( std::cout );
2028 // }
2029 //#endif
2030 }
2031 
2032 
2033 ///
2034 /// @begin HPatchBackgroundNode::update_state_for_substitution
2035 ///
2036 /// @brief
2037 /// returns the change in sasa induced by a HPatchNode undergoing a state substitution. The overlap between the HPatchNode
2038 /// and this HPatchBackgroundNode has been precomputed and stored in the HPatchBackgroundEdge that connects them.
2039 /// There is little work to do in this subroutine.
2040 ///
2041 template < typename V, typename E, typename G >
2043  RotamerDotsCache const & nodes_curr_overlap_with_bg_res, RotamerDotsCache const & nodes_alt_overlap_with_bg_res ) {
2044 
2045  get_hpatch_owner()->register_bg_node_affected_by_rotsub( parent::get_node_index() );
2046 
2047  fc_node_changing->wt_seqpos_for_node(); // do something with fc_node_changing or otherwise we get unused var warning
2048 
2049  //alt_state_rotamer_dots_.copy_spheres_not_doubly_covered( &current_state_rotamer_dots_ );
2050  //alt_state_rotamer_dots_ = current_state_rotamer_dots_;
2051  if ( ! alt_state_dots_matches_current_state_dots_ ) {
2052  alt_state_rotamer_dots_ = current_state_rotamer_dots_;
2053  }
2054  alt_state_dots_matches_current_state_dots_ = false;
2055 
2056 #ifdef FILE_DEBUG
2057  //TR_BGNODE << "update_state_for_substitution(): alt_state_rotamer_dots_" << std::endl;
2058  //alt_state_rotamer_dots_.print( std::cout );
2059  //TR_BGNODE << "update_state_for_substitution(): nodes_curr_overlap_with_bg_res" << std::endl;
2060  //nodes_curr_overlap_with_bg_res.print( std::cout );
2061 #endif
2062 
2063  alt_state_rotamer_dots_.decrement_from_cached( nodes_curr_overlap_with_bg_res );
2064 
2065 #ifdef FILE_DEBUG
2066  //TR_BGNODE << "update_state_for_substitution(): nodes_alt_overlap_with_bg_res" << std::endl;
2067  //nodes_alt_overlap_with_bg_res.print( std::cout );
2068 #endif
2069 
2070  alt_state_rotamer_dots_.increment_from_cached( nodes_alt_overlap_with_bg_res );
2071 
2072  update_alt_state_exphphobes();
2073  alt_state_inv_dots_.setup_from_rotamer_dots( alt_state_rotamer_dots_, alt_state_exp_hphobes_ );
2074 #ifdef FILE_DEBUG
2075  //TR_BGNODE << "update_state_for_substitution(): alt_state_rotamer_dots_" << std::endl;
2076  //alt_state_rotamer_dots_.print( std::cout );
2077 #endif
2078 
2079  Real sasa_difference = alt_state_rotamer_dots_.get_sasa() - current_state_rotamer_dots_.get_sasa();
2080 
2081 #ifdef FILE_DEBUG
2082  Size fc_node_resid = fc_node_changing->wt_seqpos_for_node();
2083  TR_BGNODE << "update_state_for_substitution: bg node " << parent::get_node_index()
2084  << " calculated deltaE for changing hpatch resid " << fc_node_resid << "; "
2085  << "curr state sasa: " << current_state_rotamer_dots_.get_sasa() << ", alt state sasa: " << alt_state_rotamer_dots_.get_sasa()
2086  << ", sasa difference: " << sasa_difference << std::endl;
2087 #endif
2088 
2089  return sasa_difference;
2090 }
2091 
2092 
2093 ///
2094 /// @begin HPatchBackgroundNode::reset_alt_state_dots
2095 ///
2096 /// @brief
2097 /// Sets the alt state dots to the current state dots. See comments in HIG and commit_considered_substitution
2098 /// for more information about why this method exists.
2099 ///
2100 template < typename V, typename E, typename G >
2102 
2103  //if ( alt_state_rotamer_dots_ != current_state_rotamer_dots_ ) { // alot of time spent doing comparison. just set them equal irregardless.
2104  if ( ! alt_state_dots_matches_current_state_dots_ ) {
2105  alt_state_rotamer_dots_ = current_state_rotamer_dots_;
2106  alt_state_inv_dots_ = curr_state_inv_dots_;
2107  alt_state_exp_hphobes_ = curr_state_exp_hphobes_;
2108  alt_state_dots_matches_current_state_dots_ = true;
2109 #ifdef FILE_DEBUG
2110  TR_BGNODE << "reset_alt_state_dots(): alt state rotamer dots set equal to current state rotamer dots." << std::endl;
2111 #endif
2112  }
2113 
2114 }
2115 
2116 
2117 ///
2118 /// @begin HPatchBackgroundNode::acknowledge_substitution
2119 ///
2120 /// @brief
2121 /// bookkeeping to reflect a HPatchNode's state substitution. uses the RotamerDots class method operator=.
2122 ///
2123 template < typename V, typename E, typename G >
2125  current_state_rotamer_dots_ = alt_state_rotamer_dots_;
2126  curr_state_inv_dots_ = alt_state_inv_dots_;
2127  curr_state_exp_hphobes_ = alt_state_exp_hphobes_;
2128  alt_state_dots_matches_current_state_dots_ = true;
2129 }
2130 
2131 
2132 ///
2133 /// @begin HPatchBackgroundNode::update_alt_state_exphphobes
2134 ///
2135 /// @brief
2136 /// Updates the vector alt_state_exp_hphobes_ with the atom id (??) of the exposed hydrophobic atoms in this residue.
2137 ///
2138 template < typename V, typename E, typename G >
2140  alt_state_exp_hphobes_.clear();
2141  for ( Size ii = 1; ii <= hphobe_ats_.size(); ++ii ) {
2142  Size const ii_atom = hphobe_ats_[ ii ];
2143  if ( alt_state_rotamer_dots_.get_atom_sasa( ii_atom ) > 0.0 ) {
2144  alt_state_exp_hphobes_.push_back( ii_atom );
2145  }
2146  }
2147 }
2148 
2149 
2150 ///
2151 /// @begin HPatchBackgroundNode< V, E, G >::get_current_sasa
2152 ///
2153 /// @brief
2154 /// returns the total SASA under the current state assignment
2155 ///
2156 template < typename V, typename E, typename G >
2158  return current_state_rotamer_dots_.get_sasa();
2159 }
2160 
2161 
2162 ///
2163 /// @begin HPatchBackgroundNode< V, E, G >::get_current_sasa
2164 ///
2165 /// @brief
2166 /// Returns the current state SASA for the passed in atom index
2167 ///
2168 template < typename V, typename E, typename G >
2169 Real
2171  return current_state_rotamer_dots_.get_atom_sasa( atom_index );
2172 }
2173 
2174 
2175 ///
2176 /// @begin HPatchBackgroundNode< V, E, G >::get_alternate_sasa
2177 ///
2178 /// @brief
2179 /// returns the total SASA under the alternate state assignment
2180 ///
2181 template < typename V, typename E, typename G >
2182 Real
2184  return alt_state_rotamer_dots_.get_sasa();
2185 }
2186 
2187 
2188 ///
2189 /// @begin HPatchBackgroundNode< V, E, G >::get_alternate_sasa
2190 ///
2191 /// @brief
2192 /// Returns the alternate state SASA for the passed in atom index
2193 ///
2194 template < typename V, typename E, typename G >
2195 Real
2197  return alt_state_rotamer_dots_.get_atom_sasa( atom_index );
2198 }
2199 
2200 
2201 ///
2202 /// @begin HPatchBackgroundNode< V, E, G >::get_atom_atom_self_overlaps
2203 ///
2204 /// @brief
2205 /// Returns a const reference to the atom x atom pair vector of vectors of bools that specifies which atoms are overlapping.
2206 ///
2207 template < typename V, typename E, typename G >
2209  return self_atom_atom_overlaps_;
2210 }
2211 
2212 
2213 ///
2214 /// @begin HPatchBackgroundNode::count_static_memory
2215 ///
2216 template < typename V, typename E, typename G >
2218  return sizeof ( HPatchBackgroundNode< V, E, G > );
2219 }
2220 
2221 ///
2222 /// @begin HPatchBackgroundNode::count_dynamic_memory
2223 ///
2224 template < typename V, typename E, typename G >
2226  unsigned int total_memory = parent::count_dynamic_memory();
2227 
2228  return total_memory;
2229 }
2230 
2231 ///
2232 /// @begin HPatchBackgroundNode::print
2233 ///
2234 /// @brief
2235 /// used only for debugging
2236 //template < typename V, typename E, typename G >
2237 //void HPatchBackgroundNode< V, E, G >::write_dot_kinemage( std::ofstream & output_kin ) {
2238 // current_state_rotamer_dots_.write_dot_kinemage( output_kin );
2239 //}
2240 
2241 
2242 ///
2243 /// @begin HPatchBackgroundNode::print
2244 ///
2245 /// @brief
2246 /// used only for debugging
2247 template < typename V, typename E, typename G >
2249  TR_BGNODE << "bgnode " << parent::get_node_index() << ", current state sasa: " << current_state_rotamer_dots_.get_sasa()
2250  << ", alt state sasa: " << alt_state_rotamer_dots_.get_sasa() << std::endl;
2251  current_state_rotamer_dots_.print( std::cout );
2252 }
2253 
2254 
2255 //----------------------------------------------------------------------------//
2256 //------------------------------ HPatch Edge Class -----------------------------//
2257 //----------------------------------------------------------------------------//
2258 
2259 
2260 ///
2261 /// @begin HPatchEdge::HPatchEdge
2262 ///
2263 /// @brief
2264 /// main constructor. No default, or copy constructors, no assignment operator
2265 ///
2266 /// @param
2267 /// owner - [in] - the owning interaction graph object
2268 /// node1 - [in] - the index of the lower-indexed HPatchNode
2269 /// node2 - [in] - the index of the higher-indexed HPatchNode
2270 ///
2271 template < typename V, typename E, typename G >
2272 HPatchEdge< V, E, G >::HPatchEdge( G* owner, int node1, int node2 ) :
2273  FirstClassEdge< V, E, G > ( owner, node1, node2 ),
2274  node_changing_( -1 ),
2275  node_not_changing_( -1 )
2276  //nodes_curr_pair_dot_counts_ // calls default RDC constructor, which is fine
2277  //nodes_alt_pair_dot_counts_ // calls default RDC constructor, which is fine
2278  //current_state_atom_atom_overlaps_ // vectors are init'd to nothing
2279  //alt_state_atom_atom_overlaps_;
2280 {
2281  nodes_curr_states_[ 0 ] = nodes_curr_states_[ 1 ] = 0;
2282  nodes_alt_states_[ 0 ] = nodes_alt_states_[ 1 ] = 0;
2283 
2284 }
2285 
2286 
2287 ///
2288 /// @begin HPatchEdge::~HPatchEdge
2289 ///
2290 template < typename V, typename E, typename G >
2292  //TR_EDGE << "called destructor" << std::endl;
2293 }
2294 
2295 
2296 ///
2297 /// @begin HPatchEdge::prepare_for_simulated_annealing
2298 ///
2299 /// @brief
2300 /// drops zero submatrices of the AminoAcidNeighborSparseMatrix and if the two_body_energies_ member then holds nothing,
2301 /// it checks whether or not its incident nodes have any sphere overlaps. If they don't then the edge deletes itself.
2302 ///
2303 template < typename V, typename E, typename G >
2305 
2306 #ifdef FILE_DEBUG
2307  TR_EDGE << "prepare_for_simulated_annealing called on edge e(" << parent::get_node_index( 0 ) << "," << parent::get_node_index( 1 ) << ")" << std::endl;
2308 #endif
2309 
2310  parent::prepare_for_simulated_annealing_no_deletion(); // AddtlBGNodesIG doesn't have an Edge method for prep for simA, but PDIG does
2311 
2312  if ( parent::pd_edge_table_all_zeros() ) {
2313  if ( ! (get_hpatch_node(0)->overlaps( get_hpatch_node(1)) ) ) {
2314 #ifdef FILE_DEBUG
2315  TR_EDGE << "prepare_for_simulated_annealing - dropping edge e(" << parent::get_node_index( 0 )
2316  << "," << parent::get_node_index( 1 ) << ")" << std::endl;
2317 #endif
2318  delete this;
2319  }
2320  }
2321 }
2322 
2323 
2324 ///
2325 /// @begin HPatchEdge::acknowledge_state_zeroed
2326 ///
2327 /// @brief
2328 /// respond to when one of its vertices enters the "unassigned" state.
2329 ///
2330 /// @detailed
2331 /// called during the HIG::blanket_assign_state_0 -> HPatchNode::assign_zero_state() cascade of calls.
2332 ///
2333 template < typename V, typename E, typename G >
2335 
2336  // each Edge contains a node_changing_ and node_not_changing_ int (which takes on values of 0 or 1)
2337  // node_changing_ is the node of this edge that is changing
2338  node_changing_ = ( node_that_changed == parent::get_node_index(0) ? 0 : 1 );
2339  node_not_changing_ = ! node_changing_;
2340 
2341  nodes_curr_states_[ node_changing_ ] = 0;
2342 
2343  nodes_curr_pair_dot_counts_[ node_changing_ ].resize( 0 );
2344  nodes_curr_pair_dot_counts_[ node_not_changing_ ].resize( 0 );
2345 
2346  nodes_alt_pair_dot_counts_[ node_changing_ ].resize( 0 );
2347  nodes_alt_pair_dot_counts_[ node_not_changing_ ].resize( 0 );
2348 
2349  // clear the atom-atom overlap caches; not sure if this is necessary since at construct time these vectors will be
2350  // empty. the unit tests will call blanket_assign_state_0 on the same graph multiple times though, so clear() calls
2351  // here will ensure nothing remains.
2352  // apl -- removing since it breaks monotonicity assumption -- current_state_atom_atom_overlaps_.clear();
2353  // apl -- removing since it breaks monotonicity assumption -- alt_state_atom_atom_overlaps_.clear();
2354 
2355  inform_non_changing_node_of_neighbors_change();
2356 }
2357 
2358 
2359 ///
2360 /// @begin HPatchEdge::inform_non_changing_node_of_neighbors_change
2361 ///
2362 /// @brief
2363 /// tells the node that isn't considering a substitution or changing state that its neighbor who is has changed.
2364 ///
2365 template < typename V, typename E, typename G >
2366 inline
2368  get_hpatch_node( node_not_changing_ )->acknowledge_neighbors_substitution();
2369 }
2370 
2371 
2372 ///
2373 /// @begin HPatchEdge::update_state_at_neighbor
2374 ///
2375 /// @brief
2376 /// returns the change in sasa for the neighbor of a node that is produced by the state substitution it is considering.
2377 ///
2378 /// @detailed
2379 /// Very complicated. See HPatchNode::project_deltaE_for_neighbors_state_sub
2380 /// This edge collects cached sphere overlaps and hands this cached data to
2381 /// the node that is not considering the state substitution. That node
2382 /// computes more sphere overlaps and returns a delta sasa; this method then
2383 /// passes that delta sasa along.
2384 ///
2385 /// See more comments inline.
2386 ///
2387 /// @param
2388 /// changing_node_alt_state_dots - [in] - the RotamerDots object for the alternate state at the changing Node
2389 ///
2390 template < typename V, typename E, typename G >
2391 Real HPatchEdge< V, E, G >::update_state_at_neighbor( int node_considering_substitution, int alt_state, RotamerDots & changing_node_alt_state_dots ) {
2392 
2393  using namespace utility;
2394 
2395  node_changing_ = ( node_considering_substitution == parent::get_node_index(0) ? 0 : 1 );
2396  node_not_changing_ = ! node_changing_;
2397 
2398  nodes_alt_states_[ node_changing_ ] = alt_state;
2399  nodes_alt_states_[ node_not_changing_ ] = nodes_curr_states_[ node_not_changing_ ];
2400 
2401  // zero out the RotamerDotsCache object stored for the non_changing FC node
2402  nodes_alt_pair_dot_counts_[ node_not_changing_ ].zero();
2403 
2404  // the alternate state RDC object for the changing node should be the curr state dot counts, up to the number of atoms that are the same
2405  // as the current state? but since we're not using trie ordering, the number of atoms same as current will be zero.
2406  nodes_alt_pair_dot_counts_[ node_changing_ ] = nodes_curr_pair_dot_counts_[ node_changing_ ];
2407  // nodes_alt_pair[ changing ] now contains the RDC object which represents the overlap b/t the two FC Nodes on this Edge in the
2408  // context of the current state!
2409  nodes_alt_pair_dot_counts_[ node_changing_ ].zero();
2410 
2411  // nodes_curr_pair_dot_counts_[ node_not_changing_ ] is the overlap the non-changing node experiences because of the changing Node
2412  // in its current state. (aka neighbors_curr_state_overlap_with_this) - this gets subtracted
2413 
2414  // nodes_alt_pair_dot_counts_[ node_changing_ ] is the overlap the non_changing node produces on the changing Node in its alt state
2415  // (from perspective of non-changing node: this_overlap_with_neighbors_alternate)
2416  // this, in turn, gets passed to increment_both_and_cache:
2417  // other_dots_covered_by_this - the dot coverage cache represnting dots on the surface of other_rotamer that
2418  // are covered by this rotamer
2419 
2420  // nodes_alt_pair_dot_counts_[ node_not_changing ] is the overlap the changing node in its alt state produces on the non_changing FC
2421  // node. (from perspective of nonchanging node: neighbors_alternate_overlap_with_this, or this_dots_covered_by_other)
2422 
2423  // have to invalidate/resize the caches stored on the Edge since they will both change
2424  nodes_alt_pair_dot_counts_[ node_changing_ ].resize( changing_node_alt_state_dots.get_num_atoms() );
2425  //if ( get_hpatch_node( node_not_changing_ )->get_current_state() != 0 )
2426  nodes_alt_pair_dot_counts_[ node_not_changing_ ].resize( get_hpatch_node( node_not_changing_ )->get_current_state_num_atoms() );
2427  // the RDC object for the node_not_changing may get resized to 0, but it doesn't matter because the method update_state_
2428  // for_neighbors_sub will immediately return if the current state on the non_changing node is 0.
2429 
2430  // also have to update the atom-atom overlap cache for the considered sub.
2431  // we have to resize the vector of vectors here, but we have to be consistent with which one comes first. let's always make
2432  // the fc node that's changing the outer vector and the non-changing node the inner vector.
2433  // the values in this vector will get set by the non-changing node when it's updating the sasa information. no point in
2434  // doing the sphere overlap calculations twice.
2435  Size const node_not_changing_num_atoms = get_hpatch_node( node_not_changing_ )->get_current_state_num_atoms();
2436  Size const node_changing_alt_state_num_atoms = changing_node_alt_state_dots.get_num_atoms();
2437 
2438  //alt_state_atom_atom_overlaps_.resize( node_changing_alt_state_num_atoms, utility::vector1< bool >( node_not_changing_num_atoms, false ) );
2439  /// APL -- don't resize these arrays; too expensive; just leave it large
2440  if ( alt_state_atom_atom_overlaps_.size() < node_changing_alt_state_num_atoms ) {
2441  alt_state_atom_atom_overlaps_.resize( node_changing_alt_state_num_atoms, utility::vector1< bool >( node_not_changing_num_atoms, false ) );
2442  }
2443 
2444  for ( Size ii = 1; ii <= node_changing_alt_state_num_atoms; ++ii ) {
2445  if ( alt_state_atom_atom_overlaps_[ii].size() < node_not_changing_num_atoms ) {
2446  alt_state_atom_atom_overlaps_[ii].resize( node_not_changing_num_atoms, false );
2447  }
2448  for ( Size jj = 1; jj <= node_not_changing_num_atoms; ++jj ) {
2449  alt_state_atom_atom_overlaps_[ ii ][ jj ] = false;
2450  }
2451  }
2452 
2453  Real const delta_sasa = get_hpatch_node( node_not_changing_ )->update_state_for_neighbors_substitution(
2454  get_hpatch_node( node_changing_ ), changing_node_alt_state_dots,
2455  nodes_curr_pair_dot_counts_[ node_not_changing_ ],
2456  nodes_alt_pair_dot_counts_[ node_changing_ ],
2457  nodes_alt_pair_dot_counts_[ node_not_changing_ ],
2458  alt_state_atom_atom_overlaps_ );
2459 
2460  // in get_hpatch_deltaE_for_nbs_state_sub(), non-changing node calls...
2461  // alt_state_rotamer_dots_.increment_both_and_cache( neighbors_alternate_state, this_overlap_with_neighbors_alternate,
2462  // neighbors_alternate_overlap_with_this, mask_this_covered_by_other, mask_other_covered_by_this );
2463 
2464 #ifdef FILE_DEBUG
2465  // this line just generates waaaay too much output...
2466  //TR_EDGE << "update_state_at_neighbor() for changing node: " << node_considering_substitution
2467  // << " and node: " << parent::get_node_index( node_not_changing_ ) << " returning delta sasa of " << delta_sasa << std::endl;
2468 #endif
2469 
2470  return delta_sasa;
2471 }
2472 
2473 
2474 ///
2475 /// @begin HPatchEdge::acknowledge_substitution
2476 ///
2477 /// @brief
2478 /// bookkeeping following the decision to substitute a nodes current state with the alternate it was asked to consider.
2479 ///
2480 template < typename V, typename E, typename G >
2482 
2483  inform_non_changing_node_of_neighbors_change();
2484 
2485  nodes_curr_states_[ node_changing_ ] = nodes_alt_states_[ node_changing_ ];
2486 
2487  nodes_curr_pair_dot_counts_[0] = nodes_alt_pair_dot_counts_[0];
2488  nodes_curr_pair_dot_counts_[1] = nodes_alt_pair_dot_counts_[1];
2489 
2490  //current_state_atom_atom_overlaps_ = alt_state_atom_atom_overlaps_;
2491  if ( node_changing_ == 0 ) {
2492  if ( current_state_atom_atom_overlaps_.size() < alt_state_atom_atom_overlaps_.size() ) {
2493  current_state_atom_atom_overlaps_.resize( alt_state_atom_atom_overlaps_.size() );
2494  }
2495  for ( Size ii = 1; ii <= alt_state_atom_atom_overlaps_.size(); ++ii ) {
2496  if ( current_state_atom_atom_overlaps_[ii].size() < alt_state_atom_atom_overlaps_[ii].size() ) {
2497  current_state_atom_atom_overlaps_[ii].resize( alt_state_atom_atom_overlaps_[ii].size() );
2498  }
2499  current_state_atom_atom_overlaps_[ii] = alt_state_atom_atom_overlaps_[ii];
2500  }
2501  } else {
2502 
2503  /// Preserve the convention that the current_state_atom_atom_overlaps_ dimensions 1st by node 0
2504  /// and 2nd by node 1. This means that if we just considered a substitution at node 1, that the
2505  /// alt_state_atom_atom_overlaps_ will be dimensioned 1st by node 1 and 2nd by node 0, so we need
2506  /// to copy curr[ii][jj] from alt[jj][ii];
2507  if ( alt_state_atom_atom_overlaps_.size() == 0 ) {
2508  current_state_atom_atom_overlaps_ = alt_state_atom_atom_overlaps_;
2509  return;
2510  }
2511 
2512  // debug
2513  assert( get_hpatch_node( node_changing_ )->get_alt_state_num_atoms() <= alt_state_atom_atom_overlaps_.size() );
2514  assert( get_hpatch_node( node_not_changing_ )->get_current_state_num_atoms() <= alt_state_atom_atom_overlaps_[1].size() );
2515 
2516  if ( current_state_atom_atom_overlaps_.size() < alt_state_atom_atom_overlaps_[1].size() ) {
2517  current_state_atom_atom_overlaps_.resize( alt_state_atom_atom_overlaps_[1].size() );
2518  }
2519 
2520  for ( Size ii=1; ii <= alt_state_atom_atom_overlaps_[1].size(); ++ii ) {
2521  if ( current_state_atom_atom_overlaps_[ii].size() < alt_state_atom_atom_overlaps_.size() ){
2522  current_state_atom_atom_overlaps_[ii].resize( alt_state_atom_atom_overlaps_.size() );
2523  }
2524  }
2525 
2526  for ( Size ii=1; ii <= alt_state_atom_atom_overlaps_.size(); ++ii ) {
2527  /// strict monotone growth
2528  assert( alt_state_atom_atom_overlaps_[ ii ].size() <= alt_state_atom_atom_overlaps_[ 1 ].size() );
2529  assert( ii > get_hpatch_node( node_changing_ )->get_alt_state_num_atoms() ||
2530  get_hpatch_node( node_not_changing_ )->get_current_state_num_atoms() <= alt_state_atom_atom_overlaps_[ii].size() );
2531  for ( Size jj = 1; jj <= alt_state_atom_atom_overlaps_[ ii ].size(); ++jj ) {
2532  current_state_atom_atom_overlaps_[ jj ][ ii ] = alt_state_atom_atom_overlaps_[ ii ][ jj ];
2533  }
2534  }
2535  }
2536 
2537  return;
2538 }
2539 
2540 
2541 ///
2542 /// @begin HPatchEdge< V, E, G >::get_current_state_atom_atom_overlaps
2543 ///
2544 /// @brief
2545 /// Returns a const reference to the atom-x-atom-pair vector-of-vectors of bools that specifies which atoms are overlapping,
2546 /// assuming the current state assignment.
2547 ///
2548 template < typename V, typename E, typename G >
2551  return current_state_atom_atom_overlaps_;
2552 }
2553 
2554 
2555 ///
2556 /// @begin HPatchEdge< V, E, G >::get_alt_state_atom_atom_overlaps
2557 ///
2558 /// @brief
2559 /// Returns a const reference to the atom-x-atom-pair vector-of-vectors of bools that specifies which atoms are overlapping,
2560 /// assuming the alternate state assignment.
2561 ///
2562 template < typename V, typename E, typename G >
2565  return alt_state_atom_atom_overlaps_;
2566 }
2567 
2568 
2569 ///
2570 /// @begin HPatchEdge::declare_energies_final
2571 ///
2572 /// @brief
2573 /// Reduces memory usage in the two body energy table after the energy
2574 /// calculating function declares that the energies will not change thereafter
2575 ///
2576 /// @remarks (all by apl)
2577 /// In the PDEdge's version of this method, after invoking two_body_energies_.drop_zero_submatrices_where_possible();
2578 /// the PDEdge checks if the two body energy table it now holds is empty. If the table is empty, the edge deletes itself.
2579 ///
2580 /// A HPatchEdge should not delete itself if the pair energies are all zero since the Minkowski sum of a water and a van
2581 /// der Waal's sphere extends further out from an atoms center than its (lj_atr, lj_rep, lksolv) interaction sphere.
2582 /// However, if a HPatchEdge holds no pair energies, it's a very good candidate for removal -- it just first needs to check
2583 /// that no (vdw + 1.4 A) spheres overlap between any pair of rotamers on the edges it connects.
2584 ///
2585 template < typename V, typename E, typename G >
2587  parent::declare_energies_final_no_deletion();
2588 }
2589 
2590 
2591 ///
2592 /// @begin HPatchEdge::getMemoryUsageInBytes
2593 ///
2594 /// @remarks
2595 /// Not implemented.
2596 ///
2597 template < typename V, typename E, typename G >
2599  return 0;
2600 }
2601 
2602 
2603 ///
2604 /// @begin HPatchEdge::count_static_memory
2605 ///
2606 template < typename V, typename E, typename G >
2608  return sizeof ( HPatchEdge< V, E, G > );
2609 }
2610 
2611 ///
2612 /// @begin HPatchEdge::count_dynamic_memory
2613 ///
2614 template < typename V, typename E, typename G >
2616 
2617  unsigned int total_memory = parent::count_dynamic_memory();
2618 
2619  //assert( alt_state_atom_atom_overlaps_.size() == current_state_atom_atom_overlaps_.size() );
2620  total_memory += sizeof( utility::vector1< bool > ) * alt_state_atom_atom_overlaps_.size();
2621  for ( Size ii = 1; ii <= alt_state_atom_atom_overlaps_.size(); ++ii ) {
2622  total_memory += sizeof( bool ) * alt_state_atom_atom_overlaps_[ii].size();
2623  }
2624  total_memory += sizeof( utility::vector1< bool > ) * current_state_atom_atom_overlaps_.size();
2625  for ( Size ii = 1; ii <= current_state_atom_atom_overlaps_.size(); ++ii ) {
2626  total_memory += sizeof( bool ) * current_state_atom_atom_overlaps_[ii].size();
2627  }
2628 
2629  return total_memory;
2630 }
2631 
2632 
2633 
2634 //----------------------------------------------------------------------------//
2635 //----------------------- HPatchBackgroundEdge Class ---------------------------//
2636 //----------------------------------------------------------------------------//
2637 
2638 ///
2639 /// @begin HPatchBackgroundEdge< V, E, G >::HPatchBackgroundEdge
2640 ///
2641 /// @brief
2642 /// main constructor
2643 ///
2644 template < typename V, typename E, typename G >
2646  BackgroundToFirstClassEdge< V, E, G >( owner, first_class_node_index, background_node_index ),
2647  prepared_for_simA_( false ),
2648  node_states_coverage_of_bg_res_(),
2649  nodes_curr_state_( 0 ),
2650  nodes_alt_state_( 0 ),
2651  node_states_overlap_with_bg_res_()
2652  //curr_dots_cache_( 0 ), // default constructed, which means they need to be sized before use
2653  //alt_dots_cache_( 0 ) // default constructed
2654 {}
2655 
2656 
2657 ///
2658 /// @begin HPatchBackgroundEdge::~HPatchBackgroundEdge
2659 ///
2660 template < typename V, typename E, typename G >
2662  //TR_EDGE << "called destructor" << std::endl;
2663  // node_states_coverage_of_bg_res_ is a vector, so when it goes out of scope the memory will be freed
2664 }
2665 
2666 
2667 ///
2668 /// @begin HPatchBackgroundEdge::prepare_for_simulated_annealing
2669 ///
2670 /// @brief
2671 /// Invoked by AdditionalBackgroundNodesInteractionGraph::prepare_for_simulated_annealing.
2672 ///
2673 /// @remarks
2674 /// The HPatchBackgroundEdge has no responsibilities in this function. However, when the AdditionalBackgroundNodesInteractionGraph invokes
2675 /// prepare_for_simulated_annealing on the HPatchBackgroundNode that this edge is incident upon, that node will invoke initialize_overlap_cache
2676 /// on this edge.
2677 ///
2678 template < typename V, typename E, typename G >
2680 
2681 
2682 ///
2683 /// @begin HPatchBackgroundEdge::initialize_overlap_cache
2684 ///
2685 /// @brief
2686 /// compute the sphere overlaps of the background node with every state on the first class node. The HPatchBackgroundEdge
2687 /// hands its stl vector of RotamerDotsCache objects (node_states_coverage_of_bg_res) to the HPatchNode
2688 ///
2689 /// Called during the prep for simA method in HPatchBGNodes.
2690 /// This method in turn calls a HPatchNode method, init_overlap_with_background to set the vector of RDC object pointers.
2691 ///
2692 template < typename V, typename E, typename G >
2694 
2695  //using namespace utility;
2696 
2697  bg_res_num_atoms_ = bg_residue_dots.get_num_atoms();
2698 
2699  if ( ! prepared_for_simA_ ) {
2700  // init every element of this std::vector with an instance of a RDC of size bg res num atoms
2701  // an alternative way to do this would be to make this a vector of pointers, and allocate only the pointers for
2702  // which there is nonzero overlap. but then we'd have to be extra careful about freeing the memory in the destructor.
2703  // if I find that too much memory is being used by this, I'll change it later.
2704  node_states_coverage_of_bg_res_.resize( (Size)(get_hpatch_node()->get_num_states() + 1), RotamerDotsCache( bg_res_num_atoms_ ) );
2705 
2706  // resize the atom-atom overlaps vector. but we can't init the values to anything because we don't know how many atoms
2707  // are in each state on the first class node. just have to init the values in the node method.
2708  node_states_overlap_with_bg_res_.resize( (Size)(get_hpatch_node()->get_num_states() + 1) );
2709 
2710  get_hpatch_node()->initialize_overlap_with_background( bg_residue_dots, node_states_coverage_of_bg_res_, node_states_overlap_with_bg_res_ );
2711 
2712  prepared_for_simA_ = true;
2713  }
2714 
2715  // since we now know how many atoms the bg residue has, resize the two member RDC objects to that number of atoms
2716  curr_dots_cache_.resize( bg_res_num_atoms_ );
2717  alt_dots_cache_.resize( bg_res_num_atoms_ );
2718 
2719 }
2720 
2721 
2722 ///
2723 /// @begin HPatchBackgroundEdge::acknowledge_state_change
2724 ///
2725 /// @brief
2726 /// bookkeeping in response to a HPatchNode switching states (without having gone through the usual
2727 /// consider-substitution/commit-substitution pattern).
2728 ///
2729 /// @detailed
2730 /// State "0" is handled by the HPatchBackgroundEdge just like any other state. The dot overlap cache is simply empty:
2731 /// the unassigned state induces no overlap on the background node. The HPatchBackgroundEdge keeps a stl vector of
2732 /// RotamerDotCaches. Position 0 in that vector holds a Cache object of nothing but 0's.
2733 ///
2734 template < typename V, typename E, typename G >
2736 
2737  if ( new_state == nodes_curr_state_ ) // in the case of the 0-state, just return - don't calculate deltaE
2738  return;
2739 
2740  update_state_at_neighbor( new_state );
2741  acknowledge_substitution();
2742 
2743 }
2744 
2745 
2746 ///
2747 /// @begin HPatchBackgroundEdge::update_state_at_neighbor
2748 ///
2749 /// @brief
2750 /// returns the change in hpatch energy produced by a background node in response to a considered state substitution of
2751 /// the first class node
2752 ///
2753 template < typename V, typename E, typename G >
2755 
2756 #ifdef FILE_DEBUG
2757  //TR_BGEDGE << "update_state_at_neighbor() for changing fc node: " << parent::get_first_class_node_index()
2758  // << " and bg node: " << parent::get_background_node_index() << std::endl;
2759 #endif
2760 
2761  // node_states_coverage_of_bg_res is a vector that contains whether or not a given state on a FCNode (that this edge
2762  // is connected to) overlaps with this bg residue. so if the value at the alt_state state index is nonzero, then there's
2763  // some overlap with the alt_state on this bg residue. in that case, we need to set the non_zero_overlap array and
2764  // then do some updating. (in the case of zero state being assigned, that will point at index 0 which has nothing in
2765  // it) resulting in nothing being done.
2766  alt_dots_cache_.zero();
2767  alt_dots_cache_ = node_states_coverage_of_bg_res_[ alt_state ];
2768 
2769  nodes_alt_state_ = alt_state;
2770 
2771  // for when blanket assign zero state gets called; it doesn't really matter what we return since it's an unassigned state
2772  // ah, but we do because later this 0-state sub gets "committed" and current_state gets set to alt_state. if we don't
2773  // first "consider" the 0-state sub in update_state_for_sub() then we reinit incorrectly.
2774  //if ( alt_state == 0 ) return 0.0;
2775 
2776  Real const delta_sasa = get_hpatch_bg_node()->update_state_for_substitution( get_hpatch_node(), curr_dots_cache_, alt_dots_cache_ );
2777 
2778  return delta_sasa;
2779 }
2780 
2781 
2782 ///
2783 /// @begin HPatchBackgroundEdge::acknowledge_substitution
2784 ///
2785 /// @brief
2786 /// bookkeeping in response to the HPatchNode committing the considered substitution
2787 ///
2788 template < typename V, typename E, typename G >
2790 
2791  get_hpatch_bg_node()->acknowledge_substitution();
2792 
2793  nodes_curr_state_ = nodes_alt_state_;
2794  curr_dots_cache_ = alt_dots_cache_;
2795 
2796 }
2797 
2798 
2799 ///
2800 /// @begin HPatchBackgroundEdge< V, E, G >::get_atom_atom_self_overlaps_for_state
2801 ///
2802 /// @brief
2803 /// Returns a const reference to the atom-x-atom-pair vector-of-vectors of bools that specifies which atoms are overlapping,
2804 /// assuming the alternate state assignment.
2805 ///
2806 template < typename V, typename E, typename G >
2809  assert( state <= node_states_overlap_with_bg_res_.size() );
2810  return node_states_overlap_with_bg_res_[ state ];
2811 }
2812 
2813 
2814 ///
2815 /// @begin HPatchBackgroundEdge::count_static_memory
2816 ///
2817 template < typename V, typename E, typename G >
2819  return sizeof ( HPatchBackgroundEdge< V, E, G > );
2820 }
2821 
2822 ///
2823 /// @begin HPatchBackgroundEdge::count_dynamic_memory
2824 ///
2825 template < typename V, typename E, typename G >
2827 
2828  unsigned int total_memory = parent::count_dynamic_memory();
2829  total_memory += node_states_coverage_of_bg_res_.size() * sizeof ( RotamerDotsCache );
2830  total_memory += node_states_overlap_with_bg_res_.size() * sizeof( bool ); // underestimate; each element is a vector, too! (ronj)
2831  return total_memory;
2832 }
2833 
2834 
2835 
2836 //----------------------------------------------------------------------------//
2837 //--------------------------- HPatch Interaction Graph -------------------------//
2838 //----------------------------------------------------------------------------//
2839 
2840 template < typename V, typename E, typename G >
2842 
2843 template < typename V, typename E, typename G >
2845 
2846 template < typename V, typename E, typename G >
2848 
2849 template < typename V, typename E, typename G >
2851 
2852 template < typename V, typename E, typename G >
2854 
2855 template < typename V, typename E, typename G >
2857 
2858 template < typename V, typename E, typename G >
2860 
2861 ///
2862 /// @begin HPatchInteractionGraph::HPatchInteractionGraph
2863 ///
2864 /// @detailed
2865 /// Main constructor. Initializes all member variables to 0 and false.
2866 ///
2867 template < typename V, typename E, typename G >
2869  AdditionalBackgroundNodesInteractionGraph< V, E, G > ( num_nodes ),
2870  hpatch_score_weight_( 1.0 ),
2871  num_total_residues_( 0 ),
2872  num_residues_assigned_as_background_( 0 ),
2873  some_node_in_state_0_( true ),
2874  fc_nodes_near_rotsub_( num_nodes, 0 ),
2875  fc_nodes_near_rotsub_bool_( num_nodes, true ),
2876  fc_exp_hphobe_djs_offsets_( num_nodes, 0 ),
2877  fc_n_exp_hphobes_( num_nodes, 0 ),
2878  prepared_for_simulated_annealing_( false ),
2879  observed_sufficient_hpatch_E_to_predict_min_( false ),
2880  hpatch_score_min_last_100_( 0 ),
2881  hpatch_score_min_recent_( 0 ),
2882  num_substitutions_since_hpatch_min_update_( 0 ),
2883  calculated_hpatch_deltaE_( false ),
2884  deltaE_for_substitution_( 0.0f ),
2885  node_considering_alt_state_( 0 ),
2886  alt_state_being_considered_( 0 ),
2887  total_energy_current_state_assignment_( 0 ),
2888  total_energy_alternate_state_assignment_( 0 ),
2889  hpatch_energy_current_state_assignment_( 0 ),
2890  hpatch_energy_alternate_state_assignment_( 0 ),
2891  num_commits_since_last_update_( 0 ),
2892  deltaE_threshold_for_avoiding_hpatch_calcs_( -1.0f )
2893 {
2894  /// set all nodes as participating in a rotamer substitution if any node's state is 0 (unassigned)
2895  for ( Size ii = 1; ii <= fc_nodes_near_rotsub_.size(); ++ii ) { fc_nodes_near_rotsub_[ ii ] = ii; }
2896 }
2897 
2898 
2899 ///
2900 /// @begin HPatchInteractionGraph::~HPatchInteractionGraph
2901 ///
2902 template < typename V, typename E, typename G >
2904  //TR_HIG << "called destructor" << std::endl;
2905 }
2906 
2907 
2908 ///
2909 /// @begin HPatchInteractionGraph::set_pose
2910 ///
2911 /// @detailed
2912 /// All throughout this class, I refer back to the original pose sequence. To be able to do that, I need to have a
2913 /// handle to the pose in this class. That's what this method provides. In IGFactory.cc, this method gets called with
2914 /// the pose object that's being packed/designed.
2915 ///
2916 template < typename V, typename E, typename G >
2917 void
2919 
2920 #ifdef FILE_DEBUG
2921  TR_HIG << "set_pose() called: typeid() of base class G returned: " << typeid(G).name() << std::endl;
2922 #endif
2923 
2924  // call the set_pose function in the LinMemIG class, because it, too, uses the Pose to do its thing
2925  if ( typeid(G) == typeid( pack::interaction_graph::LinearMemoryInteractionGraph ) ) {
2926  dynamic_cast<pack::interaction_graph::LinearMemoryInteractionGraph*>(this)->set_pose( pose );
2927  }
2928 
2929  pose_ = new pose::Pose( pose );
2930 }
2931 
2932 
2933 ///
2934 /// @begin HPatchInteractionGraph::set_packer_task
2935 ///
2936 /// @brief
2937 /// We need a copy of the packer task to figure out which residues are being packed and/or designed. We have to figure
2938 /// the packing options because it determines whether a residue becomes a FirstClass (HPatchNode) node or a background node.
2939 /// This method gets called in IGSupport.cc.
2940 ///
2941 template < typename V, typename E, typename G >
2942 void
2944  packer_task_ = the_task.clone();
2945 }
2946 
2947 
2948 ///
2949 /// @begin HPatchInteractionGraph::set_rotamer_sets
2950 ///
2951 /// @detailed
2952 /// It's nice to be able to print out information about the possible rotamer during initialization of the IG.
2953 /// This method gets called in IGSupport.cc.
2954 ///
2955 template < typename V, typename E, typename G >
2956 void
2958  rotamer_sets_ = new rotamer_set::RotamerSets( rotsets );
2959 }
2960 
2961 
2962 ///
2963 /// @begin HPatchInteractionGraph::initialize()
2964 ///
2965 /// @detailed
2966 /// This function is the 1st major entry point (well, after the constructor) into the HIG. It needs to set residues that
2967 /// are not changing as background residues
2968 ///
2969 /// Oldest comments:
2970 /// In ++, there's a file InteractionGraphSupport.cc which is an analog of the InteractionGraphFactory in mini. In ++,
2971 /// the InteractionGraphSupport file instantiates and initializes, depending on the command line switches, the right
2972 /// interaction graph. For the HPatchInteractionGraph, it first initializes the PDInteractionGraph (which is the base)
2973 /// and then calls the HPatchIG initialize method.
2974 ///
2975 /// The thing is that this initialize method can't be called when the graph is constructed in the InteractionGraphFactory.
2976 /// The reason is that the PDInteractionGraph base initialize() method is NOT called until later in the pack rotamers
2977 /// process. (Actually it's called from within rotsets->compute_energies().) Only after the rotsets->compute energies
2978 /// returns can I stick in an initialize() method call for the HPatchInteractionGraph (HIG). But then that's too late because
2979 /// the rotsets object has already computed some energies. Perhaps that's ok though. The rotsets object only calculates
2980 /// the PD energy terms - it doesn't do anything with non-PD terms.
2981 ///
2982 /// If a HIG init method is called during construction of the HIG, then the init method that's called by the rotsets object
2983 /// causes all the node info that was set in the HIG init method to be lost because the rotsets init method recreates all
2984 /// the nodes in the interaction graph when it runs. (That was a fun behaviour to figure out.)
2985 ///
2986 /// So the solution I'm going for is to call this init method in the prepare for simulated annealing method of this class.
2987 /// That gets called just before SA starts, so it will do the task above then. It doesn't really matter when the
2988 /// task gets done as long as it happens before SA starts. This also means that the HIG will now have to keep a reference
2989 /// to the Pose, the Task, and the RotamerSets objects since it needs all of these things to do tasks 1) and 2).
2990 /// (For the port of this HPatchIG, we might not need the task and rotamer sets objects.)
2991 ///
2992 /// prepare_for_simulated_annealing gets called by the FixbbSA::run() method. Before this method, the
2993 /// rotamersets object has called compute_energies() (the whole process being started in pack_rotamers)
2994 /// which calls initialize() on the IG. I need to place the HIG init method directly after the IG init
2995 /// method that the RS object calls.
2996 ///
2997 /// Newest comments:
2998 /// Don't call the parent classes initialize method because that calls create_new_node for all designable positions, making
2999 /// every node in the graph a first class residue (erroneously!). Then after that, some residues are set as background
3000 /// residues so I'm surprised things were even working at all! Unfortunately, the class hierarchy makes setting designable
3001 /// residues that are surface-exposed be the only FirstClassNodes difficult. What has to happen is that non-designable
3002 /// positions will be the BGNodes and molten positions will be FCNodes. Then, each type of node will store a boolean flagging
3003 /// whether it is surface-exposed or not. Then, when a consider sub call is made, the nodes will immediately check the
3004 /// value of the boolean and return 0 immediately if it's not surface-exposed.
3005 ///
3006 /// 07/16/2008- Unfortunately, I can't just replicate all of the functionality of the parent classes initialize method
3007 /// here because it's different for PDIGs and LMIGs. And some of the their corresponding function calls are not defined
3008 /// in both classes so I get compile errors if I try to do it this way. There are a few possible solutions I could use
3009 /// for the problem of schizophrenic node (nodes which are getting assigned as BG and FC nodes). 1) I could just use
3010 /// Andrew's LFs designation that any designable or packable node is a FC node and any node not being packed or designed
3011 /// is a BGNode. This approach is the easiest to implement but since nodes that are only being packed aren't changing in
3012 /// sequence, their surface score shouldn't be changing so it's an inefficiency. 2) I could change the "create_node"
3013 /// call in this class to return either a Node or BGNode depending on what the packer_task has in it. Then the parent
3014 /// templated IG classes would get the right kind of node. But then, I would have to potentially change the AddtlBGNodesIG
3015 /// class method "setNumResiduesAsBackground" because in that call is a for loop which creates background nodes. This
3016 /// would complicate creating new non-PD terms in mini, because it would be specific for this case (surface). 3) Figure
3017 /// out some OO way of handling the distinction between packable and nonpackable residues. The OO-correct way to do this
3018 /// would probably be to subclass AdditionalBackgroundNodesInteractionGraph to something like
3019 /// SASAExposedNodesInteractionGraph and then make the HPatchInteractionGraph inherit that one. Then
3020 /// "FirstClassNodes" would be nodes that are designable and surface-exposed; all other nodes would be "BackgroundNodes".
3021 ///
3022 /// Since it would require alot of work to write another derived class for probably not that significant (or necessary)
3023 /// performance improvement, I'll just make packable residues be FC nodes also. So continue to call the parent classes
3024 /// initialize() method. Just set residues which are not packable nor designable to BG nodes.
3025 ///
3026 /// Newest Newest comments": The above text was the case for the SurfaceIG. Turns out that we really do want all packable
3027 /// and designable positions to be FC Nodes. So there's no inefficiency here, as was the case for the SurfaceIG.
3028 ///
3029 template < typename V, typename E, typename G >
3031 
3032  /// TEMP!!!!
3033  // APL wants to create a parent/base class for RotamerSets called RotamerSetsBase which will hold variables and functions
3034  // that are common to RotamerSets and FlexbbRotamerSets. Each interaction graph will be passed a RotamerSetsBase object
3035  // to its initialize method, and functions in this class should only access common base-class functions. However,
3036  // this would require changing quite a bit of code and making sure that only base-class RotamerSetsBase methods are used
3037  // here which I'm not interested in doing right now. So we can cast the RotamerSetsBase object to a RotamerSets object
3038  // and use it the way it was previously.
3039  rotamer_set::RotamerSets const & rot_sets( static_cast< rotamer_set::RotamerSets const & > (rot_sets_base) );
3040 
3041 #ifdef FILE_DEBUG
3042  TR_HIG << "initialize() called" << std::endl;
3043  TR_HIG << "calling set_rotamers on " << rotamer_sets().nmoltenres() << " molten residues." << std::endl;
3044 #endif
3045 
3046  // parent refers to AdditionalBackgroundNodesIG; G refers to the templated IG: PD or LMIG
3047  // call the parent initialize() method
3048  G::initialize( rot_sets );
3049 
3050  // save references to the rotamer_set. these get used later to print information about considered subs, for example.
3051  for ( Size ii = 1; ii <= rotamer_sets().nmoltenres(); ++ii ) {
3052  get_hpatch_node( ii )->set_rotamers( rotamer_sets().rotamer_set_for_moltenresidue( ii ) );
3053  }
3054 
3055  // initializes some local variables that translate between the ig enumeration and resid
3056  set_num_residues_in_protein( pose().total_residue() );
3057 
3058  int nbackground = pose().total_residue() - rot_sets.nmoltenres();
3059  set_num_background_residues( nbackground );
3060 
3061  for ( Size ii = 1; ii <= pose().total_residue(); ++ii) {
3062 
3063  // in our case, first class residues are residues that are designable or packable (see notes in function comment).
3064  if ( packer_task().being_packed(ii) || packer_task().being_designed(ii) ) {
3065  // it's probably that being_packed() includes being_designed() so that the conditional needs only to say
3066  // being_packed(), but it'll short circuit the OR if being_packed() is true so it doesn't matter too much.
3067  continue;
3068  } else {
3069  set_residue_as_background_residue( ii );
3070  // init the RotamerDots object that each BGNode keeps for itself with its rotamer info. the line below calls
3071  // the IG method which then calls the BGNode method.
3072  set_background_residue_rotamer_dots( ii, pose().residue(ii) );
3073  }
3074  }
3075 
3076  for ( Size ii = 1; ii <= rotamer_sets().nmoltenres(); ++ii ) {
3077  // when G::initialize is called, we recreate all of the FC Nodes so that index ii in RotamerSets maps to FCNode ii.
3078  rotamer_set::RotamerSetCOP rsop = rotamer_sets().rotamer_set_for_moltenresidue( ii );
3079 
3080 #ifdef FILE_DEBUG
3081  TR_HIG << "initialize: calling set_rotamer_dots_for_node_state for node " << ii << " with rotamers [";
3082 #endif
3083  for ( Size jj = 1; jj <= rsop->num_rotamers(); ++jj ) {
3084  set_rotamer_dots_for_node_state( ii, jj, *(rsop->rotamer( jj )) );
3085  }
3086 #ifdef FILE_DEBUG
3087  TR_HIG << "] " << std::endl;
3088 #endif
3089  }
3090 
3091  //j setup the radii array, indexed by the atom type int. atom index for looking up an extra data type stored in the AtomTypes
3092  //ronj reads the values out of the database file sasa_radii.txt in the extras folder of atom_type_sets and stores the values
3093  //ronj for each atom type into the radii_ member variable. each index of the radii array corresponds to some atom type.
3094  init_SASA_radii_from_database();
3095 
3096 #ifdef FILE_DEBUG
3097  TR_HIG << "initialize_hpatch_ig: DONE with initialization.\n---" << std::endl;
3098 #endif
3099 
3100 }
3101 
3102 
3103 ///
3104 /// @begin HPatchInteractionGraph::create_new_node
3105 ///
3106 /// @brief
3107 /// factory method pattern for instantiation of HPatchNode objects, used by InteractionGraphBase class.
3108 ///
3109 template < typename V, typename E, typename G >
3111 #ifdef FILE_DEBUG
3112  TR_HIG << "create_new_node called with node_index " << node_index << " and num_states " << num_states << std::endl;
3113 #endif
3114  return new HPatchNode< V, E, G >( this, node_index, num_states );
3115 }
3116 
3117 
3118 ///
3119 /// @begin HPatchInteractionGraph::create_new_edge
3120 ///
3121 /// @brief
3122 /// factory method pattern for instantiation of HPatchEdge objects, used by InteractionGraphBase class.
3123 ///
3124 template < typename V, typename E, typename G >
3126 #ifdef FILE_DEBUG
3127  TR_HIG << "create_new_edge() called for indices " << index1 << " and " << index2 << std::endl;
3128 #endif
3129  return new HPatchEdge< V, E, G >( this, index1, index2 );
3130 }
3131 
3132 
3133 ///
3134 /// @begin HPatchInteractionGraph::create_background_node
3135 ///
3136 /// @brief
3137 /// factory method pattern for instantiation of HPatchBackgroundNode objects, used by AdditionalBackgroundNodesInteractionGraph class.
3138 ///
3139 template < typename V, typename E, typename G >
3141 #ifdef FILE_DEBUG
3142  TR_HIG << "create_background_node() called for index " << node_index << std::endl;
3143 #endif
3144  return new HPatchBackgroundNode< V, E, G >( this, node_index );
3145 }
3146 
3147 
3148 ///
3149 /// @begin HPatchInteractionGraph::create_background_edge
3150 ///
3151 /// @brief
3152 /// factory method pattern for instantiation of HPatchBackgroundEdge objects, used by AdditionalBackgroundNodesInteractionGraph class.
3153 ///
3154 template < typename V, typename E, typename G >
3156 #ifdef FILE_DEBUG
3157  TR_HIG << "create_background_edge() called for indices " << fc_node_index << " and " << bg_node_index << std::endl;
3158 #endif
3159  return new HPatchBackgroundEdge< V, E, G >( this, fc_node_index, bg_node_index );
3160 }
3161 
3162 
3163 ///
3164 /// @begin HPatchInteractionGraph::set_num_residues_in_protein
3165 ///
3166 /// @brief
3167 /// tells the graph how many residues there are total in the protein
3168 ///
3169 /// @detailed
3170 /// The graph maintains its own enumeration for the background residues; but asks that anyone wanting to refer to them
3171 /// use their original resid. The graph has to switch back and forth between enumeration schemes and must know how many
3172 /// residues there are total to do that efficiently.
3173 ///
3174 template < typename V, typename E, typename G >
3176 
3177  num_total_residues_ = num_res;
3178  resid_2_bgenumeration_.resize( num_total_residues_ );
3179 
3180  for ( Size ii = 1; ii <= num_total_residues_; ++ii ) {
3181  resid_2_bgenumeration_[ii] = 0;
3182  }
3183 
3184 }
3185 
3186 
3187 ///
3188 /// @begin HPatchInteractionGraph::set_num_background_residues
3189 ///
3190 /// @brief
3191 /// tells the graph how many residues there are as part of the protein that are not part of the combinatorial
3192 /// optimization process -- they are part of the background
3193 ///
3194 /// @detailed
3195 /// The other half of switching between enumeration schemes for the background residues is knowing how many background residues there are.
3196 ///
3197 template < typename V, typename E, typename G >
3199 
3200 #ifdef FILE_DEBUG
3201  TR_HIG << "set_num_background_residues: setting num background residues to " << num_background_residues << std::endl;
3202 #endif
3203 
3204  parent::set_num_background_nodes( num_background_residues );
3205  if ( parent::get_num_background_nodes() == 0)
3206  return;
3207 
3208  bgenumeration_2_resid_.resize( parent::get_num_background_nodes() );
3209  bg_nodes_near_rotsub_.resize( parent::get_num_background_nodes() );
3210  for ( Size ii = 1; ii <= bg_nodes_near_rotsub_.size(); ++ii ) { bg_nodes_near_rotsub_[ ii ] = ii; }
3211  bg_nodes_near_rotsub_bool_.resize( parent::get_num_background_nodes(), true );
3212  bg_exp_hphobe_djs_offsets_.resize( parent::get_num_background_nodes(), 0 );
3213  bg_n_exp_hphobes_.resize( parent::get_num_background_nodes(), 0 );
3214  for ( Size ii = 1; ii <= (Size)parent::get_num_background_nodes(); ++ii ) {
3215  bgenumeration_2_resid_[ii] = 0;
3216  }
3217 }
3218 
3219 
3220 ///
3221 /// @begin HPatchInteractionGraph::set_residue_as_background_residue
3222 ///
3223 /// @brief
3224 /// informs the graph that a particular residue is part of the background
3225 ///
3226 template < typename V, typename E, typename G >
3228 
3229  assert( resid_2_bgenumeration_[ residue ] == 0 );
3230 
3231  ++num_residues_assigned_as_background_;
3232  resid_2_bgenumeration_[ residue ] = num_residues_assigned_as_background_;
3233  bgenumeration_2_resid_[ num_residues_assigned_as_background_ ] = residue;
3234 
3235 #ifdef FILE_DEBUG
3236  TR_HIG << "set_residue_as_background_residue: set residue " << pose().residue( residue ).name3() << " "
3237  << residue << " as background node " << num_residues_assigned_as_background_ << ". bgenumeration_2_resid_: [ ";
3238  for ( Size ii=1; ii <= bgenumeration_2_resid_.size(); ++ii ) {
3239  TR_HIG << bgenumeration_2_resid_[ ii ] << ", ";
3240  }
3241  TR_HIG << " ]" << std::endl;
3242 #endif
3243 
3244 }
3245 
3246 
3247 ///
3248 /// @begin HPatchInteractionGraph::set_background_residue_rotamer_dots
3249 ///
3250 /// @brief
3251 /// Creates and inits a RotamerDots object for a background residue. the residue must first have been declared to be a background residue.
3252 ///
3253 template < typename V, typename E, typename G >
3255 
3256  Size bgid = resid_2_bgenumeration_[ residue ];
3257  // the use of an OP here seems silly. though, storing a reference in a class is not as easy as it sounds.
3258  // it seems like a raw pointer here would make the most sense, since I'm not allocating any memory, but oh well.
3259  conformation::ResidueOP rotamer_op = new conformation::Residue( rotamer ); // calls copy constructor
3260  get_hpatch_bg_node( bgid )->set_rotamer( rotamer_op );
3261 
3262  bool exclude_hydrogens = true;
3263  bool use_expanded_polar_atom_radii = true;
3264  RotamerDots rd( rotamer_op, exclude_hydrogens, use_expanded_polar_atom_radii );
3265  get_hpatch_bg_node( bgid )->set_rotamer_dots( rd );
3266 
3267 }
3268 
3269 
3270 ///
3271 /// @begin HPatchInteractionGraph::set_rotamer_dots_for_node_state
3272 ///
3273 /// @brief
3274 /// store the coordinates for a particular rotamer
3275 ///
3276 template < typename V, typename E, typename G >
3278 
3279  conformation::ResidueOP rotamer_op = new conformation::Residue( rotamer ); // calls copy constructor
3280  bool exclude_hydrogens = true;
3281  bool use_expanded_polar_atom_radii = true;
3282  RotamerDots rd( rotamer_op, exclude_hydrogens, use_expanded_polar_atom_radii );
3283 #ifdef FILE_DEBUG
3284  TR_NODE << state << ":" << rotamer.name1() << "-" << rotamer.seqpos() << ", ";
3285 #endif
3286  get_hpatch_node( node_index )->set_rotamer_dots_for_state( state, rd );
3287 
3288 }
3289 
3290 
3291 ///
3292 /// @begin HPatchInteractionGraph::prepare_for_simulated_annealing
3293 ///
3294 /// @brief
3295 /// Prepares the graph to begin simulated annealing.
3296 ///
3297 /// @detailed
3298 /// Invokes both base-class prepare_for_simulated_annealing subroutines: InteractionGraphBase first, to prepare the
3299 /// HPatchNodes and HPatchEdges. Then the AdditionalBackgroundNodesInteractionGraph, to prepare the HPatchBackgroundNodes,
3300 /// the HPatchBackgroundEdges, and to do a little more preparing of the HPatchNodes.
3301 /// Also computes background/background overlap.
3302 /// This is the 2nd major entry point into the HIG.
3303 ///
3304 /// @remarks
3305 /// As it is written, it should only be executed once; that will change, however if we make HPatchInteractionGraph work
3306 /// with ligands (ligands that stay fixed during any single sim annealing process, but that move between anealings.
3307 ///
3308 template < typename V, typename E, typename G >
3310 
3311  if ( prepared_for_simulated_annealing_ ) {
3312 
3313  // the function below just figures out which nodes and bgnodes to place edges between. this doesn't need to be repeated.
3314  //detect_background_residue_and_first_class_residue_overlap();
3315 
3316  // chains up to the IGBase method which, in turn, calls prep_for_simA() on all the FC Edges, and then all FC nodes.
3317  //G::prepare_for_simulated_annealing();
3318  // Edge::prep_for_simA() drops edges if 1) the two-body energies stored on that node are empty and 2) the incident
3319  // nodes on that edge don't have any sphere overlaps. None of this needs to be redone.
3320  //
3321  // Node::prep_for_simA() updates all the edge vectors in the parent classes (either PDIG or LinMemIG) and then
3322  // initializes the member variable self_and_bg_dots_for_states_. That is a vector1 of RotamerDots objects that contain
3323  // the self overlap each state causes and the overlap that all of that-Nodes-neighboring-BGNodes cause to a state.
3324  // this variable doesn't change during a trajectory so no need to reinitialize it.
3325 
3326  // parent::prepare() calls prep_for_simA() on all the BGEdges and BGNodes. the parent classes edge vectors are updated
3327  // and then initialize self overlap is called. the state on the BGNodes needs to be reinit'd to the point where the
3328  // self overlap and overlap from other bg nodes is stored. BGNode::prep_for_simA() also calls initialize_overlap_cache
3329  // to fill the node_states_coverage_of_bg_res_ vector. That part doesn't really need to be repeated, so it only gets
3330  // done if the BGEdge::prep_for_simA boolean isn't set. The reason we do need to call initialize_overlap_cache() though
3331  // is that the RotamerDotsCache objects get resized (and hence cleared) in that function.
3332  parent::prepare_for_simulated_annealing();
3333 
3334  // this method should get repeated to get BGNodes back to the right state
3335  initialize_bg_bg_overlaps();
3336 
3337  return;
3338  }
3339 
3340  detect_background_residue_and_first_class_residue_overlap();
3341 
3342  // G::prepare() calls InteractionGraphBase::prepare_for_simulated_annealing() - LinmemIG implements one but it also
3343  // calls the IGBase method. The IGBase method, in turn, calls prep_for_simA() on all the FC Edges, and then all FC nodes.
3344  G::prepare_for_simulated_annealing();
3345 
3346  // parent::prepare() calls prep_for_simA() on all the BGNodes
3347  parent::prepare_for_simulated_annealing();
3348 
3349 #ifdef FILE_DEBUG
3350  TR_HIG << "prepare_for_simulated_annealing(): initializing background-background overlap" << std::endl;
3351 #endif
3352 
3353  initialize_bg_bg_overlaps();
3354  initialize_bg_bg_atom_atom_overlaps();
3355 
3356  prepared_for_simulated_annealing_ = true;
3357 
3358 #ifdef FILE_DEBUG
3359  TR_HIG << "prepare_for_simulated_annealing: number edges in graph: " << parent::get_num_edges() << std::endl;
3360 #endif
3361 
3362 }
3363 
3364 
3365 ///
3366 /// @begin HPatchInteractionGraph::detect_background_residue_and_first_class_residue_overlap
3367 ///
3368 /// @brief
3369 /// iterates across all pairs of first- and second-class nodes to determine which share sphere overlaps.
3370 /// Adds a HPatchBackgroundEdge between any pair that do.
3371 ///
3372 template < typename V, typename E, typename G >
3374 
3375  for ( Size ii = 1; ii <= (Size)parent::get_num_background_nodes(); ++ii ) {
3376 
3377 #ifdef FILE_DEBUG
3378  TR_HIG << "detect_bg_and_fc_residue_neighbors: checking for neighbors of background residue " << pose().residue( bgenumeration_2_resid_[ ii ] ).name3()
3379  << " " << pose().residue( bgenumeration_2_resid_[ ii ] ).seqpos() << std::endl;
3380 #endif
3381 
3382  for ( Size jj = 1; jj <= (Size)parent::get_num_nodes(); ++jj ) {
3383 
3384  // ii: background node index, jj: first-class node index
3385  // the background nodes and first-class nodes should be set at this point due to the initalize method above.
3386  // if the background node overlaps with the first-class node, we need to add an edge between them.
3387  if ( get_hpatch_bg_node( ii )->detect_overlap( get_hpatch_node( jj ) ) ) {
3388 #ifdef FILE_DEBUG
3389  TR_HIG << "detect_bg_residue_and_fc_residue_overlap: --- adding FC/BG edge: fc node id:" << jj
3390  << " / bg node: " << ii << ", bg resid:" << bgenumeration_2_resid_[ ii ] << std::endl;
3391 #endif
3392  parent::add_background_edge( jj, ii );
3393  }
3394  }
3395  }
3396 
3397 #ifdef FILE_DEBUG
3398  TR_HIG << "DONE detecting background and first class overlap.\n---" << std::endl;
3399 #endif
3400 
3401 }
3402 
3403 
3404 ///
3405 /// @begin HPatchInteractionGraph::initialize_bg_bg_overlaps
3406 ///
3407 /// @brief
3408 /// computes the background overlaps for all background node pairs
3409 ///
3410 template < typename V, typename E, typename G >
3412 
3413  for ( Size ii = 1; ii <= (Size)parent::get_num_background_nodes(); ++ii ) {
3414  for ( Size jj = ii + 1; jj <= (Size)parent::get_num_background_nodes(); ++jj ) {
3415  // get_hpatch_bg_node() returns a pointer, so we must dereference it to pass it
3416  get_hpatch_bg_node( ii )->initialize_bg_bg_overlap( *get_hpatch_bg_node( jj ) );
3417  }
3418  }
3419 
3420 }
3421 
3422 
3423 ///
3424 /// @begin HPatchBackgroundNode::get_bg_bg_atom_atom_overlaps
3425 ///
3426 //template < typename V, typename E, typename G >
3427 template < typename V, typename E, typename G >
3430 
3431  // only the positions where node2_index is greater than node1_index will have atom-atom overlap information
3432  assert( node1_index < node2_index );
3433 
3434  return bg_bg_atom_atom_overlaps_[ node1_index ][ node2_index ];
3435 
3436 }
3437 
3438 ///
3439 /// @begin HPatchBackgroundNode::initialize_bg_bg_atom_atom_overlaps
3440 ///
3441 /// @brief
3442 /// initializes the atom-atom overlap vector stored by the IG for all the bg-bg node overlaps.
3443 ///
3444 /// @detailed
3445 /// During simulated annealing, the IG has to determine the connected components after every sub. To do this, it has to
3446 /// check a very large number of atom pairs for overlap. These pairs include intra-Node atom-pairs, intra-BGNode atom-pairs,
3447 /// BGNode-BGNode atom-pairs, BGNode-FCNode atom-pairs, and FCNode-FCNode atom-pairs. Now intra-Node/BGNode atom-pairs
3448 /// can be stored on the Nodes and BGNodes. Similarly, BG-Node-FCNode and FCNode-FCNode atom-pairs can be held on the
3449 /// BGEdges and FCEdges, respectively. Unfortunately, edges between BGNodes do not exist in the IG. So, we have to init
3450 /// a vector that will be held by the IG when we initialize the dot counts and sphere overlaps for all the BGNode pairs.
3451 /// The reason we do this is so that we don't have to go and repeat the calculation of all these sphere overlaps after
3452 /// every sub. These will remain constant during the course of a simulation.
3453 ///
3454 /// The hard part is figuring out what kind of data structure I can use here that will make it easy for the IG to get
3455 /// what it needs when it's calculating a score.
3456 ///
3457 /// Making the data structure a 4D vector, i.e. a vector of vectors of vectors of vectors of bools. The outer two vectors
3458 /// are the two bgnode ids we're checking overlap for. The innermost two vectors are the atom-atom overlap information
3459 /// for two given bgnode ids. Only the higher indexed nodes have to contain vectors of vectors of bools. For instance,
3460 /// the outer two vectors will have (1,2), (1,3), (1,4), ... (2,3), (2,4), (2,5), ..., (3,4), (3,5), (3,6), etc
3461 /// The inner two vectors is just an all-atoms-in-ii x all-atoms-in-jj.
3462 ///
3463 template < typename V, typename E, typename G >
3465 
3466  Real const probe_radius = 1.4;
3467 
3468  bg_bg_respairs_w_hphobe_olap_.resize( (Size) parent::get_num_background_nodes() );
3469  bg_bg_atom_atom_overlaps_.resize( (Size) parent::get_num_background_nodes() );
3470  curr_bg_bg_exhpobeolap_.resize( (Size) parent::get_num_background_nodes() );
3471  alt_bg_bg_exhpobeolap_.resize( (Size) parent::get_num_background_nodes() );
3472 
3473  for ( Size bgnode_ii = 1; bgnode_ii <= (Size)parent::get_num_background_nodes(); ++bgnode_ii ) {
3474 
3475  conformation::ResidueCOP bgnode_ii_rotamer = get_hpatch_bg_node( bgnode_ii )->get_rotamer();
3476  Size const ii_natoms = bgnode_ii_rotamer->nheavyatoms();
3477  utility::vector1< Size > const & ii_hphobes( get_hpatch_bg_node( bgnode_ii )->get_hphobes() );
3478 
3479  for ( Size bgnode_jj = bgnode_ii + 1; bgnode_jj <= (Size)parent::get_num_background_nodes(); ++bgnode_jj ) {
3480 
3481  conformation::ResidueCOP bgnode_jj_rotamer = get_hpatch_bg_node( bgnode_jj )->get_rotamer();
3482  Size const jj_natoms = bgnode_jj_rotamer->nheavyatoms();
3483  utility::vector1< Size > const & jj_hphobes( get_hpatch_bg_node( bgnode_jj )->get_hphobes() );
3484 
3485  utility::vector1< utility::vector1< Size > > ii_jj_overlap( ii_natoms, utility::vector1< Size >( jj_natoms, false ) );
3486 
3487  bool any_hphobe_olap = false;
3488  for ( Size ii=1; ii <= ii_hphobes.size(); ++ii ) {
3489  Size const iia = ii_hphobes[ ii ];
3490 
3491  conformation::Atom const & iia_atom( bgnode_ii_rotamer->atom( iia ) );
3492  utility::vector1< Real > const & atom_radii = radii_;
3493  Real const iia_atom_radius = atom_radii[ iia_atom.type() ] + probe_radius; // radii_ is a class member variable
3494 
3495  for ( Size jj=1; jj <= jj_hphobes.size(); ++jj ) {
3496  Size const jja = jj_hphobes[ jj ];
3497 
3498  conformation::Atom const & jja_atom( bgnode_jj_rotamer->atom( jja ) );
3499  Real const jja_atom_radius = atom_radii[ jja_atom.type() ] + probe_radius;
3500 
3501  // check if the two atoms overlap at all; use distance squared over distance to keep things faster.
3502  Vector const & iia_atom_xyz = bgnode_ii_rotamer->atom( iia ).xyz();
3503  Vector const & jja_atom_xyz = bgnode_jj_rotamer->atom( jja ).xyz();
3504 
3505  Real const distance_squared = iia_atom_xyz.distance_squared( jja_atom_xyz );
3506 
3507  if ( distance_squared <= (iia_atom_radius + jja_atom_radius) * (iia_atom_radius + jja_atom_radius) ) {
3508 
3509  Real const distance_ijxyz = std::sqrt( distance_squared );
3510  int degree_of_overlap;
3511  core::scoring::get_overlap( iia_atom_radius, jja_atom_radius, distance_ijxyz, degree_of_overlap );
3512  if ( degree_of_overlap >= 15 ) {
3513 #ifdef FILE_DEBUG
3514  /*TR_HIG << "initialize_bg_bg_atom_atom_overlaps(): overlapping bg-bg atom-atom pair: "
3515  << bgnode_ii_rotamer->seqpos() << "/" << utility::trim( bgnode_ii_rotamer->atom_name( iia ) ) << " - "
3516  << bgnode_jj_rotamer->seqpos() << "/" << utility::trim( bgnode_jj_rotamer->atom_name( jja ) )
3517  << ", degree of overlap: " << degree_of_overlap << std::endl;*/
3518 #endif
3519  ii_jj_overlap[ iia ][ jja ] = true;
3520  any_hphobe_olap = true;
3521  }
3522  } // end if distance
3523  } // for loop over all jj hphobes
3524  } // for loop over all ii hphobes
3525 
3526  if ( any_hphobe_olap ) {
3527  bg_bg_respairs_w_hphobe_olap_[ bgnode_ii ].push_back( bgnode_jj );
3528  bg_bg_atom_atom_overlaps_[ bgnode_ii ].push_back( ii_jj_overlap );
3529  // just get the dimensions right for now, set these values to false later
3530  curr_bg_bg_exhpobeolap_[ bgnode_ii ].push_back( ii_jj_overlap );
3531  alt_bg_bg_exhpobeolap_[ bgnode_ii ].push_back( ii_jj_overlap );
3532  }
3533  } // node_jj
3534  } // node_ii
3535 
3536 
3537 
3538 #ifdef FILE_DEBUG
3539  /*for ( Size bgnode_ii = 1; bgnode_ii <= (Size)parent::get_num_background_nodes(); ++bgnode_ii ) {
3540  TR_HIG << "background nodes overlapping with background node " << bgnode_ii << ": ";
3541  for ( Size jj = 1; jj <= bg_bg_respairs_w_hphobe_olap_[ bgnode_ii ].size(); ++jj ) {
3542  TR_HIG << bg_bg_respairs_w_hphobe_olap_[ bgnode_ii ][ jj ] << ", ";
3543  }
3544  TR_HIG << std::endl;
3545 
3546  for ( Size bgnode_jj = 1; bgnode_jj <= bg_bg_respairs_w_hphobe_olap_[ bgnode_ii ].size(); ++bgnode_jj ) {
3547  TR_HIG << "background node " << bgnode_ii << " x background node " << bg_bg_respairs_w_hphobe_olap_[ bgnode_ii ][ bgnode_jj ] << " overlap: " << std::endl;
3548  for ( Size ii_atom = 1; ii_atom <= bg_bg_atom_atom_overlaps_[ bgnode_ii ][ bgnode_jj ].size(); ++ii_atom ) {
3549  TR_HIG << "bgnode " << bgnode_ii << " atom " << ii_atom << ": [ ";
3550  for ( Size jj_atom = 1; jj_atom <= bg_bg_atom_atom_overlaps_[ bgnode_ii ][ bgnode_jj ][ ii_atom ].size(); ++jj_atom ) {
3551  TR_HIG << bg_bg_atom_atom_overlaps_[ bgnode_ii ][ bgnode_jj ][ ii_atom ][ jj_atom ] << ", ";
3552  }
3553  TR_HIG << "]" << std::endl;
3554  }
3555  TR_HIG << std::endl;
3556  }
3557  TR_HIG << std::endl;
3558  }*/
3559 #endif
3560 
3561 
3562 }
3563 
3564 
3565 ///
3566 /// @begin HPatchInteractionGraph::blanket_assign_state_0
3567 ///
3568 /// @brief
3569 /// assigns state 0 -- the unassigned state -- to all (first class) vertices in the graph
3570 ///
3571 /// @detailed
3572 /// This is the 3rd entry point into the HIG. It is called by the Annealer just before simulated annealing and rotamer
3573 /// substitutions begin to init the graph to unassigned values everywhere.
3574 ///
3575 template < typename V, typename E, typename G >
3577 
3578  for ( Size ii = 1; ii <= (Size)parent::get_num_nodes(); ++ii ) {
3579 #ifdef FILE_DEBUG
3580  TR_HIG << "blanket_assign_state_0() calling assign_zero_state() on node " << ii << std::endl;
3581 #endif
3582  get_hpatch_node( ii )->assign_zero_state();
3583  }
3584 
3585  //update_internal_energy_totals_hpatch();
3586  // instead of calling update_internal, just reset the cached energy values to zero. the values should already be
3587  // at zero because they are default init'd by the constructor to be 0, but the unit tests re-use the same IG and
3588  // just call prep_for_simA() and this method to reinit the IG.
3589 
3590  // Was total_energy_alternate_state_assignment_ intended below as well? ~Labonte
3591  total_energy_current_state_assignment_ = /*total_energy_current_state_assignment_ =*/ 0.0;
3592  hpatch_energy_current_state_assignment_ = hpatch_energy_alternate_state_assignment_ = 0.0;
3593 
3594  /// set all nodes as participating in a rotamer substitution if any node's state is 0 (unassigned)
3595  some_node_in_state_0_ = true;
3596  for ( Size ii = 1; ii <= fc_nodes_near_rotsub_.size(); ++ii ) { fc_nodes_near_rotsub_[ ii ] = ii; }
3597  std::fill( fc_nodes_near_rotsub_bool_.begin(), fc_nodes_near_rotsub_bool_.end(), true );
3598  for ( Size ii = 1; ii <= bg_nodes_near_rotsub_.size(); ++ii ) { bg_nodes_near_rotsub_[ ii ] = ii; }
3599  std::fill( bg_nodes_near_rotsub_bool_.begin(), bg_nodes_near_rotsub_bool_.end(), true );
3600 
3601 }
3602 
3603 
3604 ///
3605 /// @begin HPatchInteractionGraph::update_internal_energy_totals_hpatch
3606 ///
3607 /// @brief
3608 /// After every 2^10 commits, the graph traverses its nodes and edges and
3609 /// re-tallies the total energy of the current state assignment. This update
3610 /// prevents the accumulation of numerical drift, increasing accuracy.
3611 ///
3612 /// @detailed
3613 /// this function becomes less necessary in this implementation since the graph itself calculates the score. no longer do we
3614 /// have the situation where the nodes/bgnodes keep the score and the IG just applies deltaE's every commit. now the IG calculates
3615 /// the score for every consider/commit. the only "drift" that may accumulate would result from not calculating de novo
3616 /// the PD current state energy for a long time. that's why I'm leaving this function in.
3617 ///
3618 template < typename V, typename E, typename G >
3620 
3622 
3623  parent::update_internal_energy_totals();
3624  total_energy_current_state_assignment_ = parent::get_energy_PD_current_state_assignment() + hpatch_energy_current_state_assignment_;
3625 
3626  num_commits_since_last_update_ = 0;
3627 
3628 #ifdef DOUBLE_CHECK_COUNTS
3629  verify_sasas_correct();
3630 #endif
3631 
3632 }
3633 
3634 
3635 #ifdef DOUBLE_CHECK_COUNTS
3636 ///
3637 /// @begin HPatchInteractionGraph::verify_sasas_correct
3638 ///
3639 /// @brief
3640 /// Verifies that the SASAs held on the Nodes and BGNodes are correct. Only runs every 1000 commits and if DOUBLE_CHECK_COUNTS is defined.
3641 ///
3642 /// @detailed
3643 /// Constructs a new Pose object based on the current state of the IG and runs the calc_per_atom_sasa function in sasa.cc
3644 /// as an independent way of making sure that the Nodes and BGNodes are correctly keeping track of SASA. Very slow.
3645 /// Should only be used for testing.
3646 ///
3647 template < typename V, typename E, typename G >
3649 
3650  using namespace ObjexxFCL::fmt;
3651 
3652  utility::vector1< Real > node_sasas( parent::get_num_nodes(), 0.0 );
3653  utility::vector1< Real > bgnode_sasas( parent::get_num_background_nodes(), 0.0 );
3654 
3655  //TR_HIG << "verify_sasas_correct(): Node SASAs: [ ";
3656  for ( Size ii=1; ii <= (Size)parent::get_num_nodes(); ++ii ) {
3657  node_sasas[ ii ] = (get_hpatch_node(ii)->get_current_state_rotamer_dots()).get_sasa();
3658  //TR_HIG << node_sasas[ ii ] << ", ";
3659  }
3660  //TR_HIG << " ]" << std::endl;
3661 
3662  //TR_HIG << "verify_sasas_correct(): BGNode SASAs: [ ";
3663  for ( Size ii=1; ii <= (Size)parent::get_num_background_nodes(); ++ii ) {
3664  bgnode_sasas[ ii ] = (get_hpatch_bg_node(ii)->get_current_state_rotamer_dots()).get_sasa();
3665  //TR_HIG << bgnode_sasas[ ii ] << ", ";
3666  }
3667  //TR_HIG << " ]" << std::endl;
3668 
3669  // create a copy of the passed in pose...
3670  pose::Pose pose_copy = pose();
3671 
3672  // ...and place the current state rotamers on it
3673  for ( core::uint ii = 1; ii <= rotamer_sets().nmoltenres(); ++ii ) {
3674  core::uint iiresid = rotamer_sets().moltenres_2_resid( ii );
3675  core::uint iicurrrot = get_hpatch_node(ii)->get_current_state();
3676  conformation::ResidueCOP bestrot( rotamer_sets().rotamer_set_for_moltenresidue( ii )->rotamer( iicurrrot ) );
3677 
3678  conformation::ResidueOP newresidue( bestrot->create_residue() );
3679  pose_copy.replace_residue( iiresid, *newresidue, false );
3680  }
3681 
3682  Real total_sasa = 0.0;
3683  id::AtomID_Map< Real > atom_sasa;
3684  utility::vector1< Real > rsd_sasa;
3685  Real probe_radius = 1.4;
3686 
3687  // create an atom_subset mask that calculates sasa for heavyatoms and not hydrogens
3688  id::AtomID_Map< bool > atom_subset;
3689  atom_subset.resize( pose_copy.n_residue() );
3690  // init all heavy atoms to true and all H's to false
3691  for ( Size ii=1; ii <= pose_copy.n_residue(); ++ii ) {
3692  atom_subset.resize( ii, pose_copy.residue_type(ii).natoms(), false );
3693  for ( Size jj = 1; jj <= pose_copy.residue_type(ii).nheavyatoms(); ++jj ) {
3694  atom_subset[ ii ][ jj ] = true;
3695  }
3696  }
3697 
3698  total_sasa = core::scoring::calc_per_atom_sasa( pose_copy, atom_sasa, rsd_sasa, probe_radius, false /* no big polar H */, atom_subset, true /* use_naccess_sasa_radii */ );
3699 
3700  bool incorrect_sasa_found = false;
3701 
3702  //TR_HIG << "verify_sasas_correct(): calc_per_atom_sasa Node SASAs: [ ";
3703  for ( Size ii=1; ii <= node_sasas.size(); ++ii ) {
3704  //TR_HIG << rsd_sasa[ rotamer_sets().moltenres_2_resid( ii ) ] << ", ";
3705  if ( fabs( node_sasas[ ii ] - rsd_sasa[ rotamer_sets().moltenres_2_resid( ii ) ] ) > 0.1 )
3706  incorrect_sasa_found = true;
3707  }
3708  //TR_HIG << " ]" << std::endl;
3709 
3710  //TR_HIG << "verify_sasas_correct(): calc_per_atom_sasa BGNode SASAs: [ ";
3711  // all the background nodes should have some value for SASA
3712  for ( Size ii=1; ii <= bgnode_sasas.size(); ++ii ) {
3713  //TR_HIG << rsd_sasa[ bg_node_2_resid( ii ) ] << ", ";
3714  if ( fabs( bgnode_sasas[ ii ] - rsd_sasa[ bg_node_2_resid( ii ) ] ) > 0.1 )
3715  incorrect_sasa_found = true;
3716  }
3717  //TR_HIG << " ]" << std::endl;
3718 
3719  if ( incorrect_sasa_found )
3720  utility_exit_with_message( "SASA values are out of sync. Something is wrong. Quitting." );
3721 
3722  TR_HIG << "verify_sasas_correct() called. and checked out" << std::endl;
3723 
3724 }
3725 #endif
3726 
3727 ///
3728 /// @begin HPatchInteractionGraph::set_errorfull_deltaE_threshold
3729 ///
3730 /// @brief
3731 /// Allows the sim-annealer to specify a deltaE threshold above which, it is no longer necessary to be very accurate.
3732 ///
3733 /// @detailed
3734 /// When the annealer asks the graph to consider a state substitution that produces a large collision, the graph may
3735 /// approximate the hpatch deltaE instead of performing expensive sphere overlap computations. The deltaE returned by
3736 /// consider_substitution() will be inaccurate, but if the annealer is unlikely to accept the substitution, then time
3737 /// can be saved. The graph guarantees that if the annealer does commit that substitution that it will go back and
3738 /// perform the hpatch computations and return an accurate total energy for the graph.
3739 ///
3740 template < typename V, typename E, typename G >
3742 
3743 #ifdef FILE_DEBUG
3744  TR_HIG << "set_errorfull_deltaE_threshold: setting threshold to " << deltaE << std::endl;
3745  // leave this inside since it's debugging output
3747 #endif
3749 
3751  deltaE_threshold_for_avoiding_hpatch_calcs_ = deltaE;
3752 
3753 }
3754 
3755 
3756 ///
3757 /// @begin HPatchInteractionGraph::print_hpatch_avoidance_stats
3758 ///
3759 /// @brief
3760 /// reports on the level of success for hpatch score calculation procrastination
3761 ///
3762 template < typename V, typename E, typename G >
3764 
3765  if ( num_state_substitutions_considered_ == 0 )
3766  return;
3767 
3768  TR_STATS << "num state substitutions considered: " << num_state_substitutions_considered_ << ", "
3769  << "num hpatch calcs procrastinated: " << num_hpatch_comps_procrastinated_ << ", "
3770  << "num hpatch calcs later computed: " << num_hpatch_comps_later_made_ << std::endl;
3771  TR_STATS << "Percent Avoided: " << (double) (num_hpatch_comps_procrastinated_ - num_hpatch_comps_later_made_) / num_state_substitutions_considered_ << ", ";
3772 
3773  if ( num_hpatch_comps_procrastinated_ != 0 ) {
3774  TR_STATS << "Worthwhile Procrastination: " << (double) (num_hpatch_comps_procrastinated_ - num_hpatch_comps_later_made_) / num_hpatch_comps_procrastinated_ << std::endl;
3775  } else {
3776  TR_STATS << "Worthwhile Procrastination: " << "N/A" << std::endl;
3777  }
3778 
3779 }
3780 
3781 ///
3782 /// @begin HPatchInteractionGraph::reset_hpatch_avoidance_stats
3783 ///
3784 /// @brief
3785 /// resets static member variables of HPatchIG that measure how worthwhile hpatch calculation procrastination is.
3786 ///
3787 template < typename V, typename E, typename G >
3789  num_state_substitutions_considered_ = 0;
3790  num_hpatch_comps_procrastinated_ = 0;
3791  num_hpatch_comps_later_made_ = 0;
3792 }
3793 
3794 
3795 ///
3796 /// @begin HPatchInteractionGraph::consider_substitution
3797 ///
3798 /// @brief
3799 /// Returns the (possibly approximate) change in energy induced by switching a particular node from its currently assigned state to some alternate state.
3800 ///
3801 /// @detailed
3802 /// First, queries the HPatchNode for the pairwise-decomposable (PD) energy. If the PD difference
3803 /// implies a collision, then the HPatchIG pretends as if the state substitution causes the best
3804 /// improvement possible in hpatch score, and returns the PD difference + pretend hpatch difference.
3805 /// It will procrastinate computing the actual hpatch score difference until the guiding SimAnnealer
3806 /// decides to commit the substitution. If the SimAnnealer rejects the substitution, then the work
3807 /// to compute the hpatch score is never done. If it is unclear that the SimAnnealer will reject the
3808 /// substitution based on the PD difference, then the Graph goes ahead and computes the change in hpatch
3809 /// score accurately.
3810 ///
3811 /// This function is the 4th major entry point from the Annealer into the HIG.
3812 ///
3813 /// Also returns the sum of the two body energies for the node in its current state; the sim-annealer accepts state
3814 /// substitutions at higher chance if the original state was also at a poor energy.
3815 ///
3816 /// @param
3817 /// node_ind - [in] - the index of the (first class) node
3818 /// new_state - [in] - the alternate state that the node should consider
3819 /// delta_energy - [out] - the change in energy induced on the entire graph by substituting a node's current state with the alternate.
3820 /// This energy may be inaccurate if it exceeds a threshold set by the sim-annealer.
3821 /// prev_energy_for_node - [out] - the sum of the pair-wise decomposable portion of the energy function for the node's currently assigned state
3822 ///
3823 ///
3824 template < typename V, typename E, typename G >
3825 void HPatchInteractionGraph< V, E, G >::consider_substitution( int node_ind, int new_state, core::PackerEnergy & delta_energy, core::PackerEnergy & prev_energy_for_node ) {
3826 
3827  //std::cerr << "Considering substitution at node " << node_ind << std::endl;
3828 
3829  reset_from_previous_deltaHpatch_comp();
3830 
3831 #ifdef FILE_DEBUG
3832  TR_HIG << "---" << std::endl;
3833  TR_HIG << "consider_substitution(): trying new state " << new_state << " ("
3834  << get_hpatch_node( node_ind )->get_rotamer( new_state )->name() << ") on node/molten res " << node_ind << " (wt: "
3835  << pose().residue( rotamer_sets().moltenres_2_resid( node_ind ) ).name3() << " " << rotamer_sets().moltenres_2_resid( node_ind ) << ") " << std::endl;
3836 #endif
3837 
3838  ++num_state_substitutions_considered_;
3839 
3840  node_considering_alt_state_ = node_ind;
3841  alt_state_being_considered_ = new_state;
3842 
3843  // the below deltaE may be an estimate of the change in energy and not the actual value
3844  core::PackerEnergy deltaE = get_hpatch_node( node_ind )->calculate_PD_deltaE_for_substitution( new_state, prev_energy_for_node );
3845 
3846  calculated_hpatch_deltaE_ = false;
3847 
3848  if ( decide_procrastinate_hpatch_computations( deltaE, deltaE_threshold_for_avoiding_hpatch_calcs_ ) ) {
3849  //TR_HIG << "procrastinated" << std::endl;
3850  ++num_hpatch_comps_procrastinated_;
3851  } else {
3852 #ifdef FILE_DEBUG
3853  TR_HIG << "deltaE for PD: " << deltaE << std::endl;
3854 #endif
3855  deltaE += calculate_hpatch_deltaE();
3856  calculated_hpatch_deltaE_ = true;;
3857  }
3858 
3859  delta_energy = deltaE;
3860  total_energy_alternate_state_assignment_ = deltaE + total_energy_current_state_assignment_;
3861 
3862 #ifdef FILE_DEBUG
3863  TR_HIG << "total deltaE for substitution: " << delta_energy << std::endl;
3864 #endif
3865 
3866 }
3867 
3868 
3869 ///
3870 /// @begin HPatchInteractionGraph< V, E, G >::calculate_hpatch_deltaE()
3871 ///
3872 /// @detailed
3873 /// Goes through the entire process of calculating the hpatch deltaE for a substitution.
3874 ///
3875 template < typename V, typename E, typename G >
3877 
3878  // update the sasa information on all the relevant nodes and bg nodes
3879 #ifndef FILE_DEBUG
3880  get_hpatch_node( node_considering_alt_state_ )->consider_alternate_state(); // don't assign deltaSASA to a variable
3881 #else
3882  Real delta_sasa = get_hpatch_node( node_considering_alt_state_ )->consider_alternate_state();
3883  if ( delta_sasa != 0.0 ) {
3884  TR_HIG << "delta sasa: " << delta_sasa << std::endl;
3885  }
3886 #endif
3887 
3888  // determine the new patch score given the updated sasa information
3889  hpatch_energy_alternate_state_assignment_ = calculate_alt_state_hpatch_score();
3890  core::PackerEnergy hpatch_deltaE = hpatch_energy_alternate_state_assignment_ - hpatch_energy_current_state_assignment_;
3891 #ifdef FILE_DEBUG
3892  TR_HIG << "hpatchE current state: " << hpatch_energy_current_state_assignment_
3893  << ", alt state: " << hpatch_energy_alternate_state_assignment_ << ", hpatch deltaE: " << hpatch_deltaE << std::endl;
3894 #endif
3895 
3896  return hpatch_deltaE;
3897 }
3898 
3899 template < typename V, typename E, typename G >
3901 {
3902  some_node_in_state_0_ = true;
3903 }
3904 
3905 
3906 ///
3907 /// @begin HPatchInteractionGraph::register_fc_node_affected_by_rotsub()
3908 ///
3909 /// @brief
3910 /// Called by HPatchNodes to specify which first-class Nodes are affected by a given rotamer substitution. If a given
3911 /// consider gets rejected, then fc_nodes_near_rotsub_ gets cleared when reset_from_previous_deltaHpatch_comp.
3912 ///
3913 template < typename V, typename E, typename G >
3915  if ( ! fc_nodes_near_rotsub_bool_[ fc_node_ind ] ) {
3916  fc_nodes_near_rotsub_.push_back( fc_node_ind );
3917  fc_nodes_near_rotsub_bool_[ fc_node_ind ] = true;
3918  }
3919 }
3920 
3921 template < typename V, typename E, typename G >
3923  if ( ! bg_nodes_near_rotsub_bool_[ bg_node_ind ] ) {
3924  bg_nodes_near_rotsub_.push_back( bg_node_ind );
3925  bg_nodes_near_rotsub_bool_[ bg_node_ind ] = true;
3926  }
3927 }
3928 
3929 
3930 ///
3931 /// @begin HPatchInteractionGraph::init_SASA_radii_from_database()
3932 ///
3933 /// @brief
3934 /// Puts the SASA radii values in the database into the passed in radii array. Temporary location. Should only be done once.
3935 ///
3936 template < typename V, typename E, typename G >
3938 
3939  core::chemical::AtomTypeSet const & atom_type_set = pose().residue(1).atom_type_set();
3940  radii_.resize( atom_type_set.n_atomtypes(), 0.0 );
3941 
3942  core::Size SASA_RADIUS_INDEX = atom_type_set.extra_parameter_index( "NACCESS_SASA_RADIUS" );
3943  for ( core::Size ii=1; ii <= radii_.size(); ++ii ) {
3944  radii_[ii] = atom_type_set[ii].extra_parameter( SASA_RADIUS_INDEX );
3945  }
3946 
3947  initialized_SASA_radii = true;
3948 }
3949 
3950 
3951 ///
3952 /// @begin HPatchInteractionGraph::update_disjoint_sets_using_cache()
3953 ///
3954 /// @brief
3955 /// Helper function for calculating the hpatch score. This function is specific for intra-residue overlaps, the one
3956 /// below is for inter-residue overlaps. The reason they're separate is because the inner loops have different start locations.
3957 /// intra-residue nested loops only have to go over greater-indexed atoms because of commutativity. inter-residue nested
3958 /// loops have to do all ii-res x jj-res atom-atom overlaps.
3959 template < typename V, typename E, typename G >
3961  conformation::Residue const &, // rsd,
3962  InvRotamerDots const & invdots,
3963  utility::vector1< Size > const & exp_hphobes,
3964  Size residue_djs_offset,
3965  utility::vector1< utility::vector1< bool > > const & atom_atom_overlaps,
3966  graph::DisjointSets & ds
3967 ) {
3968 
3969  for ( Size ii=1, iiend = exp_hphobes.size(); ii <= iiend; ++ii ) {
3970 
3971  Size const iia = exp_hphobes[ii];
3972  Size const ii_djs_id = residue_djs_offset + ii;
3973 
3974  // start iterating jja from iia + 1!
3975  // for intra-residue atom pairs, the entries below and on the diagonal are not necessary
3976  for ( Size jj = ii + 1; jj <= iiend; ++jj ) {
3977  Size const jja( exp_hphobes[jj] );
3978  Size const jj_djs_id = residue_djs_offset + jj;
3979 
3980  if ( atom_atom_overlaps[ iia ][ jja ] ) {
3981 
3982  /*TR_HIG << "update_disjoint_sets_using_cache(): overlapping atom pair: "
3983  << rsd.aa() << " " << node_index << "/" << utility::trim( rsd.atom_name( iia ) ) << " - "
3984  << rsd.aa() << " " << node_index << "/" << utility::trim( rsd.atom_name( jja ) ) << std::endl;
3985 
3986  Real const ii_rad = RotamerDots::radius_for_attype( rsd.atom(iia).type() ) + 1.4;
3987  Real const jj_rad = RotamerDots::radius_for_attype( rsd.atom(jja).type() ) + 1.4;
3988  if ( rsd.xyz( iia ).distance_squared( rsd.xyz( jja ) ) > (ii_rad+jj_rad)*(ii_rad+jj_rad) ) {
3989  std::cerr << "ERROR discrepancy between atom_atom_overlaps array and actual overlap information" << std::endl;
3990  std::cerr << "rsd.seqpos() " << rsd.seqpos() << std::endl;
3991  std::cerr << "Atom ii= " << iia << " rad: " << ii_rad << " Atom jj= " << jja << " rad: " << jj_rad << " sum: " << ii_rad+jj_rad << std::endl;
3992  std::cerr << "Distance " << rsd.xyz(iia).distance( rsd.xyz(jja) ) << std::endl;
3993  }*/
3994 
3995  if ( ds.ds_find( ii_djs_id ) == ds.ds_find( jj_djs_id ) ) continue; // fast
3996  if ( ! invdots.atom_overlap_is_exposed( iia, jja ) ) continue; // slow
3997  ds.ds_union( ii_djs_id, jj_djs_id);
3998  }
3999  }
4000  }
4001 
4002  return;
4003 }
4004 
4005 
4006 ///
4007 /// @begin HPatchInteractionGraph::update_disjoint_sets_using_cache()
4008 ///
4009 /// @brief
4010 /// Helper function for calculating the hpatch score.
4011 ///
4012 template < typename V, typename E, typename G >
4014  conformation::Residue const & , // rsd1,
4015  InvRotamerDots const & invdots1,
4016  utility::vector1< Size > const & exp_hphobes1,
4017  Size djs_offset_1,
4018  conformation::Residue const & , // rsd2,
4019  InvRotamerDots const & invdots2,
4020  utility::vector1< Size > const & exp_hphobes2,
4021  Size djs_offset_2,
4022  utility::vector1< utility::vector1< bool > > const & atom_atom_overlaps,
4023  graph::DisjointSets & ds
4024 )
4025 {
4026 
4027  for ( Size ii=1, iiend = exp_hphobes1.size(), jjend = exp_hphobes2.size(); ii <= iiend; ++ii ) {
4028  Size const iia = exp_hphobes1[ ii ];
4029  Size const ii_djs_index = djs_offset_1 + ii;
4030 
4031  //TR_HIG << "update_disjoint_sets_using_cache: iia: " << iia << std::endl;
4032  // start iterating jja from 1! this are inter-residue atom pairs so all of them are important
4033 
4034  for ( Size jj = 1; jj <= jjend; ++jj ) {
4035  Size const jja = exp_hphobes2[ jj ];
4036  Size const jj_djs_index = djs_offset_2 + jj;
4037 
4038  //TR_HIG << "\tupdate_disjoint_sets_using_cache: jja: " << jja << std::endl;
4039  if ( atom_atom_overlaps[ iia ][ jja ] ) {
4040 
4041  /*TR_HIG << "update_disjoint_sets_using_cache(): overlapping atom pair: "
4042  << rsd1.aa() << " " << rsd1.seqpos() << "/" << utility::trim( rsd1.atom_name( iia ) ) << " - "
4043  << rsd2.aa() << " " << rsd2.seqpos() << "/" << utility::trim( rsd2.atom_name( jja ) ) << std::endl;
4044 
4045  //Real const ii_rad = RotamerDots::radius_for_attype( rsd1.atom(iia).type() ) + 1.4;
4046  //Real const jj_rad = RotamerDots::radius_for_attype( rsd2.atom(jja).type() ) + 1.4;
4047 
4048  Real const ii_rad = RotamerDots::epradius_for_attype( rsd1.atom(iia).type() ) + 1.4;
4049  Real const jj_rad = RotamerDots::epradius_for_attype( rsd2.atom(jja).type() ) + 1.4;
4050 
4051  if ( rsd1.xyz( iia ).distance_squared( rsd2.xyz( jja ) ) > (ii_rad + jj_rad) * (ii_rad + jj_rad) ) {
4052  std::cerr << "ERROR discrepancy between atom_atom_overlaps array and actual overlap information" << std::endl;
4053  std::cerr << "rsd1.seqpos() " << rsd1.seqpos() << std::endl;
4054  std::cerr << "rsd2.seqpos() " << rsd2.seqpos() << std::endl;
4055  std::cerr << "Atom ii= " << iia << " rad: " << ii_rad << " Atom jj= " << jja << " rad: " << jj_rad << " sum: " << ii_rad+jj_rad << std::endl;
4056  std::cerr << "Distance " << rsd1.xyz(iia).distance( rsd2.xyz(jja) ) << std::endl;
4057  std::cerr << "Distance swapped? ";
4058  if ( iia <= rsd2.natoms() && jja <= rsd1.natoms() ) {
4059  std::cerr << rsd2.xyz(iia).distance( rsd1.xyz(jja) ) << " w/ iirad = " <<
4060  RotamerDots::radius_for_attype( rsd2.atom(iia).type() ) + 1.4 << " and jjrad = " <<
4061  RotamerDots::radius_for_attype( rsd1.atom(jja).type() ) + 1.4 << " sum: " <<
4062  RotamerDots::radius_for_attype( rsd2.atom(iia).type() ) + 1.4 + RotamerDots::radius_for_attype( rsd1.atom(jja).type() ) + 1.4;
4063  }
4064  std::cerr << std::endl;
4065 
4066  }*/
4067 
4068  if ( ds.ds_find( ii_djs_index ) == ds.ds_find( jj_djs_index ) ) continue; // fast
4069  if ( ! invdots1.atom_overlap_is_exposed( iia, invdots2, jja ) ) continue; // slow
4070  ds.ds_union( ii_djs_index, jj_djs_index );
4071  }
4072  }
4073  }
4074 
4075  return;
4076 }
4077 
4078 
4079 ///
4080 /// @begin HPatchInteractionGraph::calculate_alt_state_hpatch_score()
4081 ///
4082 /// @brief
4083 /// Constructs an atom-level graph for the alternate state assignment on the IG and then runs the union-find algorithm on
4084 /// it to obtain the connected components. Each connected component is a surface hydrophobic patch. What the total energy
4085 /// of the IG should be hasn't yet been decided. One possibility will be to assign every CC/patch a score and return the
4086 /// sum as the total score.
4087 ///
4088 /// Queries all of the Nodes and BGNodes to determine the connectivity assuming the alternate state.
4089 ///
4090 template < typename V, typename E, typename G >
4092 
4093  // any_vertex_state_unassigned() is an O(N) operation -- only perform this check if a few times
4094  // at the beginning of simA
4095  if ( some_node_in_state_0_ && parent::any_vertex_state_unassigned() )
4096  return 0.0; // don't bother running union-find if any of the nodes are still unassigned
4097 
4098  some_node_in_state_0_ = false;
4099 
4100  if ( !initialized_SASA_radii ) {
4101  // setup radii array, temporarily located here
4102  //j setup the radii array, indexed by the atom type int. atom index for looking up an extra data type stored in the AtomTypes
4103  //ronj reads the values out of the database file sasa_radii.txt in the extras folder of atom_type_sets and stores the values
4104  //ronj for each atom type into the radii array. each index of the radii array corresponds to some atom type.
4105  init_SASA_radii_from_database();
4106  }
4107 
4108  // Figure out how many exposed hydrophobic atoms exist in the structure, and create a mapping between
4109  // these exp-hphobes and indices for nodes in a disjoint-sets data structure.
4110  // Determining this value so we can init the DisjointSets object with that number of "nodes". Instead of init'ing it to ALL
4111  // heavyatoms in a pose, init it to just all exposed hydrophobic atoms.
4112 
4113  Size tot_exp_hphobes( 0 ); // stands for total number of exposed hydrophobic ATOMS
4114  djs_id_2_hphobe_index_.clear(); // is a vector1 of exposed_hydrophobic_data structs
4115 
4116  for ( Size ii = 1; ii <= (Size) parent::get_num_nodes(); ++ii ) {
4117  fc_exp_hphobe_djs_offsets_[ ii ] = tot_exp_hphobes; // fc node 1 will have an offset of 0, node 2 will have offset however many exposed hp atoms node 1 has, etc
4118 
4119  // get the number of exposed hp atoms on this fc node. the number depends on whether this node is near the node considering substitution.
4120  Size ii_n_exhphobes( fc_nodes_near_rotsub_bool_[ ii ] ? get_hpatch_node( ii )->n_alt_state_exp_hphobes() : get_hpatch_node( ii )->n_curr_state_exp_hphobes() );
4121  fc_n_exp_hphobes_[ ii ] = ii_n_exhphobes;
4122 
4123  tot_exp_hphobes += ii_n_exhphobes;
4124  for ( Size jj = 1; jj <= ii_n_exhphobes; ++jj ) {
4125  // exposed_hydrophobic_data is a struct; 1 indicates first-class node, ii and jj are the node id and index into the exp hp atoms vector respectively
4126  djs_id_2_hphobe_index_.push_back( exposed_hydrophobic_data( 1, ii, jj ) );
4127  }
4128  }
4129 
4130  for ( Size ii = 1; ii <= (Size) parent::get_num_background_nodes(); ++ii ) {
4131  bg_exp_hphobe_djs_offsets_[ ii ] = tot_exp_hphobes;
4132 
4133  // get the number of exposed hp atoms on this bg node.
4134  Size ii_n_exhphobes( bg_nodes_near_rotsub_bool_[ ii ] ? get_hpatch_bg_node( ii )->n_alt_state_exp_hphobes() : get_hpatch_bg_node( ii )->n_curr_state_exp_hphobes() );
4135  bg_n_exp_hphobes_[ ii ] = ii_n_exhphobes;
4136 
4137  tot_exp_hphobes += ii_n_exhphobes;
4138  for ( Size jj = 1; jj <= ii_n_exhphobes; ++jj ) {
4139  // exposed_hydrophobic_data is a struct; 2 indicates background node, ii and jj are the node id and index into the exp hp atoms vector respectively
4140  djs_id_2_hphobe_index_.push_back( exposed_hydrophobic_data( 2, ii, jj ) );
4141  }
4142  }
4143 
4144  //sasa_for_djs_node_.resize( tot_exp_hphobes );
4145  ep_sasa_for_djs_node_.resize( tot_exp_hphobes );
4146 
4147  // now fill in the values for the ep_sasa_for_djs_node_ array. instead of storing the SASA/EPSASA for all heavy atoms in
4148  // the pose, the exposed hp vectors allow us to only store the SASA/EPSASA of exposed hydrophobic atoms. Uses less memory,
4149  // and is much faster to do operations on. Remember a djs node is really an exposed hydrophobic atom.
4150  for ( Size ii = 1; ii <= (Size) parent::get_num_nodes(); ++ii ) {
4151  Size const ii_offset = fc_exp_hphobe_djs_offsets_[ ii ];
4152  Size const ii_n_exhphobes( fc_n_exp_hphobes_[ ii ] ); // not strictly necessary but this allows for preventing vector resize operations
4153  utility::vector1< Size > const & ii_exhphobes( fc_nodes_near_rotsub_bool_[ ii ] ? get_hpatch_node( ii )->alt_state_exp_hphobes() : get_hpatch_node( ii )->curr_state_exp_hphobes() );
4154 
4155  // for the number of exposed hp atoms, get the atom index from the ii_exhphobes vector and convert the atom index
4156  // to a djs node id by adding the offset for first-class node ii
4157  for ( Size jj = 1; jj <= ii_n_exhphobes; ++jj ) {
4158  Size const jj_atom = ii_exhphobes[ jj ];
4159  Size const jj_djs_node_id = ii_offset + jj;
4160  //sasa_for_djs_node_[ jj_djs_node_id ] = get_hpatch_node( ii )->get_alt_state_rotamer_dots().get_atom_sasa( jj_atom );
4161  ep_sasa_for_djs_node_[ jj_djs_node_id ] = get_hpatch_node( ii )->get_alt_state_rotamer_dots().get_atom_sasa( jj_atom );
4162  }
4163  }
4164 
4165  for ( Size ii = 1; ii <= (Size) parent::get_num_background_nodes(); ++ii ) {
4166  Size const ii_offset = bg_exp_hphobe_djs_offsets_[ ii ];
4167  Size const ii_n_exhphobes( bg_n_exp_hphobes_[ ii ] );
4168  utility::vector1< Size > const & ii_exhphobes( bg_nodes_near_rotsub_bool_[ ii ] ? get_hpatch_bg_node( ii )->alt_state_exp_hphobes() : get_hpatch_bg_node( ii )->curr_state_exp_hphobes() );
4169 
4170  for ( Size jj = 1; jj <= ii_n_exhphobes; ++jj ) {
4171  Size const jj_atom = ii_exhphobes[ jj ];
4172  Size const jj_djs_node_id = ii_offset + jj;
4173  //sasa_for_djs_node_[ jj_djs_node_id ] = get_hpatch_bg_node( ii )->get_alt_state_rotamer_dots().get_atom_sasa( jj_atom );
4174  ep_sasa_for_djs_node_[ jj_djs_node_id ] = get_hpatch_bg_node( ii )->get_alt_state_rotamer_dots().get_atom_sasa( jj_atom );
4175  }
4176  }
4177 
4178  // the above loops have determined the number of exposed hydrophobic atoms that are present. now init the disjointsets object.
4179  graph::DisjointSets ds( tot_exp_hphobes );
4180 
4181  // intra-residue connections
4182  for ( Size ii = 1; ii <= (Size)parent::get_num_nodes(); ++ii ) {
4183  if ( fc_n_exp_hphobes_[ ii ] == 0 ) continue;
4184 
4185  conformation::ResidueCOP rsd( ii == node_considering_alt_state_ ? get_hpatch_node( ii )->curr_state_rotamer() : get_hpatch_node( ii )->alt_state_rotamer() );
4186  Size const ii_state = ( ii == node_considering_alt_state_ ? alt_state_being_considered_ : get_hpatch_node( ii )->get_current_state() );
4187  utility::vector1< utility::vector1< bool > > const & atom_atom_self_overlaps = get_hpatch_node( ii )->get_atom_atom_self_overlaps_for_state( ii_state );
4188  utility::vector1< Size > const & ii_exhphobes( fc_nodes_near_rotsub_bool_[ ii ] ? get_hpatch_node( ii )->alt_state_exp_hphobes() : get_hpatch_node( ii )->curr_state_exp_hphobes() );
4189 
4190  update_disjoint_sets_using_cache( *rsd, get_hpatch_node( ii )->alt_state_inv_dots(), ii_exhphobes, fc_exp_hphobe_djs_offsets_[ ii ], atom_atom_self_overlaps, ds );
4191 
4192  }
4193  for ( Size ii = 1; ii <= (Size) parent::get_num_background_nodes(); ++ii ) {
4194  if ( bg_n_exp_hphobes_[ ii ] == 0 ) continue;
4195 
4196  utility::vector1< Size > const & ii_exp_hphobes( get_hpatch_bg_node( ii )->alt_state_exp_hphobes() );
4197  conformation::Residue const & ii_rsd( * get_hpatch_bg_node( ii )->get_rotamer() );
4198  utility::vector1< utility::vector1< bool > > const & atom_atom_self_overlaps = get_hpatch_bg_node( ii )->get_atom_atom_self_overlaps();
4199 
4200  update_disjoint_sets_using_cache( ii_rsd, get_hpatch_bg_node( ii )->alt_state_inv_dots(), ii_exp_hphobes, bg_exp_hphobe_djs_offsets_[ ii ], atom_atom_self_overlaps, ds );
4201  }
4202 
4203 
4204  /// For all of the inter-residue connections, we have a vector of ints that's stored on each of the Nodes and BGNodes.
4205  /// The vector specifies which atom indexes in that ResidueType are carbon or sulfur atoms *and* are exposed. Then,
4206  /// when iterating over all atom-atom pairs, we don't have to check each time to see if an atom is hydrophobic and
4207  /// exposed. We end up never even visiting the polar atoms which is awesome.
4208 
4209  // bgnode-bgnode connections
4210  // apl -- why not keep a graph?
4211  for ( Size ii = 1; ii <= (Size) parent::get_num_background_nodes(); ++ii ) {
4212  if ( bg_n_exp_hphobes_[ ii ] == 0 ) continue;
4213  if ( bg_bg_respairs_w_hphobe_olap_[ ii ].size() == 0 ) continue;
4214 
4215  Size const ii_djs_offset = bg_exp_hphobe_djs_offsets_[ ii ];
4216 
4217  conformation::Residue const & ii_rsd( * get_hpatch_bg_node( ii )->get_rotamer() );
4218  utility::vector1< Size > const & ii_exp_hphobes( get_hpatch_bg_node( ii )->alt_state_exp_hphobes() );
4219 
4220  // instead of iterating over all higher-indexed background nodes, only iterate over the ones that bgnode ii has overlap with.
4221  // this can be a significant time savings if there are alot of bgnodes in a simulation.
4222  for ( Size jj = 1; jj <= bg_bg_respairs_w_hphobe_olap_[ ii ].size(); ++jj ) {
4223 
4224  // all of the vectors are indexed on node id - not on the value of jj!
4225  // not true. bg_bg_respairs_w_hphobe_olap_ and bg_bg_atom_atom_overlaps_ are indexed on jj, not the node id
4226  Size jj_bg_node_ind = bg_bg_respairs_w_hphobe_olap_[ ii ][ jj ];
4227 
4228  // bg_bg_respairs_w_hphobe_olap_ holds the bg node ids. bg_bg_respairs_w_hphobe_olap_[ii][jj] will be the bg node id
4229  // that has overlap with bgnode ii.
4230  //if ( bg_n_exp_hphobes_[ jj ] == 0 ) continue;
4231  if ( bg_n_exp_hphobes_[ jj_bg_node_ind ] == 0 ) continue; // bg_n_exp_hphobes_ is indexed on node id, not jj
4232 
4233  //Size const jj_djs_offset = bg_exp_hphobe_djs_offsets_[ ii ];
4234  Size const jj_djs_offset = bg_exp_hphobe_djs_offsets_[ jj_bg_node_ind ];
4235 
4236  conformation::Residue const & jj_rsd( * get_hpatch_bg_node( jj_bg_node_ind )->get_rotamer() );
4237  utility::vector1< Size > const & jj_exp_hphobes( get_hpatch_bg_node( jj_bg_node_ind )->alt_state_exp_hphobes() );
4238 
4239  utility::vector1< utility::vector1< bool > > const & atom_atom_overlaps = bg_bg_atom_atom_overlaps_[ ii ][ jj ];
4240 
4241 #ifdef FILE_DEBUG
4242  /*TR_HIG << "bg_bg_respairs_w_hphobe_olap_: [ ";
4243  for ( Size aa = 1; aa <= bg_bg_respairs_w_hphobe_olap_[ ii ].size(); ++aa ) {
4244  TR_HIG << bg_bg_respairs_w_hphobe_olap_[ ii ][ aa ] << ", ";
4245  }
4246  TR_HIG << "]" << std::endl;
4247 
4248  TR_HIG << "ii_exp_hphobes: [ ";
4249  for ( Size aa = 1; aa <= ii_exp_hphobes.size(); ++aa ) {
4250  TR_HIG << ii_exp_hphobes[ aa ] << ", ";
4251  }
4252  TR_HIG << "]" << std::endl;
4253 
4254  TR_HIG << "jj_exp_hphobes: [ ";
4255  for ( Size aa = 1; aa <= jj_exp_hphobes.size(); ++aa ) {
4256  TR_HIG << jj_exp_hphobes[ aa ] << ", ";
4257  }
4258  TR_HIG << "]" << std::endl;
4259 
4260  TR_HIG << "background node " << ii << " x background node " << jj_bg_node_ind << " overlap: " << std::endl;
4261  for ( Size ii_atom = 1; ii_atom <= ii_exp_hphobes.size(); ++ii_atom ) {
4262  TR_HIG << "bgnode " << ii << " atom " << ii_exp_hphobes[ ii_atom ] << ": [ ";
4263  for ( Size jj_atom = 1; jj_atom <= jj_exp_hphobes.size(); ++jj_atom ) {
4264  TR_HIG << atom_atom_overlaps[ ii_exp_hphobes[ ii_atom ] ][ jj_exp_hphobes[ jj_atom ] ] << ", ";
4265  }
4266  TR_HIG << "]" << std::endl;
4267  }
4268  TR_HIG << std::endl;*/
4269 #endif
4270 
4271  update_disjoint_sets_using_cache( ii_rsd, get_hpatch_bg_node( ii )->alt_state_inv_dots(), ii_exp_hphobes, ii_djs_offset,
4272  jj_rsd, get_hpatch_bg_node( jj_bg_node_ind )->alt_state_inv_dots(), jj_exp_hphobes, jj_djs_offset, atom_atom_overlaps, ds );
4273  }
4274  }
4275 
4276 #ifdef FILE_DEBUG
4277  TR_HIG << "calculate_alt_state_hpatch_score(): iterating over first-class edges" << std::endl;
4278 #endif
4279 
4280  //
4281  // first-class edges
4282  // now we have to iterate over every edge (and bg edge) in the IG and do pairwise-atom comparisons to see if two atoms should be
4283  // assigned to the same connected component. some of these edges will be connected to the node considering a substitution. that
4284  // node should have broadcast the sub being considered to all of its neighboring FC nodes. therefore, these edges will have
4285  // different values for the overlap between the current state and alt state. have to make sure we get the alt state overlap
4286  // for these edges. for all other FC edges, the alt state could be anything. it could be the same as the current state, or
4287  // it could be some alt_state that was considering a long time ago that wasn't commit'd(). so for these edges, we have to use
4288  // the overlap values for the current state rotamers at both nodes.
4289  //
4290 
4291  for ( std::list<EdgeBase*>::iterator iter = parent::get_edge_list_begin(); iter != parent::get_edge_list_end(); ++iter ) {
4292 
4293  Size node0_index = ((HPatchEdge< V, E, G >*)(*iter))->get_first_node_ind();
4294  Size node1_index = ((HPatchEdge< V, E, G >*)(*iter))->get_second_node_ind();
4295 
4296  // if the number of exposed hydrophobic atoms on either FC node is zero, then no point in doing work on this edge.
4297  // why? because, if none of the atoms are exposed, then there's no way we can connect nodes in the disjoint sets
4298  // object for the nodes on this edge.
4299  if ( fc_n_exp_hphobes_[ node0_index ] == 0 || fc_n_exp_hphobes_[ node1_index ] == 0 ) continue;
4300 
4301  conformation::ResidueCOP ii_rsd( node0_index == node_considering_alt_state_ ?
4302  get_hpatch_node( node0_index )->get_rotamer( alt_state_being_considered_ ) :
4303  get_hpatch_node( node0_index )->get_rotamer( get_hpatch_node( node0_index )->get_current_state() ) );
4304 
4305  utility::vector1< Size > const & ii_exp_hphobes( get_hpatch_node( node0_index )->alt_state_exp_hphobes() );
4306  Size const ii_djs_offset = fc_exp_hphobe_djs_offsets_[ node0_index ];
4307 
4308 #ifdef FILE_DEBUG
4309  //Size node0_current_state = get_hpatch_node( node0_index )->get_current_state();
4310  //TR_HIG << "calculate_alt_state_hpatch_score(): E(" << node0_index << "," << node1_index << "), ";
4311  //TR_HIG << "node " << node0_index << ": " << node0_current_state << " " << ii_rsd->name3();
4312 #endif
4313 
4314  conformation::ResidueCOP jj_rsd( node1_index == node_considering_alt_state_ ?
4315  get_hpatch_node( node1_index )->get_rotamer( alt_state_being_considered_ ) :
4316  get_hpatch_node( node1_index )->get_rotamer( get_hpatch_node( node1_index )->get_current_state() ) );
4317 
4318  utility::vector1< Size > const & jj_exp_hphobes( get_hpatch_node( node1_index )->alt_state_exp_hphobes() );
4319  Size const jj_djs_offset = fc_exp_hphobe_djs_offsets_[ node1_index ];
4320 
4321 #ifdef FILE_DEBUG
4322  //Size node1_current_state = get_hpatch_node( node1_index )->get_current_state();
4323  //TR_HIG << ", node " << node1_index << ": " << node1_current_state << " " << jj_rsd->name3();
4324  //TR_HIG << std::endl;
4325 #endif
4326 
4327  // it's possible we have to reorder the nodes so that the atom-atom overlap information is interpreted correctly.
4328  // this situation arises only when one of the nodes is the one that's considering a substitution.
4329  if ( node0_index == node_considering_alt_state_ || node1_index == node_considering_alt_state_ ) {
4330  utility::vector1< utility::vector1< bool > > const & atom_atom_overlaps = ((HPatchEdge< V, E, G >*)(*iter))->get_alt_state_atom_atom_overlaps();
4331  if ( node0_index == node_considering_alt_state_ ) {
4332  /// order the function parameters so that node0 is the outer-loop residue
4333  update_disjoint_sets_using_cache(
4334  *ii_rsd, get_hpatch_node( node0_index )->alt_state_inv_dots(), ii_exp_hphobes, ii_djs_offset,
4335  *jj_rsd, get_hpatch_node( node1_index )->alt_state_inv_dots(), jj_exp_hphobes, jj_djs_offset,
4336  atom_atom_overlaps, ds );
4337  } else {
4338  /// order the function parameters so that node1 is the outer-loop residue
4339  update_disjoint_sets_using_cache(
4340  *jj_rsd, get_hpatch_node( node1_index )->alt_state_inv_dots(), jj_exp_hphobes, jj_djs_offset,
4341  *ii_rsd, get_hpatch_node( node0_index )->alt_state_inv_dots(), ii_exp_hphobes, ii_djs_offset,
4342  atom_atom_overlaps, ds );
4343  }
4344  } else {
4345  utility::vector1< utility::vector1< bool > > const & atom_atom_overlaps = ((HPatchEdge< V, E, G >*)(*iter))->get_current_state_atom_atom_overlaps();
4346 
4347  /// order the function parameters so that node1 is the inner-loop residue
4348  update_disjoint_sets_using_cache(
4349  *ii_rsd, get_hpatch_node( node0_index )->alt_state_inv_dots(), ii_exp_hphobes, ii_djs_offset,
4350  *jj_rsd, get_hpatch_node( node1_index )->alt_state_inv_dots(), jj_exp_hphobes, jj_djs_offset,
4351  atom_atom_overlaps, ds );
4352  }
4353 
4354  } // for loop over all edges
4355 
4356 #ifdef FILE_DEBUG
4357  TR_HIG << "calculate_alt_state_hpatch_score(): iterating over background edges" << std::endl;
4358 #endif
4359 
4360  //
4361  // background edges
4362  // now we have to iterate over every bgedge and do the same as for the FC edges. bgedges are susceptible to the same problem
4363  // as described above for fc edges. it may be that the node of a bgedge is the node that is considering a sub for this
4364  // consider() call. in that case, we have to use the overlap that the bgnode and the alt_state on the node have for this
4365  // function. alternatively, if the node isn't the one considering a sub, then we need to use the current state on the
4366  // fc node and bgnode overlap.
4367  //
4368 
4369  typename std::list< core::pack::interaction_graph::BackgroundToFirstClassEdge< V, E, G >* >::const_iterator iter;
4370  for ( iter = parent::get_bg_edge_list_begin(); iter != parent::get_bg_edge_list_end(); ++iter ) {
4371 
4372  Size fc_node_index = ((HPatchBackgroundEdge< V, E, G >*)(*iter))->get_first_class_node_index();
4373  Size bg_node_index = ((HPatchBackgroundEdge< V, E, G >*)(*iter))->get_background_node_index();
4374  if ( fc_n_exp_hphobes_[ fc_node_index ] == 0 || bg_n_exp_hphobes_[ bg_node_index ] == 0 ) continue;
4375 
4376  Size fc_node_current_state = get_hpatch_node( fc_node_index )->get_current_state();
4377 
4378  conformation::ResidueCOP ii_rsd( fc_node_index == node_considering_alt_state_ ?
4379  get_hpatch_node( fc_node_index )->get_rotamer( alt_state_being_considered_ ) :
4380  get_hpatch_node( fc_node_index )->get_rotamer( fc_node_current_state ) );
4381 
4382  utility::vector1< Size > const & fc_exp_hphobes( get_hpatch_node( fc_node_index )->alt_state_exp_hphobes() );
4383  Size const fc_djs_offset = fc_exp_hphobe_djs_offsets_[ fc_node_index ];
4384 
4385 #ifdef FILE_DEBUG
4386  //TR_HIG << "calculate_alt_state_hpatch_score(): bgE(" << fc_node_index << "," << bg_node_index << "), ";
4387  //TR_HIG << "node " << fc_node_index << ": " << fc_node_current_state << " " << ii_rsd->name3();
4388 #endif
4389  conformation::ResidueCOP jj_rsd( pose().residue( bgenumeration_2_resid_[ bg_node_index ] ) );
4390  utility::vector1< Size > const & bg_exp_hphobes( get_hpatch_bg_node( bg_node_index )->alt_state_exp_hphobes() );
4391  Size const bg_djs_offset = bg_exp_hphobe_djs_offsets_[ bg_node_index ];
4392 
4393 
4394 #ifdef FILE_DEBUG
4395  //TR_HIG << ", bgnode " << bg_node_index << ": " << jj_rsd->name3() << std::endl;
4396 #endif
4397 
4398  // get the cached atom-atom overlap in the context of the alt_state if the fc node on this bgedge is the node considering a sub
4399  utility::vector1< utility::vector1< bool > > const & atom_atom_overlaps(
4400  fc_node_index == node_considering_alt_state_ ?
4401  ((HPatchBackgroundEdge< V, E, G >*)(*iter))->get_atom_atom_overlaps_for_state( alt_state_being_considered_ ) :
4402  ((HPatchBackgroundEdge< V, E, G >*)(*iter))->get_atom_atom_overlaps_for_state( fc_node_current_state ) );
4403 
4404  update_disjoint_sets_using_cache(
4405  *ii_rsd, get_hpatch_node( fc_node_index )->alt_state_inv_dots(), fc_exp_hphobes, fc_djs_offset,
4406  *jj_rsd, get_hpatch_bg_node( bg_node_index )->alt_state_inv_dots(), bg_exp_hphobes, bg_djs_offset,
4407  atom_atom_overlaps, ds );
4408 
4409  } // for loop over all bg edges
4410 
4411 
4412  //
4413  // finally, reprint the largest patch size atoms for easy access
4414  //
4415 #ifdef FILE_DEBUG
4417  Size const largest_set_size_index = utility::arg_max( set_sizes ); // vector1.functions.hh
4418  TR_HIG << "num atoms in largest patch: : " << set_sizes[ largest_set_size_index ] << std::endl;
4419 #endif
4420 
4421  Size n_ccs( 0 ); // number of connected components
4422  reps_for_nonzero_rank_ccs_.resize( 0 );
4423  djs_rep_node_index_2_cc_index_.resize( tot_exp_hphobes, 0 ); // use "0" to say "I'm not the representative for any CC"
4424  sasa_for_cc_.resize( 0 ); // the patch area
4425 
4426  for ( Size ii = 1; ii <= tot_exp_hphobes; ++ii ) {
4427  Size ii_rep = ds.ds_find( ii );
4428  if ( ds.node( ii_rep ).rank == 0 ) continue; /// 1-atom connected component.
4429  Size ii_cc = djs_rep_node_index_2_cc_index_[ ii_rep ];
4430  if ( ii_cc == 0 ) {
4431  ++n_ccs;
4432  reps_for_nonzero_rank_ccs_.push_back( ii_rep );
4433  sasa_for_cc_.push_back( 0.0 );
4434  djs_rep_node_index_2_cc_index_[ ii_rep ] = n_ccs;
4435  ii_cc = n_ccs;
4436  }
4437  sasa_for_cc_[ ii_cc ] += ep_sasa_for_djs_node_[ ii ];
4438  }
4439 
4440  core::Real total_alt_state_hpatch_score = 0.0;
4441  for ( Size ii = 1; ii <= sasa_for_cc_.size(); ++ii ) {
4442 
4443  Real const patch_area = sasa_for_cc_[ ii ];
4444  Real score = 0.0;
4445  if ( patch_area > SurfacePotential::MAX_HPATCH_AREA ) {
4446  score = hpatch_score_weight_ * SurfacePotential::MAX_HPATCH_SCORE;
4447  } else {
4448  score = hpatch_score_weight_ * SurfacePotential::get_instance()->hpatch_score( patch_area );
4449  }
4450 
4451  total_alt_state_hpatch_score += score;
4452 
4453  } // end loop over all patches/connected components
4454 
4455  /// now unwind the reps_for_nonzero_rank_ccs_ data:
4456  for ( Size ii = 1; ii <= reps_for_nonzero_rank_ccs_.size(); ++ii ) {
4457  djs_rep_node_index_2_cc_index_[ reps_for_nonzero_rank_ccs_[ ii ]] = 0;
4458  }
4459 
4460 
4461 #ifdef FILE_DEBUG
4462  std::map< Size, utility::vector1< Size > > sets = ds.sets();
4463  std::map< Size, utility::vector1< Size > >::iterator it;
4464 
4465  core::Real patch_area = 0.0;
4466  for ( it = sets.begin() ; it != sets.end(); it++ ) {
4467  if ( (*it).second.size() < 2 ) continue; // don't print 1-atom patches
4468  patch_area = 0.0; // reset the patch area for each patch
4469  TR_HIG << "atoms in patch: [ ";
4470 
4471  /*std::cout << "(*it).second: [ ";
4472  for ( Size ii = 1; ii <= (*it).second.size(); ++ii ) {
4473  std::cout << (*it).second[ ii ] << ", ";
4474  }
4475  std::cout << "]" << std::endl;*/
4476 
4477  // (*it).second has all the djs nodes that are in this connected component. we have to translate the djs node
4478  // into IG node and residue/atom type. djs_id_2_hphobe_index_ provides a mapping from djs node id to a exposed_hydrophobic_data
4479  // struct. the first struct field, fc_bg_, is a 1 for first-class node and 2 for bgnode.
4480  // the second field is node_index_ and the third is the atom: exhphobe_index_
4481 
4482  for ( Size ii = 1; ii <= (*it).second.size(); ++ii ) {
4483  Size const node_index = djs_id_2_hphobe_index_[ (*it).second[ ii ] ].node_index_;
4484  Size const exphobe_index = djs_id_2_hphobe_index_[ (*it).second[ ii ] ].exhphobe_index_;
4485  //std::cout << "node_index: " << node_index << ", exphobe_index: " << exphobe_index;
4486 
4487  if ( djs_id_2_hphobe_index_[ (*it).second[ ii ] ].fc_bg_ == 1 ) { // 1 == FC
4488  conformation::Residue const & rsd( node_considering_alt_state_ == node_index ?
4489  *get_hpatch_node( node_index )->get_rotamer( alt_state_being_considered_ ) :
4490  *get_hpatch_node( node_index )->get_rotamer( get_hpatch_node( node_index )->get_current_state() ) );
4491 
4492  // can't use node_considering_alt_state here; have to use the fc_nodes_near_rotsub_bool to see if a particular
4493  // IG node is near the position considering a substitution
4494  //utility::vector1< Size > const & exhphobes( node_considering_alt_state_ == node_index ?
4495  // get_hpatch_node( node_index )->alt_state_exp_hphobes() : get_hpatch_node( node_index )->curr_state_exp_hphobes() );
4496  utility::vector1< Size > const & exhphobes( fc_nodes_near_rotsub_bool_[ node_index ] ?
4497  get_hpatch_node( node_index )->alt_state_exp_hphobes() : get_hpatch_node( node_index )->curr_state_exp_hphobes() );
4498 
4499  /*std::cout << ", exhphobes: [ ";
4500  for ( Size aa=1; aa <= exhphobes.size(); ++aa ) { std::cout << exhphobes[ aa ] << ", "; }
4501  std::cout << "]" << std::endl;*/
4502  if ( exphobe_index > exhphobes.size() ) {
4503  std::cout << "node_considering_alt_state_: " << node_considering_alt_state_ << std::endl;
4504  std::cout << "node_considering_alt_state_ == node_index: " << ( node_considering_alt_state_ == node_index ? "yes" : "no" ) << std::endl;
4505  std::cout << "fc_nodes_near_rotsub_bool_[ ii ]: " << fc_nodes_near_rotsub_bool_[ node_index ] << std::endl;
4506 
4507  get_hpatch_node( node_index )->print(); // will print both current and alt state dots
4508 
4509  utility::vector1< Size > const & curr_state_exhphobes = get_hpatch_node( node_index )->curr_state_exp_hphobes();
4510  std::cout << "curr state exp hphobes: [ ";
4511  for ( Size aa=1; aa <= curr_state_exhphobes.size(); ++aa ) { std::cout << curr_state_exhphobes[ aa ] << ", "; }
4512  std::cout << "], ";
4513  utility::vector1< Size > const & alt_state_exhphobes = get_hpatch_node( node_index )->alt_state_exp_hphobes();
4514  std::cout << "alt state exp hphobes: [ ";
4515  for ( Size aa=1; aa <= alt_state_exhphobes.size(); ++aa ) { std::cout << alt_state_exhphobes[ aa ] << ", "; }
4516  std::cout << "]" << std::endl;
4517  }
4518 
4519  Size atom_index = exhphobes[ exphobe_index ];
4520 
4521  assert( rsd.atom_type( atom_index ).element() == carbon_atom || rsd.atom_type( atom_index ).element() == sulfur_atom );
4522  TR_HIG << rotamer_sets().moltenres_2_resid( node_index ) << "/" << utility::trim( rsd.atom_name( atom_index ) ) << " + ";
4523  patch_area += ep_sasa_for_djs_node_[ (*it).second[ ii ] ];
4524 
4525  } else { // 2 == BG
4526  conformation::Residue const & rsd = pose().residue( bgenumeration_2_resid_[ node_index ] );
4527 
4528  utility::vector1< Size > const & exhphobes( get_hpatch_bg_node( node_index )->alt_state_exp_hphobes() );
4529  //utility::vector1< Size > const & exhphobes( bg_nodes_near_rotsub_bool_[ node_index ] ?
4530  // get_hpatch_bg_node( node_index )->alt_state_exp_hphobes() : get_hpatch_bg_node( node_index )->curr_state_exp_hphobes() );
4531 
4532  /*std::cout << ", exhphobes: [ ";
4533  for ( Size aa=1; aa <= exhphobes.size(); ++aa ) { std::cout << exhphobes[ aa ] << ", "; }
4534  std::cout << "]" << std::endl;*/
4535 
4536  Size atom_index = exhphobes[ exphobe_index ];
4537 
4538  assert( rsd.atom_type( atom_index ).element() == carbon_atom || rsd.atom_type( atom_index ).element() == sulfur_atom );
4539  TR_HIG << bgenumeration_2_resid_[ node_index ] << "/" << utility::trim( rsd.atom_name( atom_index ) ) << " + ";
4540  patch_area += ep_sasa_for_djs_node_[ (*it).second[ ii ] ];
4541  }
4542  }
4543 
4544  Real score = 0.0;
4545  if ( patch_area > scoring::SurfacePotential::MAX_HPATCH_AREA ) {
4546  score = hpatch_score_weight_ * scoring::SurfacePotential::MAX_HPATCH_SCORE;
4547  } else {
4548  score = hpatch_score_weight_ * scoring::SurfacePotential::get_instance()->hpatch_score( patch_area );
4549  }
4550  TR_HIG << "], patch_area: " << patch_area << ", score: " << score << std::endl;
4551 
4552  }
4553  TR_HIG << std::endl;
4554 #endif
4555 
4556  return total_alt_state_hpatch_score;
4557 
4558 }
4559 
4560 
4561 ///
4562 /// @begin HPatchInteractionGraph< V, E, G >::decide_procrastinate_hpatch_computations()
4563 ///
4564 /// @detailed
4565 /// Makes the decision whether or not to procrastinate calculating the hpatch score. Basically, if the PD energy got better (dE < 0)
4566 /// then return false so we don't procrastinate the calculation (because the alternate state probably will be accepted?). If the best
4567 /// guess for the hpatch deltaE also comes back better (dE < 0), then return false. Finally, if the difference between the deltaE
4568 /// for the PD terms and the (guessed) hpatch deltaE is greater than the threshold, return true so we do procrastinate. So basically
4569 /// if the energy (especially the PD energy) gets worse, procrastinate. Otherwise, don't.
4570 ///
4571 template < typename V, typename E, typename G >
4573 
4574  Real hpatch_deltaE_max = 0;
4575 
4576  if ( ! observed_sufficient_hpatch_E_to_predict_min_ )
4577  return false;
4578 
4579  if ( threshold < 0 || pd_deltaE < 0 )
4580  return false;
4581 
4582  hpatch_deltaE_max += hpatch_energy_current_state_assignment_ - hpatch_score_min_last_100_;
4583 
4584  // pd_deltaE must be positive, hpatch_deltaE must also be positive.
4585  // threshold of 5 means, if the PD got more than 5 worse than the guessed hpatch deltaE (e.g. 10 - 3(?) = 7 > 5), procrastinate
4586 #ifdef FILE_DEBUG
4587  TR_HIG << "decide_procrastinate_hpatch_computations(): pd_deltaE: " << pd_deltaE << ", hpatch_deltaE_max: " << hpatch_deltaE_max
4588  << ", threshold: " << threshold << std::endl;
4589 #endif
4590  if ( (pd_deltaE - hpatch_deltaE_max) > threshold ) {
4591  return true;
4592  }
4593  return false;
4594 
4595 }
4596 
4597 
4598 ///
4599 /// @begin HPatchInteractionGraph::reset_from_previous_deltaHpatch_comp
4600 ///
4601 /// @brief
4602 /// Iterates through all FCNodes and BGNodes affected by the last deltaHpatch computation, and resets their
4603 /// state.
4604 ///
4605 /// @detailed
4606 /// the Node consider() function is the main entry point from the HIG when the annealer considers a sub. need to make sure that the
4607 /// node's alt_state is the same as the current state before we start incrementing/decrementing things or otherwise you wind
4608 /// up with total SASAs that are wrong. alt state will be the same as current state on the first time through because of
4609 /// prep for simA call, but not necessarily the case on following substitutions coming from annealer. any given sub only sets the alt state
4610 /// SASA on that particular (changing) node. all of the other nodes which were called on to consider a substitution and
4611 /// whose SASAs changed need to reset their alt state dots also (or, otherwise, it appears as if the substitution was
4612 /// committed). More about this problem can be read in the comments for commit_considered_substitution()
4613 ///
4614 template < typename V, typename E, typename G >
4616 
4617  /// This reset is necessary only if the last hpatch deltaE was calculated
4618  ///if ( some_node_in_state_0_ ) return;
4619 
4620 #ifdef FILE_DEBUG
4621  TR_HIG << "reset_from_previous_deltaHpatch_comp: calling reset_alt_state_dots on all FC nodes." << std::endl;
4622 #endif
4623  for ( Size ii = 1; ii <= fc_nodes_near_rotsub_.size(); ++ii ) {
4624  Size const ii_fc_node = fc_nodes_near_rotsub_[ ii ];
4625  assert( fc_nodes_near_rotsub_bool_[ ii_fc_node ] );
4626  get_hpatch_node( ii_fc_node )->reset_alt_state_dots();
4627  }
4628  if ( ! some_node_in_state_0_ ) {
4629  for ( Size ii = 1; ii <= fc_nodes_near_rotsub_.size(); ++ii ) {
4630  Size const ii_fc_node = fc_nodes_near_rotsub_[ ii ];
4631  fc_nodes_near_rotsub_bool_[ ii_fc_node ] = false;
4632  }
4633  fc_nodes_near_rotsub_.clear();
4634  }
4635 
4636 #ifdef FILE_DEBUG
4637  TR_HIG << "reset_from_previous_deltaHpatch_comp: calling reset_alt_state_dots on all BG nodes." << std::endl;
4638 #endif
4639  for ( Size ii = 1; ii <= bg_nodes_near_rotsub_.size(); ++ii ) {
4640  Size const ii_bg_node = bg_nodes_near_rotsub_[ ii ];
4641  assert( bg_nodes_near_rotsub_bool_[ ii_bg_node ] );
4642  get_hpatch_bg_node( ii_bg_node )->reset_alt_state_dots();
4643  }
4644  if ( ! some_node_in_state_0_ ) {
4645  for ( Size ii = 1; ii <= bg_nodes_near_rotsub_.size(); ++ii ) {
4646  Size const ii_bg_node = bg_nodes_near_rotsub_[ ii ];
4647  bg_nodes_near_rotsub_bool_[ ii_bg_node ] = false;
4648  }
4649  bg_nodes_near_rotsub_.clear();
4650  }
4651 }
4652 
4653 
4654 ///
4655 /// @begin HPatchInteractionGraph::commit_considered_substitution
4656 ///
4657 /// @brief
4658 /// Commits the substitution that the sim annealer had previously asked the graph to consider. Returns the accurate total energy for the graph.
4659 ///
4660 template < typename V, typename E, typename G >
4662 
4663  // std::cerr << "Committing substitution at node " << node_considering_alt_state_ << std::endl;
4664 
4665 #ifdef FILE_DEBUG
4666  TR_HIG << "commit_considered_substitution(): committing sub on node " << node_considering_alt_state_ << std::endl;
4667 #endif
4668 
4669  core::PackerEnergy hpatch_deltaE = 0.0;
4670  if ( ! calculated_hpatch_deltaE_ ) {
4671  hpatch_deltaE = calculate_hpatch_deltaE(); // updates all the Nodes and calculates the hpatch score delta
4672  ++num_hpatch_comps_later_made_;
4673  }
4674 
4675  // the call to calculate_PD_deltaE_for_substitution() always happens so parent::get_alt_pd_energy_total()
4676  // will return the correct value. to get the right deltaE we have to add the hpatch deltaE to the
4677  // PD terms deltaE. deltaE_for_substitution_ is a class member Real variable.
4678  deltaE_for_substitution_ = get_hpatch_node( node_considering_alt_state_ )->get_pd_energy_delta() + hpatch_deltaE;
4679 
4680  // have to get the pd deltaE before making this call
4681  get_hpatch_node( node_considering_alt_state_ )->commit_considered_substitution();
4682 
4683  total_energy_current_state_assignment_ = total_energy_current_state_assignment_ + deltaE_for_substitution_;
4684  hpatch_energy_current_state_assignment_ = hpatch_energy_alternate_state_assignment_;
4685 
4686  node_considering_alt_state_ = -1;
4687  ++num_commits_since_last_update_;
4688 
4689  if ( num_commits_since_last_update_ == COMMIT_LIMIT_BETWEEN_UPDATES ) {
4690  update_internal_energy_totals_hpatch();
4691  }
4692 
4693  track_hpatch_E_min();
4694 
4695  return total_energy_current_state_assignment_;
4696 }
4697 
4698 
4699 ///
4700 /// @begin HPatchInteractionGraph< V, E, G >::track_hpatch_E_min
4701 ///
4702 /// @brief
4703 /// Keeps track of the minimum hpatch score seen. Every 100 substitutions, updates the variable hpatch_score_min_last_100.
4704 ///
4705 template < typename V, typename E, typename G >
4707 
4708  ++num_substitutions_since_hpatch_min_update_;
4709 
4710  Real alt_hpatchE = hpatch_energy_current_state_assignment_;
4711 
4712  if ( hpatch_score_min_recent_ > alt_hpatchE )
4713  hpatch_score_min_recent_ = alt_hpatchE;
4714 
4715  if ( num_substitutions_since_hpatch_min_update_ == 100 ) { // only update min every 100 calls to track_hpatchE_min (aka commits)
4716  hpatch_score_min_last_100_ = hpatch_score_min_recent_;
4717  if ( hpatch_energy_current_state_assignment_ < hpatch_score_min_last_100_ )
4718  hpatch_score_min_last_100_ = hpatch_energy_current_state_assignment_;
4719  observed_sufficient_hpatch_E_to_predict_min_ = true;
4720  num_substitutions_since_hpatch_min_update_ = 0;
4721  }
4722 
4723 }
4724 
4725 
4726 ///
4727 /// @begin HPatchInteractionGraph::set_network_state
4728 ///
4729 /// @brief
4730 /// Switch the state assignment of every first class node in the graph.
4731 /// Useful, for instance, if you want to switch to the best network state that you've found so far.
4732 ///
4733 /// @detailed
4734 /// This function is the last major entry point from the Annealer into the HIG.
4735 ///
4736 template < typename V, typename E, typename G >
4738 
4739 #ifdef FILE_DEBUG
4740  TR_HIG << "set_network_state() called with states: " << node_states << std::endl;
4741 #endif
4742  for ( Size ii = 1; ii <= (Size)parent::get_num_nodes(); ++ii ) {
4743  core::PackerEnergy deltaE = 0.0;
4744  core::PackerEnergy previousE = 0.0;
4745  consider_substitution( ii, node_states( ii ), deltaE, previousE ); // might get procrastinated but that's ok
4746  commit_considered_substitution(); // it will get updated correctly here
4747  }
4748 
4749  // not necessary because the code above goes through the consider/commit process which updates the internal
4750  // energy totals.
4751  //update_internal_energy_totals_hpatch();
4752 
4753  return total_energy_current_state_assignment_;
4754 
4755 }
4756 
4757 
4758 ///
4759 /// @begin HPatchInteractionGraph::get_energy_current_state_assignment
4760 ///
4761 /// @brief
4762 /// returns the energy of the entire graph under the current network state assignment. Also sends a bunch of information to standard error.
4763 /// Only seems to be called by the MultiCoolAnnealer.
4764 ///
4765 template < typename V, typename E, typename G >
4767  return total_energy_current_state_assignment_;
4768 }
4769 
4770 
4771 
4772 ///
4773 /// @begin HPatchInteractionGraph::print_current_state_assignment
4774 ///
4775 /// @brief
4776 /// Should write the state assigned to each first class vertex to the screen.
4777 ///
4778 /*template < typename V, typename E, typename G >
4779 void HPatchInteractionGraph< V, E, G >::print_current_state_assignment() const {
4780 
4781  // print out the one-body and hpatch energies for all first class nodes
4782  TR_HIG << "internal energies: " << std::endl;
4783  for (int ii = 1; ii <= parent::get_num_nodes(); ++ii) {
4784  Real one_body = get_hpatch_node( ii )->get_curr_state_one_body_energy();
4785  TR_HIG << "node " << ii << " 1b: " << one_body;
4786  Real sasa = get_hpatch_node( ii )->get_current_state_sasa();
4787  TR_HIG << ", sasa = " << sasa;
4788 
4789  if ( ii % 3 == 0) {
4790  TR_HIG << std::endl;
4791  }
4792  }
4793 
4794  TR_HIG << std::endl;
4795 
4796  // print out the hpatch energies for all background nodes
4797  //for ( Size ii = 1; ii <= (Size)parent::get_num_background_nodes(); ++ii ) {
4798  // Real bg_sasa = get_hpatch_bg_node( ii )->get_current_sasa();
4799  // TR_HIG << "bg res: " << bgenumeration_2_resid_[ ii ] << " sasa: " << bg_sasa << std::endl;
4800  //}
4801 
4802  // print out the two-body energies for all edges between first-class nodes only?
4803  int count_edges = 0;
4804  for (std::list< core::pack::interaction_graph::EdgeBase*>::const_iterator iter = parent::get_edge_list_begin(); iter != parent::get_edge_list_end(); ++iter) {
4805  Real edge_energy = ((HPatchEdge< V, E, G >*) (*iter))->get_current_two_body_energy();
4806  TR_HIG << "edge: " << edge_energy << " ";
4807 
4808  if ( count_edges % 5 == 0)
4809  TR_HIG << std::endl;
4810  ++count_edges;
4811  }
4812 
4813 }*/
4814 
4815 
4816 ///
4817 /// @begin HPatchInteractionGraph::get_edge_memory_usage
4818 ///
4819 /// @brief
4820 /// Should return a measurement of the memory used by the interaction graph
4821 /// to store the rotamer pair energies. Unimplemented.
4822 ///
4823 template < typename V, typename E, typename G >
4825  return 0;
4826 }
4827 
4828 
4829 ///
4830 /// @begin HPatchInteractionGraph::count_static_memory
4831 ///
4832 template < typename V, typename E, typename G >
4834  return sizeof ( HPatchInteractionGraph< V, E, G > );
4835 }
4836 
4837 
4838 ///
4839 /// @begin HPatchInteractionGraph::count_dynamic_memory
4840 ///
4841 template < typename V, typename E, typename G >
4843  unsigned int total_memory = parent::count_dynamic_memory();
4844 
4845  total_memory += resid_2_bgenumeration_.size() * sizeof( Size );
4846  total_memory += bgenumeration_2_resid_.size() * sizeof( Size );
4847 
4848  return total_memory;
4849 }
4850 
4851 
4852 ///
4853 /// @begin HPatchInteractionGraph::get_energy_sum_for_vertex_group
4854 ///
4855 /// @brief
4856 /// returns the sum of the PD energy and the hpatch energy for all members first class members of a user-defined
4857 /// vertex subset. Unimplemented.
4858 ///
4859 template < typename V, typename E, typename G >
4861  //apl functionality stubbed out for now
4862  return 0;
4863 }
4864 
4865 
4866 ///
4867 /// @begin HPatchInteractionGraph::print_internal_energies_for_current_state_assignment
4868 ///
4869 template < typename V, typename E, typename G >
4871 
4872  // print out the one-body and hpatch energies for all first class nodes
4873  TR_HIG << "internal energies: " << std::endl;
4874  for ( Size ii = 1; ii <= parent::get_num_nodes(); ++ii ) {
4875  Real one_body = get_hpatch_node( ii )->get_curr_state_one_body_energy();
4876  TR_HIG << "node " << ii << " 1b: " << one_body;
4877  Real sasa = get_hpatch_node( ii )->get_current_state_sasa();
4878  TR_HIG << ", sasa = " << sasa;
4879 
4880  if ( ii % 3 == 0) {
4881  TR_HIG << std::endl;
4882  }
4883  }
4884  TR_HIG << std::endl;
4885 
4886  // print out the hpatch energies for all background nodes
4887  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
4888  Real bg_sasa = get_hpatch_bg_node( ii )->get_current_sasa();
4889  TR_HIG << "bg res: " << bgenumeration_2_resid_[ ii ] << " sasa: " << bg_sasa << std::endl;
4890  }
4891 
4892  // print out the two-body energies for all edges between first-class nodes only?
4893  int count_edges = 0;
4894  for (std::list< core::pack::interaction_graph::EdgeBase*>::const_iterator iter = parent::get_edge_list_begin(); iter != parent::get_edge_list_end(); ++iter) {
4895  Real edge_energy = ((HPatchEdge< V, E, G >*) (*iter))->get_current_two_body_energy();
4896  TR_HIG << "edge: " << edge_energy << " ";
4897 
4898  if ( count_edges % 5 == 0)
4899  TR_HIG << std::endl;
4900  ++count_edges;
4901  }
4902 }
4903 
4904 
4905 ///
4906 /// @begin HPatchInteractionGraph::write_dot_kinemage
4907 ///
4908 /*template < typename V, typename E, typename G >
4909 void HPatchInteractionGraph< V, E, G >::write_dot_kinemage( std::ofstream & output_kin ) {
4910 
4911  output_kin << "@group {dots} off" << std::endl;
4912  output_kin << "@subgroup {molten_residues} dominant" << std::endl;
4913 
4914  for (int ii = 1; ii <= parent::get_num_nodes(); ++ii) {
4915  get_hpatch_node( ii )->write_dot_kinemage( output_kin );
4916  }
4917 
4918  output_kin << "@subgroup {background_residues} dominant" << std::endl;
4919  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
4920  get_hpatch_bg_node( ii )->write_dot_kinemage( output_kin );
4921  }
4922 
4923 }*/
4924 
4925 
4926 ///
4927 /// @begin HPatchInteractionGraph::print
4928 ///
4929 /// @brief
4930 /// useful for debugging
4931 ///
4932 template< typename V, typename E, typename G >
4933 void
4935 
4936  std::cout << "HPatch Interaction Graph state: " << std::endl;
4937  std::cout << "nodes: " << std::endl;
4938  for (int jj = 1; jj <= parent::get_num_nodes(); ++jj) {
4939  get_hpatch_node( jj )->print();
4940  }
4941 
4942  std::cout << "bgnodes: " << std::endl;
4943  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
4944  get_hpatch_bg_node( ii )->print();
4945  }
4946 }
4947 
4948 
4949 // The below functions are only used for the unit tests. However, since most developers these days are running the unit
4950 // tests using release mode, I can't #ifdef these functions (to leave them out of release mode builds) or the unit
4951 // tests don't compile. So just compile them regardless of build mode.
4952 
4953 /// @begin HPatchNode::get_current_state_rotamer_dots
4954 ///
4955 /// @brief
4956 /// Returns current state. Only used by the unit tests.
4957 ///
4958 template< typename V, typename E, typename G >
4959 RotamerDots const & HPatchNode<V, E, G>::get_current_state_rotamer_dots() { return current_state_rotamer_dots_; }
4960 
4961 /// @begin HPatchNode::get_alt_state_rotamer_dots
4962 ///
4963 /// @brief
4964 /// Returns current state. Only used by the unit tests.
4965 ///
4966 template< typename V, typename E, typename G >
4967 RotamerDots const & HPatchNode<V, E, G>::get_alt_state_rotamer_dots() { return alt_state_rotamer_dots_; }
4968 
4969 
4970 /// @begin HPatchBackgroundNode::get_current_state_rotamer_dots
4971 ///
4972 /// @brief
4973 /// Returns current state. Only used by the unit tests.
4974 ///
4975 template< typename V, typename E, typename G >
4976 RotamerDots const & HPatchBackgroundNode<V, E, G>::get_current_state_rotamer_dots() { return current_state_rotamer_dots_; }
4977 
4978 
4979 /// @begin HPatchBackgroundNode::get_alt_state_rotamer_dots
4980 ///
4981 /// @brief
4982 /// Returns current state. Only used by the unit tests.
4983 ///
4984 template< typename V, typename E, typename G >
4985 RotamerDots const & HPatchBackgroundNode<V, E, G>::get_alt_state_rotamer_dots() { return alt_state_rotamer_dots_; }
4986 
4987 
4988 ///
4989 /// @begin HPatchInteractionGraph::get_network_state
4990 ///
4991 /// @brief
4992 /// Returns the state on each FCNode, but not necessarily in pose resid order. Only used by the unit tests.
4993 ///
4994 template< typename V, typename E, typename G >
4996 
4997  std::vector< int > networkstate;
4998  for ( int jj = 1; jj <= parent::get_num_nodes(); ++jj ) {
4999  networkstate.push_back( get_hpatch_node(jj)->get_current_state() );
5000  }
5001  return networkstate;
5002 }
5003 
5004 
5005 ///
5006 /// @begin HPatchInteractionGraph::set_observed_sufficient_boolean_true
5007 ///
5008 /// @brief
5009 /// Sets the observed_sufficient_hpatch_E_to_predict_min_ to true. Only used by the unit tests.
5010 ///
5011 template< typename V, typename E, typename G >
5013  observed_sufficient_hpatch_E_to_predict_min_ = true;
5014 }
5015 
5016 
5017 ///
5018 /// @begin HPatchInteractionGraph< V, E, G >::get_all_sasas
5019 ///
5020 /// @brief
5021 /// Iterates over all nodes and bgnodes
5022 /// brute-force recounting.
5023 ///
5024 template < typename V, typename E, typename G >
5026 
5027  for ( Size ii=1; ii <= (Size)parent::get_num_nodes(); ++ii ) {
5028  node_sasas[ ii ] = ((get_hpatch_node(ii))->get_current_state_rotamer_dots()).get_sasa();
5029  }
5030 
5031  for ( Size ii=1; ii <= (Size)parent::get_num_background_nodes(); ++ii ) {
5032  bgnode_sasas[ ii ] = ((get_hpatch_bg_node(ii))->get_current_state_rotamer_dots()).get_sasa();
5033  }
5034 
5035 }
5036 
5037 
5038 ///
5039 /// @begin HPatchInteractionGraph::bg_node_2_resid
5040 ///
5041 /// @brief
5042 /// Provides read access to the bg to resid array. Returns -1 if the index is not in bounds.
5043 ///
5044 template < typename V, typename E, typename G >
5046 
5047  if ( node_index > num_residues_assigned_as_background_ ) {
5048  utility_exit_with_message( "Out of bounds array index passed to bg_node_2_resid. Quitting." );
5049  }
5050  return bgenumeration_2_resid_[ node_index ];
5051 }
5052 
5053 
5054 /*///
5055 /// @begin HPatchInteractionGraph::get_fc_nodes_near_rotsub
5056 ///
5057 /// @brief
5058 /// Read access to the vector fc_nodes_near_rotsub_.
5059 ///
5060 template < typename V, typename E, typename G >
5061 utility::vector1< Size > const & HPatchInteractionGraph< V, E, G >::get_fc_nodes_near_rotsub() {
5062  return fc_nodes_near_rotsub_;
5063 }
5064 
5065 ///
5066 /// @begin HPatchInteractionGraph::get_fc_nodes_near_rotsub_bool
5067 ///
5068 /// @brief
5069 /// Read access to the vector fc_nodes_near_rotsub_bool_.
5070 ///
5071 template < typename V, typename E, typename G >
5072 utility::vector1< bool > const & HPatchInteractionGraph< V, E, G >::get_fc_nodes_near_rotsub_bool() {
5073  return fc_nodes_near_rotsub_bool_;
5074 }
5075 
5076 ///
5077 /// @begin HPatchInteractionGraph::get_bg_nodes_near_rotsub
5078 ///
5079 /// @brief
5080 /// Read access to the vector bg_nodes_near_rotsub_.
5081 ///
5082 template < typename V, typename E, typename G >
5083 utility::vector1< Size > const & HPatchInteractionGraph< V, E, G >::get_bg_nodes_near_rotsub() {
5084  return bg_nodes_near_rotsub_;
5085 }
5086 
5087 ///
5088 /// @begin HPatchInteractionGraph::get_bg_nodes_near_rotsub_bool
5089 ///
5090 /// @brief
5091 /// Read access to the vector bg_nodes_near_rotsub_bool_.
5092 ///
5093 template < typename V, typename E, typename G >
5094 utility::vector1< bool > const & HPatchInteractionGraph< V, E, G >::get_bg_nodes_near_rotsub_bool() {
5095  return bg_nodes_near_rotsub_bool_;
5096 }
5097 
5098 
5099 ///
5100 /// @begin HPatchInteractionGraph::get_fc_exp_hphobe_djs_offsets
5101 ///
5102 /// @brief
5103 /// Read access to the vector fc_exp_hphobe_djs_offsets_.
5104 ///
5105 template < typename V, typename E, typename G >
5106 utility::vector1< Size > const & HPatchInteractionGraph< V, E, G >::get_fc_exp_hphobe_djs_offsets() {
5107  return fc_exp_hphobe_djs_offsets_;
5108 }
5109 
5110 
5111 ///
5112 /// @begin HPatchInteractionGraph::get_bg_exp_hphobe_djs_offsets
5113 ///
5114 /// @brief
5115 /// Read access to the vector bg_exp_hphobe_djs_offsets_.
5116 ///
5117 template < typename V, typename E, typename G >
5118 utility::vector1< Size > const & HPatchInteractionGraph< V, E, G >::get_bg_exp_hphobe_djs_offsets() {
5119  return bg_exp_hphobe_djs_offsets_;
5120 }
5121 
5122 
5123 ///
5124 /// @begin HPatchInteractionGraph::get_fc_n_exp_hphobes
5125 ///
5126 /// @brief
5127 /// Read access to the vector fc_n_exp_hphobes_.
5128 ///
5129 template < typename V, typename E, typename G >
5130 utility::vector1< Size > const & HPatchInteractionGraph< V, E, G >::get_fc_n_exp_hphobes() {
5131  return fc_n_exp_hphobes_;
5132 }
5133 
5134 ///
5135 /// @begin HPatchInteractionGraph::get_bg_n_exp_hphobes
5136 ///
5137 /// @brief
5138 /// Read access to the vector bg_n_exp_hphobes_.
5139 ///
5140 template < typename V, typename E, typename G >
5141 utility::vector1< Size > const & HPatchInteractionGraph< V, E, G >::get_bg_n_exp_hphobes() {
5142  return bg_n_exp_hphobes_;
5143 }*/
5144 
5145 
5146 
5147 } //end namespace
5148 } //end namespace
5149 } //end namespace
5150 
5151 #endif
5152