graph.hxx

00001 // graph.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2005, 2006 The Vaucanson Group.
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // The complete GNU General Public Licence Notice can be found as the
00013 // `COPYING' file in the root directory.
00014 //
00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00016 //
00017 #ifndef VCSN_AUTOMATA_IMPLEMENTATION_GRAPH_HXX
00018 # define VCSN_AUTOMATA_IMPLEMENTATION_GRAPH_HXX
00019 
00020 # include <fstream>
00021 # include <sstream>
00022 
00023 # include <algorithm>
00024 # include <utility>
00025 
00026 # include <vaucanson/automata/implementation/graph.hh>
00027 # include <vaucanson/misc/contract.hh>
00028 
00029 
00030 namespace vcsn
00031 {
00032 
00033   /*---------------------------.
00034   | Decorators' implementation |
00035   `---------------------------*/
00036 
00037   template<typename EdgeLabel>
00038   edge_value<EdgeLabel>::edge_value(hstate_t h1,
00039                                     hstate_t h2,
00040                                     const EdgeLabel& l) :
00041     label(l),
00042     from(h1),
00043     to(h2)
00044   {}
00045 
00046   inline
00047   state_value::state_value()
00048   {}
00049 
00050 
00051   /*------------------.
00052   | Convenient macros |
00053   `------------------*/
00054 
00055 # define TParam                                                         \
00056   template <class Kind, class WordValue, class WeightValue,             \
00057             class SeriesValue, class Letter, class Tag, class Geometry>
00058 
00059 # define GClass                                                         \
00060   Graph<Kind, WordValue, WeightValue, SeriesValue, Letter, Tag, Geometry>
00061 
00062 
00063   /*-----------------------.
00064   | Graph's implementation |
00065   `-----------------------*/
00066 
00067   /*-------------.
00068   | Constructors |
00069   `-------------*/
00070 
00071   TParam
00072   GClass::Graph()
00073   { }
00074 
00075   TParam
00076   GClass::Graph
00077   (unsigned initial_number_of_state,
00078    unsigned reserve_number_of_edge)
00079   {
00080     states_.resize(initial_number_of_state);
00081     edges_.reserve(reserve_number_of_edge);
00082   }
00083 
00084 
00085   /*----------------.
00086   | Basic accessors |
00087   `----------------*/
00088 
00089   TParam
00090   typename GClass::states_t
00091   GClass::states() const
00092   {
00093     return states_t(hstate_t(0),
00094                     hstate_t(states_.size()) - 1,
00095                     removed_states_);
00096   }
00097 
00098   TParam
00099   typename GClass::edges_t
00100   GClass::edges() const
00101   {
00102     return edges_t(hedge_t(0),
00103                    hedge_t(edges_.size()) - 1,
00104                    removed_edges_);
00105   }
00106 
00107   TParam
00108   typename GClass::initial_support_t
00109   GClass::initial() const
00110   {
00111     return initial_support_t(initial_);
00112   }
00113 
00114   TParam
00115   typename GClass::final_support_t
00116   GClass::final() const
00117   {
00118     return final_support_t(final_);
00119   }
00120 
00121   /*---------------------.
00122   | State's manipulation |
00123   `---------------------*/
00124 
00125   TParam
00126   bool
00127   GClass::has_state(hstate_t n) const
00128   {
00129     bool res = ((removed_states_.find(n) == removed_states_.end())
00130                 && n >= 0
00131                 && n < int(states_.size()));
00132 # ifndef VCSN_NDEBUG
00133     if (res == false)
00134       for (int i = 0; i < int(edges_.size()); ++i)
00135         if (removed_edges_.find(hedge_t(i)) == removed_edges_.end())
00136           postcondition(edges_[i].from != n
00137                         && edges_[i].to != n);
00138 # endif // !VCSN_NDEBUG
00139     return res;
00140   }
00141 
00142   TParam
00143   hstate_t
00144   GClass::add_state()
00145   {
00146     if (removed_states_.size() == 0)
00147     {
00148       states_.push_back(state_value_t());
00149       return states_.size() - 1;
00150     }
00151 
00152     hstate_t n = *removed_states_.begin();
00153     removed_states_.erase(n);
00154     assertion(n < int(states_.size()));
00155 
00156     states_[n].output_edges.clear();
00157     states_[n].input_edges.clear();
00158 
00159     postcondition(has_state(n));
00160     return n;
00161   }
00162 
00163   TParam
00164   void
00165   GClass::del_state(hstate_t n)
00166   {
00167     if (!has_state(n))
00168       return;
00169 
00170     const state_value_t& v = states_[n];
00171     state_value::edges_t::const_iterator e = v.output_edges.begin();
00172     state_value::edges_t::const_iterator end = v.output_edges.end();
00173     state_value::edges_t::const_iterator next = e;
00174 
00175     for (; e != end; e = next)
00176     {
00177       ++next;
00178       this->del_edge(*e);
00179     }
00180 
00181     e = v.input_edges.begin();
00182     end = v.input_edges.end();
00183     for (next = e; e != end; e = next)
00184     {
00185       ++next;
00186       this->del_edge(*e);
00187     }
00188 
00189     removed_states_.insert(n);
00190     initial_.erase(n);
00191     final_.erase(n);
00192     postcondition(!has_state(n));
00193   }
00194 
00195   TParam
00196   void
00197   GClass::set_initial(hstate_t n, const series_set_elt_value_t& v,
00198                       const series_set_elt_value_t& z)
00199   {
00200     if (z == v)
00201       initial_.erase(n);
00202     else
00203       initial_[n] = v;
00204   }
00205 
00206   TParam
00207   const typename GClass::series_set_elt_value_t&
00208   GClass::get_initial(hstate_t n, const series_set_elt_value_t& z) const
00209   {
00210     typename initial_t::const_iterator i = initial_.find(n);
00211     if (i == initial_.end())
00212       return z;
00213     return i->second;
00214   }
00215 
00216   TParam
00217   void
00218   GClass::clear_initial()
00219   {
00220     return initial_.clear();
00221   }
00222 
00223   TParam
00224   void
00225   GClass::set_final(hstate_t n, const series_set_elt_value_t& v,
00226                     const series_set_elt_value_t& z)
00227   {
00228     if (v == z)
00229       final_.erase(n);
00230     else
00231       final_[n] = v;
00232   }
00233 
00234   TParam
00235   const typename GClass::series_set_elt_value_t&
00236   GClass::get_final(hstate_t n, const series_set_elt_value_t& z) const
00237   {
00238     typename final_t::const_iterator i = final_.find(n);
00239     if (i == final_.end())
00240       return z;
00241     return i->second;
00242   }
00243 
00244   TParam
00245   void
00246   GClass::clear_final()
00247   {
00248     return final_.clear();
00249   }
00250 
00251 
00252   /*--------------------.
00253   | Edge's manipulation |
00254   `--------------------*/
00255 
00256   TParam
00257   bool
00258   GClass::has_edge(hedge_t e) const
00259   {
00260     bool res = (removed_edges_.find(e) == removed_edges_.end()
00261                 && (e < int(edges_.size())));
00262 # ifndef VCSN_NDEBUG
00263     if (res == false)
00264       for (int i = 0; i < int(states_.size()); ++i)
00265         if (removed_states_.find(hstate_t(i)) == removed_states_.end())
00266           postcondition(states_[i].output_edges.find(e) ==
00267                         states_[i].output_edges.end());
00268 # endif // !VCSN_NDEBUG
00269     return res;
00270   }
00271 
00272   TParam
00273   hedge_t
00274   GClass::add_edge(hstate_t n1, hstate_t n2,
00275                    const label_t& v)
00276   {
00277     precondition(has_state(n1));
00278     precondition(has_state(n2));
00279     hedge_t e;
00280     if (removed_edges_.size() == 0)
00281     {
00282       edges_.push_back(edge_value_t(n1, n2, v));
00283       e = edges_.size() - 1;
00284     }
00285     else
00286     {
00287       e = *removed_edges_.begin();
00288       removed_edges_.erase(e);
00289       assertion(e < int(edges_.size()));
00290       edges_[e].from = n1;
00291       edges_[e].to = n2;
00292       edges_[e].label = v;
00293     }
00294     states_[n1].output_edges.insert(e);
00295     states_[n2].input_edges.insert(e);
00296 
00297     postcondition(has_edge(e));
00298     return e;
00299   }
00300 
00301   TParam
00302   void
00303   GClass::del_edge(hedge_t e)
00304   {
00305     if (!has_edge(e))
00306       return;
00307 
00308     const edge_value_t& ev = edges_[e];
00309     states_[ev.from].output_edges.erase(e);
00310     states_[ev.to].input_edges.erase(e);
00311     removed_edges_.insert(e);
00312 
00313     postcondition(!has_edge(e));
00314   }
00315 
00316 
00317   TParam
00318   hstate_t
00319   GClass::src_of(hedge_t e1) const
00320   {
00321     precondition(has_edge(e1));
00322     return edges_[e1].from;
00323   }
00324 
00325   TParam
00326   hstate_t
00327   GClass::dst_of(hedge_t e2) const
00328   {
00329     precondition(has_edge(e2));
00330     return edges_[e2].to;
00331   }
00332 
00333   TParam
00334   const typename GClass::label_t&
00335   GClass::label_of(hedge_t n) const
00336   {
00337     precondition(has_edge(n));
00338     return edges_[n];
00339   }
00340 
00341   TParam
00342   void
00343   GClass::update(hedge_t e, label_t l)
00344   {
00345     precondition(has_edge(e));
00346     edges_[e].label = l;
00347   }
00348 
00349 
00351   TParam
00352   template <class S>
00353   bool
00354   GClass::exists(const AutomataBase<S>& s) const
00355   {
00356     typename WordValue::iterator        it;
00357     typename label_t::const_iterator    r;
00358     label_t                             l;
00359     WordValue                           w;
00360 
00361     for (int i = 0; i < int(edges_.size()); ++i)
00362     {
00363       if (removed_edges_.find(hedge_t(i)) != removed_edges_.end())
00364         continue;
00365       // Make sure that origin and aim of edge are part of the automaton.
00366       if (!has_state(dst_of(hedge_t(i))) ||
00367           !has_state(src_of(hedge_t(i))))
00368         return false;
00369 
00370       // Make sure that every letter of the edge is in the alphabet.
00371       l = label_of(hedge_t(i));
00372       for (r = l.begin(); r != l.end(); ++r)
00373       {
00374         w = r->first;
00375         for (it = w.begin(); it != w.end(); ++it)
00376           if (!s.series().monoid().alphabet().contains(*it))
00377             return false;
00378       }
00379     }
00380     return true;
00381   }
00382 
00383   /*----------------.
00384   | Delta functions |
00385   `----------------*/
00386 
00387   TParam
00388   template <class OutputIterator, class Query>
00389   void
00390   GClass::delta(OutputIterator res,
00391                 hstate_t from,
00392                 const Query& q,
00393                 delta_kind::edges) const
00394   {
00395     assertion(has_state(from));
00396     const std::set<hedge_t>& edges = states_[from].output_edges;
00397     for_each_const_(std::set<hedge_t>, e, edges)
00398       if (q(*e))
00399         *res++ = *e;
00400   }
00401 
00402   TParam
00403   template <class OutputIterator, class Query>
00404   void
00405   GClass::delta(OutputIterator res,
00406                 hstate_t from,
00407                 const Query& query,
00408                 delta_kind::states) const
00409   {
00410     assertion(has_state(from));
00411     const std::set<hedge_t>& edges = states_[from].output_edges;
00412     for_each_const_(std::set<hedge_t>, e, edges)
00413       if (query(*e))
00414         *res++ = edges_[*e].to;
00415   }
00416 
00417   TParam
00418   template <class OutputIterator, class Query>
00419   void
00420   GClass::rdelta(OutputIterator res,
00421                  hstate_t from,
00422                  const Query& q,
00423                  delta_kind::edges) const
00424   {
00425     assertion(has_state(from));
00426     const std::set<hedge_t>& edges = states_[from].input_edges;
00427     for_each_const_(std::set<hedge_t>, e, edges)
00428       if (q(*e))
00429         *res++ = *e;
00430   }
00431 
00432   TParam
00433   template <class OutputIterator, class Query>
00434   void
00435   GClass::rdelta(OutputIterator res,
00436                  hstate_t from,
00437                  const Query& q,
00438                  delta_kind::states) const
00439   {
00440     assertion(has_state(from));
00441     const state_value_t::edges_t& edges =
00442       states_[from].input_edges;
00443     for_each_const_(std::set<hedge_t>, e, edges)
00444       if (q(*e))
00445         *res++ = edges_[*e].from;
00446   }
00447 
00448   template <class S,
00449             class Kind,
00450             class WordValue,
00451             class WeightValue,
00452             class SeriesValue,
00453             class Letter,
00454             class Tag,
00455             class Geometry,
00456             typename  OutputIterator,
00457             typename L>
00458   void op_rdelta(const AutomataBase<S>&,
00459                  const GClass& v,
00460                  OutputIterator res,
00461                  hstate_t from,
00462                  const L& query,
00463                  delta_kind::states k)
00464   {
00465     v.rdelta(res, from, query, k);
00466   }
00467 
00468   template <class S, class WordValue, class WeightValue, class SeriesValue,
00469             class Letter, class Tag, class Geometry,
00470             typename OutputIterator, typename L>
00471   void op_letter_delta(const AutomataBase<S>&,
00472                        const Graph<labels_are_letters,
00473                        WordValue, WeightValue,
00474                        SeriesValue, Letter, Tag, Geometry>& v,
00475                        OutputIterator res,
00476                        hstate_t from,
00477                        const L& letter,
00478                        delta_kind::states)
00479   {
00480     typedef typename state_value::edges_t edges_t;
00481     const edges_t& edges = v.states_[from].output_edges;
00482     for_each_const_(edges_t, e, edges)
00483       if (v.edges_[*e].label == letter)
00484         *res++ = v.edges_[*e].to;
00485   }
00486 
00487 
00488   /*----.
00489   | Tag |
00490   `----*/
00491 
00492   TParam
00493   inline
00494   Tag& GClass::tag()
00495   {
00496     return tag_;
00497   }
00498 
00499   TParam
00500   const Tag& GClass::tag() const
00501   {
00502     return tag_;
00503   }
00504 
00505   template <class Kind, class WordValue, class WeightValue, class SerieValue,
00506             class Letter, class Tag, class Geometry, class I>
00507   Tag& op_tag(const AutomataBase<I>&,
00508               Graph<Kind, WordValue, WeightValue,
00509               SerieValue ,Letter, Tag, Geometry>& v)
00510   {
00511     return v.tag();
00512   }
00513 
00514   template <class Kind, class WordValue, class WeightValue, class SerieValue,
00515             class Letter, class Tag, class Geometry, class I>
00516   const Tag& op_tag(const AutomataBase<I>&,
00517                     const Graph<Kind, WordValue, WeightValue,
00518                     SerieValue ,Letter, Tag, Geometry>& v)
00519   {
00520     return v.tag();
00521   }
00522 
00523 
00524   /*---------.
00525   | Geometry |
00526   `---------*/
00527 
00528   template <class Kind, class WordValue, class WeightValue, class SerieValue,
00529             class Letter, class Tag, class Geometry, class I>
00530   Geometry&
00531   op_geometry(const AutomataBase<I>&,
00532               Graph<Kind, WordValue, WeightValue,
00533               SerieValue, Letter, Tag, Geometry>& v)
00534   {
00535     return v.geometry();
00536   }
00537 
00538   template <class Kind, class WordValue, class WeightValue, class SerieValue,
00539             class Letter, class Tag, class Geometry, class I>
00540   const Geometry&
00541   op_geometry(const AutomataBase<I>&,
00542               const Graph<Kind, WordValue, WeightValue,
00543               SerieValue, Letter, Tag, Geometry>& v)
00544   {
00545     return v.geometry();
00546   }
00547 
00548 
00549   TParam
00550   const Geometry&
00551   GClass::geometry() const
00552   {
00553     return geometry_;
00554   }
00555 
00556   TParam
00557   Geometry&
00558   GClass::geometry()
00559   {
00560     return geometry_;
00561   }
00562 
00563 
00564   // Remove macros to avoid name clashes.
00565 #undef TParam
00566 #undef GClass
00567 
00568 }
00569 
00570 #endif // ! VCSN_AUTOMATA_IMPLEMENTATION_GRAPH_HXX

Generated on Fri Jul 28 12:18:34 2006 for Vaucanson by  doxygen 1.4.6