Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AdditionalBackgroundNodesInteractionGraph.hh
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file core/pack/interaction_graph/AdditionalBackgroundNodesInteractionGraph.hh
11 /// @brief Interaction graph which can handle some residues not changing during packing.
12 /// @author Andrew Leaver-Fay
13 /// @author Ron Jacak (ron.jacak@gmail.com)
14 
15 #ifndef INCLUDED_core_pack_interaction_graph_AdditionalBackgroundNodesInteractionGraph_HH
16 #define INCLUDED_core_pack_interaction_graph_AdditionalBackgroundNodesInteractionGraph_HH
17 
18 // AUTO-REMOVED #include <core/pack/interaction_graph/InteractionGraphBase.hh>
19 
20 //STL Headers
21 #include <list>
22 // AUTO-REMOVED #include <vector>
23 
24 #include <iostream>
25 
26 #include <utility/vector1_bool.hh>
27 
28 
29 namespace core {
30 namespace pack {
31 namespace interaction_graph {
32 
33 
34 template < typename V, typename E, typename G > class FirstClassNode;
35 template < typename V, typename E, typename G > class FirstClassEdge;
36 template < typename V, typename E, typename G > class BackgroundNode;
37 template < typename V, typename E, typename G > class BackgroundToFirstClassEdge;
38 template < typename V, typename E, typename G > class AdditionalBackgroundNodesInteractionGraph;
39 
40 
41 //----------------------------------------------------------------------------//
42 //------------------------- First Class Node Class ---------------------------//
43 //----------------------------------------------------------------------------//
44 
45 ///
46 /// @begin FirstClassNode
47 ///
48 /// @brief
49 ///
50 /// @detailed
51 /// A background node is a node which is not changing type or rotamer throughout a simulation.
52 ///
53 ///
54 /// @remarks
55 /// No public default constructor makes this class uncopyable.
56 ///
57 template < typename V, typename E, typename G >
58 class FirstClassNode : public V {
59 
60  public:
61  typedef typename std::list< BackgroundToFirstClassEdge< V, E, G >* > BackgroundEdgeList;
62  typedef typename std::list< BackgroundToFirstClassEdge< V, E, G >* >::iterator BackgroundEdgeListIter;
63 
64  typedef typename std::vector< BackgroundNode< V, E, G >* > BackgroundNodeVector;
65  typedef typename std::vector< BackgroundToFirstClassEdge< V, E, G >* > BackgroundEdgeVector;
66  typedef typename std::vector< BackgroundToFirstClassEdge< V, E, G >* >::iterator BackgroundEdgeVectorIter;
67 
68  public:
69  virtual ~FirstClassNode();
70  FirstClassNode( G * owner, int node_id, int num_states);
73  virtual unsigned int count_dynamic_memory() const;
74 
75  protected:
76  inline
79  }
80 
81  inline
84  return bg_edge_vector_[ index ];
85  }
86 
87  inline
88  int get_index_of_adjacent_background_node( int index ) const {
90  return adjacent_bg_node_indices_[ index ];
91  }
92 
93  inline
96  return bg_node_vector_[ index ];
97  }
98 
99  inline
102  }
103 
104  void update_bg_edge_vector();
105 
106  private:
110  std::vector< int > adjacent_bg_node_indices_;
113 
114  //no default constructor, uncopyable
115  FirstClassNode();
118 };
119 
120 
121 //----------------------------------------------------------------------------//
122 //------------------------- First Class Edge Class ---------------------------//
123 //----------------------------------------------------------------------------//
124 
125 ///
126 /// @begin FirstClassEdge
127 ///
128 /// @brief
129 ///
130 /// @detailed
131 ///
132 /// @remarks
133 /// Defines only a constructor and count_dynamic_memory().
134 ///
135 template < typename V, typename E, typename G >
136 class FirstClassEdge : public E {
137 
138  public:
139  virtual ~FirstClassEdge();
140  FirstClassEdge( G * owner, int first_node_ind, int second_node_ind );
141  virtual unsigned int count_dynamic_memory() const { return E::count_dynamic_memory(); }
142 
143  private:
144  //no default constructor, uncopyable
145  FirstClassEdge();
148 
149 };
150 
151 
152 //----------------------------------------------------------------------------//
153 //------------------- Second Class (Background) Node Class -------------------//
154 //----------------------------------------------------------------------------//
155 
156 
157 ///
158 ///
159 /// @begin BackgroundNode
160 ///
161 /// @brief
162 /// A node which is not changing type or rotamer throughout a simulation.
163 ///
164 /// @detailed
165 /// In the case of solvent-accessible surface area (SASA) scoring, a background node would be one whose SASA score can
166 /// change due to neighboring residues being changed. It itself will not change residue type or rotamer during a
167 /// simulation, but the scores on this residue can change.
168 ///
169 /// @remarks
170 /// Non-instantiable due to pure virtual methods, prepare_for_simulated_annealing(), print(), and count_static_memory().
171 ///
172 ///
173 template < typename V, typename E, typename G >
174 class BackgroundNode {
175 
176  public:
177  typedef typename std::list< BackgroundToFirstClassEdge< V, E, G >* >::iterator BackgroundEdgeListIter;
178  typedef typename std::list< BackgroundToFirstClassEdge< V, E, G >* > BackgroundEdgeList;
179  typedef typename std::vector< BackgroundToFirstClassEdge< V, E, G >* > BackgroundEdgeVector;
180  typedef typename std::vector< BackgroundToFirstClassEdge< V, E, G >* >::iterator BackgroundEdgeVectorIter;
181  typedef typename std::vector< FirstClassNode< V, E, G >* > FirstClassNodeVector;
182 
183  public:
184  virtual ~BackgroundNode();
186 
188  void drop_edge( BackgroundEdgeListIter edge);
189  BackgroundToFirstClassEdge< V, E, G >* find_edge( int fc_node_index );
190 
191  virtual void prepare_for_simulated_annealing() = 0;
192  virtual void print() const = 0;
193  virtual unsigned int count_static_memory() const = 0;
194  virtual unsigned int count_dynamic_memory() const;
195 
196  protected:
197  void update_edge_vector();
198 
199  inline
200  int get_node_index() const { return node_index_; }
201 
202  inline
204 
205  inline
207  assert( edge_vector_up_to_date_ );
208  return edge_vector_[ index ];
209  }
210 
211  inline
212  int get_index_of_adjacent_first_class_node( int index ) const {
213  assert( edge_vector_up_to_date_ );
214  return adjacent_first_class_node_indices_[ index ];
215  }
216 
217  inline
219  assert( edge_vector_up_to_date_ );
220  return adjacent_nodes_[ index ];
221  }
222 
223  inline
225 
226  inline
228 
229 
230  private:
239 
240  //no default constructor, uncopyable
241  BackgroundNode();
244 };
245 
246 
247 //----------------------------------------------------------------------------//
248 //----------------- Second Class To First Class Edge Class -------------------//
249 //----------------------------------------------------------------------------//
250 
251 ///
252 /// @begin BackgroundToFirstClassEdge
253 ///
254 /// @brief
255 /// An edge between a background node and a first class node.
256 ///
257 /// @detailed
258 ///
259 /// @remarks
260 /// Only derived classes can get non-const access to the FirstClassNode and BackgroundNode members. Const access is
261 /// provided as a public method. Non-instantiable due to pure virtual methods.
262 /// Not sure what the 'pos_in_fc_nodes_edge_list_' and other Iterator returning methods are used for.
263 ///
264 ///
265 template < typename V, typename E, typename G >
267 
268  public:
269  typedef typename std::list< BackgroundToFirstClassEdge< V, E, G >* >::iterator BackgroundEdgeListIter;
270 
271  public:
272  virtual ~BackgroundToFirstClassEdge();
273  BackgroundToFirstClassEdge( AdditionalBackgroundNodesInteractionGraph< V, E, G >* owner, int fc_node_index, int bg_node_index);
274 
275  inline
277 
278  inline
280 
283 
286 
288  void set_pos_in_node_edgevector( FirstClassNode< V, E, G >* caller, int pos );
290 
291  bool same_edge( int fc_node_index, int bg_node_index ) const;
292 
293  virtual void prepare_for_simulated_annealing() = 0;
294 
295  virtual unsigned int count_static_memory() const = 0;
296  virtual unsigned int count_dynamic_memory() const;
297 
298  protected:
299  inline
301 
302  inline
304 
305  inline
307 
308 
309  private:
312 
315 
321 
323 
324  //no default constructor, uncopyable
328 
329 };
330 
331 
332 //----------------------------------------------------------------------------//
333 //----------- Additional Background Nodes Interaction Graph Class ------------//
334 //----------------------------------------------------------------------------//
335 
336 ///
337 /// @begin AdditionalBackgroundNodesInteractionGraph
338 ///
339 /// @brief
340 /// Function declarations for the AdditionalBackgroundNodesInteractionGraph.
341 ///
342 template < typename V, typename E, typename G >
344 
345  public:
346  typedef typename std::vector< BackgroundNode< V, E, G > * > BackgroundNodeVector;
347  typedef typename std::list< BackgroundToFirstClassEdge< V, E, G > * > BackgroundEdgeList;
348  typedef typename std::list< BackgroundToFirstClassEdge< V, E, G > * >::iterator BackgroundEdgeListIter;
349  typedef typename std::list< BackgroundToFirstClassEdge< V, E, G > * >::const_iterator BackgroundEdgeListConstIter;
350 
351  public:
354 
355  friend class BackgroundToFirstClassEdge< V, E, G >;
356 
357  virtual unsigned int getTotalMemoryUsage() const;
358  virtual unsigned int count_dynamic_memory() const;
359 
360  inline
361  int get_num_background_nodes() const { return num_bg_nodes_; }
362 
363  protected:
365 
366  // Factory methods for background nodes and edges
367  virtual BackgroundNode< V, E, G >* create_background_node( int bg_node_index ) = 0;
368  virtual BackgroundToFirstClassEdge< V, E, G >* create_background_edge( int fc_node_index, int bg_node_index ) = 0;
369 
370  // call at most once
371  void set_num_background_nodes( int num_bg_nodes );
372 
373  void add_background_edge( int first_class_node_index, int bg_node_index );
374 
375  BackgroundToFirstClassEdge< V, E, G >* find_background_edge( int first_class_node_index, int bg_node_index ) const;
376 
377  inline
378  int get_num_bg_edges() const { return bg_to_fc_edge_list_.size(); }
379 
380  inline
382  assert( index > 0 && index <= num_bg_nodes_ );
383  return bg_nodes_[ index ];
384  }
385 
387 
388  inline
390  return bg_to_fc_edge_list_.begin();
391  }
392 
393  inline
395  return bg_to_fc_edge_list_.end();
396  }
397 
398  private:
402 
404 
405  //no default constructor, uncopyable
409 };
410 
411 
412 
413 //----------------------------------------------------------------------------//
414 //------------------------- First Class Node Class ---------------------------//
415 //----------------------------------------------------------------------------//
416 
417 
418 /// @begin FirstClassNode::FirstClassNode
419 ///
420 /// @brief
421 /// FirstClassNode constructor
422 ///
423 /// @param
424 /// owner - [in] - the owning interaction graph
425 /// node_id - [in] - the index for this node amongst its owners set
426 /// num_states - [in] - the number of states for this node
427 ///
428 template < typename V, typename E, typename G >
429 FirstClassNode< V, E, G > ::FirstClassNode( G* owner, int node_id, int num_states ) :
430  V( owner, node_id, num_states ),
431  num_edges_to_bg_nodes_(0),
432  bg_edge_vector_up_to_date_(false)
433 {}
434 
435 
436 /// @begin FirstClassNode::~FirstClassNode
437 ///
438 /// @brief FirstClassNode destructor
439 ///
440 template < typename V, typename E, typename G >
442 {}
443 
444 
445 /// @begin FirstClassNode::add_background_edge
446 ///
447 /// @brief
448 /// Adds a BackgroundToFirstClassEdge to the node's list of such edges and returns an iterator to that list position.
449 ///
450 /// @remarks
451 /// Edge addition invalidates the bg_edge_vector_up_to_date_ flag
452 ///
453 /// @param
454 /// edge_ptr - [in] - a pointer to the BackgroundToFirstClassEdge
455 ///
456 template < typename V, typename E, typename G >
457 typename std::list< BackgroundToFirstClassEdge< V, E, G >* >::iterator
459  ++num_edges_to_bg_nodes_;
460  bg_edge_vector_up_to_date_ = false;
461  return bg_edge_list_.insert( bg_edge_list_.end(), edge_ptr );
462 }
463 
464 
465 /// @begin FirstClassNode::drop_background_edge
466 ///
467 /// @brief
468 /// Removes an edge from the node's BackgroundToFirstClassEdge list
469 ///
470 /// @remarks
471 /// Invalidates bg_edge_vector_up_to_date_ flag
472 ///
473 /// @param
474 /// edge - [in] - the iterator to the edge; in order to guarantee constant
475 /// time edge deletion, each edge keeps iterators to its position in the
476 /// edge lists of the nodes it's incident upon. It hands these iterators
477 /// back to the nodes when it wants to delete itself.
478 ///
479 template < typename V, typename E, typename G >
481  --num_edges_to_bg_nodes_;
482  bg_edge_list_.erase( edge );
483  bg_edge_vector_up_to_date_ = false;
484 }
485 
486 
487 /// @begin FirstClassNode::count_dynamic_memory
488 ///
489 /// @brief
490 /// Returns an int representing the amount of memory in bytes used by this node
491 ///
492 /// @remarks
493 /// ronj lists consume more memory because they maintain pointers to the previous and next nodes
494 /// ronj current calculation uses 4 * # elements in list * sizeof(pointer), but I think this is wrong
495 /// ronj isn't it only 3 * # elements in list * sizeof(pointer)?
496 ///
497 /// @param
498 /// total_memory - [out] - the amount of memory used by this node
499 ///
500 template < typename V, typename E, typename G >
502 
503  //ronj calculate how much dynamic memory the base class is using
504  unsigned int total_memory = V::count_dynamic_memory();
505 
506  total_memory += 4 * bg_edge_list_.size() * sizeof( BackgroundToFirstClassEdge< V, E, G >* );
507  total_memory += bg_edge_vector_.size() * sizeof( BackgroundToFirstClassEdge< V, E, G >* );
508  total_memory += adjacent_bg_node_indices_.size() * sizeof( int );
509  total_memory += bg_node_vector_.size() * sizeof( BackgroundNode< V, E, G >* );
510 
511  return total_memory;
512 }
513 
514 
515 /// @begin FirstClassNode::update_bg_edge_vector
516 ///
517 /// @brief
518 /// Syncs the background edge vector with the background edge list
519 ///
520 /// @detailed
521 /// Updates the vector of pointers to background edges to correspond to the list of background edges. Informs its
522 /// incident edges of their position in its vector.
523 ///
524 /// @remarks
525 /// We are resizing these vectors to num_edges_to_bg_nodes PLUS ONE. This makes the vector 1-based.
526 ///
527 template < typename V, typename E, typename G >
529 
530  bg_edge_vector_.resize( num_edges_to_bg_nodes_ + 1 );
531  adjacent_bg_node_indices_.resize( num_edges_to_bg_nodes_ + 1 );
532  bg_node_vector_.resize( num_edges_to_bg_nodes_ + 1 );
533 
534  BackgroundEdgeVectorIter position1 = bg_edge_vector_.begin();
535  ++position1;
536 
537  std::copy( bg_edge_list_.begin(), bg_edge_list_.end(), position1 );
538 
539  for (int ii = 1; ii <= num_edges_to_bg_nodes_; ++ii) {
540 
541  //ronj set_pos_in_node_edgevector updates the edge vector in this FirstClassNode
542  //ronj this FirstClassNode is telling the BackgroundToFirstClass edge connected to it what position in the
543  //ronj edge vector (stored in this class) that edge is in. Hey, edge, you're fourth in my vector of incident edges
544  bg_edge_vector_[ii]->set_pos_in_node_edgevector( this, ii );
545 
546  //ronj get_other_ind is passed 'this' FirstClassNode, so it will return the index of the BackgroundNode that has
547  //ronj an edge with this FirstClassNode
548  adjacent_bg_node_indices_[ii] = bg_edge_vector_[ii]->get_other_ind( this );
549  bg_node_vector_[ii] = bg_edge_vector_[ii]->get_other_node( this );
550  }
551 
552  bg_edge_vector_up_to_date_ = true;
553  return;
554 }
555 
556 
557 //----------------------------------------------------------------------------//
558 //------------------------- First Class Edge Class ---------------------------//
559 //----------------------------------------------------------------------------//
560 
561 
562 /// @begin FirstClassEdge::FirstClassEdge
563 ///
564 /// @brief
565 /// FirstClassEdge constructor
566 ///
567 /// @detailed
568 /// This class is almost empty; a FirstClassEdge connects two first class vertices, and is ignorant of the
569 /// existence of both second class nodes (synonymous with BackgroundNode) and second-to-first-class edges
570 /// (synonymous with BackgroundToFirstClassEdge). I (apl) cannot think of any data that a FirstClassEdge should
571 /// hold that is not held in a PrecomputedPairEnergiesEdge. Nor can I think of any methods that the edge should
572 /// implement. However, I include the class in the inheritance hierarchy just in case I come up with something
573 /// later.
574 ///
575 /// @param
576 /// owner - [in] - the owning interaction graph
577 /// first_node_index - [in] - the index of the lower-indexed first class node
578 /// second_node_index - [in] - the index of the higher-indexed first class node
579 ///
580 template < typename V, typename E, typename G >
581 FirstClassEdge< V, E, G >::FirstClassEdge( G* owner, int first_node_ind, int second_node_ind) :
582  E ( owner, first_node_ind, second_node_ind ) {}
583 
584 
585 /// @begin FirstClassEdge::~FirstClassEdge
586 ///
587 /// @brief
588 /// FirstClassEdge destructor
589 ///
590 template < typename V, typename E, typename G >
592 
593 
594 
595 //----------------------------------------------------------------------------//
596 //------------------- Second Class (Background) Node Class -------------------//
597 //----------------------------------------------------------------------------//
598 
599 
600 /// @begin BackgroundNode::BackgroundNode
601 ///
602 /// @brief
603 /// BackgroundNode constructor - no default or copy constructors; no operator =
604 ///
605 /// @detailed
606 /// I use "background node" synonymously with "second class node".
607 /// This kind of node contributes to the energy of the system. It does not
608 /// have any assignable states -- the energy it contributes is a function of
609 /// the states of the first class vertices that surround it.
610 /// A simulated annealer is unaware of the presence of this kind of node;
611 /// the owning interaction graph obscures it from view of the annealer.
612 ///
613 /// @param
614 /// owner - [in] - the owning graph
615 /// node_index - [in] - the index of the background node
616 ///
617 template < typename V, typename E, typename G >
619  node_index_( node_index ),
620  num_incident_edges_( 0 ),
621  edge_vector_up_to_date_( false ),
622  owner_( owner ) {
623 }
624 
625 
626 /// @begin BackgroundNode::~BackgroundNode
627 ///
628 /// @brief
629 /// BackgroundNode destructor
630 ///
631 template < typename V, typename E, typename G >
633 
634 
635 /// @begin BackgroundNode::add_edge
636 ///
637 /// @brief
638 /// Adds a BackgroundToFirstClassEdge to the edge list for this node. Returns an iterator to the new list element.
639 ///
640 /// @remarks
641 /// Invalidates edge_vector_up_to_date_ flag
642 ///
643 /// @param
644 /// edge_ptr - [in] - pointer to the edge being added
645 ///
646 template < typename V, typename E, typename G >
647 typename std::list< BackgroundToFirstClassEdge< V, E, G >* >::iterator
649  ++num_incident_edges_;
650  edge_vector_up_to_date_ = false;
651  return edge_list_.insert( edge_list_.end(), edge_ptr );
652 }
653 
654 
655 /// @begin BackgroundNode::drop_edge
656 ///
657 /// @brief
658 /// removes an edge from the nodes edge list in constant time
659 ///
660 /// @remarks
661 /// Invalidates edge_vector_up_to_date_ flag
662 ///
663 /// @param
664 /// edge - [in] - the iterator to the edge's position in node's edge list
665 ///
666 template < typename V, typename E, typename G >
668  --num_incident_edges_;
669  edge_vector_up_to_date_ = false;
670  edge_list_.erase( edge );
671 }
672 
673 
674 /// @begin BackgroundNode::update_edge_vector
675 ///
676 /// @brief
677 /// Syncs the edge vector with the edge list
678 ///
679 /// @detailed
680 /// Updates the vector of pointers to background edges to correspond to the list of background edges. Informs its
681 /// incident edges of their position in its vector.
682 ///
683 /// @remarks
684 /// sets edge_vector_up_to_date_ flag to true
685 ///
686 template < typename V, typename E, typename G >
688 
689  edge_vector_.resize( num_incident_edges_ + 1);
690  adjacent_first_class_node_indices_.resize( num_incident_edges_ + 1);
691  adjacent_nodes_.resize(num_incident_edges_ + 1);
692 
693  BackgroundEdgeVectorIter position1 = edge_vector_.begin();
694  ++position1;
695 
696  std::copy( edge_list_.begin(), edge_list_.end(), position1 );
697 
698  for (int ii = 1; ii <= num_incident_edges_; ++ii) {
699  //ronj set_pos_in_node_edgevector updates the edge vector in this BackgroundNode.
700  //ronj this BackgroundNode is telling the BackgroundToFirstClass edge connected to it what position in the
701  //ronj edge vector (stored in this class) that edge is in. Hey, edge, you're fourth in my vector of incident edges.
702  edge_vector_[ii]->set_pos_in_node_edgevector( this, ii );
703 
704  adjacent_first_class_node_indices_[ ii ] = edge_vector_[ii]->get_other_ind( this );
705  adjacent_nodes_[ ii ] = edge_vector_[ii]->get_other_node( this );
706  }
707 
708  edge_vector_up_to_date_ = true;
709 }
710 
711 
712 /// @begin BackgroundNode::find_edge
713 ///
714 /// @brief
715 /// Linear time edge lookup function
716 ///
717 /// @param
718 /// fc_node_index - [in] - the index of the first class node that is on the other end of the sought edge
719 ///
720 template < typename V, typename E, typename G >
722 
723  for (BackgroundEdgeListIter iter = edge_list_.begin(); iter != edge_list_.end(); ++iter ) {
724  if ( (*iter)->same_edge( fc_node_index, node_index_ ) )
725  return *iter;
726  }
727  return 0;
728 }
729 
730 
731 /// @begin BackgroundNode::count_dynamic_memory
732 ///
733 /// @brief
734 /// Returns an int representing the amount of memory in bytes used by this node
735 ///
736 /// @remarks
737 /// ronj lists consume more memory because they maintain pointers to the previous and next nodes
738 /// ronj current calculation uses 4 * # elements in list * sizeof(pointer), but I think this is wrong
739 /// ronj isn't it only 3 * # elements in list * sizeof(pointer)?
740 ///
741 /// @param
742 /// total_memory - [out] - the amount of memory used by this node
743 ///
744 template < typename V, typename E, typename G >
746 
747  unsigned int total_memory = 0;
748  total_memory += adjacent_first_class_node_indices_.size() * sizeof( int );
749  total_memory += adjacent_nodes_.size() * sizeof( FirstClassNode< V, E, G >* );
750  total_memory += 4 * edge_list_.size() * sizeof( BackgroundToFirstClassEdge< V, E, G >* );
751  total_memory += edge_vector_.size() * sizeof( BackgroundToFirstClassEdge< V, E, G >* );
752 
753  return total_memory;
754 }
755 
756 
757 //----------------------------------------------------------------------------//
758 //----------------- Second Class To First Class Edge Class -------------------//
759 //----------------------------------------------------------------------------//
760 
761 
762 /// @begin BackgroundToFirstClassEdge::BackgroundToFirstClassEdge
763 ///
764 /// @brief
765 /// BackgroundToFirstClassEdge constructor - no default or copy constructors; no operator =.
766 ///
767 /// @detailed
768 /// This class of edge connects first class and second class nodes. This class of edge is very unlikely to hold the
769 /// same kind of data in a (concrete) derived class. e.g. The SASABackgroundEdge holds pre-computed rotamer sphere
770 /// overlaps for each rotamer-on-a-SASANode and the single-(fixed)-rotamer-on-a-background residue.
771 /// The first class edge does not attempt to store precomputed sphere overlaps as they would be prohibitively expensive.
772 ///
773 /// @param
774 /// owner - [in] - the owning graph
775 /// fc_node_index - [in] - the index of the first class node
776 /// bg_node_index - [in] - the index of the second class node
777 ///
778 template < typename V, typename E, typename G >
780  ( AdditionalBackgroundNodesInteractionGraph< V, E, G > * owner, int fc_node_index, int bg_node_index ) :
781  first_class_node_index_( fc_node_index ),
782  background_node_index_( bg_node_index),
783  owner_( owner )
784 {
785  first_class_node_ = ( FirstClassNode< V, E, G >* )(owner_->get_node( first_class_node_index_ ));
786  background_node_ = owner_->get_background_node( background_node_index_);
787 
788  pos_in_fc_nodes_edge_list_ = first_class_node_->add_background_edge(this);
789  pos_in_bg_nodes_edge_list_ = background_node_->add_edge(this);
790 }
791 
792 
793 /// @begin BackgroundToFirstClassEdge::~BackgroundToFirstClassEdge
794 ///
795 /// @brief
796 /// virtual destructor. The edge removes itself from the graph by informing the two vertices its incident upon
797 /// to drop it from their edge lists.
798 /// Constant time edge removal.
799 ///
800 template < typename V, typename E, typename G >
802  first_class_node_->drop_background_edge( pos_in_fc_nodes_edge_list_ );
803  background_node_->drop_edge( pos_in_bg_nodes_edge_list_ );
804  owner_->drop_background_edge( pos_in_owners_edge_list_ );
805 }
806 
807 
808 /// @begin BackgroundToFirstClassEdge::get_other_ind
809 ///
810 /// @brief
811 /// returns the index of the second class node
812 ///
813 /// @detailed
814 /// A first class vertex may request a BackgroundToFirstClassEdge for the index of the background node the edge connects
815 /// it to by invoking edge->get_other_ind( this ); The this pointer simply tells the compiler which of the two
816 /// overloaded get_other_ind() methods to invoke.
817 ///
818 /// @param
819 /// (unnamed parameter) - [in] - First Class nodes want information about second class nodes when they refer to
820 /// "the other node". The compiler resolves which of the two overloaded methods to invoke.
821 ///
822 template < typename V, typename E, typename G >
824  return background_node_index_;
825 }
826 
827 
828 /// @begin BackgroundToFirstClassEdge::get_other_ind
829 ///
830 /// @brief
831 /// returns the index of the first class node
832 ///
833 /// @detailed
834 /// A second class vertex may request a BackgroundToFirstClassEdge for the index of the first class node the edge connects
835 /// it to by invoking edge->get_other_ind( this ); The this pointer simply tells the compiler which of the two
836 /// overloaded get_other_ind() methods to invoke.
837 ///
838 /// @param
839 /// (unnamed parameter) - [in] - second class nodes want information about first class nodes when they refer to
840 /// "the other node". The compiler resolves which of the two overloaded methods to invoke.
841 ///
842 template < typename V, typename E, typename G >
844  return first_class_node_index_;
845 }
846 
847 
848 /// @begin BackgroundToFirstClassEdge::get_other_node
849 ///
850 /// @brief
851 /// returns a pointer to the second class node
852 ///
853 /// @detailed
854 /// unnamed parameter is usually the this pointer where the method is invoked
855 /// inside a method of a first class node. the pointer type must be resolved
856 /// at compile time. Same ideas here as in get_other_ind()
857 ///
858 template < typename V, typename E, typename G >
860  return background_node_;
861 }
862 
863 
864 /// @begin BackgroundToFirstClassEdge::get_other_node
865 ///
866 /// @brief
867 /// returns a pointer to the first class node
868 ///
869 /// @detailed
870 /// unnamed parameter is usually the this pointer where the method is invoked
871 /// inside a method of a second class node. the pointer type must be resolved
872 /// at compile time. Same ideas here as in get_other_ind()
873 ///
874 template < typename V, typename E, typename G >
876  return first_class_node_;
877 }
878 
879 
880 /// @begin BackgroundToFirstClassEdge::set_pos_in_owners_list
881 ///
882 /// @brief
883 /// stores the iterator to this edge in the owning graph's list of background-to-first-class edges.
884 ///
885 /// @detailed
886 /// required for constant time edge deletion
887 ///
888 template < typename V, typename E, typename G >
889 void
891  pos_in_owners_edge_list_ = iter;
892 }
893 
894 
895 /// @begin BackgroundToFirstClassEdge::set_pos_in_node_edgevector
896 ///
897 /// @brief
898 /// stores the index of this edge in its first class node's edge vector
899 ///
900 /// @detailed
901 /// again, first (unnamed) parameter is the 'this' pointer where the method has
902 /// been invoked inside a method of the first class node.
903 ///
904 /// @param
905 /// (unnamed parameter) - [in] - pointer identifying the type of the node that invoked this overloaded method.
906 /// pos - [in] - the position of 'this' edge in the edge vector of the first class node
907 ///
908 template < typename V, typename E, typename G >
910  pos_in_fc_edge_vector_ = pos;
911 }
912 
913 
914 /// @begin BackgroundToFirstClassEdge::set_pos_in_node_edgevector
915 ///
916 /// @brief
917 /// stores the index of this edge in its second class node's edge vector
918 ///
919 /// @detailed
920 /// again, first (unnamed) parameter is the this pointer where the method has
921 /// been invoked inside a method of the second class node.
922 ///
923 /// @param
924 /// (unnamed parameter) - [in] - pointer identifying the type of the node that invoked this overloaded method.
925 /// pos - [in] - the position of this node in the edge vector of the second class node
926 ///
927 template < typename V, typename E, typename G >
929  pos_in_bg_edge_vector_ = pos;
930 }
931 
932 
933 /// @begin BackgroundToFirstClassEdge::same_edge
934 ///
935 /// @brief
936 /// returns true if this node is incident upon the two input vertex indices
937 ///
938 /// @param
939 /// fc_node_index - [in] - the index of the first class node
940 /// bg_node_index - [in] - the index of the second class node
941 ///
942 /// @remarks
943 /// This graph setup will not support multigraphs: graphs that include multiple edges to the same vertices.
944 /// In my (apl) original dynamic programming algorithm I didn't want to support multigraphs either; but in the
945 /// adaptive dynamic programming implementation, multiple copies of "the same" edge ended up saving time -- though
946 /// maybe not memory. So, this framework here will not readily support adaptive dynamic programming; but that's ok.
947 ///
948 template < typename V, typename E, typename G >
949 bool BackgroundToFirstClassEdge< V, E, G >::same_edge( int fc_node_index, int bg_node_index ) const {
950  return ( (first_class_node_index_ == fc_node_index) && (background_node_index_ == bg_node_index) );
951 }
952 
953 
954 /// @begin BackgroundToFirstClassEdge::count_dynamic_memory
955 ///
956 /// @brief
957 /// Returns an int representing the amount of memory in bytes used by this node
958 ///
959 /// @remarks
960 /// return 0 because no memory is dynamically allocated for these edges.
961 ///
962 template < typename V, typename E, typename G >
964  return 0;
965 }
966 
967 
968 //----------------------------------------------------------------------------//
969 //----------- Additional Background Nodes Interaction Graph Class ------------//
970 //----------------------------------------------------------------------------//
971 
972 
973 /// @begin AdditionalBackgroundNodesInteractionGraph::AdditionalBackgroundNodesInteractionGraph
974 ///
975 /// @brief
976 /// AdditionalBackgroundNodesInteractionGraph constructor; no default or copy constructors; no operator =
977 ///
978 /// @param
979 /// num_nodes - [in] - the number of first class nodes
980 ///
981 template < typename V, typename E, typename G >
983  G( num_nodes ),
984  num_bg_nodes_( -1 ),
985  focused_bg_edge_( 0 )
986 {}
987 
988 
989 /// @begin AdditionalBackgroundNodesInteractionGraph::~AdditionalBackgroundNodesInteractionGraph
990 ///
991 /// @brief
992 /// AdditionalBackgroundNodesInteractionGraph destructor
993 ///
994 /// @detailed
995 /// deallocates each BackgroundToFirstClassEdge. Then deallocates each background
996 /// node. Order is important. The edges assume that its vertices still exist
997 /// at the time it is removed. This destructor enforces that.
998 ///
999 template < typename V, typename E, typename G >
1001 
1002  for ( BackgroundEdgeListIter iter = bg_to_fc_edge_list_.begin(); iter != bg_to_fc_edge_list_.end(); ) { //note: no increment statement here
1003  BackgroundEdgeListIter next_iter = iter;
1004  next_iter++;
1005  //edges delete themselves from this list, invalidating iterators, so
1006  //get the next iterator before calling delete
1007  delete (*iter);
1008  iter = next_iter;
1009  }
1010 
1011  for (int ii = 1; ii <= num_bg_nodes_; ++ii) {
1012  delete bg_nodes_[ ii ];
1013  }
1014 }
1015 
1016 
1017 /// @begin AdditionalBackgroundNodesInteractionGraph::drop_background_edge
1018 ///
1019 /// @brief
1020 /// Constant time edge removal.
1021 ///
1022 /// @detailed
1023 ///
1024 /// @param
1025 /// iter - [in] - the iterator to the position in the graph's edge list for the edge that is removing itself.
1026 ///
1027 template < typename V, typename E, typename G >
1029  bg_to_fc_edge_list_.erase( iter );
1030 }
1031 
1032 
1033 /// @begin AdditionalBackgroundNodesInteractionGraph::set_num_background_nodes
1034 ///
1035 /// @brief
1036 /// sets the number of background nodes in the graph. Should be called no more than once.
1037 /// Some problem instances do not require background nodes.
1038 ///
1039 /// @detailed
1040 /// Allocates the background nodes using a factory method. Their indices start from 1. The create_background_node()
1041 /// method is virtual.
1042 ///
1043 template < typename V, typename E, typename G >
1045 
1046  assert( num_bg_nodes_ == -1 && num_bg_nodes >= 0); //call this method at most once
1047  num_bg_nodes_ = num_bg_nodes;
1048 
1049  if ( num_bg_nodes_ == 0 )
1050  return;
1051 
1052  bg_nodes_.resize( num_bg_nodes_ + 1 );
1053  for ( int ii = 1; ii <= num_bg_nodes_; ++ii ) {
1054  bg_nodes_[ii] = create_background_node(ii);
1055  }
1056 }
1057 
1058 
1059 /// @begin AdditionalBackgroundNodesInteractionGraph::add_background_edge
1060 ///
1061 /// @brief
1062 /// adds a BackgroundToFirstClassEdge to the graph and performs the requisite bookkeepking.
1063 ///
1064 /// @param
1065 /// first_class_node_index - [in] - the index of the first class node
1066 /// bg_node_index - [in] - the index of the second class node
1067 ///
1068 template < typename V, typename E, typename G >
1069 void AdditionalBackgroundNodesInteractionGraph< V, E, G >::add_background_edge( int first_class_node_index, int bg_node_index ) {
1070 
1071  BackgroundToFirstClassEdge< V, E, G >* new_edge = create_background_edge( first_class_node_index, bg_node_index );
1072  bg_to_fc_edge_list_.push_front( new_edge );
1073  new_edge->set_pos_in_owners_list( bg_to_fc_edge_list_.begin() );
1074  focused_bg_edge_ = new_edge;
1075  return;
1076 }
1077 
1078 
1079 /// @begin AdditionalBackgroundNodesInteractionGraph::find_background_edge
1080 ///
1081 /// @brief
1082 /// returns a pointer to the background edge, identified by the indices of the first and second class nodes it connects.
1083 /// Returns the null pointer if the edge does not exist. Possibly linear time operation (in the number of
1084 /// BackgroundToFirstClassEdges).
1085 ///
1086 /// @detailed
1087 /// The graph keeps a pointer to a "focused edge" so that repeated requests for the same edge take constant time.
1088 ///
1089 /// @param
1090 /// first_class_node_index - [in] - the index of the first class node
1091 /// bg_node_index - [in] - the index of the second class node
1092 ///
1093 template < typename V, typename E, typename G >
1095  AdditionalBackgroundNodesInteractionGraph< V, E, G >::find_background_edge( int first_class_node_index, int bg_node_index ) const {
1096 
1097  if ( (focused_bg_edge_ != 0) && !( focused_bg_edge_->same_edge(first_class_node_index, bg_node_index) ) ) {
1098  focused_bg_edge_ = bg_nodes_[ bg_node_index ]->find_edge( first_class_node_index );
1099  }
1100  return focused_bg_edge_;
1101 }
1102 
1103 
1104 /// @begin AdditionalBackgroundNodesInteractionGraph::prepare_for_simulated_annealing
1105 ///
1106 /// @brief
1107 /// invokes prepare_for_simulated_annealing on each of the BackgroundToFirstClassEdges and then invokes
1108 /// prepare_for_simulated_annealing on each of the BackgroundNodes.
1109 ///
1110 /// @detailed
1111 /// A BackgroundToFirstClassEdges may decide to delete itself before sim annealing begins. Since the second class node
1112 /// will likely update is edge vector in its (virtual) call to prepare_for_sim_annealing, any edges that should be
1113 /// should be removed before the second class nodes update their edge vectors.
1114 ///
1115 /// @remarks
1116 /// does not invoke InteractionGraphBase::prepare_for_simulated_annealing()
1117 ///
1118 template < typename V, typename E, typename G >
1120 
1121  for ( BackgroundEdgeListIter iter = bg_to_fc_edge_list_.begin(); iter != bg_to_fc_edge_list_.end(); ) { //note: no increment statement here
1122 
1123  BackgroundEdgeListIter next_iter = iter;
1124  next_iter++;
1125 
1126  // edges sometimes delete themselves, invalidating iterators, so
1127  // get the next iterator before calling prepare_for_simulated_annealing
1128 
1129  // BackgroundToFirstClassEdge::prepare_for_simulated_annealing() is a pure virtual
1130  (*iter)->prepare_for_simulated_annealing();
1131  iter = next_iter;
1132  }
1133 
1134  for (int ii = 1; ii <= num_bg_nodes_; ++ii) {
1135  // BackgroundNode::prepare_for_simulated_annealing() is a pure virtual
1136  bg_nodes_[ ii ]->prepare_for_simulated_annealing();
1137  }
1138 
1139  return;
1140 }
1141 
1142 
1143 /// @begin AdditionalBackgroundNodesInteractionGraph::getTotalMemoryUsage
1144 ///
1145 /// @brief
1146 /// Returns an int representing the total amount of memory in bytes used by this graph
1147 ///
1148 template < typename V, typename E, typename G >
1150 
1151  unsigned int total_memory = G::getTotalMemoryUsage();
1152 
1153  for (int ii = 1; ii <= get_num_background_nodes(); ++ii) {
1154  total_memory += bg_nodes_[ii]->count_dynamic_memory();
1155  total_memory += bg_nodes_[ii]->count_static_memory();
1156  }
1157 
1158  for ( BackgroundEdgeListConstIter iter = bg_to_fc_edge_list_.begin(); iter != bg_to_fc_edge_list_.end(); ++iter ) {
1159  total_memory += (*iter)->count_dynamic_memory();
1160  total_memory += (*iter)->count_static_memory();
1161  }
1162 
1163  return total_memory;
1164 }
1165 
1166 
1167 /// @begin AdditionalBackgroundNodesInteractionGraph::count_dynamic_memory
1168 ///
1169 /// @brief
1170 /// Returns an int representing the amount of dynamic memory in bytes used by this graph
1171 ///
1172 template < typename V, typename E, typename G >
1174 
1175  unsigned int total_memory = G::count_dynamic_memory();
1176 
1177  total_memory += bg_nodes_.size() * sizeof( BackgroundNode< V, E, G >* );
1178  total_memory += 4 * bg_to_fc_edge_list_.size() * sizeof( BackgroundToFirstClassEdge< V, E, G >* );
1179 
1180  return total_memory;
1181 }
1182 
1183 
1184 }
1185 }
1186 } //end namespace pack
1187 
1188 #endif
1189