$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
util/graph.hh
1 // Copyright (C) 2007, 2008, 2009, 2010, 2012 EPITA Research and
2 // Development Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_UTIL_GRAPH_HH
28 # define MLN_UTIL_GRAPH_HH
29 
33 
34 # include <mln/util/internal/graph_base.hh>
35 # include <mln/util/internal/graph_iter.hh>
36 # include <mln/util/internal/graph_nbh_iter.hh>
37 # include <mln/util/vertex.hh>
38 # include <mln/util/edge.hh>
39 # include <mln/util/ord_pair.hh>
40 
41 namespace mln
42 {
43 
45  namespace util { class graph; }
46 
47 
48  namespace internal
49  {
50 
55  template <>
56  struct data<util::graph>
57  {
58  typedef util::graph G;
59  typedef std::vector<std::vector<util::edge_id_t> > vertices_t;
60  typedef std::vector<util::ord_pair<util::vertex_id_t> > edges_t;
61  typedef std::set<util::ord_pair<util::vertex_id_t> > edges_set_t;
62 
63  data();
66  data(unsigned nvertices);
67  ~data();
68 
70  vertices_t vertices_;
72  edges_t edges_;
73 
74 # ifndef NDEBUG
75 
76  edges_set_t edges_set_;
77 # endif // ! NDEBUG
78  };
79 
80  } // end of namespace mln::internal
81 
82 
83  namespace util
84  {
85 
89  //
90  class graph : public internal::graph_base<graph>
91  {
94 
95  typedef super::vertex_data_t vertex_data_t;
97 
98  public:
100  typedef std::vector<vertex_data_t> vertices_t;
101 
103  typedef std::vector<edge_data_t> edges_t;
105  typedef std::set<edge_data_t> edges_set_t;
106 
115 
122 
129 
136 
144 
146  graph();
148  graph(unsigned nvertices);
149 
152 
155 
159  unsigned add_vertex();
160 
164  std::pair<vertex_id_t, vertex_id_t> add_vertices(unsigned n);
165 
168  vertex_t vertex(vertex_id_t id_v) const;
170 
172  // FIXME: Rename as nvertices.
173  size_t v_nmax() const;
174 
176  // FIXME: Is the `_v' suffix really needed?
177  bool has_v(const vertex_id_t& id_v) const;
178 
179 
181  size_t v_nmax_nbh_edges(const vertex_id_t& id_v) const;
182 
184  edge_id_t
185  v_ith_nbh_edge(const vertex_id_t& id_v,
186  unsigned i) const;
187 
189  size_t v_nmax_nbh_vertices(const vertex_id_t& id_v) const;
190 
193  unsigned i) const;
195 
196 
197 
204  edge_id_t add_edge(const vertex_id_t& id_v1, const vertex_id_t& id_v2);
205 
207  edge_t edge(const edge_id_t& e) const;
208 
209 
211  const std::vector<util::ord_pair<vertex_id_t> >& edges() const;
212 
214  // FIXME: Rename as nedges.
215  size_t e_nmax() const;
216 
218  // FIXME: Is the `_e' suffix really needed?
219  bool has_e(const edge_id_t& id_e) const;
220 
223  edge_t edge(const vertex_t& v1, const vertex_t& v2) const;
224 
226  vertex_id_t v1(const edge_id_t& id_e) const;
227 
229  vertex_id_t v2(const edge_id_t& id_e) const;
230 
232  size_t e_nmax_nbh_edges(const edge_id_t& id_e) const;
233 
235  edge_id_t e_ith_nbh_edge(const edge_id_t& id_e, unsigned i) const;
236 
239  template <typename G2>
240  bool is_subgraph_of(const G2& g) const;
242 
243  };
244 
245  std::ostream&
246  operator<<(std::ostream& ostr, const graph& g);
247 
248  } // end of namespace mln::util
249 
250 } // end of namespace mln
251 
252 
253 
254 
255 # ifndef MLN_INCLUDE_ONLY
256 
257 namespace mln
258 {
259 
260  namespace internal
261  {
262 
263  inline
265  {
266  }
267 
268  inline
269  data<util::graph>::data(unsigned nvertices)
270  {
271  vertices_.resize(nvertices);
272  }
273 
274  inline
276  {
277  }
278 
279  } // end of namespace mln::internal
280 
281  namespace util
282  {
283 
284  inline
285  graph::graph()
286  {
287  this->data_ = new mln::internal::data<util::graph>();
288  }
289 
290  inline
291  graph::graph(unsigned nvertices)
292  {
293  this->data_ = new mln::internal::data<util::graph>(nvertices);
294  }
295 
296  /*--------------------------.
297  | Vertex-related services. |
298  `--------------------------*/
299 
300  inline
301  unsigned
303  {
304  /* FIXME: This is not thread-proof (these two lines should
305  form an atomic section). */
306  data_->vertices_.resize(data_->vertices_.size() + 1);
307 
308  return v_nmax() - 1;
309  }
310 
311  inline
312  std::pair<vertex_id_t, vertex_id_t>
313  graph::add_vertices(unsigned n)
314  {
315  /* FIXME: This is not thread-proof (these two lines should
316  form an atomic section). */
317  data_->vertices_.resize(data_->vertices_.size() + n);
318 
319  return std::make_pair(v_nmax() - n,
320  v_nmax() - 1);
321  }
322 
323  inline
325  graph::vertex(vertex_id_t id_v) const
326  {
327  mln_assertion(has_v(id_v));
328  return vertex_t(*this, id_v);
329  }
330 
331 
332  inline
333  size_t
334  graph::v_nmax() const
335  {
336  return data_->vertices_.size();
337  }
338 
339  inline
340  bool
341  graph::has_v(const vertex_id_t& id_v) const
342  {
343  return id_v < data_->vertices_.size();
344  }
345 
346  inline
347  size_t
348  graph::v_nmax_nbh_edges(const vertex_id_t& id_v) const
349  {
350  mln_precondition(has_v(id_v));
351  return data_->vertices_[id_v].size();
352  }
353 
354  inline
355  edge_id_t
356  graph::v_ith_nbh_edge(const vertex_id_t& id_v, unsigned i) const
357  {
358  mln_precondition(has_v(id_v));
359  if (i >= v_nmax_nbh_edges(id_v))
360  return edge_id_t();
361  return data_->vertices_[id_v][i];
362  }
363 
364  inline
365  size_t
366  graph::v_nmax_nbh_vertices(const vertex_id_t& id_v) const
367  {
368  mln_precondition(has_v(id_v));
369  return v_nmax_nbh_edges(id_v);
370  }
371 
372  inline
374  graph::v_ith_nbh_vertex(const vertex_id_t& id_v, unsigned i) const
375  {
376  mln_precondition(has_v(id_v));
377 
378  edge_id_t id_e = v_ith_nbh_edge(id_v, i);
379  return v_other(id_e, id_v);
380  }
381 
382 
383  /*-------------------------.
384  | Edges-related services. |
385  `-------------------------*/
386 
387  inline
388  edge_id_t
389  graph::add_edge(const vertex_id_t& id_v1, const vertex_id_t& id_v2)
390  {
391  mln_precondition(id_v1 != id_v2);
392  mln_precondition(has_v(id_v1));
393  mln_precondition(has_v(id_v2));
394 
395  // Does this edge already exist in the graph?
396  edge_data_t edge(id_v1, id_v2);
397  /* FIXME: This is not sound: the behavior of the algorithm
398  changes when NDEBUG is defined. */
399 # ifndef NDEBUG
400  if (data_->edges_set_.find(edge) != data_->edges_set_.end ())
401  {
402  // Return the erroneous value.
403  return edge_id_t();
404  }
405  else
406  {
407 # endif // ! NDEBUG
408  // Otherwise insert it into the graph.
409  /* FIXME: This is not thread-proof (these two lines should
410  form an atomic section). */
411  data_->edges_.push_back(edge);
412  edge_id_t id = data_->edges_.size() - 1;
413 
414  // Update the set of edges.
415 # ifndef NDEBUG
416  data_->edges_set_.insert(edge);
417 # endif // ! NDEBUG
418  data_->vertices_[edge.first()].push_back(id);
419  data_->vertices_[edge.second()].push_back(id);
420 
421  return id;
422 
423 # ifndef NDEBUG
424  }
425 # endif // ! NDEBUG
426 
427  }
428 
429  inline
430  const std::vector<util::ord_pair<vertex_id_t> >&
431  graph::edges() const
432  {
433  return this->data_->edges_;
434  }
435 
436  inline
438  graph::edge(const edge_id_t& e) const
439  {
440  mln_assertion(e < e_nmax());
441  return edge_t(*this, e);
442  }
443 
444  inline
445  size_t
446  graph::e_nmax() const
447  {
448  return data_->edges_.size();
449  }
450 
451  inline
452  bool
453  graph::has_e(const edge_id_t& id_e) const
454  {
455  return id_e < data_->edges_.size();
456  }
457 
458  inline
460  graph::edge(const vertex_t& v1, const vertex_t& v2) const
461  {
462  mln_precondition(has_v(v1));
463  mln_precondition(has_v(v2));
464 
466  id_v1 = v1.id(),
467  id_v2 = v2.id();
468 
469  if (id_v1 > id_v2)
470  std::swap(id_v1, id_v2);
471 
472  for (unsigned i = 0; i < data_->vertices_[id_v1].size(); ++i)
473  if (data_->edges_[data_->vertices_[id_v1][i]].second() == id_v2)
474  return edge_t(*this, data_->vertices_[id_v1][i]);
475 
476  // Not edges available. Return an invalid edge.
477  return edge_t();
478  }
479 
480  inline
482  graph::v1(const edge_id_t& id_e) const
483  {
484  mln_precondition(has_e(id_e));
485  return data_->edges_[id_e].first();
486  }
487 
488  inline
490  graph::v2(const edge_id_t& id_e) const
491  {
492  mln_precondition(has_e(id_e));
493  return data_->edges_[id_e].second();
494  }
495 
496  inline
497  size_t
498  graph::e_nmax_nbh_edges(const edge_id_t& id_e) const
499  {
500  mln_precondition(has_e(id_e));
501  return v_nmax_nbh_edges(v1(id_e)) + v_nmax_nbh_edges(v2(id_e));
502  }
503 
504  inline
505  edge_id_t
506  graph::e_ith_nbh_edge(const edge_id_t& id_e, unsigned i) const
507  {
508  mln_precondition(has_e(id_e));
509  if (i >= e_nmax_nbh_edges(id_e))
510  return e_nmax();
511 
512  unsigned v1_nmax = v_nmax_nbh_edges(v1(id_e));
513  if (i < v1_nmax)
514  return v_ith_nbh_edge(v1(id_e), i);
515  return v_ith_nbh_edge(v2(id_e), i - v1_nmax);
516  }
517 
518 
519  template <typename G2>
520  inline
521  bool
522  graph::is_subgraph_of(const G2& g) const
523  {
524  return g.id() == this->id();
525  }
526 
527  // FIXME: move to graph_Base.
528  inline
529  std::ostream&
530  operator<<(std::ostream& ostr, const graph& g)
531  {
532  mln_vertex_iter_(graph) v(g);
533  mln_vertex_nbh_edge_iter_(graph) e(v);
534  for_all(v)
535  {
536  ostr << "v(" << v << ") : ";
537  for_all(e)
538  ostr << e << " ";
539  ostr << std::endl;
540  }
541 
542  return ostr;
543  }
544 
545  } // end of namespace mln::util
546 
547 } // end of namespace mln
548 
549 # endif // ! MLN_INCLUDE_ONLY
550 
551 
552 #endif // ! MLN_UTIL_GRAPH_HH