- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

# 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, 2007 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, hstate_t h2,
    00039                                     const EdgeLabel& l)
    00040     : label(l),
    00041       from(h1),
    00042       to(h2)
    00043   {}
    00044
    00045   inline
    00046   state_value::state_value()
    00047   {}
    00048
    00049
    00050   /*--------------------.
    00051   | Convenient macros.  |
    00052   `--------------------*/
    00053
    00054 # define TParam                                                         \
    00055   template <class Kind, class WordValue, class WeightValue,             \
    00056             class SeriesValue, class Letter, class Tag, class Geometry>
    00057
    00058 # define GClass                                                         \
    00059   Graph<Kind, WordValue, WeightValue, SeriesValue, Letter, Tag, Geometry>
    00060
    00061
    00062   /*-------------------------.
    00063   | Graph's implementation.  |
    00064   `-------------------------*/
    00065
    00066   /*---------------.
    00067   | Constructors.  |
    00068   `---------------*/
    00069
    00070   TParam
    00071   GClass::Graph()
    00072   { }
    00073
    00074   TParam
    00075   GClass::Graph (unsigned initial_number_of_state,
    00076                  unsigned reserve_number_of_edge)
    00077   {
    00078     states_.resize(initial_number_of_state);
    00079     edges_.reserve(reserve_number_of_edge);
    00080   }
    00081
    00082
    00083   /*------------------.
    00084   | Basic accessors.  |
    00085   `------------------*/
    00086
    00087   TParam
    00088   typename GClass::states_t
    00089   GClass::states() const
    00090   {
    00091     return states_t(hstate_t(0),
    00092                     hstate_t(states_.size()) - 1,
    00093                     removed_states_);
    00094   }
    00095
    00096   TParam
    00097   typename GClass::edges_t
    00098   GClass::edges() const
    00099   {
    00100     return edges_t(hedge_t(0),
    00101                    hedge_t(edges_.size()) - 1,
    00102                    removed_edges_);
    00103   }
    00104
    00105   TParam
    00106   typename GClass::initial_support_t
    00107   GClass::initial() const
    00108   {
    00109     return initial_support_t(initial_);
    00110   }
    00111
    00112   TParam
    00113   typename GClass::final_support_t
    00114   GClass::final() const
    00115   {
    00116     return final_support_t(final_);
    00117   }
    00118
    00119
    00120   /*----------------------.
    00121   | States manipulation.  |
    00122   `----------------------*/
    00123
    00124   TParam
    00125   bool
    00126   GClass::has_state(hstate_t n) const
    00127   {
    00128     bool res = ((removed_states_.find(n) == removed_states_.end())
    00129                 && n >= 0
    00130                 && n < int(states_.size()));
    00131 # ifndef VCSN_NDEBUG
    00132     if (res == false)
    00133       for (int i = 0; i < int(edges_.size()); ++i)
    00134         if (removed_edges_.find(hedge_t(i)) == removed_edges_.end())
    00135           postcondition(edges_[i].from != n
    00136                         && edges_[i].to != n);
    00137 # endif // !VCSN_NDEBUG
    00138     return res;
    00139   }
    00140
    00141   TParam
    00142   hstate_t
    00143   GClass::add_state()
    00144   {
    00145     if (removed_states_.size() == 0)
    00146     {
    00147       states_.push_back(state_value_t());
    00148       return states_.size() - 1;
    00149     }
    00150
    00151     hstate_t n = *removed_states_.begin();
    00152     removed_states_.erase(n);
    00153     assertion(n < int(states_.size()));
    00154
    00155     states_[n].output_edges.clear();
    00156     states_[n].input_edges.clear();
    00157
    00158     postcondition(has_state(n));
    00159     return n;
    00160   }
    00161
    00162   TParam
    00163   void
    00164   GClass::del_state(hstate_t n)
    00165   {
    00166     precondition (has_state(n));
    00167
    00168     const state_value_t& v = states_[n];
    00169     state_value::edges_t::const_iterator e = v.output_edges.begin();
    00170     state_value::edges_t::const_iterator end = v.output_edges.end();
    00171     state_value::edges_t::const_iterator next = e;
    00172
    00173     for (; e != end; e = next)
    00174     {
    00175       ++next;
    00176       this->del_edge(*e);
    00177     }
    00178
    00179     e = v.input_edges.begin();
    00180     end = v.input_edges.end();
    00181     for (next = e; e != end; e = next)
    00182     {
    00183       ++next;
    00184       this->del_edge(*e);
    00185     }
    00186
    00187     removed_states_.insert(n);
    00188     initial_.erase(n);
    00189     final_.erase(n);
    00190     postcondition(!has_state(n));
    00191   }
    00192
    00193   TParam
    00194   void
    00195   GClass::set_initial(hstate_t n, const series_set_elt_value_t& v,
    00196                       const series_set_elt_value_t& z)
    00197   {
    00198     if (z == v)
    00199       initial_.erase(n);
    00200     else
    00201       initial_[n] = v;
    00202   }
    00203
    00204   TParam
    00205   const typename GClass::series_set_elt_value_t&
    00206   GClass::get_initial(hstate_t n, const series_set_elt_value_t& z) const
    00207   {
    00208     typename initial_t::const_iterator i = initial_.find(n);
    00209     if (i == initial_.end())
    00210       return z;
    00211     return i->second;
    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(hstate_t n, const series_set_elt_value_t& v,
    00224                     const series_set_elt_value_t& z)
    00225   {
    00226     if (v == z)
    00227       final_.erase(n);
    00228     else
    00229       final_[n] = v;
    00230   }
    00231
    00232   TParam
    00233   const typename GClass::series_set_elt_value_t&
    00234   GClass::get_final(hstate_t n, const series_set_elt_value_t& z) const
    00235   {
    00236     typename final_t::const_iterator i = final_.find(n);
    00237     if (i == final_.end())
    00238       return z;
    00239     return i->second;
    00240   }
    00241
    00242   TParam
    00243   void
    00244   GClass::clear_final()
    00245   {
    00246     return final_.clear();
    00247   }
    00248
    00249
    00250   /*---------------------.
    00251   | Edges manipulation.  |
    00252   `---------------------*/
    00253
    00254   TParam
    00255   bool
    00256   GClass::has_edge(hedge_t e) const
    00257   {
    00258     bool res = (removed_edges_.find(e) == removed_edges_.end()
    00259                 && (e < int(edges_.size())));
    00260 # ifndef VCSN_NDEBUG
    00261     if (res == false)
    00262       for (int i = 0; i < int(states_.size()); ++i)
    00263         if (removed_states_.find(hstate_t(i)) == removed_states_.end())
    00264           postcondition(states_[i].output_edges.find(e) ==
    00265                         states_[i].output_edges.end());
    00266 # endif // !VCSN_NDEBUG
    00267     return res;
    00268   }
    00269
    00270   TParam
    00271   hedge_t
    00272   GClass::add_edge(hstate_t n1, hstate_t n2,
    00273                    const label_t& v)
    00274   {
    00275     precondition(has_state(n1));
    00276     precondition(has_state(n2));
    00277     hedge_t e;
    00278     if (removed_edges_.size() == 0)
    00279     {
    00280       edges_.push_back(edge_value_t(n1, n2, v));
    00281       e = edges_.size() - 1;
    00282     }
    00283     else
    00284     {
    00285       e = *removed_edges_.begin();
    00286       removed_edges_.erase(e);
    00287       assertion(e < int(edges_.size()));
    00288       edges_[e].from = n1;
    00289       edges_[e].to = n2;
    00290       edges_[e].label = v;
    00291     }
    00292     states_[n1].output_edges.insert(e);
    00293     states_[n2].input_edges.insert(e);
    00294
    00295     postcondition(has_edge(e));
    00296     return e;
    00297   }
    00298
    00299   TParam
    00300   void
    00301   GClass::del_edge(hedge_t e)
    00302   {
    00303     if (!has_edge(e))
    00304       return;
    00305
    00306     const edge_value_t& ev = edges_[e];
    00307     states_[ev.from].output_edges.erase(e);
    00308     states_[ev.to].input_edges.erase(e);
    00309     removed_edges_.insert(e);
    00310
    00311     postcondition(!has_edge(e));
    00312   }
    00313
    00314
    00315   TParam
    00316   hstate_t
    00317   GClass::src_of(hedge_t e1) const
    00318   {
    00319     precondition(has_edge(e1));
    00320     return edges_[e1].from;
    00321   }
    00322
    00323   TParam
    00324   hstate_t
    00325   GClass::dst_of(hedge_t e2) const
    00326   {
    00327     precondition(has_edge(e2));
    00328     return edges_[e2].to;
    00329   }
    00330
    00331   TParam
    00332   const typename GClass::label_t&
    00333   GClass::label_of(hedge_t n) const
    00334   {
    00335     precondition(has_edge(n));
    00336     return edges_[n];
    00337   }
    00338
    00339   TParam
    00340   void
    00341   GClass::update(hedge_t e, label_t l)
    00342   {
    00343     precondition(has_edge(e));
    00344     edges_[e].label = l;
    00345   }
    00346
    00347
    00349   TParam
    00350   template <class S>
    00351   bool
    00352   GClass::exists(const AutomataBase<S>& s) const
    00353   {
    00354     typename WordValue::iterator        it;
    00355     typename label_t::const_iterator    r;
    00356     label_t                             l;
    00357     WordValue                           w;
    00358
    00359     for (int i = 0; i < int(edges_.size()); ++i)
    00360     {
    00361       if (removed_edges_.find(hedge_t(i)) != removed_edges_.end())
    00362         continue;
    00363       // Make sure that source and destination of edge are part of the
    00364       // 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