Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PDInteractionGraph.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file core/pack/interaction_graph/PDInteractionGraph.cc
11 /// @brief Pairwise Decomposable interaction graph class
12 /// @author Andrew Leaver-Fay (leaverfa@email.unc.edu)
13 
14 // Unit Headers
16 
17 // Package Headers
20 
21 // ObjexxFCL Headers
22 #include <ObjexxFCL/FArray1D.hh>
23 #include <ObjexxFCL/FArray1A.hh>
24 #include <ObjexxFCL/FArray2D.hh>
25 // AUTO-REMOVED #include <ObjexxFCL/FArray2A.hh>
26 
27 // STL Headers
28 #include <list>
29 // AUTO-REMOVED #include <vector>
30 #include <algorithm>
31 #include <iostream>
32 // AUTO-REMOVED #include <fstream>
33 #include <cassert>
34 
35 // Utility Headers
36 #include <utility/exit.hh>
37 
38 #include <utility/vector1.hh>
39 
40 
41 namespace core {
42 namespace pack {
43 namespace interaction_graph {
44 
45 //----------------------------------------------------------------------------//
46 //-------- Sparse Pairwise Decomposable Interaction Graph Node Class ---------//
47 //----------------------------------------------------------------------------//
48 
49 /// @brief main constructor, no default or copy constructors
50 ///
51 /// allocates one-body energy array and initializes it to zero.
52 /// allocates space for sparse-matrix information.
53 ///
54 PDNode::PDNode(InteractionGraphBase * owner, int node_id, int num_states) :
55  PrecomputedPairEnergiesNode( owner, node_id, num_states ),
56  num_aa_types_( get_pdig_owner()->get_num_aatypes() ),
57  num_states_for_aatype_( num_aa_types_, 0 ),
58  sparse_mat_info_for_state_( num_states + 1),
59  one_body_energies_(num_states + 1, 0.0f),
60  curr_state_total_energy_( 0.0 ),
61  alternate_state_is_being_considered_( false )
62 {}
63 
64 /// @brief destructor
65 ///
66 /// @details not responsible for any dynamically allocated memory, so node does nothing
67 /// it's member variables, of course, are implicitly destructed
69 {}
70 
71 void PDNode::print() const
72 {
73  std::cerr << "NODE: " << get_node_index() << " with " <<
74  get_num_states() << " states" << std::endl;
75  for (int ii = 1; ii <= get_num_states(); ++ii) {
76  std::cerr << "(" << ii << ", " <<
77  sparse_mat_info_for_state_[ii].get_aa_type() << ", ";
78  std::cerr <<
79  sparse_mat_info_for_state_[ii].get_state_ind_for_this_aa_type() << ", ";
80  std::cerr << one_body_energies_[ ii ] << ") ";
81  if ( ii % 3 == 0 ) std::cerr << std::endl;
82  }
83  std::cerr << std::endl << "-----------------" << std::endl;
84 }
85 
86 /// @details The graph doesn't know anything specific about amino acid types, for
87 /// instance, nothing specially distinguishes glycine and threonine.
88 /// The sparse-matrix representation for the PDEdge two-body energy tables
89 /// requires knowing when two states are of the *same* amino acid type and
90 /// when they are *different* amino acid types.
91 ///
92 /// @param aatypes_for_state - [in] - amino acid type for each state in the node
93 void PDNode::set_amino_acid_types( std::vector< int > const & aatypes_for_state)
94 {
95  assert(aatypes_for_state.size() == (Size)(get_num_states() + 1) );
96 
97  for (int ii = 1; ii <= get_num_states(); ++ii) {
98  assert( aatypes_for_state[ii] > 0 && aatypes_for_state[ii] <= (int)num_states_for_aatype_.size());
99 
100  sparse_mat_info_for_state_[ii].set_aa_type( aatypes_for_state[ii] );
101 
102  ++(num_states_for_aatype_[sparse_mat_info_for_state_[ii].get_aa_type() ] );
103 
104  sparse_mat_info_for_state_[ii].set_state_ind_for_this_aa_type(
106  }
107  return;
108 }
109 
110 int
111 PDNode::aatype_for_state( int state ) const
112 {
113  return sparse_mat_info_for_state_[ state ].get_aa_type();
114 }
115 
116 
117 /// @details Used by AminoAcidNeighborSparseMatrix. The FArray must persist for
118 /// as long as any AminoAcidNeighborSparseMatrix points to it.
119 ///
122 {
123  return num_states_for_aatype_;
124 }
125 
126 
127 /// @param state - [in] - one-based index of the state
128 /// @param energy - [in] - the energy that should be set.
130 {
131  one_body_energies_[ state ] = energy;
132  return;
133 }
134 
135 /// @param energies - [in] - the array of energies. Must hold num_states_ entries
136 void PDNode::update_one_body_energies( FArray1< core::PackerEnergy > & energies )
137 {
138  assert( energies.size() == (unsigned int) get_num_states() );
139  for (int ii = 1; ii <= get_num_states(); ++ii) {
140  one_body_energies_[ ii ] = energies( ii );
141  }
142  return;
143 }
144 
145 
146 /// @param state - [in] - one-based index of the state
147 /// @param energy - [in] - the energy that should be added.
148 ///
150 {
151  one_body_energies_[ state ] += energy;
152  return;
153 }
154 
155 /// @param energies - [in] - the array of energies. Must hold num_states_ entries
156 void PDNode::add_to_one_body_energies( FArray1< core::PackerEnergy > & energies )
157 {
158  assert( energies.size() == (unsigned int) get_num_states() );
159  for (int ii = 1; ii <= get_num_states(); ++ii) {
160  one_body_energies_[ ii ] += energies( ii );
161  }
162  return;
163 }
164 
166 {
167  for (int ii = 1; ii <= get_num_states(); ++ii) {
168  one_body_energies_[ ii ] = 0;
169  }
170 }
171 
172 
173 
174 /// @param state - [in]
176 {
177  return one_body_energies_[ state ];
178 }
179 
180 
181 
182 /// @details updates internal edge vector + other vectorized edge information
184 {
186  return;
187 }
188 
189 /*
190 /// @brief old method for figuring out how much memory the IG is using; deprecated
191 unsigned int
192 PDNode::getMemoryUsageInBytes() const
193 {
194  unsigned int total_memory = 0;
195  total_memory += num_states_for_aatype_.size() * sizeof( int );
196  total_memory += sparse_mat_info_for_state_.size() * sizeof( SparseMatrixIndex );
197  total_memory += one_body_energies_.size() * sizeof( core::PackerEnergy );
198  total_memory += neighbors_curr_state_.size() * sizeof (int );
199 
200  total_memory += aa_offsets_for_edges_.size() * sizeof( int );
201  total_memory += num_states_for_aa_type_for_higher_indexed_neighbor_.size() * sizeof( int );
202  total_memory += neighbors_curr_state_.size() * sizeof( int );
203  total_memory += neighbors_curr_state_sparse_info_.size() * sizeof( SparseMatrixIndex );
204  total_memory += edge_matrix_ptrs_.size() * sizeof( FArray1A< core::PackerEnergy > );
205 
206  total_memory += curr_state_two_body_energies_.size() * sizeof( float );
207  total_memory += alternate_state_two_body_energies_.size() * sizeof( float );
208 
209  total_memory += sizeof( PDNode );
210  //total_memory += NodeBase::getMemoryUsageInBytes();
211  return total_memory;
212 }
213 */
214 
215 
216 
217 
218 /// @details zeros the edge-energy array, informs neighbors that it's in its unassigned
219 /// state
220 ///
222 {
223 
224  //std::cerr << "assign_state: node - " << get_node_index() <<
225  // " new state " << 0 << "...";
226 
227  current_state_ = 0;
228  alternate_state_ = 0;
230 
232  //fills from [1] to end
233  std::vector< float >::iterator position1 = curr_state_two_body_energies_.begin();
234  ++position1;
235  std::fill( position1,
237  0.0f);
239 
240  for (int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
242  acknowledge_state_zeroed( get_node_index() );
243  }
244 
245  return;
246 }
247 
248 
249 
250 
251 /// @note updates its curr_state one and two body energies
252 ///
253 /// @param new_state - [in] - the new state the node should be assigned
254 ///
255 void PDNode::assign_state(int new_state)
256 {
257  assert( new_state >= 0 && new_state <= get_num_states());
258 
259  if (new_state == 0) {
261  } else {
262  //std::cerr << "assign_state: node - " << get_node_index() <<
263  // " new state " << new_state << "...";
264  current_state_ = new_state;
270 
271  for (int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
273  get_node_index(),
277 
279  }
280  //std::cerr<< "..done" << std::endl;
281  }
282  return;
283 }
284 
286 {
287  return current_state_;
288 }
289 
290 
292 {
294 }
295 
296 
297 
298 /// @brief tells the node that it should change its state to the last state it was
299 /// asked to consider (from a call to project_deltaE_for_substitution)
300 ///
301 /// updates edge energy vector, iterates across neighbors having them update
302 /// their edge energies. Bookkeeping recaptures performance lost by
303 /// leaving energy2b structure
305 {
307 
312 
313  //copies from [1] to end
314  std::vector< float >::iterator alt_position1 = alternate_state_two_body_energies_.begin();
315  ++alt_position1;
316  std::vector< float >::iterator curr_position1 = curr_state_two_body_energies_.begin();
317  ++curr_position1;
318 
319  std::copy( alt_position1,
321  curr_position1 );
322 
323  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
325  get_node_index(),
329  );
330  }
331 
333  return;
334 }
335 
336 
337 /// @brief updates bookkeeping arrays that correspond to edge-list.
338 ///
339 /// calls base class update_edge_vector function, and then proceeds to create
340 /// appropriate bookkeeping arrays used in simulated annealing
341 ///
342 /// It's possible that a derived class created an Edge, but that Edge doesn't have any two body energies. For example,
343 /// in the HPatchIG, two residues (Nodes) may have SASA overlap, but be outside of the 5.5A energy function cutoff.
344 /// To handle this case, check the size of the two-body energy table before trying to dereference it. (ronj)
345 ///
347 {
349  //aa_offsets_for_this_lookup_.resize( get_num_incident_edges() + 1);
352 
353  edge_matrix_ptrs_.clear();
355  edge_matrix_ptrs_.push_back( FArray1A< core::PackerEnergy >() ); //occupy the 0th position
356 
357  aa_offsets_for_edges_.dimension(
361 
362  //copy offsets from edges
363  //int neighb_aa_offset =
364  // num_states_for_aa_type_for_higher_indexed_neighbor_.index(1,1);
365  int count_neighbs_with_higher_indices = 0;
366  for (int ii = 1; ii <= get_num_incident_edges(); ++ii) {
367  neighbors_curr_state_sparse_info_[ii].set_aa_type( 1 );
368 
369  // Edge::get_edge_table_ptr() calls getMatrixPointer() on the AminoAcidNeighborSparseMatrix instance two_body_energies_
370  // kept on the Edge. getMatrixPointer() returns a reference to the first element in this table. Problem is that
371  // if there are no two-body energies, dereferencing the pointer that's kept in AANSM causes an FArray operator()
372  // out-of-bounds error. Instead, reorder these lines so that we first check the two-body table size, and only call
373  // get_edge_table_ptr() if the two-body energy table is nonzero. If it's all zeros, just add an FArray1A object
374  // that's been default constructed (the default constructor just sets the internal pointers to NULL) to the
375  // edge_matrix_ptrs_. (ronj)
376  int edge_table_size = get_incident_pd_edge(ii)->get_two_body_table_size();
377  if ( edge_table_size != 0 ) {
378  float & edge_table_ref = get_incident_pd_edge(ii)->get_edge_table_ptr();
379  edge_matrix_ptrs_.push_back( FArray1A< core::PackerEnergy >( edge_table_ref ));
380  edge_matrix_ptrs_[ii].dimension( edge_table_size );
381  } else {
382  edge_matrix_ptrs_.push_back( FArray1A< core::PackerEnergy >() );
383  }
384 
385  FArray2D_int const & edge_aa_neighb_offsets =
387  utility::vector1< int > const & neighb_num_states_per_aa =
389 
391  ++count_neighbs_with_higher_indices;
392  for ( int jj = 1; jj <= num_aa_types_; ++jj ) {
393  for ( int kk = 1; kk <= num_aa_types_; ++kk ) {
394  aa_offsets_for_edges_(kk, ii, jj) = edge_aa_neighb_offsets(kk, jj);
395  }
397  jj, count_neighbs_with_higher_indices) =
398  neighb_num_states_per_aa[ jj ];
399  //++neighb_aa_offset;
400  }
401  } else {
402  for ( int jj = 1; jj <= num_aa_types_; ++jj ) {
403  for ( int kk = 1; kk <= num_aa_types_; ++kk ) {
404  aa_offsets_for_edges_(kk, ii, jj) =
405  edge_aa_neighb_offsets(jj, kk);
406  }
407  }
408  }
409  }
410 
413  return;
414 }
415 
416 /// @brief - allow derived class to "drive" through the deltaE calculation
417 void
418 PDNode::calc_deltaEpd( int alternate_state )
419 {
420  //std::cout << "PDNode::calc_deltaEpd" << std::endl;
421 
422  float dummy(0.0f);
423  project_deltaE_for_substitution( alternate_state, dummy );
424 }
425 
426 
427 /// @brief returns the sparse matrix information for a paricular state
428 ///
429 /// @param state - [in] - the state whose information is requested
430 SparseMatrixIndex const &
432 {
433  assert( state > 0 && state <= get_num_states());
434  return sparse_mat_info_for_state_[ state ];
435 }
436 
437 /// @brief returns the sparse matrix information for the current state
438 ///
439 SparseMatrixIndex const &
441 {
443 }
444 
445 /// @brief returns the number of states that are of a particular amino acid type
446 ///
447 /// @param aa_type - [in] - the amino acid type in question
448 ///
449 int
451 {
452  return num_states_for_aatype_[ aa_type ];
453 }
454 
455 /// @brief outputs to standard error the bookkeeping energies for the node in its
456 /// current state assignment
457 ///
459 {
460  std::cerr << "curr_state " << current_state_ << " ";
461  std::cerr << "curr_state_sparse_mat_info_ ";
462  std::cerr << curr_state_sparse_mat_info_.get_aa_type() << " ";
464  std::cerr << "curr_state_one_body_energy_ ";
465  std::cerr << curr_state_one_body_energy_ << " ";
466  std::cerr << "curr_state_total_energy_" << curr_state_total_energy_ << " ";
467  for (int ii = 1; ii <= get_num_incident_edges(); ++ii)
468  {
469  std::cerr << "(" << get_index_of_adjacent_node( ii ) << ": " <<
470  curr_state_two_body_energies_[ ii ] << ") ";
471  }
472  std::cerr << std::endl;
473 }
474 
475 /// @brief removes numerical drift long stretches of efficient bookkeeping
476 /// produces
477 ///
479 {
480  assert( get_edge_vector_up_to_date() );
482  for (int ii = 1; ii <= get_num_incident_edges(); ++ii) {
485  }
487  return;
488 }
489 
490 unsigned int
492 {
493  return sizeof ( PDNode );
494 }
495 
496 unsigned int
498 {
499  unsigned int total_memory = 0;
500  total_memory += num_states_for_aatype_.size() * sizeof( int );
501  total_memory += sparse_mat_info_for_state_.size() * sizeof( SparseMatrixIndex );
502  total_memory += one_body_energies_.size() * sizeof( core::PackerEnergy );
503  total_memory += neighbors_curr_state_.size() * sizeof (int );
504 
505  total_memory += aa_offsets_for_edges_.size() * sizeof( int );
506  total_memory += num_states_for_aa_type_for_higher_indexed_neighbor_.size() * sizeof( int );
507  total_memory += neighbors_curr_state_.size() * sizeof( int );
508  total_memory += neighbors_curr_state_sparse_info_.size() * sizeof( SparseMatrixIndex );
509  total_memory += edge_matrix_ptrs_.size() * sizeof( FArray1A< core::PackerEnergy > );
510 
511  total_memory += curr_state_two_body_energies_.size() * sizeof( float );
512  total_memory += alternate_state_two_body_energies_.size() * sizeof( float );
513 
514  total_memory += NodeBase::count_dynamic_memory();
515  return total_memory;
516 
517 }
518 
519 
520 /*
521 
522 /// @brief ready a node for the output-to-file process
523 ///
524 /// allocates space for an additional array that counts the number of states
525 /// for each amino acid
526 ///
527 void PDNode::prepare_to_write_to_file()
528 {
529  initialize_aa_for_state_array();
530 }
531 
532 
533 /// @brief counts the number of states for each amion acid
534 void PDNode::initialize_aa_for_state_array()
535 {
536  aa_types_for_instance_states_.dimension( get_num_states() );
537  for (int ii = 1; ii <= get_num_states(); ++ii)
538  {
539  aa_types_for_instance_states_(ii) = sparse_mat_info_for_state_[ii].get_aa_type();
540  }
541 }
542 
543 /// @brief deallocates extra memory allocated before writing to a file
544 void PDNode::clean_up_after_writing_to_file()
545 {
546  aa_types_for_instance_states_.dimension(0);
547 }
548 
549 /// @brief allocates extra space required of reading to a file
550 ///
551 /// this graph instance may not correspond perfectly to the rotamers
552 /// described in the file. Before reading pair energies from the file
553 /// a correspondnece must be found between the "instance states" and
554 /// and the "file states". RotamerSets.cc finds the correspondence.
555 /// Each node keeps track of the correspondence - which instance states
556 /// correspond to which file states, and which instance states have no
557 /// corresponding file states. A vertex also keeps track of which
558 /// amino acid type for each of file state. Amino acid type information is
559 /// necessary for reading in the sparse table that relies on the amino-acid
560 /// neighbor optimization.
561 ///
562 /// @param num_states_for_node_in_file - [in] - the number of states on the corresponding
563 /// node from the file
564 ///
565 void PDNode::prepare_to_read_energies_from_file(int num_states_for_node_in_file)
566 {
567  int num_aa_types_in_file =
568  get_pdig_owner()->get_num_file_aatypes();
569 
570  num_states_in_file_ = num_states_for_node_in_file;
571  instance_states_2_file_states_.dimension( get_num_states() );
572  file_states_2_instance_states_.dimension( num_states_for_node_in_file );
573  aa_types_for_file_states_.dimension( num_states_for_node_in_file );
574  num_file_states_for_aa_.dimension( num_aa_types_in_file );
575 
576  instance_states_2_file_states_ = -1;
577  file_states_2_instance_states_ = -1;
578  aa_types_for_file_states_ = -1;
579  num_file_states_for_aa_ = 0;
580 
581  initialize_aa_for_state_array(); //apl borrowing functionality from wri
582 }
583 
584 /// @brief deallocate extra tables after having written to a file
585 void PDNode::clean_up_after_reading_energies_from_file()
586 {
587  instance_states_2_file_states_.dimension(0);
588  file_states_2_instance_states_.dimension(0);
589  aa_types_for_file_states_.dimension(0);
590  aa_types_for_instance_states_.dimension(0);
591  num_file_states_for_aa_.dimension(0);
592 }
593 
594 /// @brief set the amino acid type for a file-state
595 ///
596 /// This method assumes that each file state will have its aa type set
597 /// before edge energies are read. The structure of the interaction
598 /// graph file ensures that the amino acid type information is present for
599 /// each file state. During RotamerSets.cc::read_rotamer_sets_from_file
600 /// the information must be transmitted to the interaction graph.
601 /// If this code quit rosetta, it's because the intereaction graph file
602 /// holds an amino-acid type out of bounds.
603 ///
604 /// @param file_state - [in] - the index of the file state
605 /// @param aa - [in] - the amino acid type of the file state
606 ///
607 void PDNode::set_aa_for_file_state(int file_state, int aa )
608 {
609  if ( (unsigned int) aa > num_file_states_for_aa_.size() || aa <= 0)
610  {
611  std::cerr << "Error in interaction graph file: amino acid type out";
612  std::cerr << " of range on node: " << get_node_index() << " for file state ";
613  std::cerr << file_state << ": aa = " << aa << std::endl;
614  utility_exit();
615  }
616  aa_types_for_file_states_( file_state ) = aa;
617  ++num_file_states_for_aa_( aa );
618 }
619 
620 /// @brief declares that an instance state corresponds to a file state.
621 ///
622 /// Trouble arises if rotamers are repeated, and the code that detects the
623 /// correspondence doesn't prevent multiple correspondences (multiple file
624 /// states to a single instance state or multiple instance states to a
625 /// single file state.) The way I've written the RotamerSets.cc::
626 /// find_correspondence_between_file_and_instance() code enforces the bijection.
627 ///
628 /// @param instance_state - [in] - the index of the instance state
629 /// @param state_from_file - [in] - the index of the file state
630 ///
631 void PDNode::set_instance_state_correspondence
632 (
633  int instance_state,
634  int state_from_file
635 )
636 {
637  //apl Enforce bijection:
638  //apl Much easier to handle I/O when no to file-states map to a single
639  //apl instance state, and no two instance states map to a single file state.
640  //apl If a protocol creates two identical rotamers before reading the
641  //apl interaction graph file, then that protocol must also
642  //apl have generated the same identical rotamers before writing the
643  //apl interaction graph file.
644  if ( instance_states_2_file_states_( instance_state ) != -1
645  || file_states_2_instance_states_( state_from_file ) != -1 )
646  {
647  std::cerr << "Reading Interaction Graph from File: Bijection Failure" << std::endl;
648  std::cerr << "Node: " << get_node_index() << " instance_state " << instance_state;
649  std::cerr << "file_state: " << state_from_file << std::endl;
650  std::cerr << "First Correspondence: instance_states_2_file_states_( ";
651  std::cerr << instance_state << " ) = " << instance_states_2_file_states_( instance_state );
652  std::cerr << std::endl << "First Correspondence: file_states_2_instance_staets_( ";
653  std::cerr << state_from_file << " ) = " << file_states_2_instance_states_( state_from_file );
654  std::cerr << std::endl;
655  utility_exit();
656  }
657 
658  instance_states_2_file_states_( instance_state ) = state_from_file;
659  file_states_2_instance_states_( state_from_file ) = instance_state;
660 }
661 
662 
663 /// @brief return the file state that corresponds to an instance state
664 ///
665 /// @param instance_state - [in] - the index of the instance state
666 ///
667 int PDNode::get_correspondence_for_state( int instance_state )
668 {
669  return instance_states_2_file_states_( instance_state );
670 }
671 
672 /// @brief returns the number of instance states that did not correspond to any
673 /// file state. The rotamers these states correspond to were absent from
674 /// the file, and their pair energies must be computed.
675 ///
676 int PDNode::get_num_rots_absent_from_file()
677 {
678  if ( instance_states_2_file_states_.size() == 0 )
679  {
680  //no correspondence found with input file
681  return get_num_states();
682  }
683 
684  int count_absent = 0;
685  for (int ii = 1; ii <= get_num_states(); ++ii)
686  {
687  if (instance_states_2_file_states_(ii) == -1 )
688  {
689  ++count_absent;
690  }
691  }
692  return count_absent;
693 }
694 
695 /// @brief writes the index of the instance states with no matching file states into
696 /// the input FArray which should be large enough to hold them.
697 /// If the node itself had no matching node in the input file, then all
698 /// rotamers were absent from the file.
699 ///
700 void PDNode::get_absent_rots( FArray1_int & rots_absent )
701 {
702  if ( instance_states_2_file_states_.size() == 0 ) {
703  //no correspondence found with input file
704  for (int ii = 1; ii <= get_num_states(); ++ii) {
705  rots_absent(ii) = ii;
706  }
707  return;
708  }
709 
710  int count_absent = 0;
711  for (int ii = 1; ii <= get_num_states(); ++ii) {
712  if (instance_states_2_file_states_(ii) == -1 ) {
713  ++count_absent;
714  rots_absent( count_absent ) = ii;
715  }
716  }
717 }
718 
719 /// @brief returns the number of file states for this node
720 int PDNode::get_num_states_in_file()
721 {
722  return num_states_in_file_;
723 }
724 
725 /// @brief returns a reference to the first entry in the aa_types_for_file_states_
726 /// array so that an FArray1A can be constructed.
727 ///
728 /// used by a PDEdge while it's reading energies from a file
729 int & PDNode::get_aatypes_for_file_states()
730 {
731  return aa_types_for_file_states_(1);
732 }
733 
734 /// @brief returns a reference to the first entry in the aa_types_for_instance_states_
735 /// array so that an FArray1A can be constructed.
736 ///
737 /// used by a PDEdge while it's reading energies from a file
738 int & PDNode::get_aatypes_for_states()
739 {
740  return aa_types_for_instance_states_(1);
741 }
742 
743 /// @brief returns a reference to the first entry in the num_file_states_for_aa_
744 /// array so that an FArray1A can be constructed.
745 ///
746 /// used by a PDEdge while it's reading energies from a file
747 ///
748 int & PDNode::get_num_file_states_for_aa()
749 {
750  return num_file_states_for_aa_(1);
751 }
752 
753 /// @brief returns a reference to the first entry in the file_states_2_instance_states_
754 /// array so that an FArray1A can be constructed.
755 ///
756 /// used by a PDEdge while it's reading energies from a file
757 ///
758 int & PDNode::get_file_states_2_instance_states_array()
759 {
760  return file_states_2_instance_states_(1);
761 }
762 
763 /// @brief returns true if a node corresponds to one of the nodes described in the
764 /// input file, and false if that node does not correspond to any.
765 ///
766 bool PDNode::get_node_corresponded_to_file_node()
767 {
768  return (instance_states_2_file_states_.size() != 0 );
769 }
770 
771 */
772 
773 //-------------------------------------------------------------------------------//
774 //-------- Sparse Pairwise Decomposable Interaction Graph Edge Class ------------//
775 //-------------------------------------------------------------------------------//
776 
777 /// @brief main constructor - no default nor copy constructors provided
778 ///
779 /// @param owner - [in] - pointer to the graph that created this node
780 /// @param first_node_ind - [in] - the index of the smaller-indexed node
781 /// @param second_node_ind - [in] - the index of the larger-indexed node
782 ///
785  int first_node_ind,
786  int second_node_ind
787 ) :
788  PrecomputedPairEnergiesEdge( owner, first_node_ind, second_node_ind),
789  //energy_table_size_(0)
790  two_body_energies_(
791  get_pd_node(0)->get_num_states_for_aa_types(),
792  get_pd_node(1)->get_num_states_for_aa_types()
793  ),
794  energies_updated_since_last_prep_for_simA_( true )
795 {
796  force_all_aa_neighbors();
797 }
798 
799 /// @brief destructor
801 {}
802 
803 /// @brief allocates two-body energy table based on amino-acid neighbor relationships
804 /// and initializes the table to 0.
805 ///
806 /// @param sparse_conn_info - [in] - a MAX_AA x MAX_AA 2D array where each "true" entry
807 /// means that the corresponding amino acid pair are neighbors.
808 ///
809 /// @remarks idea borrowed from energy2b implementation
810 ///
811 void PDEdge::set_sparse_aa_info(FArray2_bool const & sparse_conn_info)
812 {
813  two_body_energies_.set_sparse_aa_info( sparse_conn_info );
815 }
816 
817 /// @brief returns whether two amino acid types are represented as neighbors
818 bool PDEdge::get_sparse_aa_info( int node1aa, int node2aa ) const
819 {
820  return two_body_energies_.get_sparse_aa_info( node1aa, node2aa );
821 }
822 
823 /// @brief re-allocates two-body energy table after forcing a pair of amino acids
824 /// to become neighbors that were not initially declared to be neighbors
825 ///
826 /// @param node1aa - [in] - the amino acid type for the node with the smaller index
827 /// @param node2aa - [in] - the amino acid type for the node with the larger index
828 ///
829 void PDEdge::force_aa_neighbors(int node1aa, int node2aa)
830 {
831  two_body_energies_.force_aa_neighbors( node1aa, node2aa );
833 }
834 
835 /// @brief re-allocates two-body energy table after forcing a pair of amino acids
836 /// to become neighbors that were not initially declared to be neighbors
837 ///
838 /// @param node1aa - [in] - the amino acid type for the node with the smaller index
839 /// @param node2aa - [in] - the amino acid type for the node with the larger index
840 ///
842 {
845 }
846 
847 /// @brief adds the input energy to the two body energy for state1 on the node with the
848 /// smaller index and state2 on the node with the larger index so long as
849 /// the amion acid types of those states have been previously declared amino
850 /// acid neighbors. Any energies for non-neighboring states are ignored.
851 ///
853 (
854  int const state1,
855  int const state2,
856  float const energy
857 )
858 {
859  two_body_energies_.add(
860  get_pd_node(0)->get_sparse_mat_info_for_state(state1),
861  get_pd_node(1)->get_sparse_mat_info_for_state(state2),
862  edge_weight() * energy);
863  energies_updated_since_last_prep_for_simA_ = true;
864  return;
865 }
866 
867 /// @brief Adds all the energies stored in the oversized_res_res_energy array to the
868 /// two body energy table for those states whose amion acid types were
869 /// previoudsly declared to be amino-acid neighbors. The res-res array
870 /// should have the dimension (node1->get_num_states() x node2->get_num_states());
871 ///
872 /// @param res_res_energy_array - [in] - an array containing the state pair
873 /// energies
874 ///
876 (
877  FArray2< core::PackerEnergy > const & res_res_energy_array
878 )
879 {
880  for ( int ii = 1; ii <= get_num_states_for_node(0); ++ii ) {
881  SparseMatrixIndex const & state1_sparse_info = get_pd_node(0)
882  ->get_sparse_mat_info_for_state( ii );
883  for ( int jj = 1; jj <= get_num_states_for_node(1); ++jj ) {
884  SparseMatrixIndex const & state2_sparse_info = get_pd_node(1)
885  ->get_sparse_mat_info_for_state( jj );
886 
887  two_body_energies_.add(
888  state1_sparse_info, state2_sparse_info,
889  edge_weight() * res_res_energy_array( jj, ii )
890  );
891  }
892  }
893  energies_updated_since_last_prep_for_simA_ = true;
894  return;
895 }
896 
897 /// @brief Sets the two-body energy for a pair of states. That is, it overwrites
898 /// whatever two-body energy there was previously for that state pair with
899 /// a new energy. Ignores non-neighboring state pairs.
900 ///
901 /// @param state1 - [in] - state index for the node with the smaller index
902 /// @param state2 - [in] - state index for the node with the larger index
903 /// @param energy - [in] - the energy which replaces the old two-body energy
904 ///
906 (
907  int const state1,
908  int const state2,
909  float const energy
910 )
911 {
912  two_body_energies_.set(
913  get_pd_node(0)->get_sparse_mat_info_for_state(state1),
914  get_pd_node(1)->get_sparse_mat_info_for_state(state2),
915  edge_weight() * energy
916  );
917  energies_updated_since_last_prep_for_simA_ = true;
918  return;
919 }
920 
921 /// @brief Sets the two-body energy for a pair of states. That is, it overwrites
922 /// whatever two-body energy there was previously for that state pair with
923 /// a new energy. Ignores non-neighboring state pairs.
924 ///
925 /// @param state1 - [in] - state index for the node with the smaller index
926 /// @param state2 - [in] - state index for the node with the larger index
927 /// @param energy - [in] - the energy which replaces the old two-body energy
928 ///
930 (
931  int const state1,
932  int const state2
933 )
934 {
935  two_body_energies_.set(
936  get_pd_node(0)->get_sparse_mat_info_for_state(state1),
937  get_pd_node(1)->get_sparse_mat_info_for_state(state2),
938  0.
939  );
940 
941  return;
942 }
943 
944 /// @brief returns the two body energy for a pair of states: 0 if those states are
945 /// not neighbors
946 ///
947 /// @param state1 - [in] - state index for the node with the smaller index
948 /// @param state2 - [in] - state index for the node with the larger index
949 ///
950 float PDEdge::get_two_body_energy( int const state1, int const state2) const
951 {
952  return two_body_energies_.get(
953  get_pd_node(0)->get_sparse_mat_info_for_state(state1),
954  get_pd_node(1)->get_sparse_mat_info_for_state(state2));
955 }
956 
957 /// @brief When all the energies that are going to be stored in an edge have been
958 /// placed in it, the edge may save some memory by shrinking its AminoAcidNeighborSparseMatrix.
959 /// This method instructs the edge to do so.
961 {
963 }
964 
965 /// @brief reduces the size of the pair-energy table if any amino-acid-neighbor
966 /// submatrices hold nothing but 0's
967 ///
968 /// since the drop_zero_submatrices_where_possible() method of the AANSM is
969 /// somewhat time consuming, and since it can only reduce memory use / simA
970 /// running time on the first execution following an update to the two-body
971 /// energies, the PDEdge member variable energies_updated_since_last_prep_
972 /// for_simA ensures that the AANSM method is only called once following
973 /// the update of any RPEs.
974 ///
976 {
978  if (two_body_energies_.get_table_size() == 0) delete this;
979 }
980 
981 /*
982 unsigned int
983 PDEdge::getMemoryUsageInBytes() const
984 {
985  unsigned int total_memory = 0;
986  total_memory += two_body_energies_.get_table_size() * sizeof( int );
987  total_memory += two_body_energies_.get_offset_table_size_in_bytes();
988  total_memory += sizeof( PDEdge );
989  return total_memory;
990 }
991 */
992 
993 /// @brief returns the two body energy corresponding to the current states assigned to
994 /// the nodes this edge is incident upon.
995 ///
997 {
998  return curr_state_energy_;
999 }
1000 
1001 /// @brief updates bookkeeping information when one of the two nodes changes its state
1002 ///
1003 /// @param node_ind - [in] - the index of the node that changed its state
1004 /// @param node_state - [in] - the index of the new state it assumed
1005 /// @param new_state_spare_info - [in] - the sparse-matrix information for the state
1006 /// @param new_energy - [out] - the two body energy produced by the new state and
1007 /// the current state on the other node
1008 ///
1009 void
1012  int node_ind,
1013  int new_state,
1014  SparseMatrixIndex const & new_state_sparse_info,
1015  float & new_energy
1016 )
1017 {
1018  int node_substituted = ( node_ind == get_node_index(0) ? 0 : 1);
1019  int node_not_substituted = ! node_substituted;
1020 
1021  int nodes_curr_states[2];
1022  SparseMatrixIndex nodes_curr_states_sparse_info[2];
1023 
1024  nodes_curr_states[ node_substituted ] = new_state;
1025  nodes_curr_states_sparse_info[ node_substituted ] = new_state_sparse_info;
1026 
1027  nodes_curr_states[ node_not_substituted ] =
1028  get_pd_node( node_not_substituted )->get_current_state();
1029  nodes_curr_states_sparse_info[ node_not_substituted ] =
1030  get_pd_node( node_not_substituted )->
1031  get_sparse_mat_info_for_curr_state();
1032 
1033  bool one_node_in_zero_state =
1034  ( nodes_curr_states[0] == 0 || nodes_curr_states[1] == 0 );
1035 
1036  if ( one_node_in_zero_state ) {
1037  curr_state_energy_ = 0;
1038  } else {
1039  curr_state_energy_ = two_body_energies_.get(
1040  nodes_curr_states_sparse_info[0],
1041  nodes_curr_states_sparse_info[1]);
1042  }
1043  new_energy = curr_state_energy_;
1044 
1045  get_pd_node( node_not_substituted )->
1046  acknowledge_neighbors_state_substitution(
1047  get_edges_position_in_nodes_edge_vector( node_not_substituted ),
1048  curr_state_energy_,
1049  new_state,
1050  new_state_sparse_info
1051  );
1052 
1053  return;
1054 }
1055 
1056 
1057 /// @param node_ind - [in] - the index of the node that has just entered its 0 state
1059 {
1060  int node_substituted = ( node_ind == get_node_index(0) ? 0 : 1);
1061  int node_not_substituted = ! node_substituted;
1062 
1063  curr_state_energy_ = 0;
1064  SparseMatrixIndex dummy_sparse_info;
1065  dummy_sparse_info.set_aa_type( 1 );
1066  dummy_sparse_info.set_state_ind_for_this_aa_type(1);
1067 
1068  get_pd_node( node_not_substituted )->
1069  acknowledge_neighbors_state_substitution(
1070  get_edges_position_in_nodes_edge_vector( node_not_substituted ),
1072  0,
1073  dummy_sparse_info
1074  );
1075  return;
1076 }
1077 
1078 
1079 
1080 
1081 
1082 
1083 
1084 FArray2D_int const &
1086 {
1088 }
1089 
1092 {
1094 }
1095 
1096 /// @brief Returns a reference to the first element in the sparse two-body energy
1097 /// table. Used to create a proxy array on the nodes for cache efficiency.
1098 ///
1100  //std::cout << "PDEdge: get_edge_table_ptr(): two_body_energies_.size(): " << two_body_energies_.get_table_size() << std::endl;
1102 }
1103 
1104 unsigned int
1106 {
1107  return sizeof ( PDEdge );
1108 }
1109 
1110 unsigned int
1112 {
1113  unsigned int total_memory = 0;
1114  total_memory += two_body_energies_.get_table_size() * sizeof( int );
1116  total_memory += EdgeBase::count_dynamic_memory();
1117  return total_memory;
1118 }
1119 
1120 ObjexxFCL::FArray2D< core::PackerEnergy >
1122  int node1aa,
1123  int node2aa
1124 ) const
1125 {
1126  return two_body_energies_.get_aa_submatrix_energies( node1aa, node2aa );
1127 }
1128 
1129 
1130 /// @details DANGER: If for some reason one were to reweight edges during simulated annealing
1131 /// then some of the cached energies in the adjacent nodes would be out-of-date; data integrity
1132 /// would be violated an all hell would break loose. The same thing is true if one were to
1133 /// change the energies on any edge during simulated annealing. One simple solution: call
1134 /// blanket_assign_state0 to wipe all cahced energies stored on nodes and then assign_network_state
1135 /// to the state just before the reweighting.
1136 /// Of course, since the annealer itself is tracking the "best" network state, one would have to worry
1137 /// about its data integrity as well. General advice: don't change energies during simA.
1138 void
1140 {
1141  Real rescale = weight / edge_weight();
1142  two_body_energies_.scale( rescale );
1143  edge_weight( weight ); // set base-class data
1144 }
1145 
1146 
1147 /*
1148 
1149 /// @brief Reads the energies for an edge described in the input file and
1150 /// copies the energies that correspond to a pair of instance states into
1151 /// the edge energy table.
1152 ///
1153 /// Energies are represented in a binary file. They are stored using the
1154 /// same amino-acid neighbor technique that saves so much memory. The
1155 /// first part of the information in the file for this edge is the amino
1156 /// acid neighbor connectivity information; 400 bools ( num_aa ^ 2).
1157 /// From the number of file states for each amino acid, and the connectivity
1158 /// the number of edge energies present can be readily computed.
1159 /// This method allocates a large buffer to read in all the energies at once,
1160 /// minimizing the number of disk reads. It then walks through the buffer
1161 /// and writes the appropriate energies to the energy table for this edge.
1162 ///
1163 /// @param infile - [in/out] - the binary input file, that has already been advanced
1164 /// so that it's pointing at the position where the information for this
1165 /// edge is stored. At the end of this method, the infile will be advanced
1166 /// past all the data for this edge.
1167 ///
1168 void PDEdge::read_edge_energies_from_file( std::ifstream & infile )
1169 {
1170  std::cerr << "Reading Edge: " << get_node_index(0) << " " << get_node_index(1) << std::endl;
1171  int node1_num_states_in_file = get_pd_node(0)->get_num_states_in_file();
1172  int node2_num_states_in_file = get_pd_node(1)->get_num_states_in_file();
1173 
1174  FArray1A_int node1_file_states_2_instance_states(
1175  get_pd_node(0)->get_file_states_2_instance_states_array(),
1176  node1_num_states_in_file);
1177 
1178  FArray1A_int node2_file_states_2_instance_states(
1179  get_pd_node(1)->get_file_states_2_instance_states_array(),
1180  node2_num_states_in_file);
1181 
1182  FArray1A_int node1_aatypes_file_states(
1183  get_pd_node(0)->get_aatypes_for_file_states(),
1184  node1_num_states_in_file);
1185 
1186  FArray1A_int node2_aatypes_file_states(
1187  get_pd_node(1)->get_aatypes_for_file_states(),
1188  node2_num_states_in_file);
1189 
1190  int num_file_aa = get_pdig_owner()->get_num_file_aatypes();
1191  int num_aa = get_pdig_owner()->get_num_aatypes();
1192 
1193  FArray1A_int node1_num_file_states_for_aa(
1194  get_pd_node(0)->get_num_file_states_for_aa(),
1195  num_file_aa);
1196 
1197  FArray1A_int node2_num_file_states_for_aa(
1198  get_pd_node(1)->get_num_file_states_for_aa(),
1199  num_file_aa);
1200 
1201  int sqr_file_aa = num_file_aa * num_file_aa;
1202  FArray2D_bool aa_neighbors( num_aa, num_aa, false );
1203  bool* aa_neighbor_buffer = new bool[ sqr_file_aa ];
1204  for (int ii = 0; ii <= sqr_file_aa; ++ii)
1205  aa_neighbor_buffer[ii] = false;
1206 
1207  //std::cerr << "square file aa: " << sqr_file_aa << std::endl;
1208  infile.read( (char*) aa_neighbor_buffer, sizeof( bool ) * sqr_file_aa );
1209  //int num_bools_read = infile.gcount();
1210  //assert( num_bools_read == sizeof( bool ) * sqr_file_aa );
1211 
1212  int buffer_index = 0;
1213  int num_pair_energies = 0;
1214  for (int ii = 1; ii <= num_file_aa; ++ii) {
1215  for (int jj = 1; jj <= num_file_aa; ++jj) {
1216  aa_neighbors(jj, ii) = aa_neighbor_buffer[ buffer_index ];
1217  //std::cerr << aa_neighbor_buffer[ buffer_index ];
1218  if ( aa_neighbor_buffer[ buffer_index ] ) {
1219  num_pair_energies += node1_num_file_states_for_aa(ii) *
1220  node2_num_file_states_for_aa( jj );
1221  }
1222  ++buffer_index;
1223 
1224  }
1225  //std::cerr << std::endl;
1226  }
1227 
1228  //std::cerr << "num pair energies: " << num_pair_energies << std::endl;
1229 
1230  two_body_energies_.set_sparse_aa_info( aa_neighbors );
1231 
1232  float * energies_buffer = new float [ num_pair_energies ];
1233 
1234  infile.read( (char*) energies_buffer, sizeof( float ) * num_pair_energies );
1235  //int read_num_floats = infile.gcount();
1236  buffer_index = 0;
1237 
1238  for (int ii = 1; ii <= node1_num_states_in_file; ++ii) {
1239  int ii_aa = node1_aatypes_file_states( ii );
1240  int ii_instance_state = node1_file_states_2_instance_states( ii );
1241  for (int jj = 1; jj <= node2_num_states_in_file; ++jj) {
1242  int jj_aa = node2_aatypes_file_states( jj );
1243  int jj_instance_state = node2_file_states_2_instance_states( jj );
1244 
1245  if ( ! aa_neighbors(jj_aa, ii_aa ) ) continue;
1246 
1247  assert( buffer_index < num_pair_energies );
1248  float energy = energies_buffer[ buffer_index ];
1249  ++buffer_index;
1250 
1251  if ( ii_instance_state == -1 || jj_instance_state == -1 ) continue;
1252 
1253  two_body_energies_.set(
1254  get_pd_node(0)->get_sparse_mat_info_for_state(ii_instance_state),
1255  get_pd_node(1)->get_sparse_mat_info_for_state(jj_instance_state),
1256  energy);
1257  }
1258  }
1259 
1260  delete [] aa_neighbor_buffer;
1261  delete [] energies_buffer;
1262 }
1263 
1264 /// @brief Advances the infile past the section describing an edge between
1265 /// one (or two) file nodes that do not correspond to an instance node.
1266 ///
1267 /// This static method is very similar to the non-static
1268 /// get_edge_energies_from_file() above, except that it requires
1269 /// more input parameters, handed to it by a PDInteractionGraph instance
1270 /// since the method cannot request information from two nodes of the graph.
1271 /// instead of allocating a large buffer for the energies, it uses
1272 /// the ofstream method seekg to advance the read head past the energies
1273 /// for the absent edge.
1274 ///
1275 /// @param infile - [in/out] - the binary input file, that's been advanced to point
1276 /// at information for a file edge that will not be included in the instance
1277 /// interaction graph. At the end of this method, the file will point
1278 /// just past the information for this edge.
1279 /// @param num_file_aa - [in] - the number of aa types according to the file
1280 /// @param node1_num_file_states_for_aa - [in] - num states for aa on node 1
1281 /// @param node2_num_file_states_for_aa - [in] - num states for aa on node 2
1282 ///
1283 void
1284 PDEdge::skip_over_edge_energies_from_file
1285 (
1286  std::ifstream & infile,
1287  int num_file_aa,
1288  FArray1_int & node1_num_file_states_for_aa,
1289  FArray1_int & node2_num_file_states_for_aa
1290 )
1291 {
1292  int sqr_file_aa = num_file_aa * num_file_aa;
1293  bool* aa_neighbor_buffer = new bool[ sqr_file_aa ];
1294 
1295  infile.read( (char*) aa_neighbor_buffer, sizeof(bool) * sqr_file_aa);
1296 
1297  int buffer_index = 0;
1298  int num_pair_energies = 0;
1299  for (int ii = 1; ii <= num_file_aa; ++ii) {
1300  for (int jj = 1; jj <= num_file_aa; ++jj) {
1301  if ( aa_neighbor_buffer[ buffer_index ] ) {
1302  num_pair_energies += node1_num_file_states_for_aa( ii ) *
1303  node2_num_file_states_for_aa( jj );
1304  }
1305  ++buffer_index;
1306  }
1307  }
1308 
1309  //skip forward
1310  infile.seekg( sizeof( float ) * num_pair_energies, std::ios::cur );
1311  delete [] aa_neighbor_buffer;
1312 }
1313 
1314 /// @brief Writes the energies for this edge to a binary output file.
1315 ///
1316 /// First writes out the amino acid neighbor information for this edge
1317 /// then writes out the energies.
1318 ///
1319 /// @param outfile - [in/out] - the binary output file to write to.
1320 ///
1321 void PDEdge::write_edge_energies_to_file( std::ofstream & outfile )
1322 {
1323  FArray1A_int node1_aatypes_for_state(
1324  get_pd_node(0)->get_aatypes_for_states(),
1325  get_num_states_for_node(0) );
1326 
1327  FArray1A_int node2_aatypes_for_state(
1328  get_pd_node(1)->get_aatypes_for_states(),
1329  get_num_states_for_node(1) );
1330 
1331  //write the aa-neighbor information
1332  int num_aa = get_pdig_owner()->get_num_aatypes();
1333  int sqr_num_aa = num_aa * num_aa;
1334  bool * aa_neighbor_buffer = new bool[ sqr_num_aa ];
1335  int buffer_index = 0;
1336 
1337  for (int ii = 1; ii <= num_aa; ++ii) {
1338  for (int jj = 1; jj <= num_aa; ++jj) {
1339  if ( two_body_energies_.get_sparse_aa_info(ii, jj) ) {
1340  aa_neighbor_buffer[ buffer_index ] = true;
1341  } else {
1342  aa_neighbor_buffer[ buffer_index ] = false;
1343  }
1344  //std::cerr << aa_neighbor_buffer[ buffer_index ];
1345  ++buffer_index;
1346  }
1347  //std::cerr << std::endl;
1348  }
1349  outfile.write( (char*) aa_neighbor_buffer, sizeof( bool ) * sqr_num_aa );
1350 
1351  float * energy_buffer = new float[ two_body_energies_.get_table_size() ];
1352  buffer_index = 0;
1353  for (int ii = 1; ii <= get_num_states_for_node(0); ++ii ) {
1354  int ii_aa = node1_aatypes_for_state( ii );
1355  for (int jj = 1; jj <= get_num_states_for_node(1); ++jj ) {
1356  int jj_aa = node2_aatypes_for_state( jj );
1357  if ( ! two_body_energies_.get_sparse_aa_info(ii_aa, jj_aa) ) continue;
1358 
1359  energy_buffer[ buffer_index ] = get_two_body_energy( ii, jj );
1360  ++buffer_index;
1361  }
1362  }
1363 
1364  outfile.write( (char*) energy_buffer, sizeof(float) * two_body_energies_.get_table_size() );
1365  std::cerr << "Writing edge: " << get_node_index(0) << " " << get_node_index(1);
1366  std::cerr << "; num_energies: " << two_body_energies_.get_table_size() << std::endl;
1367  delete [] aa_neighbor_buffer;
1368  delete [] energy_buffer;
1369 }
1370 
1371 */
1372 
1373 /// @brief allow derived class to prep this class for simA, but guarantee no call to delete this;
1375 {
1377 }
1378 
1379 /// @brief - allow derived class to prep this class for simA, but guarantee no call to delete this;
1381 {
1383 
1384  //std::cout << "PDEdge: prepare_for_simulated_annealing_no_deletion(): two_body_energies table size before drop call: " << two_body_energies_.get_table_size() << std::endl;
1386  //std::cout << "PDEdge: prepare_for_simulated_annealing_no_deletion(): two_body_energies table size after drop call: " << two_body_energies_.get_table_size() << std::endl;
1388 }
1389 
1390 //// @brief - if edge table is empty, returns true -- assumes
1391 /// prepare_for_simulated_annealing_no_deletion() has been called first.
1393 {
1395  return ( two_body_energies_.get_table_size() == 0);
1396 }
1397 
1398 
1399 
1400 /// @brief drops any amino-acid neighbor submatrix of the two-body energy table
1401 /// when the magnitudes of the energies stored in that submatrix do not exceed
1402 /// the input parameter, epsilon. Dropping submatrices that contain zero
1403 /// energies is a special case of this function where epsilon == 0.
1404 ///
1405 /// @param epsilon - [in] - the magnitude threshold for keeping amino-acid neighbor
1406 /// submatrices.
1407 ///
1409 {
1411  return;
1412 }
1413 
1414 /// @brief drops amino-acid neighbor submatrices when they do not contain any non-zero
1415 /// entries. Represents a special case of drop_small_submatrices_where_possible
1416 ///
1418 {
1420  return;
1421 }
1422 
1423 
1424 /// @brief returns the memory usage of the two body energy table for this edge
1425 ///
1427 {
1429 }
1430 
1431 //----------------------------------------------------------------------------//
1432 //-------- Sparse Pairwise Decomposable Interaction Graph Class --------------//
1433 //----------------------------------------------------------------------------//
1434 
1435 /// @brief main constructor: no default nor copy constructors provided.
1436 ///
1437 ///
1438 /// @param num_nodes - [in] - the number of nodes in this graph
1441  num_aa_types_( -1 ), num_commits_since_last_update_(0),
1442  total_energy_current_state_assignment_(0),
1443  total_energy_alternate_state_assignment_(0),
1444  node_considering_alt_state_( -1 )
1445 {}
1446 
1447 void
1449 {
1450  rotamer_set::RotamerSets const & rot_sets( static_cast< rotamer_set::RotamerSets const & > (rot_sets_base) );
1451 
1452  // determine max # of residue type groups
1453  Size max_nresgroups = 0;
1454  for ( Size ii = 1; ii <= rot_sets.nmoltenres(); ++ii ) {
1455  Size ii_nresgroups = rot_sets.rotamer_set_for_moltenresidue( ii )->get_n_residue_groups();
1456  if ( ii_nresgroups > max_nresgroups ) max_nresgroups = ii_nresgroups;
1457  }
1458 
1459  //"aa types" means "distinct groups of rotamers" -- this ig has no idea
1460  // what an amino acid is or why they might be different from one another
1461  //set_num_aatypes( (int) max_nresgroups );
1462  num_aa_types_ = (int) max_nresgroups;
1463 
1464  for ( Size ii = 1; ii <= rot_sets.nmoltenres(); ++ii ) {
1465  Size const ii_num_states = rot_sets.rotamer_set_for_moltenresidue( ii )->num_rotamers();
1466  set_num_states_for_node( ii, ii_num_states );
1467 
1468  // figure out which residue-type group each rotamer is a member of
1469  std::vector< int > aatype_for_state( ii_num_states + 1, 0 );
1470  Size curr_resgroup = 1;
1471  Size count_for_resgroup = 1;
1472  Size const ii_nresgroups = rot_sets.rotamer_set_for_moltenresidue( ii )->get_n_residue_groups();
1473  for ( uint jj = 1; jj <= ii_num_states; ++jj ) {
1474 
1475  aatype_for_state[ jj ] = curr_resgroup;
1476  ++count_for_resgroup;
1477  while ( count_for_resgroup > rot_sets.rotamer_set_for_moltenresidue( ii )->get_n_rotamers_for_residue_group( curr_resgroup )) {
1478  // increment curr_restype and skip over restypes with 0 rotamers
1479  ++curr_resgroup;
1480  count_for_resgroup = 1;
1481  if ( curr_resgroup > ii_nresgroups ) break;
1482  }
1483 
1484  }
1485 
1486  get_pd_node( ii )->set_amino_acid_types( aatype_for_state );
1487  }
1488 
1489 }
1490 
1491 
1492 
1493 /// @details The actual meaning of the integers used to represent amino acid types
1494 /// is not important, rather each state is labeled as being of some amino
1495 /// acid type. The amino acid types mean little more than equivalence classes;
1496 /// two states are either in the same equivalence class or they are in
1497 /// different ones.
1498 /// this function should be called once and only once
1499 ///
1500 /// @param num_aa_types - [in] - the number of amino acid types
1501 /*void PDInteractionGraph::set_num_aatypes(int num_aa_types)
1502 {
1503  assert( num_aa_types_ == -1 && num_aa_types > 0 );
1504  num_aa_types_ = num_aa_types;
1505  return;
1506 }*/
1507 
1508 /// @brief returns the number of different amino acid types
1510 { return num_aa_types_;}
1511 
1512 void
1513 PDInteractionGraph::add_edge(int node1, int node2)
1514 {
1515  InteractionGraphBase::add_edge( node1, node2 );
1516  PDEdge* newedge = get_pd_edge( node1, node2 );
1517  newedge->force_all_aa_neighbors();
1518 }
1519 
1520 
1521 /// @brief accessor
1522 float
1524 {
1525  return get_pd_node( node )->get_one_body_energy( state );
1526 }
1527 
1528 /// @brief assigns the state of all nodes in the interaction graph to their unassigned
1529 /// or zero states.
1531 {
1532  //a state assignment of 0 means "unassigned".
1533  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
1535  }
1537  return;
1538 }
1539 
1540 /// @brief sets the state on node node_ind to new_state
1541 ///
1542 /// @param node_ind - [in] - the index of the node in question
1543 /// @param new_state - [in] - the new state the node is being assigned to
1544 float PDInteractionGraph::set_state_for_node(int node_ind, int new_state)
1545 {
1546  get_pd_node( node_ind )->assign_state(new_state);
1549 }
1550 
1551 /// @brief takes in a vector of states, one state per node, and sets the state for
1552 /// each of the nodes to the specified state.
1553 ///
1554 /// also calls "update internal energy totals" to undo any numerical noise
1555 /// accumulated during the transition.
1556 ///
1557 /// @param node_states - [in] - array of states, one for each node.
1558 float PDInteractionGraph::set_network_state( FArray1_int & node_states)
1559 {
1560  //node_states.dimension( get_num_nodes() );
1561  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
1562  get_pd_node( ii )->assign_state( node_states(ii) );
1563  }
1566 }
1567 
1568 /// @brief considers altering the state of a particular node; returns the
1569 /// change in energy that the state substitution would produce
1570 ///
1571 /// To avoid too much numerical drift from accumulating, the bookkeeping
1572 /// arrays are updated once every 2^10 state commits
1573 ///
1574 /// @param node_ind - [in] - the index of the node considering a state change
1575 /// @param new_state - [in] - the new state that node is considering
1576 /// @param alt_total_energy - [out] - the total network energy produced under the
1577 /// new state
1578 /// @param delta_energy - [out] - the change in energy produced under the substitution
1579 /// @param prev_energy_for_node - [out] - the sum of the one and two body energies
1580 /// for this node under the current state assignment
1581 void
1584  int node_ind,
1585  int new_state,
1586  float & delta_energy,
1587  float & prev_energy_for_node
1588 )
1589 {
1590  node_considering_alt_state_ = node_ind;
1591  delta_energy = get_pd_node( node_ind )->
1592  project_deltaE_for_substitution( new_state, prev_energy_for_node );
1593 
1594  //numerical drift accumulates in the following assignment
1595  total_energy_alternate_state_assignment_ =
1596  total_energy_current_state_assignment_ + delta_energy;
1597 
1598  return;
1599 }
1600 
1601 /// @brief Accepts (commits) the state change previously considered in a call to
1602 /// consider_substitution and returns the energy of the entire graph
1603 ///
1604 /// to avoid too much numerical drift from accumulating, the bookkeeping
1605 /// arrays are updated once every 2^10 state commits
1606 ///
1607 float
1609 {
1614 
1618  }
1619 
1621 }
1622 
1623 /// @brief removes all accumulated numerical drift and returns the
1624 /// energy for the current state assignment.
1626 {
1629 }
1630 
1631 
1633 {
1635 }
1636 
1637 /// @details Iterates across nodes and then edges to look-up the energies
1638 /// for the current state assignmnet removing any numerical drift which
1639 /// accumulated in the member variable total_energy_current_state_assignment_.
1641 {
1643 
1644  //std::cerr << "updating internal energy totals: " << std::endl;
1645  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
1646  //std::cerr << " ig_node " << ii << " = " << ((PDNode *) ig_nodes_[ ii ])
1647  // ->get_one_body_energy_current_state();
1648 
1650  get_one_body_energy_current_state();
1651  }
1652 
1653  //int counter = 0;
1654  for (std::list<EdgeBase*>::iterator iter = get_edge_list_begin();
1655  iter != get_edge_list_end(); ++iter) {
1656  //std::cerr << " ig_edge " << ++counter << " =" <<
1657  //((PDEdge*) *iter)->get_current_two_body_energy();
1659  ((PDEdge*) *iter)->get_current_two_body_energy();
1660  }
1661 
1662  //std::cerr << std::endl;
1663 
1665  return;
1666 }
1667 
1669 {
1670  int sum = 0;
1671  for (std::list< EdgeBase* >::const_iterator iter = get_edge_list_begin();
1672  iter != get_edge_list_end(); ++iter)
1673  {
1674  sum += ((PDEdge*) *iter)->get_two_body_table_size();
1675  }
1676  return sum;
1677 }
1678 
1679 unsigned int
1681 {
1682  unsigned int total_memory = 0;
1683  total_memory += sizeof( PDInteractionGraph );
1684  //total_memory += InteractionGraphBase::getMemoryUsageInBytes();
1685  return total_memory;
1686 }
1687 
1689 {
1690  std::cerr << "Curr States: ";
1691  for (int ii = 1; ii <= get_num_nodes(); ++ii)
1692  {
1693  std::cerr << "(" << ii << ", ";
1694  std::cerr << get_pd_node(ii)->get_current_state() << ") ";
1696  }
1697  std::cerr << std::endl;
1698 }
1699 
1700 /*
1701 /// @brief allocates space for the arrays necessary for reading in from a file
1702 ///
1703 void PDInteractionGraph::prepare_to_read_energies_from_file()
1704 {
1705  instance_node_2_file_node_.dimension( get_num_nodes() );
1706  instance_node_2_file_node_ = -1;
1707 }
1708 
1709 
1710 /// @brief deallocates arrays used to read energies from a file
1711 void PDInteractionGraph::declare_finished_reading_from_file()
1712 {
1713  instance_node_2_file_node_.dimension( 0 );
1714  file_node_2_instance_node_.dimension( 0 );
1715  aa_types_for_states_on_file_nodes_.dimension( 0 );
1716 
1717 
1718  for (int ii = 1; ii <= get_num_nodes(); ++ii )
1719  {
1720  get_pd_node(ii)->clean_up_after_reading_energies_from_file();
1721  }
1722 }
1723 
1724 /// @brief sets the number of amino acid types according to the input file
1725 ///
1726 /// @param num_file_aatypes - [in] - the number of amino acid types
1727 void PDInteractionGraph::set_num_file_aatypes( int num_file_aatypes )
1728 {
1729  num_file_aa_types_ = num_file_aatypes;
1730 }
1731 
1732 /// @brief returns the number of amino acid types according to the input file
1733 ///
1734 int PDInteractionGraph::get_num_file_aatypes()
1735 {
1736  return num_file_aa_types_;
1737 }
1738 
1739 /// @brief sets the number of nodes for the graph described in the input file
1740 ///
1741 /// @param num_nodes_in_file - [in] - the number of nodes in the file
1742 void PDInteractionGraph::set_num_nodes_in_file( int num_nodes_in_file )
1743 {
1744  num_nodes_in_file_ = num_nodes_in_file;
1745  file_node_2_instance_node_.dimension( num_nodes_in_file );
1746  aa_types_for_states_on_file_nodes_.dimension( num_nodes_in_file );
1747  num_file_states_for_aa_for_node_.dimension( num_nodes_in_file );
1748 
1749  file_node_2_instance_node_ = -1;
1750 }
1751 
1752 /// @brief records the correspondence between an instance node and a file node
1753 ///
1754 /// @param instance_node - [in] - the index of the instance node
1755 /// @param file_node - [in] - the index of the file node
1756 ///
1757 void PDInteractionGraph::set_node_correspondence
1758 (
1759  int instance_node,
1760  int file_node
1761 )
1762 {
1763  file_node_2_instance_node_( file_node ) = instance_node;
1764  instance_node_2_file_node_( instance_node ) = file_node;
1765 }
1766 
1767 
1768 /// @brief records the number of states for a file node
1769 ///
1770 /// If a file node corresponds to an instance node, then the instance
1771 /// node keeps track of the information for the file node. If the file
1772 /// node doesn't correspond to any instance node, then the graph needs
1773 /// to keep track of the file node's information.
1774 /// Assumption: the correspondence between file nodes and instance nodes
1775 /// has been completely specified before this method is called for the first time.
1776 ///
1777 /// @param node - [in] - the index of the file node
1778 /// @param num_file_states - [in] - the number of file states for that file node
1779 ///
1780 void PDInteractionGraph::set_num_states_for_file_node
1781 (
1782  int node,
1783  int num_file_states
1784 )
1785 {
1786  if ( file_node_2_instance_node_( node ) == -1 ) {
1787  aa_types_for_states_on_file_nodes_( node ).dimension( num_file_states );
1788  num_file_states_for_aa_for_node_( node ).dimension( num_file_aa_types_ );
1789  num_file_states_for_aa_for_node_( node ) = 0;
1790  } else {
1791  int instance_node = file_node_2_instance_node_( node );
1792  get_pd_node(instance_node)->
1793  prepare_to_read_energies_from_file( num_file_states );
1794  }
1795 }
1796 
1797 /// @brief sets the amino acid type for a file state
1798 ///
1799 /// @param node - [in] - the index of the file node
1800 /// @param file_state - [in] - the file state
1801 /// @param state_aa - [in] - the amino acid type for file_state
1802 ///
1803 void PDInteractionGraph::set_aa_for_file_node_state
1804 (
1805  int node,
1806  int file_state,
1807  int state_aa
1808 )
1809 {
1810  int instance_node = file_node_2_instance_node_( node );
1811  if ( instance_node == -1 ) {
1812  aa_types_for_states_on_file_nodes_( node )( file_state ) = state_aa;
1813  ++num_file_states_for_aa_for_node_( node )(state_aa);
1814  } else {
1815  get_pd_node( instance_node )->set_aa_for_file_state(file_state, state_aa);
1816  }
1817 }
1818 
1819 /// @brief sets the correspondence between an instance state and a file state
1820 ///
1821 /// @param node - [in] - the index of the instance node
1822 /// @param state - [in] - the instance state
1823 /// @param file_state - [in] - the file state that the instance state corresponds to
1824 ///
1825 void PDInteractionGraph::set_correspondence_for_state(int node, int state, int file_state)
1826 {
1827  get_pd_node(node)->set_instance_state_correspondence( state, file_state );
1828 }
1829 
1830 /// @brief returns the file state that an instance state corresponds to
1831 ///
1832 /// @param node - [in] - the instance node
1833 /// @param state - [in] - the instance state
1834 ///
1835 int PDInteractionGraph::get_correspondence_for_state(int node, int state )
1836 {
1837  return get_pd_node(node)->get_correspondence_for_state( state );
1838 }
1839 
1840 /// @brief returns true if an instance node corresponds to a node in the file
1841 ///
1842 /// @param node - [in] - the instance node in question
1843 ///
1844 bool PDInteractionGraph::get_node_corresponded_to_file_node( int node )
1845 {
1846  return get_pd_node(node)->get_node_corresponded_to_file_node( );
1847 }
1848 
1849 /// @brief returns the number of instance states not described by any file state for
1850 /// for an instance node
1851 ///
1852 /// @param node - [in] - the instance node in question
1853 ///
1854 int PDInteractionGraph::get_num_rots_absent_from_file(int node)
1855 {
1856  return get_pd_node(node)->get_num_rots_absent_from_file();
1857 }
1858 
1859 /// @brief fills an input array with the indices of the instance states for an
1860 /// instance node that did not correspond to any instance state of the input
1861 /// file.
1862 ///
1863 /// @param node - [in] - the instance node
1864 /// @param rots_absent - [out] - the array in which to write the absent rotamers
1865 ///
1866 void PDInteractionGraph::get_absent_rots(int node, FArray1_int & rots_absent )
1867 {
1868  get_pd_node(node)->get_absent_rots( rots_absent );
1869  return;
1870 }
1871 
1872 /// @brief reads pair energies from a binary file
1873 ///
1874 /// The edge energies in the binary input file have the following structure:
1875 /// The number of edges in the graph is listed, and is followed by a long list
1876 /// of edges and edge information; each edge is identified by the indices
1877 /// of the two file nodes that it is incident upon. Following the two
1878 /// node indices, the rest of the information for that edge is stored.
1879 /// The interaction graph reads in the file nodes and, if both nodes correspond
1880 /// to instance nodes, creates a new edge between the instance nodes and
1881 /// has the new edge read in the appropriate energies from the input file.
1882 /// If either file node fails to correspond to some instance node, then the
1883 /// graph invokes the static method PDEdge::skip_past_edge_energies() to advance
1884 /// the read pointer past the information for this edge.
1885 ///
1886 /// @param infile - [in/out] - the binary input file that has been advanced to point
1887 /// at the number of edges in the file
1888 ///
1889 void PDInteractionGraph::read_edge_energies_from_file( std::ifstream & infile )
1890 {
1891  int num_edges;
1892  infile.read( (char*) &num_edges,4);
1893 
1894  for (int ii = 1; ii <= num_edges; ++ii)
1895  {
1896  int node1, node2;
1897  infile.read( (char*) & node1, 4);
1898  infile.read( (char*) & node2, 4 );
1899 
1900  int instance_node1 = file_node_2_instance_node_( node1 );
1901  int instance_node2 = file_node_2_instance_node_( node2 );
1902  if ( instance_node1 == -1 || instance_node2 == -1 )
1903  { //skip over the energies for this edge
1904  if (instance_node1 == -1 ) {
1905  FArray1A_int node1_num_states_for_aa(
1906  num_file_states_for_aa_for_node_( node1 ), num_file_aa_types_);
1907 
1908  if (instance_node2 == -1) {
1909  FArray1A_int node2_num_states_for_aa(
1910  num_file_states_for_aa_for_node_( node2 ), num_file_aa_types_);
1911 
1912 
1913  PDEdge::skip_over_edge_energies_from_file( infile,
1914  num_file_aa_types_,
1915  node1_num_states_for_aa, node2_num_states_for_aa);
1916  } else {
1917  FArray1A_int node2_num_states_for_aa(
1918  get_pd_node( instance_node2 )
1919  ->get_num_file_states_for_aa(), num_file_aa_types_ );
1920 
1921  PDEdge::skip_over_edge_energies_from_file( infile,
1922  num_file_aa_types_,
1923  node1_num_states_for_aa, node2_num_states_for_aa);
1924  }
1925  } else {
1926  FArray1A_int node1_num_states_for_aa(
1927  get_pd_node( instance_node1 )
1928  ->get_num_file_states_for_aa(), num_file_aa_types_);
1929 
1930  FArray1A_int node2_num_states_for_aa(
1931  num_file_states_for_aa_for_node_( node2 ), num_file_aa_types_);
1932 
1933  PDEdge::skip_over_edge_energies_from_file( infile,
1934  num_file_aa_types_,
1935  node1_num_states_for_aa, node2_num_states_for_aa);
1936 
1937  }
1938  } else {
1939  add_edge( instance_node1, instance_node2 );
1940  PDEdge* new_edge = (PDEdge*) find_edge( instance_node1, instance_node2);
1941 
1942  new_edge->read_edge_energies_from_file( infile );
1943  }
1944 
1945  }
1946 }
1947 
1948 /// @brief writes the edge energies, in a binary format, to the outfile.
1949 ///
1950 /// The graph writes out the number of edges, then proceeds to describe each
1951 /// edge. Each edge is identified by the two nodes its incident upon, and
1952 /// each edge is responsible for outputting itself to the file.
1953 ///
1954 /// @param outfile - [in/out] - the output file to write edge energies into
1955 ///
1956 void PDInteractionGraph::write_edge_energies_to_file( std::ofstream & outfile )
1957 {
1958  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
1959  get_pd_node(ii)->prepare_to_write_to_file();
1960  }
1961 
1962  int num_edges = get_num_edges(); //O(N) size method
1963  outfile.write( (char*) (&num_edges), 4);
1964  for ( std::list< EdgeBase* >::iterator edge_iter = get_edge_list_begin();
1965  edge_iter != get_edge_list_end(); ++edge_iter) {
1966  int first_node_ind = (*edge_iter)->get_first_node_ind();
1967  int second_node_ind = (*edge_iter)->get_second_node_ind();
1968  outfile.write( (char*) & first_node_ind, 4);
1969  outfile.write( (char*) & second_node_ind, 4);
1970  ((PDEdge*) (*edge_iter) )->write_edge_energies_to_file( outfile );
1971  }
1972 
1973  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
1974  get_pd_node(ii)->clean_up_after_writing_to_file();
1975  }
1976 
1977  return;
1978 }
1979 */
1980 
1981 /// @details For instance in a graph with 6 vertices,{a,b,c,d,e,f}
1982 /// a user may be interested in the sum of the one- and two-body energies
1983 /// for vertices {a,b,c}. The graph will return sum of the one body energies
1984 /// for vertices a b and c and also any two-body energies for the edges in the
1985 /// subgraph induced by a,b, and c. (In this case, edges {a,b}, {a,c} and {b,c}
1986 /// if these edges are part of the graph. The edge {a,d} will not be counted
1987 /// if it is part of the graph.).
1988 /// ask the graph for the energies of the induced subgraph defined
1989 /// by a particular group.
1990 ///
1991 /// @param group_id - [in] - the groups for which you're interested in retrieving
1992 /// energies of the induced subgraph
1993 ///
1994 float
1996 {
1997  float esum = 0;
1998  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
1999  if ( get_vertex_member_of_energy_sum_group( ii, group_id ) ) {
2001  }
2002  }
2003 
2004  for ( std::list< EdgeBase* >::iterator edge_iter = get_edge_list_begin();
2005  edge_iter != get_edge_list_end(); ++edge_iter) {
2006  int first_node_ind = (*edge_iter)->get_first_node_ind();
2007  int second_node_ind = (*edge_iter)->get_second_node_ind();
2008 
2009  if ( get_vertex_member_of_energy_sum_group( first_node_ind, group_id )
2010  && get_vertex_member_of_energy_sum_group( second_node_ind, group_id )) {
2011  esum += ((PDEdge*) (*edge_iter))->get_current_two_body_energy();
2012  }
2013  }
2014 
2015  return esum;
2016 }
2017 
2018 
2019 unsigned int
2021  return sizeof( PDInteractionGraph );
2022 }
2023 
2024 unsigned int
2026 {
2027  unsigned int total_memory = 0;
2029  return total_memory;
2030 }
2031 
2032 /// @details PDInteractionGraph will return aa submatrices as requested.
2033 bool
2035 {
2036  return true;
2037 }
2038 
2040  int node_ind,
2041  int node_state
2042 ) const
2043 {
2044  return get_pd_node(node_ind )->aatype_for_state( node_state );
2045 }
2046 
2047 ObjexxFCL::FArray2D< core::PackerEnergy >
2049  int node1,
2050  int node2,
2051  int node1aa,
2052  int node2aa
2053 ) const
2054 {
2055  return get_pd_edge( node1, node2 )->get_aa_submatrix_energies( node1aa, node2aa );
2056 }
2057 
2058 
2059 
2060 /// @param node_index - [in] - the index of the node being created
2061 /// @param num_states - [in] - the total number of states for the new node
2062 ///
2063 NodeBase* PDInteractionGraph::create_new_node( int node_index, int num_states)
2064 {
2065  PDNode* new_node = new PDNode(this, node_index, num_states);
2066  assert( new_node != NULL );
2067  return new_node;
2068 }
2069 
2070 
2071 /// @param index1 - [in] - the smaller-indexed node this edge is incident upon
2072 /// @param index2 - [in] - the larger-indexed node this edge is incident upon
2073 
2075 {
2076  return new PDEdge(this, index1, index2);
2077 }
2078 
2079 
2080 
2081 
2082 
2083 // <directed_design>
2084 
2085 
2086 /// calls project_deltaE_for_substitution ( the weighted version )
2087 ///
2088 
2090 (
2091  int alternate_state,
2092  float & deltaE_unweighted,
2093  float & prevE_unweighted,
2094  float & deltaE_weighted,
2095  float & prevE_weighted,
2096  FArray2D< core::PackerEnergy > const & weights
2097 )
2098 {
2099 
2100  // Step 1 - calculate unweighted energy, with side effect of filling alternate_state_one/two_body_energy
2101 
2102  deltaE_unweighted = project_deltaE_for_substitution(alternate_state,prevE_unweighted); // !!! need to return this parameter since the graph is adding it to total
2103 
2104  // Step 2 - calculate weighted energy on basis of info in:
2105  // - curr_state_one_body_energy_
2106  // - curr_state_two_body_energies_
2107  // - alternate_state_one_body_energy_
2108  // - alternate_state_two_body_energies_
2109 
2110  float curr_total_energy_weighted = curr_state_one_body_energy_;
2111  float alternate_total_energy_weighted = alternate_state_one_body_energy_;
2112 
2113  for( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
2114 
2115  // const int i = get_node_index();
2116  // const int j = get_adjacent_node(ii)->get_node_index();
2117  //const float bias_ii = get_bias(bias,i,j);//get_node_index(),get_adjacent_node(ii)->get_node_index());
2118 
2119  const float bias_ii = weights(get_incident_edge(ii)->get_first_node_ind(), // !!! symmetric bias matrix
2120  get_incident_edge(ii)->get_second_node_ind());
2121 
2122  curr_total_energy_weighted += bias_ii * curr_state_two_body_energies_[ii];
2123  alternate_total_energy_weighted += bias_ii * alternate_state_two_body_energies_[ii];
2124 
2125  } // ii
2126 
2127  prevE_weighted = curr_total_energy_weighted;
2128  deltaE_weighted = alternate_total_energy_weighted - curr_total_energy_weighted;
2129 
2130  //std::cout << __func__ << "deltaE_unweighted = " << deltaE_unweighted << "\tdeltaE_weighted = " << deltaE_weighted << std::endl;
2131 
2132 } // project_deltaE_for_substitution
2133 
2134 // THIS IS DUPLCATED CODE: EdgeBase already provides this functionality
2135 namespace {
2136 
2137  int get_other_index(const EdgeBase* edge_base, const int index) {
2138  if( index == edge_base->get_first_node_ind() ) {
2139  return edge_base->get_second_node_ind();
2140  }
2141  else if( index == edge_base->get_second_node_ind() ) {
2142  return edge_base->get_first_node_ind();
2143  }
2144  else {
2145  assert( false );
2146  utility_exit_with_message("et_other_index(const EdgeBase* edge_base, const int index) failed");
2147  return -1;
2148  }
2149  } // get_other_index
2150 
2151 } // namespace
2152 
2153 /// @brief Paul's code
2154 
2155 float
2156 PDNode::get_weighted_energy_with_higher_indexed_nodes( FArray2D< core::PackerEnergy > const & weights ) const
2157 {
2158  float rval = curr_state_one_body_energy_;
2159  for( int ii = 1; ii <= get_num_incident_edges(); ++ii ) {
2160  if( get_other_index(get_incident_edge(ii),get_node_index()) > ii ) {
2161  const float weight_ii = weights(get_incident_edge(ii)->get_first_node_ind(), // !!! symmetric bias matrix
2162  get_incident_edge(ii)->get_second_node_ind());
2163  rval += weight_ii * curr_state_two_body_energies_[ii];
2164  }
2165  } // ii
2166 
2167  return rval;
2168 } // PDNode::get_biased_energy_with_higher_indexed_nodes
2169 
2170 
2171 float PDInteractionGraph::get_weighted_energy(const FArray2D< core::PackerEnergy >& weights) const {
2172  // Compute and return biased energy
2173  float rval = 0;
2174  for( int ii = 1; ii <= get_num_nodes(); ++ii ) {
2176  }
2177  return rval;
2178 } // PDInteractionGraph::get_weighted_energy
2179 
2180 
2181 float PDInteractionGraph::set_network_state( FArray1_int & node_states, FArray2D< core::PackerEnergy > const & weights) {
2182  set_network_state(node_states);
2183  return get_weighted_energy(weights);
2184 }
2185 
2186 float PDInteractionGraph::commit_considered_substitution(const FArray2D< core::PackerEnergy >& weights) {
2188  return get_weighted_energy(weights);
2189 }
2190 
2192 (
2193  int node_ind,
2194  int new_state,
2195  float & deltaE_unweighted,
2196  float & prevE_unweighted,
2197  float & deltaE_weighted,
2198  float & prevE_weighted,
2199  const FArray2D< core::PackerEnergy >& weights
2200 )
2201 {
2202 
2203  node_considering_alt_state_ = node_ind;
2204  get_pd_node( node_ind )->project_deltaE_for_substitution( new_state, deltaE_unweighted, prevE_unweighted, deltaE_weighted, prevE_weighted, weights );
2205 
2206  //numerical drift accumulates in the following assignment
2207  // !!! need to make sure to add the unweighted energy to this variable
2209  total_energy_current_state_assignment_ + deltaE_unweighted;
2210 
2211  return;
2212 }
2213 
2214 // </directed_design>
2215 
2216 } //end namespace interaction_graph
2217 } //end namespace pack
2218 } //end namespace core
2219