Rosetta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ring_detection.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 utility/graph/ring_detection.hh
11 /// @brief Algorithms for working with rings in boost graphs
12 /// @author Rocco Moretti (rmorettiase@gmail.com)
13 
14 #ifndef INCLUDED_utility_graph_ring_detection_HH
15 #define INCLUDED_utility_graph_ring_detection_HH
16 
18 #include <utility/vector0.hh>
19 #include <utility/exit.hh>
20 
21 #include <platform/types.hh>
22 
23 #include <boost/graph/undirected_dfs.hpp>
24 
25 #include <map>
26 #include <set>
27 
28 namespace utility {
29 namespace graph {
30 
31 /// @brief A class to implement the behavior of the smallest ring size finding algorithm, accessible through the smallest_ring_size() function below.
32 /// @details Based on BCL's smallest ring size detection algorithm.
33 
34 template< class Graph, class DistanceMap, class LabelMap >
36  typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
37  typedef typename boost::graph_traits<Graph>::vertex_descriptor VD;
38 
39 private:
40  // References to avoid copying when the visitor is passed by value.
41  DistanceMap & distances_;
42  LabelMap & labels_;
43  // Reference to allow output when the visitor is passed by value
46 public:
47  RingSizeVisitor(VD const & source, Graph const & graph, DistanceMap & distances, LabelMap & labels, platform::Size & size, platform::Size const & max_size = 2*999999):
48  distances_( distances ),
49  labels_( labels ),
50  size_(size), // Tie for output.
51  stop_level_( max_size/2 + 1 ) // Integer truncation division intended
52  {
53  size_ = 999999;
54  boost::put(distances_,source,0);
55  boost::put(labels_,source,0);
56  typename boost::graph_traits<Graph>::adjacency_iterator iter, end;
58  for ( boost::tie(iter,end) = boost::adjacent_vertices(source,graph); iter != end; ++iter, ++index ) {
59  boost::put(labels_,*iter,index);
60  boost::put(distances_,*iter,1);
61  }
62  }
63 
64  bool tree_edge(Edge const & e, Graph const & g) {
65  //First time we see the target of the edge - check validity, mark distance and label
66  // We can assume the parent node is initialized on the data map.
67  VD const & parent( boost::source(e,g) );
68  VD const & child( boost::target(e,g) );
70  if ( distance == 1 ) { return false; } // We've already processed the node in the constructor.
71  if ( distance >= stop_level_ ) { return true; }
72 
73  //Set Distance and label
74  boost::put(distances_, child, distance);
75  boost::put(labels_, child, boost::get(labels_,parent));
76  return false;
77  }
78 
79  bool gray_target(Edge const & e, Graph const & g) {
80  // A grey target implies a ring closure.
81  // We can be assured that both nodes have been initialized on the data maps.
82  VD const & left( boost::source(e,g) );
83  VD const & right( boost::target(e,g) );
84  if ( boost::get(labels_,left) == boost::get(labels_,right) ) {
85  // We're closing a ring that can bypass the start vertex. Ignore.
86  return false;
87  }
88  platform::Size const & dleft( boost::get(distances_,left) );
89  platform::Size const & dright( boost::get(distances_,right) );
90  platform::Size ringsize( dleft + dright + 1 ); // +1 for the start vertex
91  // Note that the first ring encountered may not be the smallest ring.
92  // E.g. if we're working on the second level, we may close a six member ring first,
93  // but then close a five member one later while finishing up the second level.
94  // Finish this level, but don't bother working on the next level.
95  if ( ringsize < size_ ) {
96  size_ = ringsize;
97  stop_level_ = dleft + 1; // Don't follow any nodes to next level
98  }
99  return false;
100  }
101 };
102 
103 /// @brief A boost graph-based function to find the size of the smallest ring for a given vertex.
104 /// Will return the maximum ring size, or 999999 for no ring. If there is a maximum ring size,
105 /// That can be set to limit the amount of search needed.
106 template < class Graph >
108 smallest_ring_size( typename boost::graph_traits< Graph>::vertex_descriptor const & vd, Graph const & graph, platform::Size const & max_ring_size = 2*999999 ) {
109 
110  typedef typename boost::graph_traits< Graph>::vertex_descriptor VD;
111 
112  /* typedef typename boost::property_map<Graph, boost::vertex_index_t>::type VertexIDMap;
113  //vector0 as the VertexIDMap is zero-based.
114  typedef utility::vector0< platform::Size > DistanceMapStore;
115  typedef boost::iterator_property_map<DistanceMapStore::iterator, VertexIDMap,
116  std::iterator_traits<DistanceMapStore::iterator>::value_type,
117  std::iterator_traits<DistanceMapStore::iterator>::reference
118  > DistanceMap;
119  typedef utility::vector0< platform::Size > LabelMapStore;
120  typedef boost::iterator_property_map<LabelMapStore::iterator, VertexIDMap,
121  std::iterator_traits<LabelMapStore::iterator>::value_type,
122  std::iterator_traits<LabelMapStore::iterator>::reference
123  > LabelMap;
124 
125  VertexIDMap vertex_id( boost::get(boost::vertex_index, graph) );
126  DistanceMapStore distancestore( boost::num_vertices(graph), 999999 );
127  DistanceMap distances( boost::make_iterator_property_map(distancestore.begin(), vertex_id) );
128  LabelMapStore labelstore( boost::num_vertices(graph), 999999 );
129  LabelMap labels( boost::make_iterator_property_map(labelstore.begin(), vertex_id) );
130  */
131 
132  typedef typename std::map<VD,platform::Size> DataStore;
133  typedef typename boost::associative_property_map< DataStore > DataStoreMap;
134 
135  DataStore distancestore;
136  DataStoreMap distances(distancestore);
137  DataStore labelstore;
138  DataStoreMap labels(labelstore);
139 
140  platform::Size smallest_size = 999999;
141  RingSizeVisitor< Graph, DataStoreMap, DataStoreMap > vis(vd, graph, distances, labels, smallest_size, max_ring_size);
143 
144  return smallest_size;
145 }
146 
147 
148 template< class Graph, class EdgeMap, class PathMap >
149 class RingEdgeAnnotationVisitor: public boost::default_dfs_visitor {
150  typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
151  typedef typename boost::graph_traits<Graph>::vertex_descriptor VD;
152 
153 private:
154  // References to avoid copying when the visitor is passed by value.
155  // EdgeMap is a map of VD:(map of VD:bools), where EdgeMap[vd1][vd2] is true if the vd1-vd2 edge is in a cycle.
156  EdgeMap & edgemap_;
157  // PathMap is a map of VertexDescriptors:set<edge_descriptors>, representing the initial path to the vertex
158  PathMap & pathmap_;
159 public:
160  RingEdgeAnnotationVisitor(EdgeMap & edgemap, PathMap & pathmap):
161  edgemap_( edgemap ),
162  pathmap_( pathmap )
163  {}
164 
165  void examine_edge(Edge, const Graph&) {
166  //edgemap_[u] = false; // Initialize edge as non-cycle.
167  // // Maps default to zero initialized if not found.
168  }
169  void tree_edge(Edge u, const Graph& g) {
170  //std::cout << "Tree: " << boost::source(u,g) << "---" << boost::target(u,g) << std::endl;
171  typename PathMap::mapped_type path( pathmap_[boost::source(u,g)] ); // make a copy.
172  path.insert( u );
173  pathmap_[ boost::target(u,g) ] = path;
174  }
175  void back_edge(Edge u, const Graph& g) {
176  //std::cout << "Back: " << boost::source(u,g) << "---" << boost::target(u,g) << std::endl;
177  typename PathMap::mapped_type const & path( pathmap_[boost::source(u,g)] );
178  typename PathMap::mapped_type const & path2( pathmap_[boost::target(u,g)] );
179  // We've found a cycle
180  edgemap_[boost::source(u,g)][boost::target(u,g)] = true; //The back edge is always part of the cycle.
181  edgemap_[boost::target(u,g)][boost::source(u,g)] = true;
182  typename PathMap::mapped_type::const_iterator iter, iter_end;
183  for ( iter = path.begin(), iter_end = path.end(); iter != iter_end; ++iter ) {
184  if ( path2.count( *iter ) == 0 ) {
185  // If we have an edge in the longer path, but it isn't on the "stem"
186  // to the node we're going back to, it's part of a cycle.
187  //std::cout << "Marking Ring " << boost::source(*iter,g) << "---" << boost::target(*iter,g) << std::endl;
188  edgemap_[boost::source(*iter,g)][boost::target(*iter,g)] = true;
189  edgemap_[boost::target(*iter,g)][boost::source(*iter,g)] = true;
190  }
191  }
192  }
193  void forward_or_cross_edge(Edge, const Graph&) {
194  // Have to use generic tracer - can't initialize static tracer in header file.
195  //std::cout << "Cross: " << boost::source(u,g) << "---" << boost::target(u,g) << std::endl;
196  utility_exit_with_message( "Found forward or cross edge when detecting cycles - should not happen with an undirected graph." );
197  }
198 };
199 
200 template < class Graph >
201 std::map< typename boost::graph_traits<Graph>::vertex_descriptor, std::map< typename boost::graph_traits<Graph>::vertex_descriptor, bool > >
202 annotate_ring_edges( Graph & graph) {
203  typedef typename boost::graph_traits<Graph>::edge_descriptor Edge;
204  typedef typename boost::graph_traits<Graph>::vertex_descriptor VD;
205  typedef typename std::map< typename boost::graph_traits<Graph>::vertex_descriptor, std::map< typename boost::graph_traits<Graph>::vertex_descriptor, bool > > EdgeMap;
206  typedef typename std::map< VD, std::set< Edge > > PathMap;
207  typedef typename std::map< VD, boost::default_color_type> VertexColorMap;
208  typedef typename std::map< Edge, boost::default_color_type> EdgeColorMap;
209 
210  EdgeMap edgemap;
211  PathMap pathmap;
212 
213  VertexColorMap vertexcolormap;
214  EdgeColorMap edgecolormap;
215  boost::associative_property_map<VertexColorMap> vertexcolorproperty(vertexcolormap);
216  boost::associative_property_map<EdgeColorMap> edgecolorproperty(edgecolormap);
217 
219  //Use DFS here so that we only have to keep track of one active path
220  //Use undirected_dfs() because the regular DFS has a back edge for each forward edge.
221  boost::undirected_dfs(graph, vis, vertexcolorproperty, edgecolorproperty);
222 
223  return edgemap;
224 }
225 
226 } // namespace graph
227 } // namespace utility
228 
229 #endif
#define utility_exit_with_message(m)
Exit with file + line + message.
Definition: exit.hh:47
A class to implement the behavior of the smallest ring size finding algorithm, accessible through the...
utility::keys::KeyLookup< KeyType >::const_iterator const_iterator
Key collection iterators.
dictionary size
Definition: amino_acids.py:44
vector0: std::vector with assert-checked bounds
void breadth_first_search_prune(const VertexListGraph &g, typename boost::graph_traits< VertexListGraph >::vertex_descriptor s, BFSVisitor vis, ColorMap color, Buffer &Q)
breadth_first_search_prune is a slightly modified versions of the Boost functions breadth_first_searc...
Definition: BFS_prune.hh:126
boost::graph_traits< Graph >::edge_descriptor Edge
boost::graph_traits< Graph >::edge_descriptor Edge
RingEdgeAnnotationVisitor(EdgeMap &edgemap, PathMap &pathmap)
RingSizeVisitor(VD const &source, Graph const &graph, DistanceMap &distances, LabelMap &labels, platform::Size &size, platform::Size const &max_size=2 *999999)
utility::keys::lookup::end< KeyType > const end
void forward_or_cross_edge(Edge, const Graph &)
platform::Size smallest_ring_size(typename boost::graph_traits< Graph >::vertex_descriptor const &vd, Graph const &graph, platform::Size const &max_ring_size=2 *999999)
A boost graph-based function to find the size of the smallest ring for a given vertex. Will return the maximum ring size, or 999999 for no ring. If there is a maximum ring size, That can be set to limit the amount of search needed.
Fstring::size_type index(Fstring const &s, Fstring const &ss)
First Index Position of a Substring in an Fstring.
Definition: Fstring.hh:2180
std::map< typename boost::graph_traits< Graph >::vertex_descriptor, std::map< typename boost::graph_traits< Graph >::vertex_descriptor, bool > > annotate_ring_edges(Graph &graph)
boost::graph_traits< Graph >::vertex_descriptor VD
Program exit functions and macros.
A breadth first search with pruning for boost graphs.
bool gray_target(Edge const &e, Graph const &g)
bool tree_edge(Edge const &e, Graph const &g)
T distance(MathVector< T > const &VECTOR_A, MathVector< T > const &VECTOR_B)
void tree_edge(Edge u, const Graph &g)
boost::graph_traits< Graph >::vertex_descriptor VD
std::size_t Size
Definition: types.hh:37
void back_edge(Edge u, const Graph &g)