Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DoubleDensePDInteractionGraph.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/DoubleDensePDInteractionGraph.cc
11 /// @brief
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/FArray1Da.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 // AUTO-REMOVED #include <utility/basic_sys_util.hh>
37 
38 #include <utility/exit.hh>
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 //--------- DoubleDense 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 DoubleDensePDNode::DoubleDensePDNode(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  curr_state_total_energy_( 0.0 ),
60  alternate_state_is_being_considered_( false )
61 {}
62 
63 /// @brief destructor
64 ///
65 /// not responsible for any dynamically allocated memory, so node does nothing
66 /// it's member variables, of course, are implicitly destructed
68 {}
69 
70 /// @brief prints a description of the node and all of it's one-body energies
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  {
77  std::cerr << "(" << ii << ", ";
78  std::cerr << one_body_energies_[ ii ] << ") ";
79  if ( ii % 3 == 0 ) std::cerr << std::endl;
80  }
81  std::cerr << std::endl << "-----------------" << std::endl;
82 }
83 
84 /// @brief update energy to the one-body energy for state
85 ///
86 ///
87 /// @param state - [in] - one-based index of the state
88 /// @param energy - [in] - the energy that should be set.
90 {
91  one_body_energies_[ state ] = energy;
92  return;
93 }
94 
95 /// @brief set all the one-body energies for this node
96 ///
97 /// @param energies - [in] - the array of energies. Must hold num_states_ entries
98 void DoubleDensePDNode::update_one_body_energies( FArray1< core::PackerEnergy > & energies )
99 {
100  assert( energies.size() == (unsigned int) get_num_states() );
101  for (int ii = 1; ii <= get_num_states(); ++ii)
102  {
103  one_body_energies_[ ii ] = energies( ii );
104  }
105  return;
106 }
107 
108 /// @brief adds energy to the one-body energy for state state
109 ///
110 /// @param state - [in] - one-based index of the state
111 /// @param energy - [in] - the energy that should be added.
113 {
114  one_body_energies_[ state ] += energy;
115  return;
116 }
117 
118 /// @brief adds all the energies in energies to the one-body energies for this node
119 ///
120 /// @param energies - [in] - the array of energies. Must hold num_states_ entries
121 void DoubleDensePDNode::add_to_one_body_energies( FArray1< core::PackerEnergy > & energies )
122 {
123  assert( energies.size() == (unsigned int) get_num_states() );
124  for (int ii = 1; ii <= get_num_states(); ++ii)
125  {
126  one_body_energies_[ ii ] += energies( ii );
127  }
128  return;
129 }
130 
131 /// @brief sets all of the one-body energies for this node to zero
133 {
134  for (int ii = 1; ii <= get_num_states(); ++ii)
135  {
136  one_body_energies_[ ii ] = 0;
137  }
138 }
139 
140 /// @brief returns the one body energy for a state
141 ///
142 /// @param state - [in]
144 {
145  return one_body_energies_[ state ];
146 }
147 
148 /// @brief prepares node for simulated annealing
149 ///
150 /// updates internal edge vector + other vectorized edge information
152 {
154  return;
155 }
156 
157 /// @brief assigns node's state to it's zero, or "unassigned" state.
158 ///
159 /// zeros the edge-energy array, informs neighbors that it's in its unassigned
160 /// state
162 {
163 
164  //std::cerr << "assign_state: node - " << get_node_index() <<
165  // " new state " << 0 << "...";
166 
167  current_state_ = 0;
168  alternate_state_ = 0;
170 
172  //fills from [1] to end
173  std::vector< core::PackerEnergy >::iterator position1 = curr_state_two_body_energies_.begin();
174  ++position1;
175  std::fill( position1,
177  0.0f);
179 
180  for (int ii = 1; ii <= get_num_incident_edges(); ++ii )
181  {
183  acknowledge_state_zeroed( get_node_index() );
184  }
185 
186  return;
187 }
188 
189 
190 /// @brief assigns node a new_state
191 ///
192 /// node updates its curr_state one and two body energies
193 ///
194 /// @param new_state - [in] - the new state the node should be assigned
196 {
197  assert( new_state >= 0 && new_state <= get_num_states());
198 
199  if (new_state == 0) assign_zero_state();
200  else
201  {
202  //std::cerr << "assign_state: node - " << get_node_index() <<
203  // " new state " << new_state << "...";
204  current_state_ = new_state;
208 
209  for (int ii = 1; ii <= get_num_incident_edges(); ++ii )
210  {
212  get_node_index(),
215 
217  }
218  //std::cerr<< "..done" << std::endl;
219  }
220  return;
221 }
222 
223 /// @brief returns the state the node is currently assigned
225 {
226  return current_state_;
227 }
228 
229 /// @brief returns the one body energy for the state the node is currently assigned
232 
233 
234 /// @brief tells the node that it should change its state to the last state it was
235 /// asked to consider (from a call to project_deltaE_for_substitution)
236 ///
237 /// updates edge energy vector, iterates across neighbors having them update
238 /// their edge energies. Bookkeeping recaptures performance lost by
239 /// leaving energy2b structure
241 {
243 
247 
248  //copies from [1] to end
249  std::vector< core::PackerEnergy >::iterator alt_position1 = alternate_state_two_body_energies_.begin();
250  ++alt_position1;
251  std::vector< core::PackerEnergy >::iterator curr_position1 = curr_state_two_body_energies_.begin();
252  ++curr_position1;
253 
254  std::copy( alt_position1,
256  curr_position1 );
257 
258  for ( int ii = 1; ii <= get_num_incident_edges(); ++ii )
259  {
261  get_node_index(),
264  );
265  }
266 
268  return;
269 }
270 
271 
272 /// @brief updates bookkeeping arrays that correspond to edge-list.
273 ///
274 /// calls base class update_edge_vector function, and then proceeds to create
275 /// appropriate bookkeeping arrays used in simulated annealing
277 {
279  //aa_offsets_for_this_lookup_.resize( get_num_incident_edges() + 1);
284 
285  for (int ii = 1; ii <= get_num_incident_edges(); ++ii) {
287  if ( ii > 1 ) {
289  } else {
290  neighbors_rotindex_offset_[ ii ] = 0;
291  }
292  }
293 
295 
296  rotamer_energies_.dimension( n_neighboring_rotamers, get_num_states() );
297  for ( int ii = 1; ii <= get_num_edges_to_smaller_indexed_nodes(); ++ii) {
298  int const ii_roff = neighbors_rotindex_offset_[ ii ];
299  for ( int jj = 1; jj <= get_num_states(); ++jj ) {
300  for ( int kk = 1; kk <= neighbors_num_states_[ ii ]; ++kk ) {
301  rotamer_energies_( kk + ii_roff, jj ) = get_incident_dpd_edge( ii )->get_two_body_energy( kk, jj );
302  }
303  }
304  }
305 
306  for ( int ii = get_num_edges_to_smaller_indexed_nodes() + 1; ii <= get_num_incident_edges(); ++ii) {
307  int const ii_roff = neighbors_rotindex_offset_[ ii ];
308  for ( int jj = 1; jj <= get_num_states(); ++jj ) {
309  for ( int kk = 1; kk <= neighbors_num_states_[ ii ]; ++kk ) {
310  rotamer_energies_( kk + ii_roff, jj ) = get_incident_dpd_edge( ii )->get_two_body_energy( jj, kk );
311  }
312  }
313  }
314 
317  return;
318 }
319 
320 /// @brief outputs to standard error the bookkeeping energies for the node in its
321 /// current state assignment
323 {
324  std::cerr << "curr_state " << current_state_ << " ";
325  std::cerr << "curr_state_one_body_energy_ ";
326  std::cerr << curr_state_one_body_energy_ << " ";
327  std::cerr << "curr_state_total_energy_" << curr_state_total_energy_ << " ";
328  for (int ii = 1; ii <= get_num_incident_edges(); ++ii)
329  {
330  std::cerr << "(" << get_index_of_adjacent_node( ii ) << ": " <<
331  curr_state_two_body_energies_[ ii ] << ") ";
332  }
333  std::cerr << std::endl;
334 }
335 
336 /// @brief removes numerical drift long stretches of efficient bookkeeping
337 /// produces
339 {
340  assert( get_edge_vector_up_to_date() );
342  for (int ii = 1; ii <= get_num_incident_edges(); ++ii)
343  {
346  }
348  return;
349 }
350 
351 /// @brief If DoubleDensePDNode is the most-derived class being used, then this function
352 /// will be called and will return the amount of memory statically allocated by
353 /// a single DoubleDensePDNode.
354 unsigned int
356 {
357  return sizeof( DoubleDensePDNode );
358 }
359 
360 /// @brief Called either by the IGBase if the DoubleDensePDNode is the most-derived class, or
361 /// called recursively by a derived class. Called to account for the dynamically allocated
362 /// memory that this node uses.
363 unsigned int
365 {
366  unsigned int dynamic_memory = 0;
367  dynamic_memory += one_body_energies_.size() * sizeof( core::PackerEnergy );
368  dynamic_memory += neighbors_curr_state_.size() * sizeof( int );
369  dynamic_memory += neighbors_curr_state_plus_offset_.size() * sizeof( int );
370  dynamic_memory += neighbors_num_states_.size() * sizeof( int );
371  dynamic_memory += neighbors_rotindex_offset_.size() * sizeof( int );
372  dynamic_memory += rotamer_energies_.size() * sizeof ( core::PackerEnergy );
373 
374  dynamic_memory += curr_state_two_body_energies_.size() * sizeof ( core::PackerEnergy );
375  dynamic_memory += alternate_state_two_body_energies_.size() * sizeof ( core::PackerEnergy );
376  dynamic_memory += NodeBase::count_dynamic_memory();
377  return dynamic_memory;
378 }
379 
380 //-------------------------------------------------------------------------------//
381 //--------- DoubleDense Pairwise Decomposable Interaction Graph Edge Class ------------//
382 //-------------------------------------------------------------------------------//
383 
384 /// @brief main constructor - no default nor copy constructors provided
385 ///
386 /// @param owner - [in] - pointer to the graph that created this node
387 /// @param first_node_ind - [in] - the index of the smaller-indexed node
388 /// @param second_node_ind - [in] - the index of the larger-indexed node
391  int first_node_ind,
392  int second_node_ind
393 ) :
394  PrecomputedPairEnergiesEdge( owner, first_node_ind, second_node_ind),
395  two_body_energies_(
396  get_dpd_node(1)->get_num_states(),
397  get_dpd_node(0)->get_num_states(),
398  0.0f
399  ),
400  energies_updated_since_last_prep_for_simA_( true )
401 {
402 }
403 
404 /// @brief destructor. All dynamically allocated memory is managed by the objects contained
405 /// inside the DoubleDensePDEdge, so there is no work to be (explicitly) done.
407 {}
408 
409 /// @brief adds the input energy to the two body energy for state1 on the node with the
410 /// smaller index and state2 on the node with the larger index.
412 (
413  int const state1,
414  int const state2,
415  core::PackerEnergy const energy
416 )
417 {
418  two_body_energies_(state2, state1) += edge_weight() * energy;
419  energies_updated_since_last_prep_for_simA_ = true;
420  return;
421 }
422 
423 /// @brief Adds all the energies stored in the oversized_res_res_energy array to the
424 /// two body energy table for those states whose amion acid types were
425 /// previoudsly declared to be amino-acid neighbors. The res-res array
426 /// should have the dimension (node1->get_num_states() x node2->get_num_states());
427 ///
428 /// @param res_res_energy_array - [in] - an array containing the state pair energies
430 (
431  FArray2< core::PackerEnergy > const & res_res_energy_array
432 )
433 {
434  assert( res_res_energy_array.size1() == two_body_energies_.size1() );
435  assert( res_res_energy_array.size2() == two_body_energies_.size2() );
436  for ( Size ii = 1, iie = two_body_energies_.size1(); ii <= iie; ++ii ) {
437  for ( Size jj = 1, jje = two_body_energies_.size2(); jj <= jje; ++jj ) {
438  two_body_energies_( ii, jj ) += edge_weight() * res_res_energy_array( ii, jj );
439  }
440  }
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  core::PackerEnergy const energy
457 )
458 {
459  two_body_energies_( state2, state1 ) = edge_weight() * energy;
460  energies_updated_since_last_prep_for_simA_ = true;
461  return;
462 }
463 
464 /// @brief Sets the two-body energy for a pair of states. That is, it overwrites
465 /// whatever two-body energy there was previously for that state pair with
466 /// a new energy. Ignores non-neighboring state pairs.
467 ///
468 /// @param state1 - [in] - state index for the node with the smaller index
469 /// @param state2 - [in] - state index for the node with the larger index
470 /// @param energy - [in] - the energy which replaces the old two-body energy
472 (
473  int const state1,
474  int const state2
475 )
476 {
477  two_body_energies_(state2,state1) = 0.0f;
478  energies_updated_since_last_prep_for_simA_ = true;
479  return;
480 }
481 
482 /// @brief returns the two body energy for a pair of states: 0 if those states are
483 /// not neighbors
484 ///
485 /// @param state1 - [in] - state index for the node with the smaller index
486 /// @param state2 - [in] - state index for the node with the larger index
487 core::PackerEnergy DoubleDensePDEdge::get_two_body_energy( int const state1, int const state2) const
488 {
489  return two_body_energies_(state2, state1);
490 }
491 
492 /// @brief If all of the energies for an edge have been added in, then declare the edge energies
493 /// final. This may mean that the edge deletes itself.
495 {
497 }
498 
499 /// @brief looks at all pair energies, and if they are all 0, deletes itself
501 {
503 
504 
506 
507  bool any_non_zero = false;
508  unsigned int const num_energies = two_body_energies_.size();
509  for (unsigned int ii = 0; ii < num_energies; ++ii)
510  {
511  if ( two_body_energies_[ ii ] != 0.0f ) { any_non_zero = true; break;}
512  }
513 
514  if ( ! any_non_zero ) delete this;
515 }
516 
517 /// @brief returns the two body energy corresponding to the current states assigned to
518 /// the nodes this edge is incident upon.
520 {
521  return curr_state_energy_;
522 }
523 
524 /// @brief updates bookkeeping information when one of the two nodes changes its state
525 ///
526 /// @param node_ind - [in] - the index of the node that changed its state
527 /// @param node_state - [in] - the index of the new state it assumed
528 /// @param new_energy - [out] - the two body energy produced by the new state and
529 /// the current state on the other node
530 void
532 (
533  int node_ind,
534  int new_state,
535  core::PackerEnergy & new_energy
536 )
537 {
538  int node_substituted = ( node_ind == get_node_index(0) ? 0 : 1);
539  int node_not_substituted = ! node_substituted;
540 
541  int nodes_curr_states[2];
542 
543  nodes_curr_states[ node_substituted ] = new_state;
544 
545  nodes_curr_states[ node_not_substituted ] =
546  get_dpd_node( node_not_substituted )->get_current_state();
547 
548  bool one_node_in_zero_state =
549  ( nodes_curr_states[0] == 0 || nodes_curr_states[1] == 0 );
550 
551  if ( one_node_in_zero_state ) {
552  curr_state_energy_ = 0;
553  } else {
554  curr_state_energy_ = two_body_energies_( nodes_curr_states[ 1 ], nodes_curr_states[ 0 ] );
555  }
556  new_energy = curr_state_energy_;
557 
558  get_dpd_node( node_not_substituted )->acknowledge_neighbors_state_substitution (
559  get_edges_position_in_nodes_edge_vector( node_not_substituted ),
560  curr_state_energy_,
561  new_state
562  );
563 
564  return;
565 }
566 
567 /// @brief updates bookkeeping information when one of the two nodes enters its
568 /// "unassigned" state.
569 ///
570 /// @param node_ind - [in] - the index of the node that has just entered its 0 state
572 {
573  int node_substituted = ( node_ind == get_node_index(0) ? 0 : 1);
574  int node_not_substituted = ! node_substituted;
575 
576  curr_state_energy_ = 0;
577 
579  get_edges_position_in_nodes_edge_vector( node_not_substituted ),
581  0
582  );
583 }
584 
585 
586 
587 
588 /// @brief Returns a reference to the first element in the dense two-body energy
589 /// table. Used to create a proxy array on the nodes for cache efficiency.
590 /*
591 FArray2Da< core::PackerEnergy > DoubleDensePDEdge::get_edge_table_ptr() {
592  return FArray2Da< core::PackerEnergy >( two_body_energies_( 1, 1 ),
593  get_num_states_for_node( 1 ),
594  get_num_states_for_node( 0 ) );
595 }*/
596 
597 
598 /// @brief returns the memory usage of the two body energy table for this edge
600 {
601  return two_body_energies_.size();
602 }
603 
604 /// @brief returns sizeof DoubleDensePDEdge if this is the most-derived instance of the class
605 unsigned int
607 {
608  return sizeof( DoubleDensePDEdge );
609 }
610 
611 /// @brief returns the amount of memory dynamically allocated by the edge and
612 /// recurses on its parent (in this case, the EdgeBase class)
613 unsigned int
615 {
616  unsigned int dynamic_memory = 0;
617  dynamic_memory += two_body_energies_.size() * sizeof( core::PackerEnergy );
618  dynamic_memory += EdgeBase::count_dynamic_memory();
619  return dynamic_memory;
620 }
621 
622 /// @details DANGER: If for some reason one were to reweight edges during simulated annealing
623 /// then some of the cached energies in the adjacent nodes would be out-of-date; data integrity
624 /// would be violated an all hell would break loose. The same thing is true if one were to
625 /// change the energies on any edge during simulated annealing. One simple solution: call
626 /// blanket_assign_state0 to wipe all cahced energies stored on nodes and then assign_network_state
627 /// to the state just before the reweighting.
628 /// Of course, since the annealer itself is tracking the "best" network state, you'd have to worry
629 /// about its data integrity as well. General advice: don't change energies during simA.
630 void
632 {
633  if ( weight == 0.0 ) {
634  utility_exit_with_message( "Error: set edge weight to 0 not a legal operation. Delete this edge instead" );
635  }
636  Real rescale = weight / edge_weight();
637  two_body_energies_ *= rescale;
638  curr_state_energy_ *= rescale;
639  edge_weight( weight ); // set base-class data
640 
641 }
642 
643 //----------------------------------------------------------------------------//
644 //--------- DoubleDense Pairwise Decomposable Interaction Graph Class --------------//
645 //----------------------------------------------------------------------------//
646 
647 
648 /// @brief main constructor: no default nor copy constructors provided.
649 ///
650 /// @param num_nodes - [in] - the number of nodes in this graph
653  num_commits_since_last_update_(0),
654  total_energy_current_state_assignment_(0),
655  total_energy_alternate_state_assignment_(0),
656  node_considering_alt_state_( -1 )
657 {}
658 
659 /// @brief The DoubleDensePDIG only needs to know how many states each node has.
660 /// This function causes the downstream instantiation of the DoubleDensePDNodes.
661 void
663 {
664  rotamer_set::RotamerSets const & rot_sets( static_cast< rotamer_set::RotamerSets const & > (rot_sets_base) );
665  for ( uint ii = 1; ii <= rot_sets.nmoltenres(); ++ii ) {
666  set_num_states_for_node( ii, rot_sets.rotamer_set_for_moltenresidue( ii )->num_rotamers() );
667  }
668 
669 }
670 
671 /// @brief returns the one body energy for a particular state on a node
674 {
675  return get_dpd_node( node )->get_one_body_energy( state );
676 }
677 
678 /// @brief assigns the state of all nodes in the interaction graph to their unassigned
679 /// or zero states.
681 {
682  //a state assignment of 0 means "unassigned".
683  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
685  }
687  return;
688 }
689 
690 /// @brief sets the state on node node_ind to new_state
691 ///
692 /// @param node_ind - [in] - the index of the node in question
693 /// @param new_state - [in] - the new state the node is being assigned to
695 {
696  get_dpd_node( node_ind )->assign_state(new_state);
699 }
700 
701 /// @brief takes in a vector of states, one state per node, and sets the state for
702 /// each of the nodes to the specified state.
703 ///
704 /// also calls "update internal energy totals" to undo any numerical noise
705 /// accumulated during the transition.
706 ///
707 /// @param node_states - [in] - array of states, one for each node.
709 {
710  for (int ii = 1; ii <= get_num_nodes(); ++ii ) {
711  get_dpd_node( ii )->assign_state( node_states(ii) );
712  }
715 }
716 
717 /// @brief considers altering the state of a particular node; returns the
718 /// change in energy that the state substitution would produce
719 ///
720 /// to avoid too much numerical drift from accumulating, the bookkeeping
721 /// arrays are updated once every 2^10 state commits
722 ///
723 /// @param node_ind - [in] - the index of the node considering a state change
724 /// @param new_state - [in] - the new state that node is considering
725 /// @param alt_total_energy - [out] - the total network energy produced under the
726 /// new state
727 /// @param delta_energy - [out] - the change in energy produced under the substitution
728 /// @param prev_energy_for_node - [out] - the sum of the one and two body energies
729 /// for this node under the current state assignment
730 void
732 (
733  int node_ind,
734  int new_state,
735  core::PackerEnergy & delta_energy,
736  core::PackerEnergy & prev_energy_for_node
737 )
738 {
739  node_considering_alt_state_ = node_ind;
740  delta_energy = get_dpd_node( node_ind )->
741  project_deltaE_for_substitution( new_state, prev_energy_for_node );
742 
743  //numerical drift accumulates in the following assignment
744  total_energy_alternate_state_assignment_ =
745  total_energy_current_state_assignment_ + delta_energy;
746 
747  return;
748 }
749 
750 
751 /// @details to avoid too much numerical drift from accumulating, the bookkeeping
752 /// arrays are updated once every 2^10 state commits
755 {
760 
764  }
765 
767 }
768 
770 {
773 }
774 
775 
776 
777 /// @details Iterates across nodes and then edges to look-up the energies
778 /// for the current state assignmnet removing any numerical drift which
779 /// accumulated in the member variable total_energy_current_state_assignment_.
781 {
783 
784  //std::cerr << "updating internal energy totals: " << std::endl;
785  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
786  //std::cerr << " ig_node " << ii << " = " << ((DoubleDensePDNode *) ig_nodes_[ ii ])
787  // ->get_one_body_energy_current_state();
788 
790  get_one_body_energy_current_state();
791  }
792 
793  //int counter = 0;
794  for (std::list<EdgeBase*>::iterator iter = get_edge_list_begin();
795  iter != get_edge_list_end(); ++iter) {
796  //std::cerr << " ig_edge " << ++counter << " =" <<
797  //((DoubleDensePDEdge*) *iter)->get_current_two_body_energy();
799  ((DoubleDensePDEdge*) *iter)->get_current_two_body_energy();
800  }
801 
802  //std::cerr << std::endl;
803 
805  return;
806 }
807 
808 
810 {
811  int sum = 0;
812  for (std::list< EdgeBase* >::const_iterator iter = get_edge_list_begin();
813  iter != get_edge_list_end(); ++iter) {
814  sum += ((DoubleDensePDEdge*) *iter)->get_two_body_table_size();
815  }
816  return sum;
817 }
818 
819 /// @brief returns the amount of static memory allocated for a single DoubleDensePDInteractionGraph.
820 /// Does not account for any of the edges or nodes that the graph contains: that part of the
821 /// algorithm is implemented by the InteractionGraphBase class.
822 unsigned int
824 {
825  return sizeof( DoubleDensePDInteractionGraph );
826 }
827 
828 /// @brief returns the amount of dynamic memory allocated for a single DoubleDensePDInteractionGraph
829 /// and recurses on the parent class.
830 /// Does not account for any of the edges or nodes that the graph contains: that part of the
831 /// algorithm is implemented by the InteractionGraphBase class.
832 unsigned int
834 {
836 }
837 
839 {
840  std::cerr << "Curr States: ";
841  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
842  std::cerr << "(" << ii << ", ";
843  std::cerr << get_dpd_node(ii)->get_current_state() << ") ";
845  }
846  std::cerr << std::endl;
847 }
848 
849 
850 /// @details For instance in a graph with 6 vertices,
851 /// {a,b,c,d,e,f}
852 /// a user may be interested in the sum of the one- and two-body energies
853 /// for vertices {a,b,c}. The graph will return sum of the one body energies
854 /// for vertices a b and c and also any two-body energies for the edges in the
855 /// subgraph induced by a,b, and c. (In this case, edges {a,b}, {a,c} and {b,c}
856 /// if these edges are part of the graph. The edge {a,d} will not be counted
857 /// if it is part of the graph.)
858 /// ask the graph for the energies of the induced subgraph defined
859 /// by a particular group.
860 ///
861 /// @param group_id - [in] - the groups for which you're interested in retrieving
862 /// energies of the induced subgraph
865 {
866  core::PackerEnergy esum = 0;
867  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
868  if ( get_vertex_member_of_energy_sum_group( ii, group_id ) ) {
870  }
871  }
872 
873  for ( std::list< EdgeBase* >::iterator edge_iter = get_edge_list_begin();
874  edge_iter != get_edge_list_end(); ++edge_iter) {
875  int first_node_ind = (*edge_iter)->get_first_node_ind();
876  int second_node_ind = (*edge_iter)->get_second_node_ind();
877 
878  if ( get_vertex_member_of_energy_sum_group( first_node_ind, group_id )
879  && get_vertex_member_of_energy_sum_group( second_node_ind, group_id )) {
880  esum += ((DoubleDensePDEdge*) (*edge_iter))->get_current_two_body_energy();
881  }
882  }
883  return esum;
884 }
885 
886 
887 /// @brief factory method that instantiates a DoubleDensePDNode.
888 ///
889 /// @param node_index - [in] - the index of the node being created
890 /// @param num_states - [in] - the total number of states for the new node
892 {
893  DoubleDensePDNode* new_node = new DoubleDensePDNode(this, node_index, num_states);
894  assert( new_node != NULL );
895  return new_node;
896 }
897 
898 /// @brief factory method that instantiates a DoubleDensePDEdge
899 ///
900 /// @param index1 - [in] - the smaller-indexed node this edge is incident upon
901 /// @param index2 - [in] - the larger-indexed node this edge is incident upon
903 {
904  return new DoubleDensePDEdge(this, index1, index2);
905 }
906 
907 } // namespace interaction_graph
908 } // namespace pack
909 } // namespace core
910