Scaffolding  0.1
This program can assemble genome scaffolds using the pairing information in paired-end reads.
graph_parameters.hpp
Go to the documentation of this file.
1 
9 #ifndef GRAPH_PARAMETERS_HPP
10 #define GRAPH_PARAMETERS_HPP
11 
12 #include <vector>
13 #include <queue>
14 #include <iostream>
15 
16 #include <boost/graph/graph_traits.hpp>
17 #include <boost/graph/connected_components.hpp>
18 
19 #include "graph_typedefs.hpp"
20 #include "graph_utils.hpp"
21 #include "low_priority_queue.hpp"
22 
23 using namespace boost;
24 
25 namespace scaffold { namespace graph_parameters {
26 
28  template<class Graph>
29  struct degree_less{
30  const Graph& g;
31  // constructor, needs to save a reference to the graph in which to compare degrees
32  degree_less(const Graph& _g):g(_g) {}
33  // actual compare operator
34  bool operator()(const Vertex<Graph>& u, const Vertex<Graph>& v) const{
35  return boost::degree(u, g) < boost::degree(v, g);
36  }
37  };
38 
40  template<class Graph>
42  const Graph& g;
43  // constructor, needs to save a reference to the graph in which to compare degrees
44  degree_greater(const Graph& _g):g(_g) {}
45  // actual compare operator
46  bool operator()(const Vertex<Graph>& u, const Vertex<Graph>& v) const{
47  return boost::degree(u, g) > boost::degree(v, g);
48  }
49  };
50 // can be used in priority queues like this:
51 // typedef typename std::priority_queue<Vertex<Graph>, std::vector<Vertex<Graph> >, degree_greater<Graph> > degree_comparing_queue;
52 // degree_comparing_queue degree_queue( (degree_greater<Graph>(g)) );
53 
55  struct interval{
56  unsigned lower_bound, upper_bound;
57  interval(): lower_bound(0), upper_bound(UINT_MAX) {}
58  };
59 
61 
63  unsigned vertices;
64  unsigned edges;
65  unsigned components;
66  unsigned max_degree;
67  unsigned min_degree;
68  unsigned h_index;
69  unsigned degeneracy;
70  interval treewidth;
71  interval pathwidth;
72  interval cliquewidth;
73  interval vertex_cover;
74  interval max_clique;
75  interval independent_set;
76  interval chromatic_number;
77  interval FVS;
78  };
80  std::ostream& operator<<(std::ostream& os, const interval& i){
81  return os << "["<<i.lower_bound<<","<<i.upper_bound<<"]";
82  }
84  std::ostream& operator<<(std::ostream& os, const graph_parameters& params){
85  os << "vertices:\t"<< params.vertices <<std::endl;
86  os << "edges:\t\t"<< params.edges <<std::endl;
87  os << "min degree:\t"<< params.min_degree <<std::endl;
88  os << "max degree:\t"<< params.max_degree <<std::endl;
89  os << "avg degree:\t"<< ((float)2*params.edges)/params.vertices <<std::endl;
90 
91  os << "components:\t"<< params.components <<std::endl;
92  os << "FES:\t\t"<< compute_FES(params.vertices, params.edges, params.components) <<std::endl;
93  os << "h-index:\t"<< params.h_index <<std::endl;
94  os << "degeneracy:\t"<< params.degeneracy <<std::endl;
95  os << "FVS:\t\t"<< params.FVS <<std::endl;
96  os << "treewidth:\t"<< params.treewidth <<std::endl;
97  os << "pathwidth:\t"<< params.pathwidth <<std::endl;
98  os << "vertex cover:\t"<<params.vertex_cover<<std::endl;
99  os << "cliquewidth:\t"<<params.cliquewidth<<std::endl;
100  os << "maxclique:\t"<< params.max_clique <<std::endl;
101  os << "ind.-set:\t"<< params.independent_set <<std::endl;
102  os << "chrom.-num:\t"<< params.chromatic_number<<std::endl;
103  return os;
104  }
105 
106  template<class Graph>
107  using vertex_ordering = std::vector<Vertex<Graph> >;
108 
110 
111  template <class Graph>
112  unsigned num_connected_components(const Graph& g, ComponentMap<Graph>& compMap, graph_parameters* const params = NULL)
113  {
114  typedef typename Graph::vertex_bundled VertexInfos;
115  // trust that the VertexInfos have an ::index
116  unsigned num_components = boost::connected_components(g, boost::associative_property_map<ComponentMap<Graph> >(compMap), vertex_index_map(boost::get(&VertexInfos::index, g)));
117  if(params) params->components = num_components;
118  return num_components;
119  }
120 
122  template <class Graph>
123  unsigned num_connected_components(const Graph& g, graph_parameters* const params = NULL)
124  {
125  ComponentMap<Graph> compMap;
126  return num_connected_components<Graph>(g, compMap, params);
127  }
128 
130 
131  template <class Graph>
132  std::pair<Vertex<Graph>,unsigned> get_max_degree(const Graph& g, graph_parameters* const params = NULL)
133  {
134  assert(num_vertices(g));
135 
136  VertexIterRange<Graph> r = vertices(g);
137  VertexIter<Graph> max_v = std::max_element(r.first, r.second, degree_cmp<Graph>(g));
138  const unsigned v_deg = boost::degree(*max_v, g);
139 
140  // finally, update parameters & return the result
141  if(params)
142  params->max_degree = v_deg;
143 
144  return std::make_pair(*max_v, v_deg);
145  }
146 
148 
149  template <class Graph>
150  unsigned h_index(const Graph& g, graph_parameters* const params = NULL)
151  {
152  // step 1: sort vertices descendingly by degree, using a priority_queue
153  // step 1a: construct a priority queue that sorts incoming vertices by degree
154  std::priority_queue<unsigned, std::vector<unsigned>, std::less<unsigned> > degree_queue;
155  // step 1b: insert all vertices into the queue
156  unsigned min_deg = ULONG_MAX;
157  for(VertexIterRange<Graph> r = vertices(g); r.first != r.second; ++r.first){
158  const unsigned deg = degree(*r.first, g);
159  // update minimum degree
160  if(deg < min_deg) min_deg = deg;
161  degree_queue.push(deg);
162  }
163  // extract the max degree
164  const unsigned max_deg = degree_queue.top();
165  // step 2: walk the degree order until #steps = degree
166  unsigned x = 0;
167  while(degree_queue.empty() ? false : (degree_queue.top() >= x)){
168  ++x;
169  degree_queue.pop();
170  }
171  // finally, update parameters & return the result
172  if(params){
173  params->h_index = x;
174  params->min_degree = min_deg;
175  params->max_degree = max_deg;
176  }
177  return x;
178  }
179 
180  // compute a degeneracy and its ordering (that is, an ordering of the vertices minimizing the "right-degree")
181  template <class Graph>
182  unsigned degeneracy(const Graph& g, vertex_ordering<Graph>* order = NULL, graph_parameters* const params = NULL)
183  {
184  // use a priority queue to order vertices based on their degrees
185  typedef typename std::low_priority_queue<Vertex<Graph> > DegreeQueue;
186  typedef typename DegreeQueue::value_type VertexAndDegree;
187  DegreeQueue degree_queue;
188  // keep a mapping of vertices to iterators within the DegreeQueue having num_vertices(g) buckets to keep the load factor low
189  typedef typename boost::unordered_map<Vertex<Graph>, typename DegreeQueue::const_iterator> VertexToIter;
190  typedef typename VertexToIter::value_type VertexAndIter;
191  VertexToIter vertex_to_iter(boost::num_vertices(g));
192  // make a copy of g
193  Graph h;
194  typedef unordered_map<Vertex<Graph>, Vertex<Graph> > VtoVMap;
195  VtoVMap translate_map, inv;
196 
197  boost::copy_graph(g, h, orig_to_copy(associative_property_map<VtoVMap>(inv)).vertex_index_map(boost::get(&Graph::vertex_bundled::index, g)));
198  // invert to get a translate map from copy to orig (if the FVS is requested)
199  if(order) for(auto& i : inv) translate_map.emplace(i.second, i.first);
200 
201  // step 2: set up the degree queue
202  unsigned min_deg = ULONG_MAX;
203  unsigned max_deg = 0;
204  for(VertexIterRange<Graph> r = boost::vertices(h); r.first != r.second; ++r.first){
205  const Vertex<Graph>& u = *r.first;
206  const unsigned deg = boost::degree(u, h);
207  // update minimum degree
208  if(deg < min_deg) min_deg = deg;
209  if(deg > max_deg) max_deg = deg;
210  // set up the queue
211  vertex_to_iter.emplace(VertexAndIter(u, degree_queue.insert(VertexAndDegree(u, deg))));
212  }
213  if(params) {
214  params->min_degree = min_deg;
215  params->max_degree = max_deg;
216  }
217  DEBUG5(std::cout << "found min degree "<<min_deg<<" & max_deg "<<max_deg<<std::endl);
218 
219  // step 3: repeatedly delete the smallest-degree vertex of h to find the degeneracy
220  unsigned degeneracy = min_deg;
221  while(boost::num_vertices(h)){
222  // step 3a: pop a vertex of minimum degree...
223  const typename DegreeQueue::value_type& next_pair = degree_queue.get_min();
224  const Vertex<Graph> u = next_pair.first;
225  const unsigned min_deg = next_pair.second;
226  DEBUG5(std::cout << "found vertex of degree "<<boost::degree(u, h)<<" ("<<min_deg<<"), "<<boost::num_vertices(h)<<" vertices left"<<std::endl);
227  degree_queue.pop_min();
228  vertex_to_iter.erase(u);
229  // update degeneracy if necessary
230  if(min_deg > degeneracy) degeneracy = min_deg;
231  DEBUG5(std::cout << "degeneracy set to "<<degeneracy<<std::endl);
232  // step 3b: add it at the end of the ordering
233  if(order) order->push_back(translate_map[u]);
234  // step 3c: decrease the degree of each its non-visited neighbors
235  for(AdjIterRange<Graph> r = boost::adjacent_vertices(u, h); r.first != r.second; ++r.first){
236  const Vertex<Graph>& v = *r.first;
237  const typename DegreeQueue::const_iterator di = vertex_to_iter.at(v);
238  DEBUG5(std::cout << "seeing a neighbor of degree "<<boost::degree(v, h)<<" (stored as "<<di->second<<")"<<std::endl);
239  degree_queue.decrement_priority(di);
240  DEBUG5(std::cout<<"decremented priority of someone to "<<di->second<<std::endl);
241  }
242  boost::clear_vertex(u, h);
243  boost::remove_vertex(u, h);
244  } // while
245  if(params) params->degeneracy = degeneracy;
246  return degeneracy;
247  } // function
248 
249 
251 
252  template <class Graph>
253  unsigned feedback_vertex_set_greedy(const Graph& g, VertexSet<Graph>* FVS = NULL, graph_parameters *params = NULL)
254  {
255  unsigned result_fvs = 0;
256  unsigned result_tw = 0;
257  unsigned tw_ub = 0;
258 
259  // Step 1: make a copy of g
260  Graph h;
261  typedef unordered_map<Vertex<Graph>, Vertex<Graph> > VtoVMap;
262  VtoVMap translate_map, inv;
263  boost::copy_graph(g, h, orig_to_copy(associative_property_map<VtoVMap>(inv)).vertex_index_map(boost::get(&Graph::vertex_bundled::index, g)));
264  // invert inv to get a translate map from copy to orig (if the FVS is requested)
265  if(FVS) for(auto& i : inv) translate_map.emplace(i.second, i.first);
266 
267  // Step 2: split off connected components
268  while(true){
269  VTranslateMap<Graph,Graph> tr_back;
270  graph_parameters sub_params;
271 
272  Graph* comp = split_off_component(h, (VTranslateMap<Graph,Graph>*)NULL, &tr_back);
273  if(comp) {
274  result_fvs += feedback_vertex_set_greedy(*comp, FVS, &sub_params);
275  delete comp;
276  // update the global upper bound on the treewidth
277  tw_ub = std::max(tw_ub, result_tw + sub_params.treewidth.upper_bound);
278  } else break;
279  };
280 
281  // use a priority queue to order vertices based on their degrees
282  typedef typename std::low_priority_queue<Vertex<Graph>, unsigned> DegreeQueue;
283  typedef typename DegreeQueue::value_type VertexAndDegree;
284  DegreeQueue degree_queue;
285  // keep a mapping of vertices to iterators within the DegreeQueue having num_vertices(g) buckets to keep the load factor low
286  typedef typename boost::unordered_map<Vertex<Graph>, typename DegreeQueue::const_iterator> VertexToIter;
287  typedef typename VertexToIter::value_type VertexAndIter;
288  VertexToIter vertex_to_iter(boost::num_vertices(h));
289 
290  // step 3: setup data structures
291  for(VertexIterRange<Graph> r = boost::vertices(h); r.first != r.second; ++r.first){
292  const Vertex<Graph>& u = *r.first;
293  const unsigned deg = boost::degree(u, h);
294  vertex_to_iter.emplace(VertexAndIter(u, degree_queue.insert(VertexAndDegree(u, deg))));
295  }
296 
297  while(true){
298  // Step 4: delete all bridges from h
299  BridgeMap<Graph> bridges;
300  mark_bridges(h, bridges);
301  for(const auto& i : bridges) {
302  const VertexPair<Graph>& b = i.first;
303  boost::remove_edge(boost::edge(b.first, b.second, h).first, h);
304  for(const Vertex<Graph>& u : {b.first, b.second})
305  if(boost::degree(u, h) > 0)
306  degree_queue.decrement_priority(vertex_to_iter.at(u));
307  else{
308  typename VertexToIter::const_iterator i = vertex_to_iter.find(u);
309  degree_queue.erase(i->second);
310  vertex_to_iter.erase(i);
311  boost::remove_vertex(u, h);
312  }
313  }
314 
315  // if h still has edges left
316  if(boost::num_edges(h)){
317  // Step 5: get max degree vertex in the rest of the graph
318  const VertexAndDegree& max_pair = degree_queue.get_max();
319  const Vertex<Graph> max_deg_vertex = max_pair.first;
320  DEBUG3(std::cout << "treated graph ("<<num_vertices(h)<<" vertices), found FVS ("<<FVS<<") candidate "<<VertexAndGraph<Graph>(max_deg_vertex, h) << " with degree "<<max_pair.second<<std::endl);
321 
322  // Step 6: take the max degree vertex in g into the FVS and delete it in h
323  if(FVS) FVS->insert(translate_map.at(max_deg_vertex));
324  for(AdjIterRange<Graph> r = boost::adjacent_vertices(max_deg_vertex, h); r.first != r.second; ++r.first){
325  const Vertex<Graph>& v = *r.first;
326  const typename VertexToIter::const_iterator v_iter = vertex_to_iter.find(v);
327  const typename DegreeQueue::const_iterator dq_iter = v_iter->second;
328 
329  if(boost::degree(v, h) > 1){
330  degree_queue.decrement_priority(dq_iter);
331  DEBUG5(std::cout<<"decremented priority of someone to "<<dq_iter->second<<std::endl);
332  } else{
333  degree_queue.erase(dq_iter);
334  vertex_to_iter.erase(v_iter);
335  boost::remove_vertex(v, h);
336  }
337  }
338  // clean up data structures
339  boost::clear_vertex(max_deg_vertex, h);
340  typename VertexToIter::const_iterator max_ref = vertex_to_iter.find(max_deg_vertex);
341  degree_queue.erase(max_ref->second);
342  vertex_to_iter.erase(max_ref);
343  boost::remove_vertex(max_deg_vertex, h);
344 
345  ++result_fvs;
346  ++result_tw;
347  } else break;
348  } // while
349  if(params) {
350  tw_ub = std::max(tw_ub, result_tw);
351  // update the upper bound on the treewidth
352  if(params) params->treewidth.upper_bound = std::min(params->treewidth.upper_bound, tw_ub);
353  // update the FVS upper bound
354  params->FVS.upper_bound = std::min(params->FVS.upper_bound, result_fvs);
355  }
356  return result_fvs;
357  }
358 
359 
361 
368  template <class Graph>
369  void compute_easy_parameters(const Graph& g, graph_parameters& params)
370  {
371  params.vertices = boost::num_vertices(g);
372  params.edges = boost::num_edges(g);
373  DEBUG5(std::cout << "computing connected components..."<<std::endl);
374  num_connected_components(g, &params);
375  DEBUG5(std::cout << "computing h-index..."<<std::endl);
376  h_index(g, &params);
377  DEBUG5(std::cout << "computing degeneracy..."<<std::endl);
378  degeneracy(g, (vertex_ordering<Graph>*)NULL, &params);
379  }
380 
381 }} // namespace
382 
383 #endif
comparator class, comparing two vertices u,v such that comp(u,v) = true <=> deg(u) < deg(v) ...
Definition: graph_parameters.hpp:29
Definition: graph_utils.hpp:18
a low-priority queue of Elements with Priorities
Definition: low_priority_queue.hpp:28
Definition: read_adj_list.hpp:22
Definition: graph_typedefs.hpp:180
comparator class, comparing two vertices u,v such that comp(u,v) = true <=> deg(u) > deg(v) ...
Definition: graph_parameters.hpp:41
an interval consists of a lower & an upper bound
Definition: graph_parameters.hpp:55