Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
UpperEdgeGraph.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/UpperEdgeGraph.hh
11 /// @brief templated graph for fast edge additions
12 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
13 
14 #ifndef INCLUDED_core_graph_UpperEdgeGraph_hh
15 #define INCLUDED_core_graph_UpperEdgeGraph_hh
16 
17 // Unit Headers
19 
20 // Package headers
21 #include <platform/types.hh>
22 
23 // Utility Headers
24 #include <utility/pointer/ReferenceCount.hh>
25 
26 #include <utility/vector1.fwd.hh>
27 
28 
29 namespace core {
30 namespace graph {
31 
32 // The point of this graph is to provide fast edge additions: new() is somewhat slow, whereas
33 // push_back with a vector that has reserved space for its edges ( through the method reserve())
34 // doesn't require new.
35 
36 // Vertices contain a data member of class V so that their size is known at compile time and so that data can be stored on vertices.
37 // Edges contain a data member of class E so that their size is known at compile time and so that data can be stored on edges
38 
39 // e.g. class EnergyEdgeData { public: EnergyMap emap; }; could be held inside a UEEdge object
40 
41 // This class does not allow tight control over data integrity in the V and E classes. For instance, you can imagine
42 // wanting the vertex objects to update the sum of their two body energies if you ever changed the two body energy of
43 // one of their edges. If you were to derive from class Graph (as scoring::EnergyGraph does) then you could have that graph
44 // enforce that bit of data integrity (EnergyGraph does not do that, currently, but it could).
45 // However, that is not an option with this graph class.
46 
47 // The other major weakness is that each vertex is unaware of who its lower neighbors are; its not possible to
48 // iterate over all of the edges incident on a vertex. This is also its major strength -- the cost of
49 // maintaining upper and lower edge lists is much greater than the cost of maintaining only upper edge lists.
50 // Each vertex is aware of how many lower edges it has.
51 
52 // This graph does not (yet) support loops (edges incident on a single vertex)
53 
54 // If the edge data is quite large, this graph will occupy more space than class Graph would, which stores edge data
55 // for only those edges that actually exist. (With reserve(), vertices allocate space for edges that do not exist).
56 
57 template < class V, class E >
58 class UEVertex : public utility::pointer::ReferenceCount
59 {
60 public:
67 
68 public:
69 
70  /// @brief standard constructor; though if vertices are to be allocated
71  /// in a single vector1, then this ctor requires creating and destroying
72  /// an anonymous vertex to add each vertex to the graph... wasteful
73  UEVertex( GraphClass * owner, platform::Size index ) :
74  index_( index ),
75  upper_edges_( V::NUM_EDGES_TO_RESERVE ),
76  num_upper_edges_( 0 ),
77  num_lower_edges_( 0 ),
79  owner_( owner )
80  {
81  upper_edges_.resize( 0 );
82  }
83 
84  /// @brief default constructor; useful for allocating all vertices at once
85  /// in a single vector1 using the resize() method. Note that both
86  /// index_ and owner_ are set to 0. This state must be corrected before the vertex
87  /// is of any use.
89  index_( 0 ),
90  upper_edges_( V::NUM_EDGES_TO_RESERVE ),
91  num_upper_edges_( 0 ),
92  num_lower_edges_( 0 ),
94  owner_( 0 )
95  {
96  upper_edges_.reserve( 0 );
97  }
98 
99  /// @brief dstor, should be non-virtual
101  {
102  }
103 
104 private:
105 
106  /// @brief method for completing the construction of a vertex if the defaul ctor was used.
107  ///
108  /// @detailed to be called by class UEGraph only
109  void
111  platform::Size index,
112  GraphClass * owner
113  )
114  {
115  assert( index_ == 0 && owner_ == 0 ); // this can be called at most once
116  index_ = index;
117  owner_ = owner;
118  }
119 
120 public:
121 
122  /// @brief reserves space for the edges. Due to the nature of vertex construction
123  /// in the UEGraph, this method should be called separately from the constructor.
124  ///
125  /// @details class V must define a static member "NUM_EDGES_TO_RESERVE()"; the
126  /// UEVertex constructor allocates space for that many edges -- if fewer than
127  /// that many edges are added to a sigle node, then new() need never be called.
128  /// if more are added, the class does not crash -- it simply grows the vector out
129  void
131  upper_edges_.reserve( V::NUM_EDGES_TO_RESERVE );
132  }
133 
134  EdgeClass * get_edge( platform::Size upper_vertex_id )
135  {
137  for ( platform::Size ii = 1; ii <= upper_edges_.size(); ++ii )
138  {
139  if ( upper_edges_[ ii ].upper_vertex() == upper_vertex_id )
140  {
141  return & upper_edges_[ ii ];
142  }
143  }
144  return 0;
145  }
146 
147  EdgeClass const * get_edge( platform::Size upper_vertex_id ) const
148  {
149  //pretend this is a non-const vertex
150  return const_cast< VertexClass * > (this)->get_edge( upper_vertex_id );
151  }
152 
153  bool edge_exists( platform::Size upper_vertex_id )
154  {
156  for ( platform::Size ii = 1; ii <= upper_edges_.size(); ++ii )
157  {
158  if ( upper_edges_[ ii ].upper_vertex() == upper_vertex_id )
159  {
160  return true;
161  }
162  }
163  return false;
164  }
165 
168  {
170  return upper_edges_.begin();
171  }
172 
175  {
177  return upper_edges_.end();
178  }
179 
182  {
184  return upper_edges_.begin();
185  }
186 
189  {
191  return upper_edges_.end();
192  }
193 
198 
199  void drop_all_edges() {
200  num_upper_edges_ = 0;
201  num_lower_edges_ = 0;
203  upper_edges_.resize( 0 ); // does not deallocate space
204  }
205 
206  // accessors for data held by this vertex
207  V & data() { return data_; }
208  V const & data() const { return data_; }
209 
210  friend class UEEdge< V, E >;
211  friend class UpperEdgeGraph< V, E >;
212 
213 private:
214 
215  /// @brief add an edge
216  ///
217  /// @detailed do not try to use this method or the other add_edge method to add edges to
218  /// a vertex; they are for class UpperEdgeGraph only. Invoke add_edge on the graph itself.
219  void
220  add_edge( platform::Size upper_vertex_index ) // called by UpperEdgeGraph
221  {
222  //if ( upper_edges_.capacity() == upper_edges_.size() ) {
223  // std::cout << this << " " << index_ << " About to resize edge vector on vertex " << index_ << " adding edge to " << upper_vertex_index << " upper_edges_.size() " << upper_edges_.size() << std::endl;
224  //}
225  upper_edges_.push_back( EdgeClass( owner_, index_, upper_vertex_index ) );
226  add_edge_common();
227  }
228 
229  void
230  add_edge( platform::Size upper_vertex_index, E const & edge_data ) // called by UpperEdgeGraph
231  {
232  //if ( upper_edges_.capacity() == upper_edges_.size() ) {
233  // std::cout << this << " " << index_ << " About to resize edge vector on vertex " << index_ << " adding edge to " << upper_vertex_index << " upper_edges_.size() " << upper_edges_.size() << std::endl;
234  //}
235  upper_edges_.push_back( EdgeClass( owner_, index_, upper_vertex_index, edge_data ) );
236  add_edge_common();
237  }
238 
239 
240  // called by UEEdge
242  {
245  }
246 
247  // called by UEEdge
249 
250  // called by UEEdge
252 
253 
255  {
256  if ( ! lazily_deleted_edges_present_ ) return;
257 
258  platform::Size shift( 0 );
259  for ( platform::Size ii = 1; ii <= upper_edges_.size(); ++ii )
260  {
261  if ( upper_edges_[ii].deleted() )
262  {
263  ++shift;
264  }
265  else
266  {
267  if ( shift > 0 )
268  {
269  upper_edges_[ ii - shift ] = upper_edges_[ ii ];
270  }
271  }
272 
273  assert ( ii != upper_edges_.size() || (ii - shift == num_upper_edges_) );
274  }
275  upper_edges_.resize( num_upper_edges_ );
277  }
278 
279  inline
280  void
282  {
284  }
285 
286 private:
287  // Data
288 
291 
293  platform::Size num_lower_edges_; // each vertex knows how many lower edges it has; it just doesn't know who they are
294 
296 
298  V data_;
299 
300 
301 };
302 
303 template < class V, class E >
304 class UEEdge
305 {
306 public:
309 
310 public:
311 
312  UEEdge() :
313  owner_( 0 ),
314  lower_vertex_( 0 ),
315  upper_vertex_( 0 ),
316  deleted_( true ),
318  {}
319 
320  UEEdge( GraphClass * owner, int lower_node, int upper_node )
321  :
322  owner_( owner ),
323  lower_vertex_( owner->get_vertex_ptr( lower_node )),
324  upper_vertex_( owner->get_vertex_ptr( upper_node )),
325  deleted_( false ),
326  upper_vertex_index_( upper_node )
327  {
329  }
330 
332  {
333  //std::cout << "UEEdge dstor" << std::endl;
334  }
335 
336 
337  UEEdge( GraphClass * owner, int lower_node, int upper_node, E const & data )
338  :
339  owner_( owner ),
340  lower_vertex_( owner->get_vertex_ptr( lower_node )),
341  upper_vertex_( owner->get_vertex_ptr( upper_node )),
342  deleted_( false ),
343  upper_vertex_index_( upper_node ),
344  data_( data )
345  {
347  }
348 
349 
351 
352  void delete_edge() {
353  if ( deleted_ ) return;
354  deleted_ = true;
358  }
359 
360  bool deleted() const { return deleted_; } // vertex needs read info, no one else should
361 
362  // accessors for data held by this edge
363  E & data() { return data_; }
364  E const & data() const { return data_; }
365 
366  friend class UpperEdgeGraph< V, E >;
367 
368 private:
369 
373 
374  bool deleted_;
376 
378 
379 };
380 
381 // Copy ctor and operator = not yet implemented
382 // do not use!
383 template < class V, class E >
385 {
386 public:
391  typedef typename utility::vector1< UEEdge< V, E > >::const_iterator UpperEdgeListConstIter;
392 
393 
394 public:
395 
397  UpperEdgeGraph( platform::Size nverts ) : num_vertices_( nverts ), num_edges_( 0 ), vertices_( nverts, 0 )
398  {
399  create_vertices();
400  }
401 
403  utility::pointer::ReferenceCount()
404  {
405  copy_from( other );
406  }
407 
408  virtual ~UpperEdgeGraph() {};
409 
410  UpperEdgeGraph< V, E > const &
412  {
413  copy_from( other );
414  return *this;
415  }
416 
417  //clears all edge data
418  void
420  {
421  if ( num_vertices_ != num_vertices ) {
423  create_vertices();
424  } else {
425  drop_all_edges();
426  }
427  }
428 
429  VertexClass &
430  get_vertex( platform::Size index ) { return *vertices_[ index ]; }
431 
432  VertexClass const &
433  get_vertex( platform::Size index ) const { return *vertices_[ index ]; }
434 
435  // add an edge and return a reference to it
436  EdgeClass & add_edge( platform::Size lower_vertex, platform::Size upper_vertex )
437  {
438  //assert( lower_vertex < upper_vertex );
439  assert( ! edge_exists( lower_vertex, upper_vertex ));
440  assert( ! edge_exists( upper_vertex, lower_vertex )); //fpd
441  vertices_[ lower_vertex ]->add_edge( upper_vertex );
442  ++num_edges_;
443  }
444 
445  // add an edge and set its data
446  void
447  add_edge( platform::Size lower_vertex, platform::Size upper_vertex, E const & edge_data )
448  {
449  //assert( lower_vertex < upper_vertex );
450  assert( ! edge_exists( lower_vertex, upper_vertex ));
451  assert( ! edge_exists( upper_vertex, lower_vertex )); //fpd
452  vertices_[ lower_vertex ]->add_edge( upper_vertex, edge_data );
453  ++num_edges_;
454  }
455 
456  // slow; O(V)
457  bool
458  edge_exists( platform::Size lower_vertex, platform::Size upper_vertex )
459  {
460  return vertices_[ lower_vertex ]->edge_exists( upper_vertex );
461  }
462 
463  EdgeClass * get_edge( platform::Size lower_vertex, platform::Size upper_vertex )
464  {
465  return vertices_[ lower_vertex ]->get_edge( upper_vertex );
466  }
467 
468  platform::Size num_edges() const { return num_edges_; }
470 
471  void drop_all_edges() {
472  for ( platform::Size ii = 1; ii <= vertices_.size(); ++ii ) vertices_[ ii ]->drop_all_edges();
473  num_edges_ = 0;
474  }
475 
476  friend class UEEdge< V, E >;
477  friend class UEVertex< V, E >;
478 
479 private:
480 
481  void
483  {
484  if ( vertices_.size() != 0 ) vertices_.clear();
485  if ( vertices_.size() != num_vertices_ ) vertices_.resize( num_vertices_ );
486  for ( platform::Size ii = 1; ii <= num_vertices_; ++ii )
487  {
489  //vertices_[ ii ]->set_index_and_owner( ii, this );
490  //vertices_[ ii ]->reserve_edge_space();
491  }
492  num_edges_ = 0;
493  }
494 
495  void
497  {
499  create_vertices();
500  for ( platform::Size ii = 1; ii <= other.num_vertices_; ++ii )
501  {
502  //std::cout << "vertices_.size() " << vertices_.size() << std::endl;
503  //std::cout << "vertices_[ ii ].index_ " << vertices_[ ii ].index_ << std::endl;
504  vertices_[ ii ]->data() = other.vertices_[ ii ]->data();
505  //std::cout << "vertex data copied; vertices_.size() " << vertices_.size() << std::endl;
506 
507  //std::cout << "vertices_[ ii ].index_ " << vertices_[ ii ].index_ << std::endl;
509  iter = other.get_vertex( ii ).const_upper_edge_list_begin(),
510  eiter = other.get_vertex( ii ).const_upper_edge_list_end();
511  iter != eiter; ++iter )
512  {
513  //std::cout << "Adding edge.vertices_.size() " << vertices_.size() << std::endl;
514  add_edge( ii, iter->upper_vertex(), iter->data() );
515  }
516  }
517  }
518 
519  // called by edge class
520  VertexClass * get_vertex_ptr( int index ) { return vertices_[ index ](); }
521 
522  // called by edge class
524 
525 private:
526  // Data
527 
531 
532 };
533 
534 
535 
536 }
537 }
538 
539 #endif