Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DensePDInteractionGraph.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/DensePDInteractionGraph.cc
11 /// @brief Dense Edge-Matrix, Pairwise Decomposable interaction graph class implementation
12 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
13 
14 // Unit Headers
16 
17 // Package Headers
20 
21 // ObjexxFCL Headers
22 #include <ObjexxFCL/FArray1D.hh>
23 // AUTO-REMOVED #include <ObjexxFCL/FArray1A.hh>
24 #include <ObjexxFCL/FArray2D.hh>
25 #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/string_util.hh>
37 // AUTO-REMOVED #include <utility/basic_sys_util.hh>
38 
39 #include <utility/vector1.hh>
40 
41 
42 using namespace ObjexxFCL;
43 
44 namespace core {
45 namespace pack {
46 namespace interaction_graph {
47 
48 //----------------------------------------------------------------------------//
49 //--------- Dense Pairwise Decomposable Interaction Graph Node Class ---------//
50 //----------------------------------------------------------------------------//
51 
52 /// @brief main constructor, no default or copy constructors
53 ///
54 /// allocates one-body energy array and initializes it to zero.
55 ///
56 DensePDNode::DensePDNode(InteractionGraphBase * owner, int node_id, int num_states) :
57  PrecomputedPairEnergiesNode( owner, node_id, num_states ),
58  one_body_energies_(num_states + 1, 0.0f),
59  current_state_( 0 ),
60  curr_state_one_body_energy_( core::PackerEnergy( 0.0 )),
61  curr_state_total_energy_( core::PackerEnergy( 0.0 )),
62  alternate_state_( 0 ),
63  alternate_state_one_body_energy_( core::PackerEnergy( 0.0 )),
64  alternate_state_total_energy_( core::PackerEnergy( 0.0 )),
65  alternate_state_is_being_considered_( false )
66 {}
67 
68 /// @brief destructor
69 ///
70 /// not responsible for any dynamically allocated memory, so node does nothing
71 /// it's member variables, of course, are implicitly destructed
73 {}
74 
75 /// @brief prints a description of the node and all of it's one-body energies
76 void DensePDNode::print() const
77 {
78  std::cerr << "NODE: " << get_node_index() << " with " <<
79  get_num_states() << " states" << std::endl;
80  for (int ii = 1; ii <= get_num_states(); ++ii)
81  {
82  std::cerr << "(" << ii << ", ";
83  std::cerr << one_body_energies_[ ii ] << ") ";
84  if ( ii % 3 == 0 ) std::cerr << std::endl;
85  }
86  std::cerr << std::endl << "-----------------" << std::endl;
87 }
88 
89 
90 /// @brief update energy to the one-body energy for state
91 ///
92 ///
93 /// @param state - [in] - one-based index of the state
94 /// @param energy - [in] - the energy that should be set.
96 {
97  one_body_energies_[ state ] = energy;
98  return;
99 }
100 
101 /// @brief set all the one-body energies for this node
102 ///
103 /// @param energies - [in] - the array of energies. Must hold num_states_ entries
104 void DensePDNode::update_one_body_energies( FArray1< core::PackerEnergy > & energies )
105 {
106  assert( energies.size() == (unsigned int) get_num_states() );
107  for (int ii = 1; ii <= get_num_states(); ++ii)
108  {
109  one_body_energies_[ ii ] = energies( ii );
110  }
111  return;
112 }
113 
114 /// @brief adds energy to the one-body energy for state state
115 ///
116 /// @param state - [in] - one-based index of the state
117 /// @param energy - [in] - the energy that should be added.
119 {
120  one_body_energies_[ state ] += energy;
121  return;
122 }
123 
124 /// @brief adds all the energies in energies to the one-body energies for this node
125 ///
126 /// @param energies - [in] - the array of energies. Must hold num_states_ entries
127 void DensePDNode::add_to_one_body_energies( FArray1< core::PackerEnergy > & energies )
128 {
129  assert( energies.size() == (unsigned int) get_num_states() );
130  for (int ii = 1; ii <= get_num_states(); ++ii)
131  {
132  one_body_energies_[ ii ] += energies( ii );
133  }
134  return;
135 }
136 
137 /// @brief sets all of the one-body energies for this node to zero
139 {
140  for (int ii = 1; ii <= get_num_states(); ++ii)
141  {
142  one_body_energies_[ ii ] = 0;
143  }
144 }
145 
146 /// @brief returns the one body energy for a state
147 ///
148 /// @param state - [in]
150 {
151  return one_body_energies_[ state ];
152 }
153 
154 /// @brief prepares node for simulated annealing
155 ///
156 /// updates internal edge vector + other vectorized edge information
158 {
160  return;
161 }
162 
163 /// @brief assigns node's state to it's zero, or "unassigned" state.
164 ///
165 /// zeros the edge-energy array, informs neighbors that it's in its unassigned
166 /// state
168 {
169 
170  //std::cerr << "assign_state: node - " << get_node_index() <<
171  // " new state " << 0 << "...";
172 
173  current_state_ = 0;
174  alternate_state_ = 0;
176 
178  //fills from [1] to end
179  std::vector< core::PackerEnergy >::iterator position1 = curr_state_two_body_energies_.begin();
180  ++position1;
181  std::fill( position1,
183  0.0f);
185 
186  for (int ii = 1; ii <= get_num_incident_edges(); ++ii )
187  {
189  acknowledge_state_zeroed( get_node_index() );
190  }
191 
192  return;
193 }
194 
195 
196 /// @brief assigns node a new_state
197 ///
198 /// node updates its curr_state one and two body energies
199 ///
200 /// @param new_state - [in] - the new state the node should be assigned
201 void DensePDNode::assign_state(int new_state)
202 {
203  assert( new_state >= 0 && new_state <= get_num_states());
204 
205  if (new_state == 0) assign_zero_state();
206  else
207  {
208  //std::cerr << "assign_state: node - " << get_node_index() <<
209  // " new state " << new_state << "...";
210  current_state_ = new_state;
214 
215  for (int ii = 1; ii <= get_num_incident_edges(); ++ii )
216  {
218  get_node_index(),
221 
223  }
224  //std::cerr<< "..done" << std::endl;
225  }
226  return;
227 }
228 
229 /// @brief returns the state the node is currently assigned
231 {
232  return current_state_;
233 }
234 
235 /// @brief returns the one body energy for the state the node is currently assigned
238 
239 
240 /// @brief tells the node that it should change its state to the last state it was
241 /// asked to consider (from a call to project_deltaE_for_substitution)
242 ///
243 /// updates edge energy vector, iterates across neighbors having them update
244 /// their edge energies. Bookkeeping recaptures performance lost by
245 /// leaving energy2b structure
247 {
249 
253 
254  //copies from [1] to end
255  std::vector< core::PackerEnergy >::iterator alt_position1 = alternate_state_two_body_energies_.begin();
256  ++alt_position1;
257  std::vector< core::PackerEnergy >::iterator curr_position1 = curr_state_two_body_energies_.begin();
258  ++curr_position1;
259 
260  std::copy( alt_position1,
262  curr_position1 );
263 
264  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii )
265  {
267  get_node_index(),
270  );
271  }
272 
274  return;
275 }
276 
277 
278 /// @brief updates bookkeeping arrays that correspond to edge-list.
279 ///
280 /// calls base class update_edge_vector function, and then proceeds to create
281 /// appropriate bookkeeping arrays used in simulated annealing
283 {
285  //aa_offsets_for_this_lookup_.resize( get_num_incident_edges() + 1);
287 
288  edge_matrix_ptrs_.clear();
290  edge_matrix_ptrs_.push_back( FArray2A< core::PackerEnergy >() ); //occupy the 0th position
291 
292  for (int ii = 1; ii <= get_num_incident_edges(); ++ii)
293  {
294  edge_matrix_ptrs_.push_back( get_incident_dpd_edge(ii)->get_edge_table_ptr() );
295  }
296 
299  return;
300 }
301 
302 /// @brief outputs to standard error the bookkeeping energies for the node in its
303 /// current state assignment
305 {
306  std::cerr << "curr_state " << current_state_ << " ";
307  std::cerr << "curr_state_one_body_energy_ ";
308  std::cerr << curr_state_one_body_energy_ << " ";
309  std::cerr << "curr_state_total_energy_" << curr_state_total_energy_ << " ";
310  for (int ii = 1; ii <= get_num_incident_edges(); ++ii)
311  {
312  std::cerr << "(" << get_index_of_adjacent_node( ii ) << ": " <<
313  curr_state_two_body_energies_[ ii ] << ") ";
314  }
315  std::cerr << std::endl;
316 }
317 
318 /// @brief removes numerical drift long stretches of efficient bookkeeping
319 /// produces
321 {
322  assert( get_edge_vector_up_to_date() );
324  for (int ii = 1; ii <= get_num_incident_edges(); ++ii)
325  {
328  }
330  return;
331 }
332 
333 /// @brief If DensePDNode is the most-derived class being used, then this function
334 /// will be called and will return the amount of memory statically allocated by
335 /// a single DensePDNode.
336 unsigned int
338 {
339  return sizeof( DensePDNode );
340 }
341 
342 /// @brief Called either by the IGBase if the DensePDNode is the most-derived class, or
343 /// called recursively by a derived class. Called to account for the dynamically allocated
344 /// memory that this node uses.
345 unsigned int
347 {
348  unsigned int dynamic_memory = 0;
349  dynamic_memory += one_body_energies_.size() * sizeof( core::PackerEnergy );
350  dynamic_memory += neighbors_curr_state_.size() * sizeof( int );
351  dynamic_memory += edge_matrix_ptrs_.size() * sizeof ( FArray2A< core::PackerEnergy > );
352  dynamic_memory += curr_state_two_body_energies_.size() * sizeof ( core::PackerEnergy );
353  dynamic_memory += alternate_state_two_body_energies_.size() * sizeof ( core::PackerEnergy );
354  dynamic_memory += NodeBase::count_dynamic_memory();
355  return dynamic_memory;
356 }
357 
358 //-------------------------------------------------------------------------------//
359 //--------- Dense Pairwise Decomposable Interaction Graph Edge Class ------------//
360 //-------------------------------------------------------------------------------//
361 
362 /// @brief main constructor - no default nor copy constructors provided
363 ///
364 /// @param owner - [in] - pointer to the graph that created this node
365 /// @param first_node_ind - [in] - the index of the smaller-indexed node
366 /// @param second_node_ind - [in] - the index of the larger-indexed node
369  int first_node_ind,
370  int second_node_ind
371 ) :
372  PrecomputedPairEnergiesEdge( owner, first_node_ind, second_node_ind),
373  two_body_energies_(
374  get_dpd_node(1)->get_num_states(),
375  get_dpd_node(0)->get_num_states(),
376  0.0f
377  ),
378  energies_updated_since_last_prep_for_simA_( true )
379 {
380 }
381 
382 /// @brief destructor. All dynamically allocated memory is managed by the objects contained
383 /// inside the DensePDEdge, so there is no work to be (explicitly) done.
385 {}
386 
387 /// @brief adds the input energy to the two body energy for state1 on the node with the
388 /// smaller index and state2 on the node with the larger index.
390 (
391  int const state1,
392  int const state2,
393  core::PackerEnergy const energy
394 )
395 {
396  two_body_energies_(state2, state1) += edge_weight() * energy;
397  energies_updated_since_last_prep_for_simA_ = true;
398  return;
399 }
400 
401 /// @brief Adds all the energies stored in the oversized_res_res_energy array to the
402 /// two body energy table for those states whose amion acid types were
403 /// previoudsly declared to be amino-acid neighbors. The res-res array
404 /// should have the dimension (node1->get_num_states() x node2->get_num_states());
405 ///
406 /// @param res_res_energy_array - [in] - an array containing the state pair energies
408 (
409  FArray2< core::PackerEnergy > const & res_res_energy_array
410 )
411 {
412  assert( res_res_energy_array.size1() == two_body_energies_.size1() );
413  assert( res_res_energy_array.size2() == two_body_energies_.size2() );
414  for ( Size ii = 1, iie = two_body_energies_.size1(); ii <= iie; ++ii ) {
415  for ( Size jj = 1, jje = two_body_energies_.size2(); jj <= jje; ++jj ) {
416  two_body_energies_( ii, jj ) += edge_weight() * res_res_energy_array( ii, jj );
417  }
418  }
419  energies_updated_since_last_prep_for_simA_ = true;
420  return;
421 }
422 
423 bool DensePDEdge::get_sparse_aa_info( int, int) const {return true;} //"all amino acids are neighbors"
424 
425 
426 /// @brief Sets the two-body energy for a pair of states. That is, it overwrites
427 /// whatever two-body energy there was previously for that state pair with
428 /// a new energy. Ignores non-neighboring state pairs.
429 ///
430 /// @param state1 - [in] - state index for the node with the smaller index
431 /// @param state2 - [in] - state index for the node with the larger index
432 /// @param energy - [in] - the energy which replaces the old two-body energy
434 (
435  int const state1,
436  int const state2,
437  core::PackerEnergy const energy
438 )
439 {
440  two_body_energies_( state2, state1 ) = edge_weight() * energy;
441  energies_updated_since_last_prep_for_simA_ = true;
442  return;
443 }
444 
445 /// @brief Sets the two-body energy for a pair of states. That is, it overwrites
446 /// whatever two-body energy there was previously for that state pair with
447 /// a new energy. Ignores non-neighboring state pairs.
448 ///
449 /// @param state1 - [in] - state index for the node with the smaller index
450 /// @param state2 - [in] - state index for the node with the larger index
451 /// @param energy - [in] - the energy which replaces the old two-body energy
453 (
454  int const state1,
455  int const state2
456 )
457 {
458  two_body_energies_(state2,state1) = 0.0f;
459  energies_updated_since_last_prep_for_simA_ = true;
460  return;
461 }
462 
463 /// @brief returns the two body energy for a pair of states: 0 if those states are
464 /// not neighbors
465 ///
466 /// @param state1 - [in] - state index for the node with the smaller index
467 /// @param state2 - [in] - state index for the node with the larger index
468 core::PackerEnergy DensePDEdge::get_two_body_energy( int const state1, int const state2) const
469 {
470  return two_body_energies_(state2, state1);
471 }
472 
473 /// @brief If all of the energies for an edge have been added in, then declare the edge energies
474 /// final. This may mean that the edge deletes itself.
476 {
478 }
479 
480 /// @brief looks at all pair energies, and if they are all 0, deletes itself
482 {
484 
485 
487 
488  bool any_non_zero = false;
489  unsigned int const num_energies = two_body_energies_.size();
490  for (unsigned int ii = 0; ii < num_energies; ++ii)
491  {
492  if ( two_body_energies_[ ii ] != 0.0f ) { any_non_zero = true; break;}
493  }
494 
495  if ( ! any_non_zero ) delete this;
496 }
497 
498 /// @brief returns the two body energy corresponding to the current states assigned to
499 /// the nodes this edge is incident upon.
501 {
502  return curr_state_energy_;
503 }
504 
505 /// @brief updates bookkeeping information when one of the two nodes changes its state
506 ///
507 /// @param node_ind - [in] - the index of the node that changed its state
508 /// @param node_state - [in] - the index of the new state it assumed
509 /// @param new_energy - [out] - the two body energy produced by the new state and
510 /// the current state on the other node
511 void
513 (
514  int node_ind,
515  int new_state,
516  core::PackerEnergy & new_energy
517 )
518 {
519  int node_substituted = ( node_ind == get_node_index(0) ? 0 : 1);
520  int node_not_substituted = ! node_substituted;
521 
522  int nodes_curr_states[2];
523 
524  nodes_curr_states[ node_substituted ] = new_state;
525 
526  nodes_curr_states[ node_not_substituted ] =
527  get_dpd_node( node_not_substituted )->get_current_state();
528 
529  bool one_node_in_zero_state =
530  ( nodes_curr_states[0] == 0 || nodes_curr_states[1] == 0 );
531 
532  if ( one_node_in_zero_state ) {
533  curr_state_energy_ = 0;
534  } else {
535  curr_state_energy_ = two_body_energies_( nodes_curr_states[ 1 ], nodes_curr_states[ 0 ] );
536  }
537  new_energy = curr_state_energy_;
538 
539  get_dpd_node( node_not_substituted )->acknowledge_neighbors_state_substitution (
540  get_edges_position_in_nodes_edge_vector( node_not_substituted ),
541  curr_state_energy_,
542  new_state
543  );
544 
545  return;
546 }
547 
548 /// @brief updates bookkeeping information when one of the two nodes enters its
549 /// "unassigned" state.
550 ///
551 /// @param node_ind - [in] - the index of the node that has just entered its 0 state
553 {
554  int node_substituted = ( node_ind == get_node_index(0) ? 0 : 1);
555  int node_not_substituted = ! node_substituted;
556 
557  curr_state_energy_ = 0;
558 
560  get_edges_position_in_nodes_edge_vector( node_not_substituted ),
562  0
563  );
564 }
565 
566 
567 
568 
569 /// @brief Returns a reference to the first element in the dense two-body energy
570 /// table. Used to create a proxy array on the nodes for cache efficiency.
571 FArray2A< core::PackerEnergy > DensePDEdge::get_edge_table_ptr() {
572  return FArray2A< core::PackerEnergy >( two_body_energies_( 1, 1 ),
575 }
576 
577 
578 /// @brief returns the memory usage of the two body energy table for this edge
580 {
581  return two_body_energies_.size();
582 }
583 
584 /// @brief returns sizeof DensePDEdge if this is the most-derived instance of the class
585 unsigned int
587 {
588  return sizeof( DensePDEdge );
589 }
590 
591 /// @brief returns the amount of memory dynamically allocated by the edge and
592 /// recurses on its parent (in this case, the EdgeBase class)
593 unsigned int
595 {
596  unsigned int dynamic_memory = 0;
597  dynamic_memory += two_body_energies_.size() * sizeof( core::PackerEnergy );
598  dynamic_memory += EdgeBase::count_dynamic_memory();
599  return dynamic_memory;
600 }
601 
602 /// @details DANGER: If for some reason one were to reweight edges during simulated annealing
603 /// then some of the cached energies in the adjacent nodes would be out-of-date; data integrity
604 /// would be violated an all hell would break loose. The same thing is true if one were to
605 /// change the energies on any edge during simulated annealing. One simple solution: call
606 /// blanket_assign_state0 to wipe all cahced energies stored on nodes and then assign_network_state
607 /// to the state just before the reweighting.
608 /// Of course, since the annealer itself is tracking the "best" network state, you'd have to worry
609 /// about its data integrity as well. General advice: don't change energies during simA.
610 void
612 {
613  if ( weight == 0.0 ) {
614  utility_exit_with_message( "Error: set edge weight to 0 not a legal operation. Delete this edge instead" );
615  }
616  Real rescale = weight / edge_weight();
617  two_body_energies_ *= rescale;
618  curr_state_energy_ *= rescale;
619  edge_weight( weight ); // set base-class data
620 
621 }
622 
623 ObjexxFCL::FArray2D< core::PackerEnergy >
625 {
626  return two_body_energies_;
627 }
628 
629 void
631  ObjexxFCL::FArray2D< core::PackerEnergy > & new_edge_table
632 )
633 {
634  if ( two_body_energies_.size1() != new_edge_table.size1() ) {
635  utility_exit_with_message( "swap_edge_energies failed as size1 does not match: two_body_energies_.size1()= "
636  + utility::to_string( two_body_energies_.size1() ) + " new_edge_table.size1()= "
637  + utility::to_string( new_edge_table.size1() ) );
638  }
639  if ( two_body_energies_.size2() != new_edge_table.size2() ) {
640  utility_exit_with_message( "swap_edge_energies failed as size2 does not match: two_body_energies_.size2()= "
641  + utility::to_string( two_body_energies_.size2() ) + " new_edge_table.size2()= "
642  + utility::to_string( new_edge_table.size2() ) );
643  }
644  two_body_energies_.swap( new_edge_table );
645 }
646 
647 
648 //----------------------------------------------------------------------------//
649 //--------- Dense Pairwise Decomposable Interaction Graph Class --------------//
650 //----------------------------------------------------------------------------//
651 
652 
653 /// @brief main constructor: no default nor copy constructors provided.
654 ///
655 /// @param num_nodes - [in] - the number of nodes in this graph
658  num_commits_since_last_update_(0),
659  total_energy_current_state_assignment_(0),
660  total_energy_alternate_state_assignment_(0),
661  node_considering_alt_state_( -1 )
662 {}
663 
664 /// @brief The DensePDIG only needs to know how many states each node has.
665 /// This function causes the downstream instantiation of the DensePDNodes.
666 void
668 {
669  rotamer_set::RotamerSets const & rot_sets( static_cast< rotamer_set::RotamerSets const & > (rot_sets_base) );
670  for ( uint ii = 1; ii <= rot_sets.nmoltenres(); ++ii ) {
671  set_num_states_for_node( ii, rot_sets.rotamer_set_for_moltenresidue( ii )->num_rotamers() );
672  }
673 
674 }
675 
676 /// @brief returns the one body energy for a particular state on a node
679 {
680  return get_dpd_node( node )->get_one_body_energy( state );
681 }
682 
683 /// @brief assigns the state of all nodes in the interaction graph to their unassigned
684 /// or zero states.
686 {
687  //a state assignment of 0 means "unassigned".
688  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
690  }
692  return;
693 }
694 
695 /// @brief sets the state on node node_ind to new_state
696 ///
697 /// @param node_ind - [in] - the index of the node in question
698 /// @param new_state - [in] - the new state the node is being assigned to
700 {
701  get_dpd_node( node_ind )->assign_state(new_state);
704 }
705 
706 /// @brief takes in a vector of states, one state per node, and sets the state for
707 /// each of the nodes to the specified state.
708 ///
709 /// also calls "update internal energy totals" to undo any numerical noise
710 /// accumulated during the transition.
711 ///
712 /// @param node_states - [in] - array of states, one for each node.
714 {
715  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
716  get_dpd_node( ii )->assign_state( node_states(ii) );
717  }
720 }
721 
722 /// @brief considers altering the state of a particular node; returns the
723 /// change in energy that the state substitution would produce
724 ///
725 /// to avoid too much numerical drift from accumulating, the bookkeeping
726 /// arrays are updated once every 2^10 state commits
727 ///
728 /// @param node_ind - [in] - the index of the node considering a state change
729 /// @param new_state - [in] - the new state that node is considering
730 /// @param alt_total_energy - [out] - the total network energy produced under the
731 /// new state
732 /// @param delta_energy - [out] - the change in energy produced under the substitution
733 /// @param prev_energy_for_node - [out] - the sum of the one and two body energies
734 /// for this node under the current state assignment
735 void
737 (
738  int node_ind,
739  int new_state,
740  core::PackerEnergy & delta_energy,
741  core::PackerEnergy & prev_energy_for_node
742 )
743 {
744  node_considering_alt_state_ = node_ind;
745  delta_energy = get_dpd_node( node_ind )->
746  project_deltaE_for_substitution( new_state, prev_energy_for_node );
747 
748  //numerical drift accumulates in the following assignment
749  total_energy_alternate_state_assignment_ =
750  total_energy_current_state_assignment_ + delta_energy;
751 
752  return;
753 }
754 
755 
756 /// @details to avoid too much numerical drift from accumulating, the bookkeeping
757 /// arrays are updated once every 2^10 state commits
760 {
765 
769  }
770 
772 }
773 
775 {
778 }
779 
780 
781 
782 /// @details Iterates across nodes and then edges to look-up the energies
783 /// for the current state assignmnet removing any numerical drift which
784 /// accumulated in the member variable total_energy_current_state_assignment_.
786 {
788 
789  //std::cerr << "updating internal energy totals: " << std::endl;
790  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
791  //std::cerr << " ig_node " << ii << " = " << ((DensePDNode *) ig_nodes_[ ii ])
792  // ->get_one_body_energy_current_state();
793 
795  get_one_body_energy_current_state();
796  }
797 
798  //int counter = 0;
799  for (std::list<EdgeBase*>::iterator iter = get_edge_list_begin();
800  iter != get_edge_list_end(); ++iter) {
801  //std::cerr << " ig_edge " << ++counter << " =" <<
802  //((DensePDEdge*) *iter)->get_current_two_body_energy();
804  ((DensePDEdge*) *iter)->get_current_two_body_energy();
805  }
806 
807  //std::cerr << std::endl;
808 
810  return;
811 }
812 
813 
815 {
816  int sum = 0;
817  for (std::list< EdgeBase* >::const_iterator iter = get_edge_list_begin();
818  iter != get_edge_list_end(); ++iter) {
819  sum += ((DensePDEdge*) *iter)->get_two_body_table_size();
820  }
821  return sum;
822 }
823 
824 /// @brief returns the amount of static memory allocated for a single DensePDInteractionGraph.
825 /// Does not account for any of the edges or nodes that the graph contains: that part of the
826 /// algorithm is implemented by the InteractionGraphBase class.
827 unsigned int
829 {
830  return sizeof( DensePDInteractionGraph );
831 }
832 
833 /// @brief returns the amount of dynamic memory allocated for a single DensePDInteractionGraph
834 /// and recurses on the parent class.
835 /// Does not account for any of the edges or nodes that the graph contains: that part of the
836 /// algorithm is implemented by the InteractionGraphBase class.
837 unsigned int
839 {
841 }
842 
843 void
845  int node1,
846  int node2,
847  ObjexxFCL::FArray2D< core::PackerEnergy > & new_edge_table
848 )
849 {
850  get_dpd_edge( node1, node2 )->swap_edge_energies( new_edge_table );
851 }
852 
853 
855 {
856  std::cerr << "Curr States: ";
857  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
858  std::cerr << "(" << ii << ", ";
859  std::cerr << get_dpd_node(ii)->get_current_state() << ") ";
861  }
862  std::cerr << std::endl;
863 }
864 
865 
866 /// @details For instance in a graph with 6 vertices,
867 /// {a,b,c,d,e,f}
868 /// a user may be interested in the sum of the one- and two-body energies
869 /// for vertices {a,b,c}. The graph will return sum of the one body energies
870 /// for vertices a b and c and also any two-body energies for the edges in the
871 /// subgraph induced by a,b, and c. (In this case, edges {a,b}, {a,c} and {b,c}
872 /// if these edges are part of the graph. The edge {a,d} will not be counted
873 /// if it is part of the graph.)
874 /// ask the graph for the energies of the induced subgraph defined
875 /// by a particular group.
876 ///
877 /// @param group_id - [in] - the groups for which you're interested in retrieving
878 /// energies of the induced subgraph
881 {
882  core::PackerEnergy esum = 0;
883  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
884  if ( get_vertex_member_of_energy_sum_group( ii, group_id ) ) {
886  }
887  }
888 
889  for ( std::list< EdgeBase* >::iterator edge_iter = get_edge_list_begin();
890  edge_iter != get_edge_list_end(); ++edge_iter) {
891  int first_node_ind = (*edge_iter)->get_first_node_ind();
892  int second_node_ind = (*edge_iter)->get_second_node_ind();
893 
894  if ( get_vertex_member_of_energy_sum_group( first_node_ind, group_id )
895  && get_vertex_member_of_energy_sum_group( second_node_ind, group_id )) {
896  esum += ((DensePDEdge*) (*edge_iter))->get_current_two_body_energy();
897  }
898  }
899  return esum;
900 }
901 
902 /// @details PDInteractionGraph will return aa submatrices as requested.
903 bool
905 {
906  return true;
907 }
908 
910  int,
911  int
912 ) const
913 {
914  return 1;
915 }
916 
917 ObjexxFCL::FArray2D< core::PackerEnergy >
919  int node1,
920  int node2,
921  int,
922  int
923 ) const
924 {
925  return get_dpd_edge( node1, node2 )->get_aa_submatrix_energies();
926 }
927 
928 
929 
930 /// @brief factory method that instantiates a DensePDNode.
931 ///
932 /// @param node_index - [in] - the index of the node being created
933 /// @param num_states - [in] - the total number of states for the new node
934 NodeBase* DensePDInteractionGraph::create_new_node( int node_index, int num_states)
935 {
936  DensePDNode* new_node = new DensePDNode(this, node_index, num_states);
937  assert( new_node != NULL );
938  return new_node;
939 }
940 
941 /// @brief factory method that instantiates a DensePDEdge
942 ///
943 /// @param index1 - [in] - the smaller-indexed node this edge is incident upon
944 /// @param index2 - [in] - the larger-indexed node this edge is incident upon
946 {
947  return new DensePDEdge(this, index1, index2);
948 }
949 
950 } // namespace interaction_graph
951 } // namespace pack
952 } // namespace core
953