Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
InteractionGraphBase.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/InteractionGraphBase.cc
11 /// @brief Interaction graph base class
12 /// @author Andrew Leaver-Fay (leaverfa@email.unc.edu)
13 
14 // Unit Headers
16 
17 /// Utility headers
18 #include <utility/exit.hh>
19 
20 //STL Headers
21 #include <list>
22 // AUTO-REMOVED #include <vector>
23 #include <algorithm>
24 #include <iostream>
25 #include <cassert>
26 
27 //ObjexxFCL Headers
28 #include <ObjexxFCL/FArray1A.hh>
29 
30 using namespace ObjexxFCL;
31 
32 namespace core {
33 namespace pack {
34 namespace interaction_graph {
35 
36 //----------------------------------------------------------------------------//
37 //---------------------- Interaction Graph Node Base Class -------------------//
38 //----------------------------------------------------------------------------//
39 
40 
41 //bool output_interaction_graph_memory_usage = false;
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// @begin NodeBase::~NodeBase
45 ///
46 /// @brief
47 /// virtual destructor
48 ///
49 /// @detailed
50 ///
51 /// @global_read
52 ///
53 /// @global_write
54 ///
55 /// @remarks
56 ///
57 /// @references
58 ///
59 /// @authors apl
60 ///
61 /// @last_modified
62 ////////////////////////////////////////////////////////////////////////////////
63 NodeBase::~NodeBase()
64 {}
65 
66 ////////////////////////////////////////////////////////////////////////////////
67 /// @begin NodeBase::NodeBase(InteractionGraphBase *, int, int)
68 ///
69 /// @brief
70 /// Main constructor, no default constructor nor copy constructor
71 ///
72 /// @detailed
73 ///
74 /// @param
75 /// owner - [in] - the owning interaction graph
76 /// node_id - [in] - the index for this node amongst its owners set
77 /// num_states - [in] - the number of states for this node
78 ///
79 /// @global_read
80 ///
81 /// @global_write
82 ///
83 /// @remarks
84 ///
85 /// @references
86 ///
87 /// @authors apl
88 ///
89 /// @last_modified
90 ////////////////////////////////////////////////////////////////////////////////
91 NodeBase::NodeBase(InteractionGraphBase * owner, int node_id, int num_states) :
92  node_index_(node_id), num_states_(num_states), num_incident_edges_(0),
93  num_edges_to_smaller_indexed_nodes_(0),
94  num_edges_to_larger_indexed_nodes_(0),
95  edge_vector_up_to_date_(false), owner_(owner)
96 {}
97 
98 
99 ////////////////////////////////////////////////////////////////////////////////
100 /// @begin NodeBase::~get_num_states
101 ///
102 /// @brief
103 /// returns the number of states for this node
104 ///
105 /// @detailed
106 ///
107 /// @global_read
108 ///
109 /// @global_write
110 ///
111 /// @remarks
112 ///
113 /// @references
114 ///
115 /// @authors apl
116 ///
117 /// @last_modified
118 ////////////////////////////////////////////////////////////////////////////////
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// @begin NodeBase::add_edge
123 ///
124 /// @brief adds edge pointer to edge list; returns an iterator to the new
125 /// list element
126 ///
127 /// @detailed
128 /// If the other node this node is attached to by edge_ptr has a higher index
129 /// then the edge is added to the end of its edge list; if the node has a
130 /// smaller index, the edge pointer is added to the front of the edge list.
131 /// The presence of a new edge means the edge vector is not up to date.
132 ///
133 /// @param
134 /// edge_ptr - [in] - the new edge
135 ///
136 /// @global_read
137 ///
138 /// @global_write
139 ///
140 /// @remarks
141 ///
142 /// @references
143 ///
144 /// @authors apl
145 ///
146 /// @last_modified
147 ////////////////////////////////////////////////////////////////////////////////
148 std::list< EdgeBase* >::iterator NodeBase::add_edge(EdgeBase* edge_ptr)
149 {
151  edge_vector_up_to_date_ = false;
152  int other_node_index = edge_ptr->get_other_ind( node_index_);
153  if (other_node_index < node_index_) {
155  return incident_edge_list_.insert( incident_edge_list_.begin(), edge_ptr);
156  } else {
158  return incident_edge_list_.insert(incident_edge_list_.end(), edge_ptr);
159  }
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// @begin NodeBase::drop_edge
164 ///
165 /// @brief removes an edge iterator from the node's edge list
166 ///
167 /// @detailed
168 /// edges efficiently delete themselves from the edge lists of the nodes they
169 /// are incident upon by keeping a pair of iterators. Edges request nodes
170 /// delete them by handing the iterator back to the node.
171 ///
172 /// @param
173 /// edge - [in] - the iterator for this node's edge list that points at the
174 /// edge which is trying to delete itself
175 ///
176 /// @global_read
177 ///
178 /// @global_write
179 ///
180 /// @remarks
181 ///
182 /// @references
183 ///
184 /// @authors apl
185 ///
186 /// @last_modified
187 ////////////////////////////////////////////////////////////////////////////////
188 void NodeBase::drop_edge(std::list< EdgeBase* >::iterator edge)
189 {
190  int other_node_index = (*edge)->get_other_ind( node_index_ );
191  if (node_index_ < other_node_index) {
193  } else {
195  }
196  incident_edge_list_.erase(edge);
198  edge_vector_up_to_date_ = false;
199 }
200 
201 ////////////////////////////////////////////////////////////////////////////////
202 /// @begin NodeBase::drop_all_edges
203 ///
204 /// @brief
205 /// deletes all edges incident upon this node
206 ///
207 /// @detailed
208 ///
209 /// @param
210 //
211 /// @global_read
212 ///
213 /// @global_write
214 ///
215 /// @remarks
216 ///
217 /// @references
218 ///
219 /// @authors apl
220 ///
221 /// @last_modified
222 ////////////////////////////////////////////////////////////////////////////////
224 {
225  for (std::list< EdgeBase* >::iterator iter = incident_edge_list_.begin();
226  iter != incident_edge_list_.end(); ) {
227  std::list< EdgeBase* >::iterator nextiter = iter;
228  ++nextiter;
229  delete *iter; iter = nextiter;
230  }
231  edge_vector_up_to_date_ = false;
232 }
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 /// @begin NodeBase::find_edge
236 ///
237 /// @brief a slow (linear) search for an edge. The edge is identified by the
238 /// index of the node to which the edge connects this node. Returns NULL when
239 /// there is no such connecting edge.
240 ///
241 /// @detailed
242 ///
243 /// @param
244 /// other_node - [in] - the index of the node that the desired
245 /// edge connects this node to
246 ///
247 /// @global_read
248 ///
249 /// @global_write
250 ///
251 /// @remarks
252 ///
253 /// @references
254 ///
255 /// @authors
256 ///
257 /// @last_modified
258 ////////////////////////////////////////////////////////////////////////////////
259 EdgeBase* NodeBase::find_edge(int other_node) const
260 {
261  for (std::list< EdgeBase* >::const_iterator iter = incident_edge_list_.begin();
262  iter != incident_edge_list_.end(); iter++) {
263  if ( (*iter)->same_edge( node_index_, other_node) ) return (*iter);
264  }
265  return NULL;
266 }
267 
268 
269 ////////////////////////////////////////////////////////////////////////////////
270 /// @begin NodeBase::depth_first_connected_component_counting
271 ///
272 /// @brief
273 /// performs a depth first traversal of the graph. Each node informs
274 /// the graph that the traversal resulted in arriving at the node.
275 ///
276 /// @detailed
277 ///
278 /// @param
279 ///
280 /// @global_read
281 ///
282 /// @global_write
283 ///
284 /// @remarks
285 ///
286 /// @references
287 ///
288 /// @authors apl
289 ///
290 /// @last_modified
291 ////////////////////////////////////////////////////////////////////////////////
293 {
294  if ( owner_->vertex_already_reached( node_index_) ) return;
295 
296  //std::cerr << "Arrived at node: " << node_index_ << std::endl;
298 
299  for (std::list< EdgeBase* >::const_iterator iter = incident_edge_list_.begin();
300  iter != incident_edge_list_.end(); ++iter) {
301  ((*iter)->get_other_node( node_index_ ))->
303  }
304 
305 }
306 
307 
308 std::list< EdgeBase * >::const_iterator
310 {
311  return incident_edge_list_.begin();
312 }
313 
314 std::list< EdgeBase * >::const_iterator
316 {
317  return incident_edge_list_.end();
318 }
319 
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// @begin NodeBase::update_edge_vector
323 ///
324 /// @brief converts edge-list to edge-vector representation
325 ///
326 /// @detailed
327 ///
328 /// @param
329 ///
330 /// @global_read
331 ///
332 /// @global_write
333 ///
334 /// @remarks
335 ///
336 /// @references
337 ///
338 /// @authors apl
339 ///
340 /// @last_modified
341 ////////////////////////////////////////////////////////////////////////////////
343 {
347 
348  std::vector< EdgeBase* >::iterator position1 = incident_edge_vector_.begin();
349  ++position1;
350 
351  std::copy( incident_edge_list_.begin(), incident_edge_list_.end(), position1 );
352 
353  for (int ii = 1; ii <= num_incident_edges_; ++ii) {
354  incident_edge_vector_[ii]->set_pos_in_node_edgevector( node_index_, ii );
355  adjacent_node_ind_[ ii ] = incident_edge_vector_[ii]->get_other_ind( node_index_);
356 
357  assert( (adjacent_node_ind_[ii] < node_index_ &&
359  ||
362 
363  adjacent_node_[ ii ] = incident_edge_vector_[ii]->get_other_node( node_index_ );
364  }
365 
367  return;
368 }
369 
370 /// @brief memory accounting scheme
371 unsigned int
373 {
374  unsigned int total_memory = 0;
375  total_memory += 4 * incident_edge_list_.size() * sizeof( EdgeBase* );
376  total_memory += incident_edge_vector_.size() * sizeof( EdgeBase* );
377  total_memory += adjacent_node_ind_.size() * sizeof( int );
378  total_memory += adjacent_node_.size() * sizeof( NodeBase* );
379  return total_memory;
380 }
381 
382 
383 ////////////////////////////////////////////////////////////////////////////////
384 /// @begin NodeBase::NodeBase( NodeBase const & rhs)
385 ///
386 /// @brief copy constructor, do not use
387 ///
388 /// @detailed
389 ///
390 /// @param
391 ///
392 /// @global_read
393 ///
394 /// @global_write
395 ///
396 /// @remarks
397 ///
398 /// @references
399 ///
400 /// @authors apl
401 ///
402 /// @last_modified
403 ////////////////////////////////////////////////////////////////////////////////
404 //NodeBase::NodeBase( NodeBase const & ) {}
405 
406 //----------------------------------------------------------------------------//
407 //--------------------- Interaction Graph Edge Base Class --------------------//
408 //----------------------------------------------------------------------------//
409 
410 ////////////////////////////////////////////////////////////////////////////////
411 /// @begin EdgeBase::~EdgeBase
412 ///
413 /// @brief destructor
414 ///
415 /// @detailed removes all record of this edge from edge-lists of
416 /// the 1) nodes this edge is incident upon and 2) the owning
417 /// interaction graph
418 ///
419 /// @param
420 ///
421 /// @global_read
422 ///
423 /// @global_write
424 ///
425 /// @remarks
426 ///
427 /// @references
428 ///
429 /// @authors apl
430 ///
431 /// @last_modified
432 ////////////////////////////////////////////////////////////////////////////////
434 {
435  //std::cerr << "~EdgeBase(): " << this << " node 1 " << node_indices_[0]
436  //<< " node 2 " << node_indices_[1] << " owner " <<
437  //*pos_in_owners_edge_list_ << " ";
438  //assert( this == *pos_in_owners_edge_list_);
442 }
443 
444 ////////////////////////////////////////////////////////////////////////////////
445 /// @begin EdgeBase::EdgeBase(InteractionGraphBase, int, int)
446 ///
447 /// @brief main constructor for edge, no default nor copy constructors
448 ///
449 /// @detailed edge adds itself to the edge list of the two nodes its set to be
450 /// incident upon, and stores the list-iterators that the nodes return.
451 ///
452 /// @param
453 /// owner - [in] - owning InteractionGraph
454 /// @param
455 /// first_node_ind - [in] - the index of the first node
456 /// @param
457 /// second_node_ind - [in] - the index of the second node
458 ///
459 /// @global_read
460 ///
461 /// @global_write
462 ///
463 /// @remarks
464 ///
465 /// @references
466 ///
467 /// @authors apl
468 ///
469 /// @last_modified
470 ////////////////////////////////////////////////////////////////////////////////
472 (
473  InteractionGraphBase* owner,
474  int first_node_ind,
475  int second_node_ind
476 )
477  : owner_(owner),
478  edge_weight_( 1.0 )
479 { //pre condition: first_node_ind < second_node_ind.
480  node_indices_[0] = first_node_ind;
481  node_indices_[1] = second_node_ind;
482  nodes_[0] = owner->ig_nodes_[ node_indices_[0] ];
483  nodes_[1] = owner->ig_nodes_[ node_indices_[1] ];
484  num_node_states_[0] = nodes_[0]->get_num_states();
485  num_node_states_[1] = nodes_[1]->get_num_states();
486 
487  pos_in_nodes_edge_list_[0] = nodes_[0]->add_edge(this);
488  pos_in_nodes_edge_list_[1] = nodes_[1]->add_edge(this);
489 
490  return;
491 }
492 
493 ////////////////////////////////////////////////////////////////////////////////
494 /// @begin EdgeBase::get_other_ind
495 ///
496 /// @brief returns the index of the other node that the edge is incident upon
497 ///
498 /// @detailed
499 ///
500 /// @param
501 /// node_ind - [in] - the node index of the node whose index is already known
502 ///
503 /// @global_read
504 ///
505 /// @global_write
506 ///
507 /// @remarks
508 ///
509 /// @references
510 ///
511 /// @authors apl
512 ///
513 /// @last_modified
514 ////////////////////////////////////////////////////////////////////////////////
515 int EdgeBase::get_other_ind(int node_ind) const
516 { assert( node_ind == node_indices_[0] || node_ind == node_indices_[1]);
517  return node_indices_[0] == node_ind ? node_indices_[1] : node_indices_[0];
518 }
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 /// @begin EdgeBase::get_other_node
522 ///
523 /// @brief returns a pointer to the other node that the edge is incident upon
524 ///
525 /// @detailed
526 ///
527 /// @param
528 /// node_ind - [in] - the node index of the node whose index is already known
529 ///
530 /// @global_read
531 ///
532 /// @global_write
533 ///
534 /// @remarks
535 ///
536 /// @references
537 ///
538 /// @authors apl
539 ///
540 /// @last_modified
541 ////////////////////////////////////////////////////////////////////////////////
542 NodeBase* EdgeBase::get_other_node(int node_ind) const
543 { assert( node_ind == node_indices_[0] || node_ind == node_indices_[1]);
544  return node_indices_[0] == node_ind ? nodes_[1] : nodes_[0];
545 }
546 
547 ////////////////////////////////////////////////////////////////////////////////
548 /// @begin EdgeBase::get_first_node_ind
549 ///
550 /// @brief returns the index of the smaller-indexed node
551 ///
552 /// @detailed
553 ///
554 /// @param
555 ///
556 /// @global_read
557 ///
558 /// @global_write
559 ///
560 /// @remarks
561 ///
562 /// @references
563 ///
564 /// @authors apl
565 ///
566 /// @last_modified
567 ////////////////////////////////////////////////////////////////////////////////
569 { return node_indices_[0]; }
570 
571 ////////////////////////////////////////////////////////////////////////////////
572 /// @begin EdgeBase::get_second_node_ind()
573 ///
574 /// @brief returns the index of the larger-indexed node
575 ///
576 /// @detailed
577 ///
578 /// @param
579 ///
580 /// @global_read
581 ///
582 /// @global_write
583 ///
584 /// @remarks
585 ///
586 /// @references
587 ///
588 /// @authors apl
589 ///
590 /// @last_modified
591 ////////////////////////////////////////////////////////////////////////////////
593 { return node_indices_[1]; }
594 
595 ////////////////////////////////////////////////////////////////////////////////
596 /// @begin EdgeBase::set_pos_in_owners_list
597 ///
598 /// @brief edge keeps iterator to its position in it's owner's edge list
599 ///
600 /// @detailed
601 ///
602 /// @param
603 ///
604 /// @global_read
605 ///
606 /// @global_write
607 ///
608 /// @remarks
609 ///
610 /// @references
611 ///
612 /// @authors apl
613 ///
614 /// @last_modified
615 ////////////////////////////////////////////////////////////////////////////////
616 void EdgeBase::set_pos_in_owners_list( std::list< EdgeBase* >::iterator iter )
617 {
618  assert( this == *iter);
620  return;
621 }
622 
623 ////////////////////////////////////////////////////////////////////////////////
624 /// @begin EdgeBase::set_pos_in_node_edgevector
625 ///
626 /// @brief edge keeps index it has in node_ind's edge vector
627 ///
628 /// @detailed
629 ///
630 /// @param
631 /// node_ind - [in] - the index of the node calling this method
632 /// @param
633 /// vect_position - [in] - the position for this edge in the node's edge vector
634 ///
635 /// @global_read
636 ///
637 /// @global_write
638 ///
639 /// @remarks
640 ///
641 /// @references
642 ///
643 /// @authors apl
644 ///
645 /// @last_modified
646 ////////////////////////////////////////////////////////////////////////////////
647 void EdgeBase::set_pos_in_node_edgevector(int node_ind, int vect_position)
648 {
649  assert( node_ind == node_indices_[0] || node_ind == node_indices_[1]);
650  int node_pos = (node_ind == node_indices_[0] ? 0 : 1 );
651  pos_in_nodes_edge_vector_[node_pos] = vect_position;
652  return;
653 }
654 
655 ////////////////////////////////////////////////////////////////////////////////
656 /// @begin EdgeBase::same_edge
657 ///
658 /// @brief returns true if this edge connects nodes of index node1 and node2
659 /// the order of node1 and node2 is not important
660 ///
661 /// @detailed
662 ///
663 /// @param
664 /// node1 - [in] - index of one of the two nodes
665 /// @param
666 /// node2 - [in] - index of the other of the two nodes
667 ///
668 /// @global_read
669 ///
670 /// @global_write
671 ///
672 /// @remarks
673 ///
674 /// @references
675 ///
676 /// @authors apl
677 ///
678 /// @last_modified
679 ////////////////////////////////////////////////////////////////////////////////
680 bool EdgeBase::same_edge(int node1, int node2) const
681 {
682  //swap
683  if (node1 > node2)
684  {
685  int temp = node2;
686  node2 = node1;
687  node1 = temp;
688  }
689  return (node1 == node_indices_[0] && node2 == node_indices_[1]);
690 }
691 
692 
693 unsigned int
695 {
696  return 0;
697 }
698 
699 void
701 {
702  edge_weight_ = new_weight;
703 }
704 
705 
706 //----------------------------------------------------------------------------//
707 //------------------------- Interaction Graph Base Class ---------------------//
708 //----------------------------------------------------------------------------//
709 
710 ////////////////////////////////////////////////////////////////////////////////
711 /// @begin InteractionGraphBase::~InteractionGraphBase
712 ///
713 /// @brief destructor
714 ///
715 /// @detailed deletes each edge in the graph and deletes each node
716 ///
717 /// @param
718 ///
719 /// @global_read
720 ///
721 /// @global_write
722 ///
723 /// @remarks
724 ///
725 /// @references
726 ///
727 /// @authors apl
728 ///
729 /// @last_modified
730 ////////////////////////////////////////////////////////////////////////////////
732 {
733 
734  for (std::list< EdgeBase* >::iterator iter = ig_edge_list_.begin();
735  iter != ig_edge_list_.end(); )
736  {
737  std::list< EdgeBase* >::iterator next_iter = iter;
738  next_iter++;
739  delete (*iter);
740  iter = next_iter;
741  }
742  for (int ii = 1; ii <= num_ig_nodes_; ii++)
743  delete ig_nodes_[ii];
744 }
745 
746 ////////////////////////////////////////////////////////////////////////////////
747 /// @begin InteractionGraphBase::InteractionGraphBase
748 ///
749 /// @brief main constructor
750 ///
751 /// @detailed no default or copy constructors provided.
752 ///
753 /// @param
754 /// num_ig_nodes - [in] - number of nodes that this graph will contain
755 ///
756 /// @global_read
757 ///
758 /// @global_write
759 ///
760 /// @remarks
761 ///
762 /// @references
763 ///
764 /// @authors apl
765 ///
766 /// @last_modified
767 ////////////////////////////////////////////////////////////////////////////////
769  num_ig_nodes_(num_ig_nodes),
770  ig_nodes_(num_ig_nodes + 1, (NodeBase*) NULL),
771  node_state_offsets_( num_ig_nodes + 1, 0 ),
772  num_total_states_(0),
773  focused_edge_(NULL),
774  num_energy_sum_groups_( -1 )
775 {}
776 
777 ////////////////////////////////////////////////////////////////////////////////
778 /// @begin InteractionGraphBase::set_num_states_for_node
779 ///
780 /// @brief sets the number of states for a node of a particular index
781 /// NEW REQUIREMENT: Nodes must have their num-states set in ascending order by
782 /// node index; that is, node 1 must go first, node 2 next, and so on.
783 ///
784 /// @detailed once the graph knows how many states a node has, it instantiates
785 /// a new node using the NodeBase(int) constructor through the graph's
786 /// factory method create_new_node()
787 ///
788 /// @param
789 /// node_index - [in] - the index of the node
790 /// @param
791 /// num_states - [in] - the number of states for that node
792 ///
793 /// @global_read
794 ///
795 /// @global_write
796 ///
797 /// @remarks
798 ///
799 /// @references
800 ///
801 /// @authors apl
802 ///
803 /// @last_modified
804 ////////////////////////////////////////////////////////////////////////////////
806 (
807  int node_index,
808  int num_states
809 )
810 {
811  assert (ig_nodes_[node_index] == NULL);
812  ig_nodes_[node_index] = create_new_node( node_index, num_states);
813  num_total_states_ += num_states;
814  if ( node_index != num_ig_nodes_ )
815  {
816  node_state_offsets_[ node_index + 1 ] =
817  node_state_offsets_[ node_index ] + num_states;
818  }
819  return;
820 }
821 
822 ////////////////////////////////////////////////////////////////////////////////
823 /// @begin InteractionGraphBase::get_num_states_for_node
824 ///
825 /// @brief returns the number of states for a particular node
826 ///
827 /// @detailed
828 ///
829 /// @param
830 /// node_index - [in] - the index of the node in question
831 ///
832 /// @global_read
833 ///
834 /// @global_write
835 ///
836 /// @remarks
837 ///
838 /// @references
839 ///
840 /// @authors apl
841 ///
842 /// @last_modified
843 ////////////////////////////////////////////////////////////////////////////////
845 {
846  assert( ig_nodes_[node_index] );
847  return ig_nodes_[node_index]->get_num_states();
848 }
849 
850 ////////////////////////////////////////////////////////////////////////////////
851 /// @begin InteractionGraphBase::add_edge
852 ///
853 /// @brief creates a new edge between nodes index1 and index2. Nodes do
854 /// not have to be listed in order
855 ///
856 /// @detailed uses factory method create_new_edge and adds
857 /// the created edge to the graph's edge list.
858 ///
859 /// @param
860 /// index1 - [in] - index of one of the two nodes the edge is to connect
861 /// @param
862 /// index2 - [in] - index of the second of the two nodes the edge is to connect
863 ///
864 /// @global_read
865 ///
866 /// @global_write
867 ///
868 /// @remarks
869 ///
870 /// @references
871 ///
872 /// @authors apl
873 ///
874 /// @last_modified
875 ////////////////////////////////////////////////////////////////////////////////
876 void InteractionGraphBase::add_edge(int index1, int index2)
877 {
878  //swap so that index1 < index2
879  int temp = index1 < index2 ? index1 : index2;
880  index2 = index1 < index2 ? index2 : index1;
881  index1 = temp;
882 
883  assert( index1 != index2 );
884 
885  EdgeBase* new_edge = create_new_edge(index1, index2);
886  ig_edge_list_.push_front( new_edge );
887  new_edge->set_pos_in_owners_list( ig_edge_list_.begin() );
888  focused_edge_ = new_edge;
889  return;
890 }
891 
892 
893 ////////////////////////////////////////////////////////////////////////////////
894 /// @begin InteractionGraphBase::get_edge_exists
895 ///
896 /// @brief returns true if an edge between node1 and node2 exists
897 ///
898 /// @detailed
899 ///
900 /// @param
901 /// node1 - [in] - index of the one of the nodes
902 /// node2 - [in] - index of the other node
903 ///
904 /// @global_read
905 ///
906 /// @global_write
907 ///
908 /// @remarks
909 ///
910 /// @references
911 ///
912 /// @authors apl
913 ///
914 /// @last_modified
915 ////////////////////////////////////////////////////////////////////////////////
916 bool InteractionGraphBase::get_edge_exists(int node1, int node2)
917 {
918  EdgeBase* edge = find_edge( node1, node2 );
919  return (edge != NULL);
920 }
921 
922 ////////////////////////////////////////////////////////////////////////////////
923 /// @begin InteractionGraphBase::drop_all_edges_for_node
924 ///
925 /// @brief
926 /// deletes all edges adjacent to the node specified
927 ///
928 /// @detailed
929 ///
930 /// @param
931 /// node - [in] - index of the node
932 ///
933 /// @global_read
934 ///
935 /// @global_write
936 ///
937 /// @remarks
938 ///
939 /// @references
940 ///
941 /// @authors apl
942 ///
943 /// @last_modified
944 ////////////////////////////////////////////////////////////////////////////////
946 {
947  NodeBase* nodeptr = get_node( node );
948  nodeptr->drop_all_edges();
949 }
950 
951 /// @details Edges may decide to delete themselves during this subroutine; therefore
952 /// edges are prepared first. Afterwards, the nodes must update their
953 /// edge vector representation.
955 {
956  for (std::list< EdgeBase* >::iterator iter = get_edge_list_begin();
957  iter != get_edge_list_end();
958  /* note: no increment statement here */ ) {
959  std::list< EdgeBase* >::iterator next_iter = iter;
960  next_iter++;
961  //edges sometimes delete themselves, invalidating iterators, so
962  //get the next iterator before calling prepare_for_simulated_annealing
963  (*iter)->prepare_for_simulated_annealing();
964  iter = next_iter;
965  }
966 
967  for (int ii = 1; ii <= get_num_nodes(); ++ii) {
969  }
970  return;
971 }
972 
973 
974 ////////////////////////////////////////////////////////////////////////////////
975 /// @begin InteractionGraphBase::print_vertices
976 ///
977 /// @brief calls print() on each of the nodes in the graph
978 ///
979 /// @detailed
980 ///
981 /// @param
982 ///
983 /// @global_read
984 ///
985 /// @global_write
986 ///
987 /// @remarks
988 ///
989 /// @references
990 ///
991 /// @authors apl
992 ///
993 /// @last_modified
994 ////////////////////////////////////////////////////////////////////////////////
996 {
997  for (int ii = 1; ii <= num_ig_nodes_; ii++)
998  ig_nodes_[ii]->print();
999  return;
1000 }
1001 
1002 ////////////////////////////////////////////////////////////////////////////////
1003 /// @begin InteractionGraphBase::output_connectivity
1004 ///
1005 /// @brief writes out a list of all the edges in the graph
1006 ///
1007 /// @detailed
1008 ///
1009 /// @param
1010 /// os - [in] - the output stream to write to
1011 ///
1012 /// @global_read
1013 ///
1014 /// @global_write
1015 ///
1016 /// @remarks
1017 ///
1018 /// @references
1019 ///
1020 /// @authors apl
1021 ///
1022 /// @last_modified
1023 ////////////////////////////////////////////////////////////////////////////////
1024 void InteractionGraphBase::output_connectivity(std::ostream & os) const
1025 {
1026  int counter = 1;
1027  for (std::list< EdgeBase* >::const_iterator iter = ig_edge_list_.begin();
1028  iter != ig_edge_list_.end(); iter++)
1029  { os << "edge " << counter << " between " << (*iter)->get_first_node_ind()
1030  << " " << (*iter)->get_second_node_ind() << std::endl;
1031  counter++;
1032  }
1033  return;
1034 }
1035 
1036 ////////////////////////////////////////////////////////////////////////////////
1037 /// @begin InteractionGraphBase::output_dimacs
1038 ///
1039 /// @brief writes out a connectivity description of the graph in the famous
1040 /// dimacs format. (where the first column "DIMACS:" should be sed'ed out)
1041 ///
1042 /// @detailed
1043 ///
1044 /// @param
1045 /// os - [in] - the output stream to write to
1046 ///
1047 /// @global_read
1048 ///
1049 /// @global_write
1050 ///
1051 /// @remarks
1052 ///
1053 /// @references
1054 ///
1055 /// @authors apl
1056 ///
1057 /// @last_modified
1058 ////////////////////////////////////////////////////////////////////////////////
1059 void InteractionGraphBase::output_dimacs(std::ostream & os) const
1060 {
1061  int num_edges = ig_edge_list_.size();
1062  os << "DIMACS: " << "p edges " << num_ig_nodes_ << " " ;
1063  os << num_edges << std::endl;
1064  for (std::list< EdgeBase* >::const_iterator iter = ig_edge_list_.begin();
1065  iter != ig_edge_list_.end(); iter++)
1066  {
1067  os << "DIMACS: " << "e " << (*iter)->get_first_node_ind();
1068  os << " " << (*iter)->get_second_node_ind() << std::endl;
1069  }
1070 
1071  return;
1072 }
1073 
1074 ////////////////////////////////////////////////////////////////////////////////
1075 /// @begin InteractionGraphBase::output_dimacs
1076 ///
1077 /// @brief
1078 /// Returns true if any node in the graph is in state 0, the unassigned state.
1079 ///
1080 /// @detailed
1081 /// Useful for debugging. If simulated annealing completes, and any vertex
1082 /// remains in state 0, then the state assignment is not meaningful nor
1083 /// is the energy for that assignment. The cases in which state-0 problems
1084 /// turn up are from passing an annealer a list of states to restrict itself to
1085 /// wherein some vertex has no states listed. Such cases are bugs; this
1086 /// subroutine helps identify them.
1087 ///
1088 /// @param
1089 ///
1090 /// @global_read
1091 ///
1092 /// @global_write
1093 ///
1094 /// @remarks
1095 ///
1096 /// @references
1097 ///
1098 /// @authors apl
1099 ///
1100 /// @last_modified
1101 ////////////////////////////////////////////////////////////////////////////////
1102 bool
1104 {
1105  for (int ii = 1; ii <= get_num_nodes(); ++ii)
1106  {
1107  if ( get_node( ii )->state_unassigned() ) return true;
1108  }
1109  return false;
1110 }
1111 
1112 ////////////////////////////////////////////////////////////////////////////////
1113 /// @begin InteractionGraphBase::add_to_one_body_energies
1114 ///
1115 /// @brief
1116 /// takes one FArray of energies -- one energy for each state for each node
1117 ///
1118 /// @detailed
1119 /// The input array should have \sum_{v\inV} |S_v| entries, where S_v is the
1120 /// state-space for vertex v. If the graph has two vertices, with 15 and 20
1121 /// states respectively, then entries 1 to 15 correspond to vertex 1, and
1122 /// entries 16 to 36 correspond to vertex 2. This compact enumeration scheme
1123 /// is the same as the enumeration scheme used by rotindex, rotcoord, etc
1124 ///
1125 /// @param
1126 /// one_body_energies - [in] - the array of one body energies
1127 ///
1128 /// @global_read
1129 ///
1130 /// @global_write
1131 ///
1132 /// @remarks
1133 ///
1134 /// @references
1135 ///
1136 /// @authors apl
1137 ///
1138 /// @last_modified
1139 ////////////////////////////////////////////////////////////////////////////////
1142  FArray1< core::PackerEnergy > & one_body_energies
1143 )
1144 {
1145  for (int ii = 1; ii <= num_ig_nodes_; ++ii )
1146  {
1147  int ii_num_states;
1148  if ( ii == num_ig_nodes_ )
1149  {
1150  ii_num_states = num_total_states_ - node_state_offsets_[ii];
1151  }
1152  else
1153  {
1154  ii_num_states = node_state_offsets_[ ii + 1 ] - node_state_offsets_[ ii ];
1155  }
1156  FArray1A< core::PackerEnergy > ii_one_body_energies( one_body_energies( node_state_offsets_[ii] + 1), ii_num_states );
1157  ig_nodes_[ ii ]->add_to_one_body_energies( ii_one_body_energies );
1158  }
1159 }
1160 
1161 
1162 ////////////////////////////////////////////////////////////////////////////////
1163 /// @begin InteractionGraphBase::add_to_one_body_energies
1164 ///
1165 /// @brief
1166 /// decrements the one body energies by the values held in old_energy1b,
1167 /// increments the one body energies by the values held in new_energy1b,
1168 /// and copies new_energy1b into old_energy1b.
1169 ///
1170 /// @detailed
1171 ///
1172 /// @param
1173 /// old_energy1b - [in/out] - the one body energies representing interactions
1174 /// with portions of the background that are no longer valid
1175 /// new_energy1b - [in] - the one body energies representing interactions
1176 /// with the background after the background has changed
1177 ///
1178 /// @global_read
1179 ///
1180 /// @global_write
1181 ///
1182 /// @remarks
1183 /// useful if you want to move something in the background like a ligand.
1184 /// moving the background does not invalidate the two-body energies.
1185 ///
1186 /// @references
1187 ///
1188 /// @authors apl
1189 ///
1190 /// @last_modified
1191 ////////////////////////////////////////////////////////////////////////////////
1194  FArray1< core::PackerEnergy > & old_energy1b,
1195  FArray1< core::PackerEnergy > & new_energy1b
1196 )
1197 {
1198  old_energy1b *= -1;
1199  add_to_one_body_energies( old_energy1b );
1200  add_to_one_body_energies( new_energy1b );
1201  old_energy1b = new_energy1b;
1202 }
1203 
1205 {
1206  ig_nodes_[ node ]->zero_one_body_energies();
1207 }
1208 
1209 
1210 /// @param node_ind - [in] - the node in question
1211 /// @param one_body_energies - [in] - the energies to be added to the one-body energies
1212 /// on that node. One entry per state.
1215  int node_ind,
1216  utility::vector1< core::PackerEnergy > const & one_body_energies
1217 )
1218 {
1219  int num_states_for_node = get_node( node_ind )->get_num_states();
1220  for (int ii = 1; ii <= num_states_for_node; ++ii ) {
1221  get_node( node_ind )->add_to_one_body_energy( ii, one_body_energies[ ii ] );
1222  }
1223  return;
1224 }
1225 
1226 /// @param node_ind - [in] - the node in question
1227 /// @param one_body_energies - [in] - the energies to be added to the one-body energies
1228 /// on that node. One entry per state.
1230 (
1231  int node_ind,
1232  FArray1< core::PackerEnergy > const & one_body_energies
1233 )
1234 {
1235  int num_states_for_node = get_node( node_ind )->get_num_states();
1236  for (int ii = 1; ii <= num_states_for_node; ++ii ) {
1237  get_node( node_ind )->add_to_one_body_energy( ii, one_body_energies( ii ) );
1238  }
1239  return;
1240 }
1241 
1242 /// @param node_ind - [in] - the index of the node in question
1243 /// @param state_id - [in] - the state in question
1244 /// @param one_body_energy - [in] - the energy to be added
1247  int node_ind,
1248  int state_id,
1249  core::PackerEnergy const one_body_energy
1250 )
1251 {
1252  get_node( node_ind )->add_to_one_body_energy( state_id, one_body_energy );
1253  return;
1254 }
1255 
1256 /// @details invokes polymorphic method of EdgeBase class; no-op if edge is not part
1257 /// of the graph.
1258 void
1260  int node1,
1261  int node2,
1262  Real edge_weight
1263 )
1264 {
1265  if ( edge_weight == 0.0 ) {
1266  utility_exit_with_message( "Error: set edge weight to 0 not a legal operation. Consider an edge deletion. ");
1267  }
1268 
1269  EdgeBase * edge = find_edge( node1, node2 );
1270  if ( edge ) {
1271  edge->set_edge_weight( edge_weight );
1272  }
1273 }
1274 
1275 /// @details returns 0 if edge is not part of the graph
1276 Real
1278  int node1,
1279  int node2
1280 ) const
1281 {
1282  EdgeBase const * edge = find_edge( node1, node2 );
1283  if ( edge ) {
1284  return edge->edge_weight();
1285  } else {
1286  return 0.0;
1287  }
1288 }
1289 
1290 
1291 // @brief Memory account algorithm. Each node/edge/graph class in the heirarchy reports the dynamic
1292 // memory it uses, and "recurses" on it's parent class to have the parent report its dynamic memory use.
1293 // (NOTE: class writer must actually implement the recursive call, it will not happen automatically.)
1294 // The static memory is reported by the "final" class or the most-derived class, in a straitforward sizeof
1295 // call. This way, all the dynamically allocated memory is reported and the statically allocated memory
1296 // is reported without being double counted.
1297 unsigned int
1299 {
1300  //std::cout << "calling InteractionGraphBase::getTotalMemoryUsage() const" << std::endl;
1301 
1302  unsigned int total_memory = 0;
1303  for (int ii = 1; ii <= num_ig_nodes_; ++ii) {
1304  total_memory += ig_nodes_[ ii ]->count_dynamic_memory();
1305  total_memory += ig_nodes_[ ii ]->count_static_memory();
1306  }
1307  for (std::list< EdgeBase* >::const_iterator iter = ig_edge_list_.begin();
1308  iter != ig_edge_list_.end(); iter++) {
1309  total_memory += (*iter)->count_dynamic_memory();
1310  total_memory += (*iter)->count_static_memory();
1311  }
1312 
1313  total_memory += count_dynamic_memory();
1314  total_memory += count_static_memory();
1315 
1316  return total_memory;
1317 }
1318 
1319 /// @brief set the Graph's (single) edge list iterator to the beginning of the edge list
1320 /// for a particular node
1322 {
1323  focused_edge_iterator_ = ig_nodes_[ node_index ]->edge_list_begin();
1324  focused_edge_iterator_end_ = ig_nodes_[ node_index ]->edge_list_end();
1325 }
1326 
1327 /// @brief increment the (single) edge list iterator to the next element
1329 {
1332 }
1333 
1334 /// @brief test: have we arrived at the edge list end?
1336 {
1338 }
1339 
1340 /// @brief return a const reference to an edge pointed at by the list iterator
1342 {
1343  return **focused_edge_iterator_;
1344 }
1345 
1346 // @brief IGBase dynamic memory: memory cost is for a vector of node pointers and for a list
1347 // of edge pointers -- stl list elements cost four pointers (I think), so the math is 4 times
1348 // the number of edges in the graph. Since this is not a time-sensitive function, I use the
1349 // list::size() method which is O(N).
1350 //
1351 // There is unaccounted memory in the base class ATM: ANDREW come back to this later and account
1352 // for everything.
1353 unsigned int
1355 {
1356  unsigned int tot = 0;
1357  tot += sizeof( NodeBase* ) * num_ig_nodes_;
1358  tot += 4 * sizeof( EdgeBase* ) * ig_edge_list_.size();
1359  return tot;
1360 }
1361 
1362 
1363 ////////////////////////////////////////////////////////////////////////////////
1364 /// @begin InteractionGraphBase::set_number_of_energy_sum_vertex_groups
1365 ///
1366 /// @brief
1367 /// a user may define subsets of the vertex set for which they would like to
1368 /// know the internal energy sum. For instance in a graph with 6 vertices,
1369 /// {a,b,c,d,e,f}
1370 /// a user may be interested in the sum of the one- and two-body energies
1371 /// for vertices {a,b,c}. The graph will return sum of the one body energies
1372 /// for vertices a b and c and also any two-body energies for the edges in the
1373 /// subgraph induced by a,b, and c. (In this case, edges {a,b}, {a,c} and {b,c}
1374 /// if these edges are part of the graph. The edge {a,d} will not be counted
1375 /// if it is part of the graph.)
1376 ///
1377 /// First you must declare how many groups you are interested in. Do that
1378 /// with this method.
1379 /// Second you must declare which node is a member of each group. Only
1380 /// tell the graph which node is a member, do not tell the graph if a node is
1381 /// not a member.
1382 /// Third, when you want to know the energy sum for the group in the graph's
1383 /// current state assignment, call get_energy_sum_for_vertex_group( group_id)
1384 ///
1385 /// @detailed
1386 ///
1387 /// @param
1388 /// num_groups - [in] - the number of groups; set this at most once.
1389 ///
1390 /// @global_read
1391 ///
1392 /// @global_write
1393 ///
1394 /// @remarks
1395 ///
1396 /// @references
1397 ///
1398 /// @authors apl
1399 ///
1400 /// @last_modified
1401 ////////////////////////////////////////////////////////////////////////////////
1402 void
1404 {
1405  assert( num_energy_sum_groups_ == -1 && num_groups > 0 );
1406  num_energy_sum_groups_ = num_groups;
1407  energy_sum_group_membership_.dimension(
1410 }
1411 
1412 ////////////////////////////////////////////////////////////////////////////////
1413 /// @begin InteractionGraphBase::
1414 /// count_connected_components_and_initialize_vertex_groups
1415 ///
1416 /// @brief
1417 /// makes a depth first traversal of the graph, counting the number of
1418 /// connected components, and initializes the vertex group memberships
1419 /// to reflect the connected components. Returns the number of connected
1420 /// components in the graph.
1421 ///
1422 /// @detailed
1423 ///
1424 /// @param
1425 ///
1426 /// @global_read
1427 ///
1428 /// @global_write
1429 ///
1430 /// @remarks
1431 ///
1432 /// @references
1433 ///
1434 /// @authors apl
1435 ///
1436 /// @last_modified
1437 ////////////////////////////////////////////////////////////////////////////////
1438 int
1440 {
1441  component_membership_.dimension( num_ig_nodes_) = 0;
1443  for (int ii = 1; ii <= num_ig_nodes_; ++ii)
1444  {
1445  if ( vertex_already_reached( ii ) ) continue;
1447  //std::cerr << "Starting depth first search at node: " << ii << " of group # " << num_energy_sum_groups_ << std::endl;
1448 
1449  ig_nodes_[ ii ]->depth_first_connected_component_counting();
1450  }
1451 
1454  for ( int ii = 1; ii <= num_ig_nodes_; ++ii )
1455  {
1457  }
1458  component_membership_.dimension( 0 );
1459  return num_energy_sum_groups_;
1460 }
1461 
1462 
1463 ////////////////////////////////////////////////////////////////////////////////
1464 /// @begin InteractionGraphBase::note_vertex_reached
1465 ///
1466 /// @brief
1467 /// marks a vertex as belonging to the connected component currently being
1468 /// traversed in the depth first traversal.
1469 ///
1470 /// @detailed
1471 ///
1472 /// @param
1473 /// node_index - [in] - the index of the node invoking this method.
1474 ///
1475 /// @global_read
1476 ///
1477 /// @global_write
1478 ///
1479 /// @remarks
1480 /// This method should be used by the NodeBase class only.
1481 ///
1482 /// @references
1483 ///
1484 /// @authors apl
1485 ///
1486 /// @last_modified
1487 ////////////////////////////////////////////////////////////////////////////////
1488 void
1490 {
1491  assert( component_membership_( node_index ) == 0 );
1493  //std::cerr << "Marked node " << node_index << " in group " << num_energy_sum_groups_ << std::endl;
1494 }
1495 
1496 
1497 ////////////////////////////////////////////////////////////////////////////////
1498 /// @begin InteractionGraphBase::
1499 /// vertex_already_reached
1500 ///
1501 /// @brief
1502 /// used by class NodeBase during the depth-first traversal to determine the
1503 /// number of connected components in the graph. returns true if the dft has
1504 /// already reached the node.
1505 ///
1506 /// @detailed
1507 ///
1508 /// @param
1509 /// node_index - [in] - the index of the node calling the method.
1510 ///
1511 /// @global_read
1512 ///
1513 /// @global_write
1514 ///
1515 /// @remarks
1516 /// This method should be used by the NodeBase class only.
1517 ///
1518 /// @references
1519 ///
1520 /// @authors apl
1521 ///
1522 /// @last_modified
1523 ////////////////////////////////////////////////////////////////////////////////
1524 bool
1526 {
1527  return component_membership_( node_index ) != 0;
1528 }
1529 
1530 ////////////////////////////////////////////////////////////////////////////////
1531 /// @begin InteractionGraphBase::set_vertex_member_of_group
1532 ///
1533 /// @brief
1534 /// a user may define subsets of the vertex set for which they would like to
1535 /// know the internal energy sum. For instance in a graph with 6 vertices,
1536 /// {a,b,c,d,e,f}
1537 /// a user may be interested in the sum of the one- and two-body energies
1538 /// for vertices {a,b,c}. The graph will return sum of the one body energies
1539 /// for vertices a b and c and also any two-body energies for the edges in the
1540 /// subgraph induced by a,b, and c. (In this case, edges {a,b}, {a,c} and {b,c}
1541 /// if these edges are part of the graph. The edge {a,d} will not be counted
1542 /// if it is part of the graph.)
1543 ///
1544 /// @detailed
1545 /// tell the graph which vertices you want to be part of which groups
1546 ///
1547 /// @param
1548 /// vertex - [in] - the index of the vertex you wish to include in the group
1549 /// group - [in] - the group index you wish to add the vertex to.
1550 ///
1551 /// @global_read
1552 ///
1553 /// @global_write
1554 ///
1555 /// @remarks
1556 ///
1557 /// @references
1558 ///
1559 /// @authors apl
1560 ///
1561 /// @last_modified
1562 ////////////////////////////////////////////////////////////////////////////////
1563 void
1565 {
1566  energy_sum_group_membership_( vertex, group ) = true;
1567 }
1568 
1569 void
1571 {
1572  for (int ii = 1; ii <= get_num_nodes(); ++ii )
1573  {
1574  std::cerr << "Node " << ii << ": ";
1575  for (int jj = 1; jj <= num_energy_sum_groups_; ++jj)
1576  {
1577  std::cerr << energy_sum_group_membership_( ii, jj ) << " ";
1578  }
1579  std::cerr << std::endl;
1580  }
1581 }
1582 /*
1583 unsigned int
1584 InteractionGraphBase::getTotalMemoryUsage() const
1585 {
1586  unsigned int total_memory = 0;
1587  for (int ii = 1; ii <= get_num_nodes(); ++ii)
1588  {
1589  total_memory += ig_nodes_[ ii ]->getMemoryUsageInBytes();
1590  }
1591  for (std::list< EdgeBase* >::const_iterator iter = ig_edge_list_.begin();
1592  iter != ig_edge_list_.end(); ++iter )
1593  {
1594  total_memory += (*iter)->getMemoryUsageInBytes();
1595  }
1596 
1597  total_memory += getMemoryUsageInBytes();
1598  return total_memory;
1599 }
1600 
1601 unsigned int
1602 InteractionGraphBase::getMemoryUsageInBytes() const
1603 {
1604  unsigned int total_memory = 0;
1605  total_memory += ig_nodes_.size() * sizeof ( NodeBase * );
1606  total_memory += 4 * ig_nodes_.size() * sizeof ( EdgeBase * );
1607  total_memory += node_state_offsets_.size() * sizeof ( int );
1608  return total_memory;
1609 }
1610 */
1611 
1612 ////////////////////////////////////////////////////////////////////////////////
1613 /// @begin InteractionGraphBase::drop_edge
1614 ///
1615 /// @brief removes edge from edge list at iterator iter
1616 ///
1617 /// @detailed
1618 /// each edge keeps track of its position in its owner's graph's edge list
1619 /// so it can efficiently delete itself should it need to.
1620 ///
1621 /// @param
1622 /// iter - [in] - the iterator pointing at the edge that's deleting itself
1623 ///
1624 /// @global_read
1625 ///
1626 /// @global_write
1627 ///
1628 /// @remarks
1629 ///
1630 /// @references
1631 ///
1632 /// @authors apl
1633 ///
1634 /// @last_modified
1635 ////////////////////////////////////////////////////////////////////////////////
1636 void InteractionGraphBase::drop_edge(std::list< EdgeBase* >::iterator iter)
1637 {
1638  //std::cerr << "ig.drop_edge: " << *iter << " ";
1639  ig_edge_list_.erase(iter);
1640  //std::cerr << *ig_edge_list_.begin() << " " << *(++ig_edge_list_.begin()) << std::endl;
1641 
1642  //invalidate focused_edge_
1643  focused_edge_ = NULL;
1644  return;
1645 }
1646 
1647 ////////////////////////////////////////////////////////////////////////////////
1648 /// @begin InteractionGraphBase::find_edge
1649 ///
1650 /// @brief
1651 /// returns the edge connecting node1 and node2
1652 ///
1653 /// @detailed
1654 /// graph keeps a pointer to the last edge that was accessed to that search is
1655 /// fairly efficient.
1656 ///
1657 /// @param
1658 /// node1 - [in] - index of the first node
1659 /// @param
1660 /// node2 - [in] - index of the second node
1661 ///
1662 /// @global_read
1663 ///
1664 /// @global_write
1665 ///
1666 /// @remarks
1667 ///
1668 /// @references
1669 ///
1670 /// @authors apl
1671 ///
1672 /// @last_modified
1673 ////////////////////////////////////////////////////////////////////////////////
1674 EdgeBase const * InteractionGraphBase::find_edge(int node1, int node2) const
1675 {
1676  if (focused_edge_ == NULL || !( focused_edge_->same_edge(node1, node2)) ) {
1677  focused_edge_ = ig_nodes_[node1]->find_edge(node2);
1678  }
1679  return focused_edge_;
1680 }
1681 
1683 {
1684  if ( focused_edge_ == NULL || !( focused_edge_->same_edge(node1, node2)) ) {
1685  focused_edge_ = ig_nodes_[node1]->find_edge(node2);
1686  }
1687  return focused_edge_;
1688 }
1689 
1690 } //end namespace interaction_graph
1691 } //end namespace pack
1692 } //end namespace core
1693