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

graph.hh

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

Generated on Thu Sep 8 2011 18:31:52 for Milena (Olena) by  doxygen 1.7.1