Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
mln/util/graph.hh
1 // Copyright (C) 2007, 2008, 2009, 2010 EPITA Research and Development
2 // 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 
52  template <>
53  struct data<util::graph>
54  {
55  typedef util::graph G;
56  typedef std::vector<std::vector<util::edge_id_t> > vertices_t;
57  typedef std::vector<util::ord_pair<util::vertex_id_t> > edges_t;
58  typedef std::set<util::ord_pair<util::vertex_id_t> > edges_set_t;
59 
60  data();
63  data(unsigned nvertices);
64  ~data();
65 
67  vertices_t vertices_;
69  edges_t edges_;
70 
71 # ifndef NDEBUG
72 
73  edges_set_t edges_set_;
74 # endif // ! NDEBUG
75  };
76 
77  } // end of namespace mln::internal
78 
79 
80  namespace util
81  {
82 
86  //
87  class graph : public internal::graph_base<graph>
88  {
90  typedef internal::graph_base<graph> super;
91 
92  typedef super::vertex_data_t vertex_data_t;
93  typedef super::edge_data_t edge_data_t;
94 
95  public:
97  typedef std::vector<vertex_data_t> vertices_t;
98 
100  typedef std::vector<edge_data_t> edges_t;
102  typedef std::set<edge_data_t> edges_set_t;
103 
108  typedef mln::internal::vertex_fwd_iterator<graph> vertex_fwd_iter;
109  typedef mln::internal::vertex_bkd_iterator<graph> vertex_bkd_iter;
110  typedef vertex_fwd_iter vertex_iter;
112 
115  typedef mln::internal::vertex_nbh_edge_fwd_iterator<graph> vertex_nbh_edge_fwd_iter;
116  typedef mln::internal::vertex_nbh_edge_bkd_iterator<graph> vertex_nbh_edge_bkd_iter;
117  typedef vertex_nbh_edge_fwd_iter vertex_nbh_edge_iter;
119 
122  typedef mln::internal::vertex_nbh_vertex_fwd_iterator<graph> vertex_nbh_vertex_fwd_iter;
123  typedef mln::internal::vertex_nbh_vertex_bkd_iterator<graph> vertex_nbh_vertex_bkd_iter;
124  typedef vertex_nbh_vertex_fwd_iter vertex_nbh_vertex_iter;
126 
129  typedef mln::internal::edge_fwd_iterator<graph> edge_fwd_iter;
130  typedef mln::internal::edge_bkd_iterator<graph> edge_bkd_iter;
131  typedef edge_fwd_iter edge_iter;
133 
136  typedef mln::internal::edge_nbh_edge_fwd_iterator<graph> edge_nbh_edge_fwd_iter;
137  typedef mln::internal::edge_nbh_edge_bkd_iterator<graph> edge_nbh_edge_bkd_iter;
138  typedef edge_nbh_edge_fwd_iter edge_nbh_edge_iter;
141 
143  graph();
145  graph(unsigned nvertices);
146 
149 
152 
156  unsigned add_vertex();
157 
161  std::pair<vertex_id_t, vertex_id_t> add_vertices(unsigned n);
162 
165  vertex_t vertex(vertex_id_t id_v) const;
167 
169  // FIXME: Rename as nvertices.
170  size_t v_nmax() const;
171 
173  // FIXME: Is the `_v' suffix really needed?
174  bool has_v(const vertex_id_t& id_v) const;
175 
176 
178  size_t v_nmax_nbh_edges(const vertex_id_t& id_v) const;
179 
181  edge_id_t
182  v_ith_nbh_edge(const vertex_id_t& id_v,
183  unsigned i) const;
184 
186  size_t v_nmax_nbh_vertices(const vertex_id_t& id_v) const;
187 
190  unsigned i) const;
192 
193 
194 
201  edge_id_t add_edge(const vertex_id_t& id_v1, const vertex_id_t& id_v2);
202 
204  edge_t edge(const edge_id_t& e) const;
205 
206 
208  const std::vector<util::ord_pair<vertex_id_t> >& edges() const;
209 
211  // FIXME: Rename as nedges.
212  size_t e_nmax() const;
213 
215  // FIXME: Is the `_e' suffix really needed?
216  bool has_e(const edge_id_t& id_e) const;
217 
220  edge_t edge(const vertex_t& v1, const vertex_t& v2) const;
221 
223  vertex_id_t v1(const edge_id_t& id_e) const;
224 
226  vertex_id_t v2(const edge_id_t& id_e) const;
227 
229  size_t e_nmax_nbh_edges(const edge_id_t& id_e) const;
230 
232  edge_id_t e_ith_nbh_edge(const edge_id_t& id_e, unsigned i) const;
233 
236  template <typename G2>
237  bool is_subgraph_of(const G2& g) const;
239 
240  };
241 
242  std::ostream&
243  operator<<(std::ostream& ostr, const graph& g);
244 
245  } // end of namespace mln::util
246 
247 } // end of namespace mln
248 
249 
250 
251 
252 # ifndef MLN_INCLUDE_ONLY
253 
254 namespace mln
255 {
256 
257  namespace internal
258  {
259 
260  inline
262  {
263  }
264 
265  inline
266  data<util::graph>::data(unsigned nvertices)
267  {
268  vertices_.resize(nvertices);
269  }
270 
271  inline
273  {
274  }
275 
276  } // end of namespace mln::internal
277 
278  namespace util
279  {
280 
281  inline
283  {
284  this->data_ = new mln::internal::data<util::graph>();
285  }
286 
287  inline
288  graph::graph(unsigned nvertices)
289  {
290  this->data_ = new mln::internal::data<util::graph>(nvertices);
291  }
292 
293  /*--------------------------.
294  | Vertex-related services. |
295  `--------------------------*/
296 
297  inline
298  unsigned
300  {
301  /* FIXME: This is not thread-proof (these two lines should
302  form an atomic section). */
303  data_->vertices_.resize(data_->vertices_.size() + 1);
304 
305  return v_nmax() - 1;
306  }
307 
308  inline
309  std::pair<vertex_id_t, vertex_id_t>
311  {
312  /* FIXME: This is not thread-proof (these two lines should
313  form an atomic section). */
314  data_->vertices_.resize(data_->vertices_.size() + n);
315 
316  return std::make_pair(v_nmax() - n,
317  v_nmax() - 1);
318  }
319 
320  inline
321  graph::vertex_t
323  {
324  mln_assertion(has_v(id_v));
325  return vertex_t(*this, id_v);
326  }
327 
328 
329  inline
330  size_t
332  {
333  return data_->vertices_.size();
334  }
335 
336  inline
337  bool
338  graph::has_v(const vertex_id_t& id_v) const
339  {
340  return id_v < data_->vertices_.size();
341  }
342 
343  inline
344  size_t
345  graph::v_nmax_nbh_edges(const vertex_id_t& id_v) const
346  {
347  mln_precondition(has_v(id_v));
348  return data_->vertices_[id_v].size();
349  }
350 
351  inline
352  edge_id_t
353  graph::v_ith_nbh_edge(const vertex_id_t& id_v, unsigned i) const
354  {
355  mln_precondition(has_v(id_v));
356  if (i >= v_nmax_nbh_edges(id_v))
357  return edge_id_t();
358  return data_->vertices_[id_v][i];
359  }
360 
361  inline
362  size_t
363  graph::v_nmax_nbh_vertices(const vertex_id_t& id_v) const
364  {
365  mln_precondition(has_v(id_v));
366  return v_nmax_nbh_edges(id_v);
367  }
368 
369  inline
371  graph::v_ith_nbh_vertex(const vertex_id_t& id_v, unsigned i) const
372  {
373  mln_precondition(has_v(id_v));
374 
375  edge_id_t id_e = v_ith_nbh_edge(id_v, i);
376  return v_other(id_e, id_v);
377  }
378 
379 
380  /*-------------------------.
381  | Edges-related services. |
382  `-------------------------*/
383 
384  inline
385  edge_id_t
386  graph::add_edge(const vertex_id_t& id_v1, const vertex_id_t& id_v2)
387  {
388  mln_precondition(id_v1 != id_v2);
389  mln_precondition(has_v(id_v1));
390  mln_precondition(has_v(id_v2));
391 
392  // Does this edge already exist in the graph?
393  edge_data_t edge(id_v1, id_v2);
394  /* FIXME: This is not sound: the behavior of the algorithm
395  changes when NDEBUG is defined. */
396 # ifndef NDEBUG
397  if (data_->edges_set_.find(edge) != data_->edges_set_.end ())
398  {
399  // Return the erroneous value.
400  return edge_id_t();
401  }
402  else
403  {
404 # endif // ! NDEBUG
405  // Otherwise insert it into the graph.
406  /* FIXME: This is not thread-proof (these two lines should
407  form an atomic section). */
408  data_->edges_.push_back(edge);
409  edge_id_t id = data_->edges_.size() - 1;
410 
411  // Update the set of edges.
412 # ifndef NDEBUG
413  data_->edges_set_.insert(edge);
414 # endif // ! NDEBUG
415  data_->vertices_[edge.first()].push_back(id);
416  data_->vertices_[edge.second()].push_back(id);
417 
418  return id;
419 
420 # ifndef NDEBUG
421  }
422 # endif // ! NDEBUG
423 
424  }
425 
426  inline
427  const std::vector<util::ord_pair<vertex_id_t> >&
428  graph::edges() const
429  {
430  return this->data_->edges_;
431  }
432 
433  inline
434  graph::edge_t
435  graph::edge(const edge_id_t& e) const
436  {
437  mln_assertion(e < e_nmax());
438  return edge_t(*this, e);
439  }
440 
441  inline
442  size_t
444  {
445  return data_->edges_.size();
446  }
447 
448  inline
449  bool
450  graph::has_e(const edge_id_t& id_e) const
451  {
452  return id_e < data_->edges_.size();
453  }
454 
455  inline
456  graph::edge_t
457  graph::edge(const vertex_t& v1, const vertex_t& v2) const
458  {
459  mln_precondition(has_v(v1));
460  mln_precondition(has_v(v2));
461 
463  id_v1 = v1.id(),
464  id_v2 = v2.id();
465 
466  if (id_v1 > id_v2)
467  std::swap(id_v1, id_v2);
468 
469  for (unsigned i = 0; i < data_->vertices_[id_v1].size(); ++i)
470  if (data_->edges_[data_->vertices_[id_v1][i]].second() == id_v2)
471  return edge_t(*this, data_->vertices_[id_v1][i]);
472 
473  // Not edges available. Return an invalid edge.
474  return edge_t();
475  }
476 
477  inline
479  graph::v1(const edge_id_t& id_e) const
480  {
481  mln_precondition(has_e(id_e));
482  return data_->edges_[id_e].first();
483  }
484 
485  inline
487  graph::v2(const edge_id_t& id_e) const
488  {
489  mln_precondition(has_e(id_e));
490  return data_->edges_[id_e].second();
491  }
492 
493  inline
494  size_t
495  graph::e_nmax_nbh_edges(const edge_id_t& id_e) const
496  {
497  mln_precondition(has_e(id_e));
498  return v_nmax_nbh_edges(v1(id_e)) + v_nmax_nbh_edges(v2(id_e));
499  }
500 
501  inline
502  edge_id_t
503  graph::e_ith_nbh_edge(const edge_id_t& id_e, unsigned i) const
504  {
505  mln_precondition(has_e(id_e));
506  if (i >= e_nmax_nbh_edges(id_e))
507  return e_nmax();
508 
509  unsigned v1_nmax = v_nmax_nbh_edges(v1(id_e));
510  if (i < v1_nmax)
511  return v_ith_nbh_edge(v1(id_e), i);
512  return v_ith_nbh_edge(v2(id_e), i - v1_nmax);
513  }
514 
515 
516  template <typename G2>
517  inline
518  bool
519  graph::is_subgraph_of(const G2& g) const
520  {
521  return g.id() == this->id();
522  }
523 
524  // FIXME: move to graph_Base.
525  inline
526  std::ostream&
527  operator<<(std::ostream& ostr, const graph& g)
528  {
529  mln_vertex_iter_(graph) v(g);
530  mln_vertex_nbh_edge_iter_(graph) e(v);
531  for_all(v)
532  {
533  ostr << "v(" << v << ") : ";
534  for_all(e)
535  ostr << e << " ";
536  ostr << std::endl;
537  }
538 
539  return ostr;
540  }
541 
542  } // end of namespace mln::util
543 
544 } // end of namespace mln
545 
546 # endif // ! MLN_INCLUDE_ONLY
547 
548 
549 #endif // ! MLN_UTIL_GRAPH_HH