Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Graph.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/graph/Graph.hh
11 /// @brief generic graph class header
12 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
13 
14 #ifndef INCLUDED_core_graph_Graph_hh
15 #define INCLUDED_core_graph_Graph_hh
16 
17 // Rosetta Headers
18 #include <core/graph/Graph.fwd.hh>
19 
20 #include <platform/types.hh>
21 
22 // Utility Headers
23 #include <utility/pointer/ReferenceCount.hh>
24 // AUTO-REMOVED #include <utility/vector1.hh>
25 
26 // STL Headers
27 #include <iosfwd>
28 // AUTO-REMOVED #include <list>
29 #include <cassert>
30 
31 // Boost Headers
33 
34 #ifdef PYROSETTA
36 #endif
37 
38 // ObjexxFCL Headers
39 // AUTO-REMOVED #include <ObjexxFCL/FArray1D.hh>
40 // AUTO-REMOVED #include <ObjexxFCL/FArray2D.hh>
41 
42 #include <utility/vector1_bool.hh>
43 #include <ObjexxFCL/FArray2D.fwd.hh>
44 
45 
46 namespace core {
47 namespace graph {
48 
49  ///@brief An extensible graph class
50 
51  /**
52  @li Nodes are identified by positive integers -- each node is assigned a unique integer starting at 1.
53 
54  @li Nodes know about both their upper and their lower edges. Iterators can range over all
55  edges, just the upper edges or just the lower edges.
56 
57  @li Nodes store their incident edge information in edge lists; they provide const and non-const
58  iterators which return const and non-const pointers to Edge objects.
59 
60  @li The Graph object provides iterators for all of the edges in the graph; this list is unordered.
61 
62  @li This graph is instantiatable (ie not a pure virtual class). It was also built with extension
63  in mind. See core/scoring/EnergyGraph for an example on how to create an extension of
64  the Node, Edge and Graph classes
65 
66  @li Derived graph classes must define two factory methods: create_node and create_edge
67  which are called by the base class when adding graph elements.
68 
69  @li Edges offer constant-time deletion -- edges remove themselves from the edge-lists
70  that their nodes maintain, and from the edge-list that the Graph maintains without
71  having to iterate over those lists.
72 
73  @li Memory is carefully managed to make edge addition and deletion exceedingly fast.
74  The management is through a class "unodered_object_pool" which is very much
75  like boost::object_pool. The base class ueses these unordered object pools for
76  base class edges (when used) and for the edge lists elements. Derived classes
77  may take advantage of this by defining their own unordered_object_pool objects.
78 
79  @li Graphs own the vertices and edges they create. Graphs cannot share or give away edges.
80 
81  @li To delete an edge pointed to by Edge* e in a graph g, call the virtual function
82  "g->delete_edge( &e );"
83 
84  @li Derived classes must invoke the "destroy_everything" method in their virtual destructors so that
85  they are empty by the time the base class destructor is called. The destroy_everything method
86  invokes the virtual delete_edge() method -- remember, virtual methods do not work in base class
87  constructors or destructors. If a derived class does not call destroy_everything in its destructor,
88  ~Graph() will call Graph::destroy_everything which will call (surprisingly) Graph::delete_edge
89  and not Derived::delete_edge.
90 
91  @li Derived classes should not invoke the base class copy constructors for the same reason.
92  The base class copy constructor will call the base class create_node and create_edge methods
93  and not the desired derived class versions.
94 
95  @li The virtual functions Derived graph classes must override:
96  Node: copy_from, print, count_static_memory, count_dynamic_memory
97  Edge: copy_from, count_static_mmory, count_dynamic_memory
98  Graph: create_node, create_edge, delete_edge, count_static_memory, count_dynamic_memory
99 
100  **/
101 
102 
103 /// @brief Custom written edge list element class. Little more than a struct.
104 /// Defined so that edge list memory management could rely on boost::pool like object
106 {
107 public:
108  EdgeListElement() : edge_( 0 ), previous_( 0 ), next_( 0 ) {}
110  : edge_( edge ), previous_( previous ), next_( next ) {}
111 
112 
114 
115  Edge * edge() { assert( edge_ ); return edge_; }
116  void edge( Edge * setting ) { edge_ = setting; }
117  Edge const * const_edge() const { assert( edge_ ); return edge_; }
118 
119  EdgeListElement * next() { return next_; }
120  void next( EdgeListElement * setting ) { next_ = setting; }
121  EdgeListElement const * const_next() const { return next_; }
122 
124  void previous( EdgeListElement * setting ) { previous_ = setting; }
125  EdgeListElement const * const_previous() const { return previous_; }
126 
127  friend class EdgeList;
128 
129 private:
133 
134 };
135 
136 /// @brief Custom Edge list (non-const) iterator class, which can return non-const
137 /// Edge pointers. This iterator cannot be used to change the structure of its list
138 /// without access to that list directly. Customized since STL's const-iterator cannot
139 /// be prevented from giving non-const access to its data. The former workaround to
140 /// this problem was to define two sets of edge lists on each vertex: a list< Edge * >
141 /// and a list< Edge const * >.
143 {
144 public:
145 
146  /// @brief default constructor, owner and element set to null
148  : owner_( 0 ), element_( 0 ) {}
149 
150  /// @brief owner constructor
151  EdgeListIterator( EdgeList const * owner )
152  : owner_( owner ), element_( 0 ) {}
153 
154  /// @brief owner and element constructor: points at a position in a list
155  EdgeListIterator( EdgeList const * owner, EdgeListElement * element )
156  : owner_( owner ), element_( element ) {}
157 
158  /// @brief copy constructor
160  : owner_( src.owner_ ), element_( src.element_ ) {}
161 
162  /// @brief non-virtual destructor, does nothing
164 
165  /// @brief assignmnet operator
167  {
168  owner_ = rhs.owner_;
169  element_ = rhs.element_;
170  return *this;
171  }
172 
173  /// @brief increment operator. Point this iterator at the next element in the list.
174  inline
176  { assert( valid() ); element_ = element_->next(); return *this; }
177 
178  /// @brief decrement operator. Point this iterator at the previous element in the list.
179  inline
181  { assert( valid() ); element_ = element_->previous(); return *this; }
182 
183  /// @brief equality operator. Do these elements point at the same list element? Asserts
184  /// that they belong to the same list. Never compare elements from separate lists.
185  inline
186  bool operator == ( EdgeListIterator const & rhs ) const {
187  assert( owner_ == rhs.owner_ );
188  return element_ == rhs.element_;
189  }
190 
191  /// @brief inequality operator. Do these elements point to different elements from the same list? Asserts
192  /// that they belong to the same list. Never compare elements from separate lists.
193  inline
194  bool operator != ( EdgeListIterator const & rhs ) const {
195  return ! ( operator == ( rhs ) );
196  }
197 
198  /// @brief dereference operator: return the edge pointer pointed to by the list element this iterator
199  /// is hovering over. This method returns a non-const edge pointer, which defines this class
200  /// as a non-const iterator. There are no methods, though, to access the list element itself.
201  Edge * operator * () const { assert( valid() ); return element_->edge(); }
202 
203  /// @brief dereference operator: return the edge pointer pointed to by the list element this iterator
204  /// is hovering over. This method returns a non-const edge pointer, which defines this class
205  /// as a non-const iterator. There are no methods, though, to access the list element itself.
206  Edge & operator -> () const { assert( valid() ); return * (element_->edge()) ; }
207 
208  /// @brief check that this iterator is valid. Will not guarantee that the iterator points at an element
209  /// that has not been destroyed.
210  bool valid() const;
211 
212  friend class EdgeList;
213  friend class EdgeListConstIterator;
214 
215 private:
216  EdgeList const * owner_;
218 
219 };
220 
221 /// @brief Custom Edge list const iterator class, which returns only const
222 /// Edge pointers. This iterator cannot be used to change the structure of its list
223 /// without access to that list directly. Customized since STL's const-iterator cannot
224 /// be prevented from giving non-const access to its data. The former workaround to
225 /// this problem was to define two sets of edge lists on each vertex: a list< Edge * >
226 /// and a list< Edge const * >.
228 {
229 public:
230 
231  /// @brief default constructor, owner and element set to null
233  : owner_( 0 ), element_( 0 ) {}
234 
235  /// @brief owner constructor
237  : owner_( owner ), element_( 0 ) {}
238 
239  /// @brief owner and element constructor: points at a position in a list
240  EdgeListConstIterator( EdgeList const * owner, EdgeListElement const * element )
241  : owner_( owner ), element_( element ) {}
242 
243  /// @brief copy constructor
245  : owner_( src.owner_ ), element_( src.element_ ) {}
246 
247  /// @brief const-cast constructor
249  : owner_( src.owner_ ), element_( src.element_ ) {}
250 
251 
252  /// @brief non-virtual destructor, does nothing
254 
255  /// @brief assignmnet operator
257  {
258  owner_ = rhs.owner_;
259  element_ = rhs.element_;
260  return *this;
261  }
262 
263  /// @brief increment operator. Point this iterator at the next element in the list.
264  inline
266  { assert( valid() ); element_ = element_->const_next(); return *this; }
267 
268  /// @brief decrement operator. Point this iterator at the previous element in the list.
269  inline
271  { assert( valid() ); element_ = element_->const_previous(); return *this; }
272 
273  /// @brief equality operator. Do these elements point at the same list element? Asserts
274  /// that they belong to the same list. Never compare elements from separate lists.
275  inline
276  bool operator == ( EdgeListConstIterator const & rhs ) const {
277  assert( owner_ == rhs.owner_ );
278  return element_ == rhs.element_;
279  }
280 
281  /// @brief const-cast equality operator. Do these elements point at the same list element? Asserts
282  /// that they belong to the same list. Never compare elements from separate lists.
283  inline
284  bool operator == ( EdgeListIterator const & rhs ) const {
285  assert( owner_ == rhs.owner_ );
286  return element_ == rhs.element_;
287  }
288 
289 
290  /// @brief inequality operator. Do these elements point to different elements from the same list? Asserts
291  /// that they belong to the same list. Never compare elements from separate lists.
292  /// Elements need not be valid to be compared.
293  inline
294  bool operator != ( EdgeListConstIterator const & rhs ) const {
295  return ! ( operator == ( rhs ) );
296  }
297 
298  /// @brief const-cast inequality operator. Do these elements point to different elements from the same list? Asserts
299  /// that they belong to the same list. Never compare elements from separate lists.
300  /// Elements need not be valid to be compared.
301  inline
302  bool operator != ( EdgeListIterator const & rhs ) const {
303  return ! ( operator == ( rhs ) );
304  }
305 
306  /// @brief dereference operator: return the edge pointer pointed to by the list element this iterator
307  /// is hovering over. This method returns a const edge pointer, which defines this class
308  /// as a const iterator. There are no methods, of course, to access the list element itself.
309  Edge const * operator * () const { assert( valid() ); return element_->const_edge(); }
310 
311 
312  /// @brief dereference operator: return the edge pointer pointed to by the list element this iterator
313  /// is hovering over. This method returns a const edge pointer, which defines this class
314  /// as a const iterator. There are no methods, of course, to access the list element itself.
315  Edge const & operator -> () const { assert( valid() ); return * (element_->const_edge()); }
316 
317  /// @brief Is this a valid iterator?
318  inline
319  bool valid() const;
320 
321  friend class EdgeList;
322 
323 private:
324  EdgeList const * owner_;
326 
327 };
328 
329 /// @brief Custom edge list class. Returns const-iterators which only return Edge const *'s
330 /// and non-const-iterators which can return either const or non-const Edge*'s. Manages its
331 /// own memory using an unordered-object-pool for fast insertion and deletion of EdgeListElements.
332 /// Implemented as a doubly linked list, though there's no practical way to start at the
333 /// end of a list and work backward since decrementing the end iterator is not a valid operation.
334 class EdgeList
335 {
336 public:
337  EdgeList( boost::unordered_object_pool< EdgeListElement > & edge_list_element_pool );
338  ~EdgeList();
339 
340  /// @brief create a new edge-list element and insert it at the front of the list
341  void push_back( Edge * edgeptr );
342 
343  /// @brief create a new edge-list element and insert it at the end of the list
344  void push_front( Edge * edgeptr );
345 
346  /// @brief insert a new edge-list element in the list infront of the input iterator and
347  /// return an iterator to the position of the new element
348  EdgeListIterator insert( EdgeListIterator const & element_to_insert_before, Edge * edgeptr );
349 
350  /// @brief returns a non-const iterator to the front of the list
352 
353  /// @brief returns a const iterator to the front of the list
355 
356  /// @brief returns a const iterator to the front of the list
358 
359  /// @brief returns a non-const iterator to the last element in the list
361 
362  /// @brief returns a const iterator to the last element in the list
364 
365  /// @brief returns a const iterator to the last element in the list
367 
368  /// @brief returns a non-const iterator to the end of the list
369  EdgeListIterator end() { return EdgeListIterator( this, end_ ); }
370 
371  /// @brief returns a const iterator to the end of the list
373 
374  /// @brief returns a const iterator to the end of the list
376 
377  /// @brief removes an element from the list pointed to by the input iterator
378  void erase( EdgeListIterator to_erase );
379 
380  /// @brief method invoked by the EdgeListIterator class: is an iterator the special
381  /// end iterator for a list?
382  bool is_end_element( EdgeListElement const * element ) const { return element == end_; }
383 
384  /// O(N)
385  platform::Size size() const;
386 
387 private:
388 
389  ///@brief Uncopyable -- private and unimplemented copy ctor
390  EdgeList( EdgeList const & );
391  ///@brief Uncopyable -- private and unimplemented assignment operator
392  EdgeList const & operator = ( EdgeList const & );
393 
394  /// @brief this edge-list-element-pool reference is handed to the list
395  /// to draw from. This pool must outlive the edge-list itself.
396  /// To guarantee this, for the case of class Graph, the graph deletes its
397  /// nodes (and their edge lists) before it deletes itself.
399 
400  /// @brief The special "end" position in the list.
402 };
403 
404 
405 class Node
406 {
407 public:
408 
411 
412 public:
413  virtual ~Node();
414  Node( Graph*, platform::Size node_id );
415 
416  /// @brief invoked during graph assignment operators to copy any
417  /// node data from one graph to another graph. The source node must
418  /// be the same type as this node.
419  virtual void copy_from( Node const * source );
420 
421  /// @brief adds edge pointer to edge list; returns an iterator to the new
422  /// list element
423  void add_edge( Edge* edge_ptr, EdgeListIter & );
424 
425  /// @brief removes an edge iterator from the node's edge list. Only called by Edge class.
426  void drop_edge( EdgeListIter edge_iterator );
427 
428  /// @brief deletes all edges incident upon this node
429  void drop_all_edges();
430 
431  /// @details manually change the number of neighbors for a Node. Used
432  /// for symmetry scoring
434 
435  /// @brief a "slow" (linear) search for an edge.
436  Edge const * find_edge(platform::Size other_node_index) const;
437  Edge * find_edge(platform::Size other_node_index);
438 
439  /// @brief send summaray data about this node to the screen
440  virtual void print() const;
441 
442  /// @brief returns a non-const iterator to the beginning of its edge list
444  /// @brief returns a const iterator to the beginning of its edge list
446 
447  /// @brief returns a non-const iterator to the end of its edge list
449  /// @brief returns a const iterator to the end of its edge list
451 
452  /// @brief returns a non-const iterator to the beginning of its lower-edge list
454  /// @brief returns a const iterator to the beginning of its lower-edge list
456 
457  /// @brief returns a non-const iterator to the end of its lower-edge list
459  /// @brief returns a const iterator to the end of its lower-edge list
461 
462  /// @brief returns a non-const iterator to the beginning of its upper-edge list
464  /// @brief returns a const iterator to the beginning of its upper-edge list
466 
467  /// @brief returns a non-const iterator to the end of its upper-edge list
469  /// @brief returns a const iterator to the end of its upper-edge list
471 
472  /// @brief the index for this node
473  inline
475  {
476  return node_index_;
477  }
478 
479  /// @brief the number of edges incident on this node, which may include a loop edge
480  inline
482  {
483  return num_incident_edges_;
484  }
485 
486  /// @brief the number of neighbors counting "self" as a neighbor.
487  inline
489  {
490  if ( loop_incident_ ) { return num_incident_edges_; }
491  else { return num_incident_edges_ + 1; }
492  }
493 
494  /// @brief the number of neighbors counting "self" as neighbor. Defaults to
495  /// num_neighbors_counting_self() but can be set to other values as well.
496  /// Useful in calculation of symmetrical structures.
497  inline
499  {
501  }
502 
503  /// @brief the number of lower neighbors
504  inline
506  {
508  }
509 
510  /// @brief the number of upper neighbors -- which "self" neighborness is counted if a loop edge
511  /// is present
512  inline
514  {
516  }
517 
518  /// @brief memory accounting scheme
519  virtual platform::Size count_static_memory() const;
520  /// @brief memory accounting scheme
521  virtual platform::Size count_dynamic_memory() const;
522 
523  /// NOTE TO SELF: remove loop support
524  bool loop_incident() const { return loop_incident_; }
525 protected:
526 
527  /// @brief derived class access to the owner
528  inline
529  Graph* get_owner() const
530  {
531  return owner_;
532  }
533 
534 private:
535 
539  bool loop_incident_; /// NOTE TO SELF: remove loop support
542 
543  // edge list
545 
548 
549  //no default constructor, uncopyable
550  Node();
551  Node( Node const & );
552  Node & operator = ( Node & );
553 };
554 
555 class Edge
556 {
557 public:
559 
560 public:
561  virtual ~Edge();
562 
563  /// @brief Main edge constructor. This should only be invoked by create_new_edge, which
564  /// itself is only called by add_edge. The ONLY way an edge should be added to a graph
565  /// is through add_edge. NOTE: edges should be only be deleted by a call to the Graph's
566  /// delete_edge method, and this method absolutely must be implemented by derived Graph
567  /// classes.
568  Edge(Graph* owner, platform::Size first_node_ind, platform::Size second_node_ind);
569 
570  /// @brief copy-from for use in Graph::operator= and copy ctors
571  virtual void copy_from( Edge const * source );
572 
573  /// @brief returns the index of the one node given the index of the other.
574  /// node_index must be one of the two nodes that this edge is incident upon.
575  platform::Size get_other_ind(platform::Size node_index) const;
576 
577  /// @brief returns a const pointer to one node given the index of the other.
578  /// node_index must be one of the two nodes that this edge is incident upon.
579  Node const * get_other_node(platform::Size node_index) const;
580  /// @brief returns a non-const pointer to one node given the index of the other.
581  /// node_index must be one of the two nodes that this edge is incident upon.
582  Node * get_other_node(platform::Size node_index);
583 
584  /// @brief returns the index of the lower node
585  inline
587  /// @brief returns the index of the upper node
588  inline
590 
591  /// @brief called only by class Graph, this function gives the Edge the data it needs
592  /// to later delete itself from its owner's edge list in constant time.
593  void set_pos_in_owners_list( EdgeListIter edge_iterator );
594 
595  /// @brief Is this the same edge as another edge (node1,node2)? Note:
596  /// this graph does not work for multi-graphs. Edges must be unique.
597  bool same_edge(platform::Size node1, platform::Size node2) const;
598 
599  /// @brief Is this edge a loop? In Pseudographs, loop edges are incident twice on a single vertex.
600  bool is_loop() const { return node_indices_[ 0 ] == node_indices_[ 1 ];}
601 
602  /// @brief how much memory is statically allocated by this edge
603  virtual platform::Size count_static_memory() const;
604  /// @brief how much memory is dynamically allocated by this edge -- must be recursively invoked
605  /// by a derived class.
606  virtual platform::Size count_dynamic_memory() const;
607 
608 protected:
609 
610  //Read access to private data granted to derived classes
611 
612  /// @brief get the node index for one of the two nodes this edge is incident upon
613  /// uses c-style index-from-0.
614  inline
616  {
617  assert( index == 0 || index == 1 );
618  return node_indices_[ index ];
619  }
620 
621  /// @brief get a const * to one node that this edge is incident upon
622  /// uses c-style index-from-0 for these two nodes
623  inline
624  Node const *
625  get_node( platform::Size index ) const
626  {
627  assert( index == 0 || index == 1 );
628  return nodes_[ index ];
629  }
630 
631  /// @brief get a non-const * to one node that this edge is incident upon
632  /// uses c-style index-from-0 for these two nodes
633  inline
634  Node *
636  {
637  assert( index == 0 || index == 1 );
638  return nodes_[ index ];
639  }
640 
641 
642  /// @brief get a const * to the owning graph
643  inline
644  Graph const *
645  get_owner() const
646  {
647  return owner_;
648  }
649 
650  /// @brief get a non-const * to the owning graph
651  inline
652  Graph *
654  {
655  return owner_;
656  }
657 
658 private:
661 
663 
666 
667  //no default constructor, uncopyable
668  Edge();
669  Edge( Edge const & );
670  Edge & operator = ( Edge & );
671 
672 };
673 
674 /// @brief A Graph with constant time edge insertion and deletion. Extensible.
676 {
677 public:
679 
682 
684 
685 public:
686 
687  /// @brief virtual destructor. Derived classes must ensure they've destroyed all their
688  /// nodes and edges through a call to "destroy_everything" before this function is arrived at
689  virtual ~Graph();
690 
691  /// @brief ctor
692  Graph();
693 
694  /// @brief num nodes ctor
696 
697  /// @brief copy ctor. Must not be called by derived class copy ctors.
698  Graph( Graph const & source );
699 
700  /// @brief assignment operator. source and this must have the same type.
701  Graph & operator = ( Graph const & source );
702 
703  /// @brief copy the edge connectivity from a source graph with a potentially
704  /// unknown type.
705  void copy_connectivity( Graph const & source );
706 
707  /// @brief the number of nodes in the graph
708  inline
710  {
711  return num_nodes_;
712  }
713 
714  /// @brief set the number of nodes in the graph -- deletes any existing edges in the graph
716 
717  /// @brief add an edge between two vertices. Invokes "create_edge" from the derived class.
718  /// Returns a pointer to the edge after its been added, allowing the calling function
719  /// to immediately set data for this edge.
720  Edge * add_edge(platform::Size node1, platform::Size node2);
721  /// @brief add an edge to this graph copying the data from an edge in another graph.
722  /// Returns a pointer to the edge after its been added, allowing the calling function
723  /// to immediately set data for this edge.
724  Edge * add_edge( Edge const * example_edge );
725 
726  /// @brief is an edge already present in the graph? O(V) worst case. O(1) iff all vertices have O(1) edges
727  bool get_edge_exists(platform::Size node1, platform::Size node2) const;
728  /// @brief delete all the edges present in the graph
729  void drop_all_edges();
730  /// @brief delete all the edges for a single vertex in the graph
732 
733  /// @brief send summary information to the screen for all vertices in the graph
734  void print_vertices() const;
735 
736  /// @brief send an edge list to the stream os.
737  void output_connectivity(std::ostream & os) const;
738  /// @brief describe this graph in dimacs form to the stream os.
739  void output_dimacs(std::ostream & os) const;
740 
741  /// @brief O(V^3). Computes all pairs shortest paths using Warshall's algorithm
742  /// and writes all the path distances to the two-dimensional table.
743  ObjexxFCL::FArray2D_int all_pairs_shortest_paths() const;
744 
745 public:
746  inline
747  Node const * get_node( platform::Size index ) const
748  {
749  assert( index > 0 && index <= num_nodes_ );
750  return nodes_[ index ];
751  }
752 
753  inline
755  {
756  assert( index > 0 && index <= num_nodes_ );
757  return nodes_[ index ];
758  }
759 
760 
761  inline
763  {
764  return num_edges_;
765  }
766 
767  /// @brief returns a const iterator to the beginning of the (unordered) edge list for the graph.
768  /// this edge list contains all the edges in the graph, not simply those for a particular vertex
769  inline
771  {
772  return edge_list_.const_begin();
773  }
774 
775  /// @brief returns a non-const iterator to the beginning of the (unordered) edge list for the graph.
776  /// this edge list contains all the edges in the graph, not simply those for a particular vertex
777  inline
779  {
780  return edge_list_.begin();
781  }
782 
783  /// @brief returns a const iterator to the end of the (unordered) edge list for the graph.
784  /// this edge list contains all the edges in the graph, not simply those for a particular vertex
785  inline
787  {
788  return edge_list_.const_end();
789  }
790 
791  /// @brief returns a non-const iterator to the end of the (unordered) edge list for the graph.
792  /// this edge list contains all the edges in the graph, not simply those for a particular vertex
793  inline
795  {
796  return edge_list_.end();
797  }
798 
799  /// @brief returns a pointer to the edge connecting nodes node1 and node2, if that edge exists
800  /// in the graph, o.w. returns 0. Focuses the graph on this edge for fast subsequent retrieval.
801  Edge * find_edge( platform::Size node1, platform::Size node2 );
802  /// @brief returns a const pointer to the edge connecting nodes node1 and node2, if that edge exists
803  /// in the graph, o.w. returns 0. Focuses the graph on this edge for fast subsequent retrieval.
804  Edge const * find_edge(platform::Size node1, platform::Size node2) const;
805 
806  /// @brief returns a pointer to the focused edge
808  /// @brief returns a const-pointer to the focused edge
809  Edge const * focused_edge() const { return focused_edge_;}
810 
811  /// @brief remove an edge from the graph. (NEW AS OF 12/9/07) Never call C++'s
812  /// "delete" function on an edge pointer directly. Derived classes must implement this function.
813  /// If they wish to use unordered_object_pools to manage their memory
814  virtual void delete_edge( Edge * edge );
815 
816  /// @brief returns a count of all the memory used by every vertex and edge in a graph
817  /// by invoking the polymorphic count_static_memory and count_dynamic_memory of each
818  /// (possibly derived) node and edge object as well as for the (possibly derived) graph
819  /// class.
821 
822  friend class Node;
823  friend class Edge;
824 
825 protected:
826 
827  virtual platform::Size count_static_memory() const;
828  virtual platform::Size count_dynamic_memory() const;
829 
830  /// @brief remove an edge from the entire-graph edge list. Called only by class Edge
831  /// during its destructor
832  void drop_edge( EdgeListIter edge_iter );
833 
834  /// @brief deallocate all nodes and edges from the graph
835  void delete_everything();
836 
837  /// @brief factory method for node creation, defined by derived graph
838  /// classes, called by the base class
839  virtual Node* create_new_node( platform::Size node_index );
840 
841  /// @brief factory method for edge creation, defined by derived graph
842  /// classes, called by the base class
843  virtual Edge* create_new_edge( platform::Size index1, platform::Size index2 );
844 
845  /// @brief factory method for edge copy-construction. Derived class
846  /// should downcast the example_edge pointer and may read that edge's data.
847  virtual Edge* create_new_edge( Edge const * example_edge );
848 
849  /// @brief Used by class Node only, this is the pool from which edge lists are to
850  /// allocate their edge lists elements from.
853  return * edge_list_element_pool_;
854  }
855 
856 private:
860 
861  /// @brief the pool from which edge lists are to allocate their edge list elements
864 
865  /// @brief the pool from which class Graph allocates Edge objects.
866  /// Not used by derived classes
868 
869  /// @brief Quick-access to a frequently needed edge -- the most recently sought edge
870  /// in a call to find_edge() or the most recently added edge
871  mutable Edge* focused_edge_;
872 
873 };
874 
875 inline
877 { return ( owner_ != 0 && element_ != 0 && ! owner_->is_end_element( element_ ) );}
878 
879 inline
881 { return ( owner_ != 0 && element_ != 0 && ! owner_->is_end_element( element_ ) ); }
882 
883 
884 } //end namespace graph
885 } //end namespace core
886 
887 #endif