listg_graph_impl.hxx

00001 // listg_graph_impl.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, 2007, 2008 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_LISTG_GRAPH_IMPL_HXX
00018 # define VCSN_AUTOMATA_IMPLEMENTATION_LISTG_GRAPH_IMPL_HXX
00019 
00020 # include <fstream>
00021 # include <sstream>
00022 
00023 # include <algorithm>
00024 # include <utility>
00025 
00026 # include <vaucanson/automata/implementation/listg_graph_impl.hh>
00027 # include <vaucanson/misc/contract.hh>
00028 # include <vaucanson/misc/static.hh>
00029 
00030 namespace vcsn
00031 {
00032   namespace listg
00033   {
00034 
00035     /*--------------------.
00036     | Convenient macros.  |
00037     `--------------------*/
00038 
00039     # define TParam                                                             \
00040     template <class Kind, class WordValue, class WeightValue,           \
00041             class SeriesValue, class Letter, class Tag, class GeometryCoords>
00042 
00043     # define GClass                                                             \
00044     Graph<Kind, WordValue, WeightValue, SeriesValue, Letter, Tag, GeometryCoords>
00045 
00046     /*-------------------------.
00047     | Graph's implementation.  |
00048     `-------------------------*/
00049 
00050     /*---------------.
00051     | Constructors.  |
00052     `---------------*/
00053 
00054     TParam
00055     GClass::Graph()
00056     { }
00057 
00058     TParam
00059     GClass::Graph (unsigned initial_number_of_state,
00060                    unsigned reserve_number_of_edge)
00061     {
00062       states_.resize(initial_number_of_state);
00063       edges_.reserve(reserve_number_of_edge);
00064     }
00065 
00066     /*------------------.
00067     | Basic accessors.  |
00068     `------------------*/
00069 
00070     TParam
00071     typename GClass::states_t
00072     GClass::states() const
00073     {
00074       return states_t(hstate_t(0),
00075                       hstate_t(states_.size() - 1),
00076                       removed_states_);
00077     }
00078 
00079     TParam
00080     typename GClass::edges_t
00081     GClass::edges() const
00082     {
00083       return edges_t(hedge_t(0),
00084                      hedge_t(edges_.size() - 1),
00085                      removed_edges_);
00086     }
00087 
00088     TParam
00089     typename GClass::initial_support_t
00090     GClass::initial() const
00091     {
00092       return initial_support_t(initial_);
00093     }
00094 
00095     TParam
00096     typename GClass::final_support_t
00097     GClass::final() const
00098     {
00099       return final_support_t(final_);
00100     }
00101 
00102 
00103     /*----------------------.
00104     | States manipulation.  |
00105     `----------------------*/
00106 
00107     TParam
00108     bool
00109     GClass::has_state(const hstate_t& n) const
00110     {
00111       bool res = (n.is_valid() &&
00112                   n < unsigned(states_.size()) &&
00113                   (removed_states_.find(n) == removed_states_.end()));
00114      # ifndef VCSN_NDEBUG
00115       if (res == false)
00116       for (unsigned i = 0; i < edges_.size(); ++i)
00117               if (removed_edges_.find(hedge_t(i)) == removed_edges_.end())
00118               postcondition(edges_[i].from != n
00119                               && edges_[i].to != n);
00120       # endif // !VCSN_NDEBUG
00121       return res;
00122     }
00123 
00124     TParam
00125     typename GClass::hstate_t
00126     GClass::get_state(int n) const
00127     {
00128       precondition(has_state(hstate_t(n)));
00129       return hstate_t(n);
00130     }
00131 
00132     TParam
00133     typename GClass::hstate_t
00134     GClass::add_state()
00135     {
00136       if (removed_states_.size() == 0)
00137       {
00138         states_.push_back(state_value_t());
00139         return hstate_t(states_.size() - 1);
00140       }
00141 
00142       hstate_t n = *removed_states_.begin();
00143       removed_states_.erase(n);
00144       assertion(n < states_.size());
00145 
00146       states_[n].output_edges.clear();
00147       states_[n].input_edges.clear();
00148 
00149       postcondition(has_state(n));
00150       return n;
00151     }
00152 
00153     TParam
00154     void
00155     GClass::del_state(const hstate_t& n)
00156     {
00157       precondition (has_state(n));
00158 
00159       const state_value_t& v = states_[n];
00160       typename state_value::edges_t::const_iterator e = v.output_edges.begin();
00161       typename state_value::edges_t::const_iterator end = v.output_edges.end();
00162       typename state_value::edges_t::const_iterator next = e;
00163 
00164       for (; e != end; e = next)
00165       {
00166         ++next;
00167         this->del_edge(*e);
00168       }
00169 
00170       e = v.input_edges.begin();
00171       end = v.input_edges.end();
00172       for (next = e; e != end; e = next)
00173       {
00174         ++next;
00175         this->del_edge(*e);
00176       }
00177 
00178       removed_states_.insert(n);
00179       initial_.erase(n);
00180       final_.erase(n);
00181       postcondition(!has_state(n));
00182     }
00183 
00184     TParam
00185     void
00186     GClass::set_initial(const hstate_t& n, const series_set_elt_value_t& v,
00187                         const series_set_elt_value_t& z)
00188     {
00189       precondition (has_state(n));
00190       if (z == v)
00191         initial_.erase(n);
00192       else
00193         initial_[n] = v;
00194     }
00195 
00196     TParam
00197     const typename GClass::series_set_elt_value_t&
00198     GClass::get_initial(const hstate_t& n, const series_set_elt_value_t& z) const
00199     {
00200       precondition(has_state(n));
00201       typename initial_t::const_iterator i = initial_.find(n);
00202       if (i == initial_.end())
00203         return z;
00204       return i->second;
00205     }
00206 
00207     TParam
00208     bool
00209     GClass::is_initial(const hstate_t& s, const series_set_elt_value_t& z) const
00210     {
00211       return get_initial(s, z) != z;
00212     }
00213 
00214     TParam
00215     void
00216     GClass::clear_initial()
00217     {
00218       return initial_.clear();
00219     }
00220 
00221     TParam
00222     void
00223     GClass::set_final(const hstate_t& n, const series_set_elt_value_t& v,
00224                       const series_set_elt_value_t& z)
00225     {
00226       precondition (has_state(n));
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(const hstate_t& n, const series_set_elt_value_t& z) const
00236     {
00237       precondition (has_state(n));
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     bool
00246     GClass::is_final(const hstate_t& s, const series_set_elt_value_t& z) const
00247     {
00248       return get_final(s, z) != z;
00249     }
00250 
00251     TParam
00252     void
00253     GClass::clear_final()
00254     {
00255       return final_.clear();
00256     }
00257 
00258 
00259     /*---------------------.
00260     | Edges manipulation.  |
00261     `---------------------*/
00262 
00263     TParam
00264     bool
00265     GClass::has_edge(const hedge_t& e) const
00266     {
00267       bool res = (removed_edges_.find(e) == removed_edges_.end()
00268                   && (e < edges_.size()));
00269       # ifndef VCSN_NDEBUG
00270       if (res == false)
00271         for (unsigned i = 0; i < states_.size(); ++i)
00272           if (removed_states_.find(hstate_t(i)) == removed_states_.end())
00273             postcondition(states_[i].output_edges.find(e) ==
00274                           states_[i].output_edges.end());
00275       # endif // !VCSN_NDEBUG
00276       return res;
00277     }
00278 
00279     TParam
00280     typename GClass::hedge_t
00281     GClass::add_edge(const hstate_t& n1, const hstate_t& n2,
00282                      const label_t& v)
00283     {
00284       precondition(has_state(n1));
00285       precondition(has_state(n2));
00286       hedge_t e;
00287       if (removed_edges_.size() == 0)
00288       {
00289         edges_.push_back(edge_value_t(n1, n2, v));
00290         e = hedge_t(edges_.size() - 1);
00291       }
00292       else
00293       {
00294         e = *removed_edges_.begin();
00295         removed_edges_.erase(e);
00296         assertion(e < edges_.size());
00297         edges_[e].from = n1;
00298         edges_[e].to = n2;
00299         edges_[e].label = v;
00300       }
00301       states_[n1].output_edges.insert(e);
00302       states_[n2].input_edges.insert(e);
00303 
00304       postcondition(has_edge(e));
00305       return e;
00306     }
00307 
00308     TParam
00309     void
00310     GClass::del_edge(const hedge_t& e)
00311     {
00312       precondition (has_edge(e));
00313 
00314       const edge_value_t& ev = edges_[e];
00315       states_[ev.from].output_edges.erase(e);
00316       states_[ev.to].input_edges.erase(e);
00317       removed_edges_.insert(e);
00318 
00319       postcondition(!has_edge(e));
00320     }
00321 
00322 
00323     TParam
00324     typename GClass::hstate_t
00325     GClass::src_of(const hedge_t& e1) const
00326     {
00327       precondition(has_edge(e1));
00328       return edges_[e1].from;
00329     }
00330 
00331     TParam
00332     typename GClass::hstate_t
00333     GClass::dst_of(const hedge_t& e2) const
00334     {
00335       precondition(has_edge(e2));
00336       return edges_[e2].to;
00337     }
00338 
00339     TParam
00340     const typename GClass::label_t&
00341     GClass::label_of(const hedge_t& n) const
00342     {
00343       precondition(has_edge(n));
00344       return edges_[n];
00345     }
00346 
00347     TParam
00348     void
00349     GClass::update(const hedge_t& e, label_t l)
00350     {
00351       precondition(has_edge(e));
00352       edges_[e].label = l;
00353     }
00354 
00355 
00357     TParam
00358     template <class S>
00359     bool
00360     GClass::exists(const AutomataBase<S>& s) const
00361     {
00362       typename WordValue::iterator      it;
00363       typename label_t::const_iterator  r;
00364       label_t                           l;
00365       WordValue                         w;
00366 
00367       for (unsigned i = 0; i < edges_.size(); ++i)
00368       {
00369         if (removed_edges_.find(hedge_t(i)) != removed_edges_.end())
00370           continue;
00371         // Make sure that source and destination of edge are part of the
00372         // automaton.
00373         if (!has_state(dst_of(hedge_t(i)))
00374             || !has_state(src_of(hedge_t(i))))
00375           return false;
00376 
00377         // Make sure that every letter of the edge is in the alphabet.
00378         l = label_of(hedge_t(i));
00379         for (r = l.begin(); r != l.end(); ++r)
00380         {
00381           w = r->first;
00382           for (it = w.begin(); it != w.end(); ++it)
00383             if (!s.series().monoid().alphabet().contains(*it))
00384               return false;
00385         }
00386       }
00387       return true;
00388     }
00389 
00390     /*------------------.
00391     | Delta functions.  |
00392     `------------------*/
00393 
00394     // Classical ones.
00395 
00396     # define DEFINE_DELTA_FUNCTION(DeltaName, DKind, IO, WhatFromE)     \
00397     TParam                                                              \
00398     template <class OutputIterator, class Query>                        \
00399     void                                                                \
00400     GClass::DeltaName(OutputIterator res,                               \
00401                       const hstate_t& from,                             \
00402                       const Query& query,                               \
00403                       ::vcsn::delta_kind::DKind) const                  \
00404     {                                                                   \
00405       assertion(has_state(from));                                       \
00406       const std::set<hedge_t>& edges = states_[from].IO ## _edges;      \
00407       for_all_const_(std::set<hedge_t>, e, edges)                       \
00408       if (query(*e))                                                    \
00409               *res++ = WhatFromE;                                       \
00410     }                                                                   \
00411 
00412     DEFINE_DELTA_FUNCTION (delta, transitions, output, *e);
00413     DEFINE_DELTA_FUNCTION (delta, states, output, edges_[*e].to);
00414     DEFINE_DELTA_FUNCTION (rdelta, transitions, input, *e);
00415     DEFINE_DELTA_FUNCTION (rdelta, states, input, edges_[*e].from);
00416 
00417     # undef DEFINE_DELTA_FUNCTION
00418 
00419     // Delta with functor.  Much more than the previous one, because
00420     // functor is statically checked for return type of its operator(),
00421     // and behave differently if it is bool: loop breaks if false is
00422     // returned.
00423     # define DEFINE_DELTAF_FUNCTION(DeltaName, DKind, IO, IsBool, Action)\
00424     TParam                                                              \
00425     template <typename Functor, class Query>                            \
00426     void                                                                \
00427     GClass::DeltaName(Functor& fun,                                     \
00428                       const hstate_t& from,                             \
00429                       const Query& query,                               \
00430                       ::vcsn::delta_kind::DKind,                        \
00431                       misc::IsBool ## _t) const                         \
00432     {                                                                   \
00433       assertion(has_state(from));                                       \
00434       const std::set<hedge_t>& edges = states_[from].IO ## _edges;      \
00435       for_all_const_(std::set<hedge_t>, e, edges)                       \
00436         if (query(*e))                                                  \
00437           { Action; }                                                   \
00438     }
00439 
00440     DEFINE_DELTAF_FUNCTION (deltaf, states, output, true,
00441                             if (not fun(edges_[*e].to)) break);
00442     DEFINE_DELTAF_FUNCTION (deltaf, states, output, false, fun(edges_[*e].to));
00443     DEFINE_DELTAF_FUNCTION (deltaf, transitions, output, true,
00444                             if (not fun(*e)) break);
00445     DEFINE_DELTAF_FUNCTION (deltaf, transitions, output, false, fun(*e));
00446 
00447     DEFINE_DELTAF_FUNCTION (rdeltaf, states, input, true,
00448                             if (not fun(edges_[*e].from)) break);
00449     DEFINE_DELTAF_FUNCTION (rdeltaf, states, input, false, fun(edges_[*e].from));
00450     DEFINE_DELTAF_FUNCTION (rdeltaf, transitions, input, true,
00451                             if (not fun(*e)) break);
00452     DEFINE_DELTAF_FUNCTION (rdeltaf, transitions, input, false, fun(*e));
00453 
00454     # undef DEFINE_DELTAF_FUNCTION
00455 
00456     // Helpers for static dispatch.
00457     namespace deltaf_helper {
00458       template <typename T, typename R, typename Arg>
00459       char is_returning_bool_helper (R (T::*) (Arg));
00460 
00461       template <typename T, typename Arg>
00462       int is_returning_bool_helper (bool (T::*) (Arg));
00463 
00464       # define is_returning_bool(T)                                       \
00465       (sizeof (deltaf_helper::is_returning_bool_helper (T)) == sizeof (int))
00466     }
00467 
00468     # define DEFINE_DELTAF_HELPER(DeltaName)                            \
00469     TParam                                                              \
00470     template <typename Functor, class Query, typename DKind>            \
00471     void                                                                \
00472     GClass::DeltaName(Functor& fun,                                     \
00473                     const hstate_t& from,                               \
00474                     const Query& query,                                 \
00475                     delta_kind::kind<DKind> k) const                    \
00476     {                                                                   \
00477       DeltaName (fun, from, query, k,                                   \
00478             BOOL_TO_TYPE (is_returning_bool (&Functor::operator ())) ());\
00479     }
00480 
00481     DEFINE_DELTAF_HELPER (deltaf);
00482     DEFINE_DELTAF_HELPER (rdeltaf);
00483 
00484     # undef DEFINE_DELTAF_HELPER
00485     # undef is_returning_bool
00486 
00487     /*------.
00488     | Tag.  |
00489     `------*/
00490 
00491     TParam
00492     inline
00493     Tag& GClass::tag()
00494     {
00495       return tag_;
00496     }
00497 
00498     TParam
00499     const Tag& GClass::tag() const
00500     {
00501       return tag_;
00502     }
00503 
00504     template <class Kind, class WordValue, class WeightValue, class SerieValue,
00505               class Letter, class Tag, class GeometryCoords, class I>
00506     Tag& op_tag(const AutomataBase<I>&,
00507                 Graph<Kind, WordValue, WeightValue,
00508                 SerieValue ,Letter, Tag, GeometryCoords>& v)
00509     {
00510       return v.tag();
00511     }
00512 
00513     template <class Kind, class WordValue, class WeightValue, class SerieValue,
00514               class Letter, class Tag, class GeometryCoords, class I>
00515     const Tag& op_tag(const AutomataBase<I>&,
00516                       const Graph<Kind, WordValue, WeightValue,
00517                       SerieValue ,Letter, Tag, GeometryCoords>& v)
00518     {
00519       return v.tag();
00520     }
00521 
00522 
00523     /*-----------.
00524     | Geometry.  |
00525     `-----------*/
00526 
00527     template <class Kind, class WordValue, class WeightValue, class SeriesValue,
00528               class Letter, class Tag, class GeometryCoords, class I>
00529     typename GClass::geometry_t&
00530     op_geometry(const AutomataBase<I>&,
00531                 Graph<Kind, WordValue, WeightValue,
00532                 SeriesValue, Letter, Tag, GeometryCoords>& v)
00533     {
00534       return v.geometry();
00535     }
00536 
00537     template <class Kind, class WordValue, class WeightValue, class SeriesValue,
00538               class Letter, class Tag, class GeometryCoords, class I>
00539     const typename GClass::geometry_t&
00540     op_geometry(const AutomataBase<I>&,
00541                 const Graph<Kind, WordValue, WeightValue,
00542                 SeriesValue, Letter, Tag, GeometryCoords>& v)
00543     {
00544       return v.geometry();
00545     }
00546 
00547 
00548     TParam
00549     const typename GClass::geometry_t&
00550     GClass::geometry() const
00551     {
00552       return geometry_;
00553     }
00554 
00555     TParam
00556     typename GClass::geometry_t&
00557     GClass::geometry()
00558     {
00559       return geometry_;
00560     }
00561 
00562 
00563     // Remove macros to avoid name clashes.
00564 # undef TParam
00565 # undef GClass
00566   }
00567 }
00568 
00569 #endif // ! VCSN_AUTOMATA_IMPLEMENTATION_LISTG_GRAPH_IMPL_HXX

Generated on Thu Oct 9 20:22:40 2008 for Vaucanson by  doxygen 1.5.1