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 # include <vaucanson/misc/static.hh>
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     precondition (has_state(n));
00168 
00169     const state_value_t& v = states_[n];
00170     state_value::edges_t::const_iterator e = v.output_edges.begin();
00171     state_value::edges_t::const_iterator end = v.output_edges.end();
00172     state_value::edges_t::const_iterator next = e;
00173 
00174     for (; e != end; e = next)
00175     {
00176       ++next;
00177       this->del_edge(*e);
00178     }
00179 
00180     e = v.input_edges.begin();
00181     end = v.input_edges.end();
00182     for (next = e; e != end; e = next)
00183     {
00184       ++next;
00185       this->del_edge(*e);
00186     }
00187 
00188     removed_states_.insert(n);
00189     initial_.erase(n);
00190     final_.erase(n);
00191     postcondition(!has_state(n));
00192   }
00193 
00194   TParam
00195   void
00196   GClass::set_initial(hstate_t n, const series_set_elt_value_t& v,
00197                       const series_set_elt_value_t& z)
00198   {
00199     if (z == v)
00200       initial_.erase(n);
00201     else
00202       initial_[n] = v;
00203   }
00204 
00205   TParam
00206   const typename GClass::series_set_elt_value_t&
00207   GClass::get_initial(hstate_t n, const series_set_elt_value_t& z) const
00208   {
00209     typename initial_t::const_iterator i = initial_.find(n);
00210     if (i == initial_.end())
00211       return z;
00212     return i->second;
00213   }
00214 
00215   TParam
00216   void
00217   GClass::clear_initial()
00218   {
00219     return initial_.clear();
00220   }
00221 
00222   TParam
00223   void
00224   GClass::set_final(hstate_t n, const series_set_elt_value_t& v,
00225                     const series_set_elt_value_t& z)
00226   {
00227     if (v == z)
00228       final_.erase(n);
00229     else
00230       final_[n] = v;
00231   }
00232 
00233   TParam
00234   const typename GClass::series_set_elt_value_t&
00235   GClass::get_final(hstate_t n, const series_set_elt_value_t& z) const
00236   {
00237     typename final_t::const_iterator i = final_.find(n);
00238     if (i == final_.end())
00239       return z;
00240     return i->second;
00241   }
00242 
00243   TParam
00244   void
00245   GClass::clear_final()
00246   {
00247     return final_.clear();
00248   }
00249 
00250 
00251   /*--------------------.
00252   | Edge's manipulation |
00253   `--------------------*/
00254 
00255   TParam
00256   bool
00257   GClass::has_edge(hedge_t e) const
00258   {
00259     bool res = (removed_edges_.find(e) == removed_edges_.end()
00260                 && (e < int(edges_.size())));
00261 # ifndef VCSN_NDEBUG
00262     if (res == false)
00263       for (int i = 0; i < int(states_.size()); ++i)
00264         if (removed_states_.find(hstate_t(i)) == removed_states_.end())
00265           postcondition(states_[i].output_edges.find(e) ==
00266                         states_[i].output_edges.end());
00267 # endif // !VCSN_NDEBUG
00268     return res;
00269   }
00270 
00271   TParam
00272   hedge_t
00273   GClass::add_edge(hstate_t n1, hstate_t n2,
00274                    const label_t& v)
00275   {
00276     precondition(has_state(n1));
00277     precondition(has_state(n2));
00278     hedge_t e;
00279     if (removed_edges_.size() == 0)
00280     {
00281       edges_.push_back(edge_value_t(n1, n2, v));
00282       e = edges_.size() - 1;
00283     }
00284     else
00285     {
00286       e = *removed_edges_.begin();
00287       removed_edges_.erase(e);
00288       assertion(e < int(edges_.size()));
00289       edges_[e].from = n1;
00290       edges_[e].to = n2;
00291       edges_[e].label = v;
00292     }
00293     states_[n1].output_edges.insert(e);
00294     states_[n2].input_edges.insert(e);
00295 
00296     postcondition(has_edge(e));
00297     return e;
00298   }
00299 
00300   TParam
00301   void
00302   GClass::del_edge(hedge_t e)
00303   {
00304     if (!has_edge(e))
00305       return;
00306 
00307     const edge_value_t& ev = edges_[e];
00308     states_[ev.from].output_edges.erase(e);
00309     states_[ev.to].input_edges.erase(e);
00310     removed_edges_.insert(e);
00311 
00312     postcondition(!has_edge(e));
00313   }
00314 
00315 
00316   TParam
00317   hstate_t
00318   GClass::src_of(hedge_t e1) const
00319   {
00320     precondition(has_edge(e1));
00321     return edges_[e1].from;
00322   }
00323 
00324   TParam
00325   hstate_t
00326   GClass::dst_of(hedge_t e2) const
00327   {
00328     precondition(has_edge(e2));
00329     return edges_[e2].to;
00330   }
00331 
00332   TParam
00333   const typename GClass::label_t&
00334   GClass::label_of(hedge_t n) const
00335   {
00336     precondition(has_edge(n));
00337     return edges_[n];
00338   }
00339 
00340   TParam
00341   void
00342   GClass::update(hedge_t e, label_t l)
00343   {
00344     precondition(has_edge(e));
00345     edges_[e].label = l;
00346   }
00347 
00348 
00350   TParam
00351   template <class S>
00352   bool
00353   GClass::exists(const AutomataBase<S>& s) const
00354   {
00355     typename WordValue::iterator        it;
00356     typename label_t::const_iterator    r;
00357     label_t                             l;
00358     WordValue                           w;
00359 
00360     for (int i = 0; i < int(edges_.size()); ++i)
00361     {
00362       if (removed_edges_.find(hedge_t(i)) != removed_edges_.end())
00363         continue;
00364       // Make sure that origin and aim of edge are part of the automaton.
00365       if (!has_state(dst_of(hedge_t(i))) ||
00366           !has_state(src_of(hedge_t(i))))
00367         return false;
00368 
00369       // Make sure that every letter of the edge is in the alphabet.
00370       l = label_of(hedge_t(i));
00371       for (r = l.begin(); r != l.end(); ++r)
00372       {
00373         w = r->first;
00374         for (it = w.begin(); it != w.end(); ++it)
00375           if (!s.series().monoid().alphabet().contains(*it))
00376             return false;
00377       }
00378     }
00379     return true;
00380   }
00381 
00382   /*----------------.
00383   | Delta functions |
00384   `----------------*/
00385 
00386   // Classical ones.
00387 
00388 # define DEFINE_DELTA_FUNCTION(DeltaName, DKind, IO, WhatFromE)         \
00389   TParam                                                                \
00390   template <class OutputIterator, class Query>                          \
00391   void                                                                  \
00392   GClass::DeltaName(OutputIterator res,                                 \
00393                     hstate_t from,                                      \
00394                     const Query& query,                                 \
00395                     delta_kind::DKind) const                            \
00396   {                                                                     \
00397     assertion(has_state(from));                                         \
00398     const std::set<hedge_t>& edges = states_[from].IO ## _edges;        \
00399     for_all_const_(std::set<hedge_t>, e, edges)                         \
00400       if (query(*e))                                                    \
00401         *res++ = WhatFromE;                                             \
00402   }                                                                     \
00403 
00404   DEFINE_DELTA_FUNCTION (delta, edges, output, *e);
00405   DEFINE_DELTA_FUNCTION (delta, states, output, edges_[*e].to;);
00406   DEFINE_DELTA_FUNCTION (rdelta, edges, input, *e);
00407   DEFINE_DELTA_FUNCTION (rdelta, states, input, edges_[*e].from);
00408 
00409 # undef DEFINE_DELTA_FUNCTION
00410 
00411   // Delta with functor.  Much more than the previous one, because
00412   // functor is statically checked for return type of its operator(),
00413   // and behave differently if it is bool: loop breaks if false is
00414   // returned.
00415 # define DEFINE_DELTAF_FUNCTION(DeltaName, DKind, IO, IsBool, Action)   \
00416   TParam                                                                \
00417   template <typename Functor, class Query>                              \
00418   void                                                                  \
00419   GClass::DeltaName(Functor& fun,                                       \
00420                     hstate_t from,                                      \
00421                     const Query& query,                                 \
00422                     delta_kind::DKind,                                  \
00423                     misc::IsBool ## _t) const                   \
00424   {                                                                     \
00425     assertion(has_state(from));                                         \
00426     const std::set<hedge_t>& edges = states_[from].IO ## _edges;        \
00427     for_all_const_(std::set<hedge_t>, e, edges)                         \
00428       if (query(*e))                                                    \
00429       { Action; }                                                       \
00430   }
00431 
00432   DEFINE_DELTAF_FUNCTION (deltaf, states, output, true,
00433                           if (not fun(edges_[*e].to)) break);
00434   DEFINE_DELTAF_FUNCTION (deltaf, states, output, false, fun(edges_[*e].to));
00435   DEFINE_DELTAF_FUNCTION (deltaf, edges, output, true,
00436                           if (not fun(*e)) break);
00437   DEFINE_DELTAF_FUNCTION (deltaf, edges, output, false, fun(*e));
00438 
00439   DEFINE_DELTAF_FUNCTION (rdeltaf, states, input, true,
00440                           if (not fun(edges_[*e].from)) break);
00441   DEFINE_DELTAF_FUNCTION (rdeltaf, states, input, false, fun(edges_[*e].from));
00442   DEFINE_DELTAF_FUNCTION (rdeltaf, edges, input, true,
00443                           if (not fun(*e)) break);
00444   DEFINE_DELTAF_FUNCTION (rdeltaf, edges, input, false, fun(*e));
00445 
00446 # undef DEFINE_DELTAF_FUNCTION
00447 
00448   // Helpers for static dispatch.
00449   namespace deltaf_helper {
00450     template <typename T, typename R, typename Arg>
00451     char is_returning_bool_helper (R (T::*) (Arg));
00452 
00453     template <typename T, typename Arg>
00454     int is_returning_bool_helper (bool (T::*) (Arg));
00455 
00456 # define is_returning_bool(T)                                           \
00457     (sizeof (deltaf_helper::is_returning_bool_helper (T)) == sizeof (int))
00458   }
00459 
00460 # define DEFINE_DELTAF_HELPER(DeltaName)                                \
00461   TParam                                                                \
00462   template <typename Functor, class Query, typename DKind>              \
00463   void                                                                  \
00464   GClass::DeltaName(Functor& fun,                                       \
00465                     hstate_t from,                                      \
00466                     const Query& query,                                 \
00467                     delta_kind::kind<DKind> k) const                    \
00468   {                                                                     \
00469     DeltaName (fun, from, query, k,                                     \
00470                BOOL_TO_TYPE (is_returning_bool (&Functor::operator ())) ()); \
00471   }
00472 
00473   DEFINE_DELTAF_HELPER (deltaf);
00474   DEFINE_DELTAF_HELPER (rdeltaf);
00475 
00476 # undef DEFINE_DELTAF_HELPER
00477 # undef is_returning_bool
00478 
00479   /*----.
00480   | Tag |
00481   `----*/
00482 
00483   TParam
00484   inline
00485   Tag& GClass::tag()
00486   {
00487     return tag_;
00488   }
00489 
00490   TParam
00491   const Tag& GClass::tag() const
00492   {
00493     return tag_;
00494   }
00495 
00496   template <class Kind, class WordValue, class WeightValue, class SerieValue,
00497             class Letter, class Tag, class Geometry, class I>
00498   Tag& op_tag(const AutomataBase<I>&,
00499               Graph<Kind, WordValue, WeightValue,
00500               SerieValue ,Letter, Tag, Geometry>& v)
00501   {
00502     return v.tag();
00503   }
00504 
00505   template <class Kind, class WordValue, class WeightValue, class SerieValue,
00506             class Letter, class Tag, class Geometry, class I>
00507   const Tag& op_tag(const AutomataBase<I>&,
00508                     const Graph<Kind, WordValue, WeightValue,
00509                     SerieValue ,Letter, Tag, Geometry>& v)
00510   {
00511     return v.tag();
00512   }
00513 
00514 
00515   /*---------.
00516   | Geometry |
00517   `---------*/
00518 
00519   template <class Kind, class WordValue, class WeightValue, class SerieValue,
00520             class Letter, class Tag, class Geometry, class I>
00521   Geometry&
00522   op_geometry(const AutomataBase<I>&,
00523               Graph<Kind, WordValue, WeightValue,
00524               SerieValue, Letter, Tag, Geometry>& v)
00525   {
00526     return v.geometry();
00527   }
00528 
00529   template <class Kind, class WordValue, class WeightValue, class SerieValue,
00530             class Letter, class Tag, class Geometry, class I>
00531   const Geometry&
00532   op_geometry(const AutomataBase<I>&,
00533               const Graph<Kind, WordValue, WeightValue,
00534               SerieValue, Letter, Tag, Geometry>& v)
00535   {
00536     return v.geometry();
00537   }
00538 
00539 
00540   TParam
00541   const Geometry&
00542   GClass::geometry() const
00543   {
00544     return geometry_;
00545   }
00546 
00547   TParam
00548   Geometry&
00549   GClass::geometry()
00550   {
00551     return geometry_;
00552   }
00553 
00554 
00555   // Remove macros to avoid name clashes.
00556 # undef TParam
00557 # undef GClass
00558 
00559 }
00560 
00561 #endif // ! VCSN_AUTOMATA_IMPLEMENTATION_GRAPH_HXX

Generated on Sat Jul 29 17:13:00 2006 for Vaucanson by  doxygen 1.4.6