• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

graph.hh

00001 // Copyright (C) 2007, 2008, 2009, 2010 EPITA Research and Development
00002 // Laboratory (LRDE)
00003 //
00004 // This file is part of Olena.
00005 //
00006 // Olena is free software: you can redistribute it and/or modify it under
00007 // the terms of the GNU General Public License as published by the Free
00008 // Software Foundation, version 2 of the License.
00009 //
00010 // Olena is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software project without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to produce
00022 // an executable, this file does not by itself cause the resulting
00023 // executable to be covered by the GNU General Public License.  This
00024 // exception does not however invalidate any other reasons why the
00025 // executable file might be covered by the GNU General Public License.
00026 
00027 #ifndef MLN_UTIL_GRAPH_HH
00028 # define MLN_UTIL_GRAPH_HH
00029 
00033 
00034 # include <mln/util/internal/graph_base.hh>
00035 # include <mln/util/internal/graph_iter.hh>
00036 # include <mln/util/internal/graph_nbh_iter.hh>
00037 # include <mln/util/vertex.hh>
00038 # include <mln/util/edge.hh>
00039 # include <mln/util/ord_pair.hh>
00040 
00041 namespace mln
00042 {
00043 
00045   namespace util { class graph; }
00046 
00047 
00048   namespace internal
00049   {
00050 
00052     template <>
00053     struct data<util::graph>
00054     {
00055       typedef util::graph G;
00056       typedef std::vector<std::vector<util::edge_id_t> > vertices_t;
00057       typedef std::vector<util::ord_pair<util::vertex_id_t> > edges_t;
00058       typedef std::set<util::ord_pair<util::vertex_id_t> > edges_set_t;
00059 
00060       data();
00063       data(unsigned nvertices);
00064       ~data();
00065 
00067       vertices_t vertices_;
00069       edges_t edges_;
00070 
00071 # ifndef NDEBUG
00072 
00073       edges_set_t edges_set_;
00074 # endif // ! NDEBUG
00075     };
00076 
00077   } // end of namespace mln::internal
00078 
00079 
00080   namespace util
00081   {
00082 
00086     //
00087     class graph : public internal::graph_base<graph>
00088     {
00090       typedef internal::graph_base<graph> super;
00091 
00092       typedef super::vertex_data_t vertex_data_t;
00093       typedef super::edge_data_t edge_data_t;
00094 
00095     public:
00097       typedef std::vector<vertex_data_t> vertices_t;
00098 
00100       typedef std::vector<edge_data_t> edges_t;
00102       typedef std::set<edge_data_t> edges_set_t;
00103 
00108       typedef mln::internal::vertex_fwd_iterator<graph> vertex_fwd_iter;
00109       typedef mln::internal::vertex_bkd_iterator<graph> vertex_bkd_iter;
00110       typedef vertex_fwd_iter vertex_iter;
00112 
00115       typedef mln::internal::vertex_nbh_edge_fwd_iterator<graph> vertex_nbh_edge_fwd_iter;
00116       typedef mln::internal::vertex_nbh_edge_bkd_iterator<graph> vertex_nbh_edge_bkd_iter;
00117       typedef vertex_nbh_edge_fwd_iter vertex_nbh_edge_iter;
00119 
00122       typedef mln::internal::vertex_nbh_vertex_fwd_iterator<graph> vertex_nbh_vertex_fwd_iter;
00123       typedef mln::internal::vertex_nbh_vertex_bkd_iterator<graph> vertex_nbh_vertex_bkd_iter;
00124       typedef vertex_nbh_vertex_fwd_iter vertex_nbh_vertex_iter;
00126 
00129       typedef mln::internal::edge_fwd_iterator<graph> edge_fwd_iter;
00130       typedef mln::internal::edge_bkd_iterator<graph> edge_bkd_iter;
00131       typedef edge_fwd_iter edge_iter;
00133 
00136       typedef mln::internal::edge_nbh_edge_fwd_iterator<graph> edge_nbh_edge_fwd_iter;
00137       typedef mln::internal::edge_nbh_edge_bkd_iterator<graph> edge_nbh_edge_bkd_iter;
00138       typedef edge_nbh_edge_fwd_iter edge_nbh_edge_iter;
00141 
00143       graph();
00145       graph(unsigned nvertices);
00146 
00149 
00152 
00156       unsigned add_vertex();
00157 
00161       std::pair<vertex_id_t, vertex_id_t> add_vertices(unsigned n);
00162 
00165       vertex_t vertex(vertex_id_t id_v) const;
00167 
00169       // FIXME: Rename as nvertices.
00170       size_t v_nmax() const;
00171 
00173       // FIXME: Is the `_v' suffix really needed?
00174       bool has_v(const vertex_id_t& id_v) const;
00175 
00176 
00178       size_t v_nmax_nbh_edges(const vertex_id_t& id_v) const;
00179 
00181       edge_id_t
00182       v_ith_nbh_edge(const vertex_id_t& id_v,
00183                      unsigned i) const;
00184 
00186       size_t v_nmax_nbh_vertices(const vertex_id_t& id_v) const;
00187 
00189       vertex_id_t v_ith_nbh_vertex(const vertex_id_t& id_v,
00190                                    unsigned i) const;
00192 
00193 
00194 
00201       edge_id_t add_edge(const vertex_id_t& id_v1, const vertex_id_t& id_v2);
00202 
00204       edge_t edge(const edge_id_t& e) const;
00205 
00206 
00208       const std::vector<util::ord_pair<vertex_id_t> >& edges() const;
00209 
00211       // FIXME: Rename as nedges.
00212       size_t e_nmax() const;
00213 
00215       // FIXME: Is the `_e' suffix really needed?
00216       bool has_e(const edge_id_t& id_e) const;
00217 
00220       edge_t edge(const vertex_t& v1, const vertex_t& v2) const;
00221 
00223       vertex_id_t v1(const edge_id_t& id_e) const;
00224 
00226       vertex_id_t v2(const edge_id_t& id_e) const;
00227 
00229       size_t e_nmax_nbh_edges(const edge_id_t& id_e) const;
00230 
00232       edge_id_t e_ith_nbh_edge(const edge_id_t& id_e, unsigned i) const;
00233 
00236       template <typename G2>
00237       bool is_subgraph_of(const G2& g) const;
00239 
00240     };
00241 
00242     std::ostream&
00243     operator<<(std::ostream& ostr, const graph& g);
00244 
00245   } // end of namespace mln::util
00246 
00247 } // end of namespace mln
00248 
00249 
00250 
00251 
00252 # ifndef MLN_INCLUDE_ONLY
00253 
00254 namespace mln
00255 {
00256 
00257   namespace internal
00258   {
00259 
00260     inline
00261     data<util::graph>::data()
00262     {
00263     }
00264 
00265     inline
00266     data<util::graph>::data(unsigned nvertices)
00267     {
00268       vertices_.resize(nvertices);
00269     }
00270 
00271     inline
00272     data<util::graph>::~data()
00273     {
00274     }
00275 
00276   } // end of namespace mln::internal
00277 
00278   namespace util
00279   {
00280 
00281     inline
00282     graph::graph()
00283     {
00284       this->data_ = new mln::internal::data<util::graph>();
00285     }
00286 
00287     inline
00288     graph::graph(unsigned nvertices)
00289     {
00290       this->data_ = new mln::internal::data<util::graph>(nvertices);
00291     }
00292 
00293     /*--------------------------.
00294     | Vertex-related services.  |
00295     `--------------------------*/
00296 
00297     inline
00298     unsigned
00299     graph::add_vertex()
00300     {
00301       /* FIXME: This is not thread-proof (these two lines should
00302          form an atomic section).  */
00303       data_->vertices_.resize(data_->vertices_.size() + 1);
00304 
00305       return v_nmax() - 1;
00306     }
00307 
00308     inline
00309     std::pair<vertex_id_t, vertex_id_t>
00310     graph::add_vertices(unsigned n)
00311     {
00312       /* FIXME: This is not thread-proof (these two lines should
00313          form an atomic section).  */
00314       data_->vertices_.resize(data_->vertices_.size() + n);
00315 
00316       return std::make_pair(v_nmax() - n,
00317                             v_nmax() - 1);
00318     }
00319 
00320     inline
00321     graph::vertex_t
00322     graph::vertex(vertex_id_t id_v) const
00323     {
00324       mln_assertion(has_v(id_v));
00325       return vertex_t(*this, id_v);
00326     }
00327 
00328 
00329     inline
00330     size_t
00331     graph::v_nmax() const
00332     {
00333       return data_->vertices_.size();
00334     }
00335 
00336     inline
00337     bool
00338     graph::has_v(const vertex_id_t& id_v) const
00339     {
00340       return id_v < data_->vertices_.size();
00341     }
00342 
00343     inline
00344     size_t
00345     graph::v_nmax_nbh_edges(const vertex_id_t& id_v) const
00346     {
00347       mln_precondition(has_v(id_v));
00348       return data_->vertices_[id_v].size();
00349     }
00350 
00351     inline
00352     edge_id_t
00353     graph::v_ith_nbh_edge(const vertex_id_t& id_v, unsigned i) const
00354     {
00355       mln_precondition(has_v(id_v));
00356       if (i >= v_nmax_nbh_edges(id_v))
00357         return edge_id_t();
00358       return data_->vertices_[id_v][i];
00359     }
00360 
00361     inline
00362     size_t
00363     graph::v_nmax_nbh_vertices(const vertex_id_t& id_v) const
00364     {
00365       mln_precondition(has_v(id_v));
00366       return v_nmax_nbh_edges(id_v);
00367     }
00368 
00369     inline
00370     vertex_id_t
00371     graph::v_ith_nbh_vertex(const vertex_id_t& id_v, unsigned i) const
00372     {
00373       mln_precondition(has_v(id_v));
00374 
00375       edge_id_t id_e = v_ith_nbh_edge(id_v, i);
00376       return v_other(id_e, id_v);
00377     }
00378 
00379 
00380     /*-------------------------.
00381     | Edges-related services.  |
00382     `-------------------------*/
00383 
00384     inline
00385     edge_id_t
00386     graph::add_edge(const vertex_id_t& id_v1, const vertex_id_t& id_v2)
00387     {
00388       mln_precondition(id_v1 != id_v2);
00389       mln_precondition(has_v(id_v1));
00390       mln_precondition(has_v(id_v2));
00391 
00392       // Does this edge already exist in the graph?
00393       edge_data_t edge(id_v1, id_v2);
00394       /* FIXME: This is not sound: the behavior of the algorithm
00395          changes when NDEBUG is defined.  */
00396 # ifndef NDEBUG
00397       if (data_->edges_set_.find(edge) != data_->edges_set_.end ())
00398         {
00399           // Return the erroneous value.
00400           return edge_id_t();
00401         }
00402       else
00403         {
00404 # endif // ! NDEBUG
00405           // Otherwise insert it into the graph.
00406           /* FIXME: This is not thread-proof (these two lines should
00407              form an atomic section).  */
00408           data_->edges_.push_back(edge);
00409           edge_id_t id = data_->edges_.size() - 1;
00410 
00411           // Update the set of edges.
00412 # ifndef NDEBUG
00413           data_->edges_set_.insert(edge);
00414 # endif // ! NDEBUG
00415           data_->vertices_[edge.first()].push_back(id);
00416           data_->vertices_[edge.second()].push_back(id);
00417 
00418           return id;
00419 
00420 # ifndef NDEBUG
00421         }
00422 # endif // ! NDEBUG
00423 
00424     }
00425 
00426     inline
00427     const std::vector<util::ord_pair<vertex_id_t> >&
00428     graph::edges() const
00429     {
00430       return this->data_->edges_;
00431     }
00432 
00433     inline
00434     graph::edge_t
00435     graph::edge(const edge_id_t& e) const
00436     {
00437       mln_assertion(e < e_nmax());
00438       return edge_t(*this, e);
00439     }
00440 
00441     inline
00442     size_t
00443     graph::e_nmax() const
00444     {
00445       return data_->edges_.size();
00446     }
00447 
00448     inline
00449     bool
00450     graph::has_e(const edge_id_t& id_e) const
00451     {
00452       return id_e < data_->edges_.size();
00453     }
00454 
00455     inline
00456     graph::edge_t
00457     graph::edge(const vertex_t& v1, const vertex_t& v2) const
00458     {
00459       mln_precondition(has_v(v1));
00460       mln_precondition(has_v(v2));
00461 
00462       vertex_id_t
00463         id_v1 = v1.id(),
00464         id_v2 = v2.id();
00465 
00466       if (id_v1 > id_v2)
00467         std::swap(id_v1, id_v2);
00468 
00469       for (unsigned i = 0; i < data_->vertices_[id_v1].size(); ++i)
00470         if (data_->edges_[data_->vertices_[id_v1][i]].second() == id_v2)
00471           return edge_t(*this, data_->vertices_[id_v1][i]);
00472 
00473       // Not edges available. Return an invalid edge.
00474       return edge_t();
00475     }
00476 
00477     inline
00478     vertex_id_t
00479     graph::v1(const edge_id_t& id_e) const
00480     {
00481       mln_precondition(has_e(id_e));
00482       return data_->edges_[id_e].first();
00483     }
00484 
00485     inline
00486     vertex_id_t
00487     graph::v2(const edge_id_t& id_e) const
00488     {
00489       mln_precondition(has_e(id_e));
00490       return data_->edges_[id_e].second();
00491     }
00492 
00493     inline
00494     size_t
00495     graph::e_nmax_nbh_edges(const edge_id_t& id_e) const
00496     {
00497       mln_precondition(has_e(id_e));
00498       return v_nmax_nbh_edges(v1(id_e)) + v_nmax_nbh_edges(v2(id_e));
00499     }
00500 
00501     inline
00502     edge_id_t
00503     graph::e_ith_nbh_edge(const edge_id_t& id_e, unsigned i) const
00504     {
00505       mln_precondition(has_e(id_e));
00506       if (i >= e_nmax_nbh_edges(id_e))
00507         return e_nmax();
00508 
00509       unsigned v1_nmax = v_nmax_nbh_edges(v1(id_e));
00510       if (i < v1_nmax)
00511         return v_ith_nbh_edge(v1(id_e), i);
00512       return  v_ith_nbh_edge(v2(id_e), i - v1_nmax);
00513     }
00514 
00515 
00516     template <typename G2>
00517     inline
00518     bool
00519     graph::is_subgraph_of(const G2& g) const
00520     {
00521       return g.id() == this->id();
00522     }
00523 
00524     // FIXME: move to graph_Base.
00525     inline
00526     std::ostream&
00527     operator<<(std::ostream& ostr, const graph& g)
00528     {
00529       mln_vertex_iter_(graph) v(g);
00530       mln_vertex_nbh_edge_iter_(graph) e(v);
00531       for_all(v)
00532       {
00533         ostr << "v(" << v << ") : ";
00534         for_all(e)
00535           ostr << e << " ";
00536         ostr << std::endl;
00537       }
00538 
00539       return ostr;
00540     }
00541 
00542   } // end of namespace mln::util
00543 
00544 } // end of namespace mln
00545 
00546 # endif // ! MLN_INCLUDE_ONLY
00547 
00548 
00549 #endif // ! MLN_UTIL_GRAPH_HH

Generated on Tue Oct 4 2011 15:23:49 for Milena (Olena) by  doxygen 1.7.1